1cb69b360Sopenharmony_ci/* 2cb69b360Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3cb69b360Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4cb69b360Sopenharmony_ci * you may not use this file except in compliance with the License. 5cb69b360Sopenharmony_ci * You may obtain a copy of the License at 6cb69b360Sopenharmony_ci * 7cb69b360Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8cb69b360Sopenharmony_ci * 9cb69b360Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10cb69b360Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11cb69b360Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12cb69b360Sopenharmony_ci * See the License for the specific language governing permissions and 13cb69b360Sopenharmony_ci * limitations under the License. 14cb69b360Sopenharmony_ci */ 15cb69b360Sopenharmony_ci 16cb69b360Sopenharmony_ci#include <stdint.h> 17cb69b360Sopenharmony_ci#include <stdlib.h> 18cb69b360Sopenharmony_ci 19cb69b360Sopenharmony_ci#include <ohos_errno.h> 20cb69b360Sopenharmony_ci#include <ohos_types.h> 21cb69b360Sopenharmony_ci#include <pthread.h> 22cb69b360Sopenharmony_ci#include <registry.h> 23cb69b360Sopenharmony_ci#include <samgr_lite.h> 24cb69b360Sopenharmony_ci#include <securec.h> 25cb69b360Sopenharmony_ci#include <unistd.h> 26cb69b360Sopenharmony_ci 27cb69b360Sopenharmony_ci#include "hilog_wrapper.h" 28cb69b360Sopenharmony_ci#include "power_manage_interface.h" 29cb69b360Sopenharmony_ci#include "power_mgr.h" 30cb69b360Sopenharmony_ci 31cb69b360Sopenharmony_ci#define MAX_DATA_LEN 1024 32cb69b360Sopenharmony_ci 33cb69b360Sopenharmony_citypedef struct { 34cb69b360Sopenharmony_ci INHERIT_IUNKNOWNENTRY(PowerManageProxyInterface); 35cb69b360Sopenharmony_ci} PowerManageProxyEntry; 36cb69b360Sopenharmony_ci 37cb69b360Sopenharmony_cistatic pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; 38cb69b360Sopenharmony_cistatic PowerManageProxyInterface *g_intf = NULL; 39cb69b360Sopenharmony_ci 40cb69b360Sopenharmony_cistatic int32_t AcquireRunningLockEntryProxy(IUnknown *iUnknown, RunningLockEntry *entry, int32_t timeoutMs); 41cb69b360Sopenharmony_cistatic int32_t ReleaseRunningLockEntryProxy(IUnknown *iUnknown, RunningLockEntry *entry); 42cb69b360Sopenharmony_cistatic BOOL IsAnyRunningLockHoldingProxy(IUnknown *iUnknown); 43cb69b360Sopenharmony_cistatic void SuspendDeviceProxy(IUnknown *iUnknown, SuspendDeviceType reason, BOOL suspendImmed); 44cb69b360Sopenharmony_cistatic void WakeupDeviceProxy(IUnknown *iUnknown, WakeupDeviceType reason, const char* details); 45cb69b360Sopenharmony_ci 46cb69b360Sopenharmony_cistatic void *CreatClient(const char *service, const char *feature, uint32_t size) 47cb69b360Sopenharmony_ci{ 48cb69b360Sopenharmony_ci (void)service; 49cb69b360Sopenharmony_ci (void)feature; 50cb69b360Sopenharmony_ci uint32_t len = size + sizeof(PowerManageProxyEntry); 51cb69b360Sopenharmony_ci uint8_t *client = (uint8_t *)malloc(len); 52cb69b360Sopenharmony_ci if (client == NULL) { 53cb69b360Sopenharmony_ci POWER_HILOGE("Failed to allocate memory for power manage proxy entry"); 54cb69b360Sopenharmony_ci return NULL; 55cb69b360Sopenharmony_ci } 56cb69b360Sopenharmony_ci (void)memset_s(client, len, 0, len); 57cb69b360Sopenharmony_ci PowerManageProxyEntry *entry = (PowerManageProxyEntry *)&client[size]; 58cb69b360Sopenharmony_ci entry->ver = ((uint16)CLIENT_PROXY_VER | (uint16)DEFAULT_VERSION); 59cb69b360Sopenharmony_ci entry->ref = 1; 60cb69b360Sopenharmony_ci entry->iUnknown.QueryInterface = IUNKNOWN_QueryInterface; 61cb69b360Sopenharmony_ci entry->iUnknown.AddRef = IUNKNOWN_AddRef; 62cb69b360Sopenharmony_ci entry->iUnknown.Release = IUNKNOWN_Release; 63cb69b360Sopenharmony_ci entry->iUnknown.Invoke = NULL; 64cb69b360Sopenharmony_ci entry->iUnknown.AcquireRunningLockEntryFunc = AcquireRunningLockEntryProxy; 65cb69b360Sopenharmony_ci entry->iUnknown.ReleaseRunningLockEntryFunc = ReleaseRunningLockEntryProxy; 66cb69b360Sopenharmony_ci entry->iUnknown.IsAnyRunningLockHoldingFunc = IsAnyRunningLockHoldingProxy; 67cb69b360Sopenharmony_ci entry->iUnknown.SuspendDeviceFunc = SuspendDeviceProxy; 68cb69b360Sopenharmony_ci entry->iUnknown.WakeupDeviceFunc = WakeupDeviceProxy; 69cb69b360Sopenharmony_ci return client; 70cb69b360Sopenharmony_ci} 71cb69b360Sopenharmony_ci 72cb69b360Sopenharmony_cistatic void DestroyClient(const char *service, const char *feature, void *iproxy) 73cb69b360Sopenharmony_ci{ 74cb69b360Sopenharmony_ci (void)service; 75cb69b360Sopenharmony_ci (void)feature; 76cb69b360Sopenharmony_ci free(iproxy); 77cb69b360Sopenharmony_ci} 78cb69b360Sopenharmony_ci 79cb69b360Sopenharmony_cistatic PowerManageProxyInterface *GetPowerManageProxyInterface(void) 80cb69b360Sopenharmony_ci{ 81cb69b360Sopenharmony_ci if (g_intf != NULL) { 82cb69b360Sopenharmony_ci return g_intf; 83cb69b360Sopenharmony_ci } 84cb69b360Sopenharmony_ci pthread_mutex_lock(&g_mutex); 85cb69b360Sopenharmony_ci if (g_intf != NULL) { 86cb69b360Sopenharmony_ci pthread_mutex_unlock(&g_mutex); 87cb69b360Sopenharmony_ci return g_intf; 88cb69b360Sopenharmony_ci } 89cb69b360Sopenharmony_ci 90cb69b360Sopenharmony_ci SAMGR_RegisterFactory(POWER_MANAGE_SERVICE, POWER_MANAGE_FEATURE, CreatClient, DestroyClient); 91cb69b360Sopenharmony_ci 92cb69b360Sopenharmony_ci IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(POWER_MANAGE_SERVICE, POWER_MANAGE_FEATURE); 93cb69b360Sopenharmony_ci if (iUnknown == NULL) { 94cb69b360Sopenharmony_ci POWER_HILOGE("Failed to get power manage iUnknown"); 95cb69b360Sopenharmony_ci pthread_mutex_unlock(&g_mutex); 96cb69b360Sopenharmony_ci return NULL; 97cb69b360Sopenharmony_ci } 98cb69b360Sopenharmony_ci 99cb69b360Sopenharmony_ci int ret = iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION, (void **)&g_intf); 100cb69b360Sopenharmony_ci if ((ret != EC_SUCCESS) || (g_intf == NULL)) { 101cb69b360Sopenharmony_ci POWER_HILOGE("Failed to query power manage interface"); 102cb69b360Sopenharmony_ci pthread_mutex_unlock(&g_mutex); 103cb69b360Sopenharmony_ci return NULL; 104cb69b360Sopenharmony_ci } 105cb69b360Sopenharmony_ci pthread_mutex_unlock(&g_mutex); 106cb69b360Sopenharmony_ci POWER_HILOGI("Succeed to get power manage proxy interface"); 107cb69b360Sopenharmony_ci return g_intf; 108cb69b360Sopenharmony_ci} 109cb69b360Sopenharmony_ci 110cb69b360Sopenharmony_cistatic int32_t AcquireReleaseCallback(IOwner owner, int32_t code, IpcIo *reply) 111cb69b360Sopenharmony_ci{ 112cb69b360Sopenharmony_ci if ((reply == NULL) || (owner == NULL)) { 113cb69b360Sopenharmony_ci POWER_HILOGE("Invalid parameter"); 114cb69b360Sopenharmony_ci return EC_INVALID; 115cb69b360Sopenharmony_ci } 116cb69b360Sopenharmony_ci 117cb69b360Sopenharmony_ci int32_t *ret = (int32_t *)owner; 118cb69b360Sopenharmony_ci ReadInt32(reply, ret); 119cb69b360Sopenharmony_ci POWER_HILOGD("Running lock callback: %d, code: %d", *ret, code); 120cb69b360Sopenharmony_ci return EC_SUCCESS; 121cb69b360Sopenharmony_ci} 122cb69b360Sopenharmony_ci 123cb69b360Sopenharmony_cistatic int32_t AcquireRunningLockEntryProxy(IUnknown *iUnknown, RunningLockEntry *entry, int32_t timeoutMs) 124cb69b360Sopenharmony_ci{ 125cb69b360Sopenharmony_ci if (IsValidRunningLockEntry(entry) == FALSE) { 126cb69b360Sopenharmony_ci POWER_HILOGE("Invalid running lock entry"); 127cb69b360Sopenharmony_ci return EC_INVALID; 128cb69b360Sopenharmony_ci } 129cb69b360Sopenharmony_ci 130cb69b360Sopenharmony_ci IpcIo request; 131cb69b360Sopenharmony_ci char buffer[MAX_DATA_LEN]; 132cb69b360Sopenharmony_ci IpcIoInit(&request, buffer, MAX_DATA_LEN, 0); 133cb69b360Sopenharmony_ci bool value = WriteRawData(&request, entry, sizeof(RunningLockEntry)); 134cb69b360Sopenharmony_ci if (!value) { 135cb69b360Sopenharmony_ci POWER_HILOGE("WriteRawData faild"); 136cb69b360Sopenharmony_ci return EC_INVALID; 137cb69b360Sopenharmony_ci } 138cb69b360Sopenharmony_ci WriteInt32(&request, timeoutMs); 139cb69b360Sopenharmony_ci 140cb69b360Sopenharmony_ci int32_t ret; 141cb69b360Sopenharmony_ci PowerManageProxyInterface *proxy = (PowerManageProxyInterface *)iUnknown; 142cb69b360Sopenharmony_ci proxy->Invoke((IClientProxy *)proxy, POWERMANAGE_FUNCID_ACQUIRERUNNINGLOCK, 143cb69b360Sopenharmony_ci &request, &ret, AcquireReleaseCallback); 144cb69b360Sopenharmony_ci POWER_HILOGD("Acquire running lock done, name: %s, type: %d", entry->lock.name, entry->lock.type); 145cb69b360Sopenharmony_ci 146cb69b360Sopenharmony_ci return ret; 147cb69b360Sopenharmony_ci} 148cb69b360Sopenharmony_ci 149cb69b360Sopenharmony_cistatic int32_t ReleaseRunningLockEntryProxy(IUnknown *iUnknown, RunningLockEntry *entry) 150cb69b360Sopenharmony_ci{ 151cb69b360Sopenharmony_ci if (IsValidRunningLockEntry(entry) == FALSE) { 152cb69b360Sopenharmony_ci POWER_HILOGE("Invalid running lock entry"); 153cb69b360Sopenharmony_ci return EC_INVALID; 154cb69b360Sopenharmony_ci } 155cb69b360Sopenharmony_ci 156cb69b360Sopenharmony_ci IpcIo request; 157cb69b360Sopenharmony_ci char buffer[MAX_DATA_LEN]; 158cb69b360Sopenharmony_ci IpcIoInit(&request, buffer, MAX_DATA_LEN, 0); 159cb69b360Sopenharmony_ci bool value = WriteRawData(&request, entry, sizeof(RunningLockEntry)); 160cb69b360Sopenharmony_ci if (!value) { 161cb69b360Sopenharmony_ci POWER_HILOGE("WriteRawData faild"); 162cb69b360Sopenharmony_ci return EC_INVALID; 163cb69b360Sopenharmony_ci } 164cb69b360Sopenharmony_ci 165cb69b360Sopenharmony_ci int32_t ret; 166cb69b360Sopenharmony_ci PowerManageProxyInterface *proxy = (PowerManageProxyInterface *)iUnknown; 167cb69b360Sopenharmony_ci proxy->Invoke((IClientProxy *)proxy, POWERMANAGE_FUNCID_RELEASERUNNINGLOCK, 168cb69b360Sopenharmony_ci &request, &ret, AcquireReleaseCallback); 169cb69b360Sopenharmony_ci POWER_HILOGD("Release running lock done, name: %s, type: %d", entry->lock.name, entry->lock.type); 170cb69b360Sopenharmony_ci 171cb69b360Sopenharmony_ci return ret; 172cb69b360Sopenharmony_ci} 173cb69b360Sopenharmony_ci 174cb69b360Sopenharmony_cistatic int32_t IsAnyHoldingCallback(IOwner owner, int32_t code, IpcIo *reply) 175cb69b360Sopenharmony_ci{ 176cb69b360Sopenharmony_ci if ((reply == NULL) || (owner == NULL)) { 177cb69b360Sopenharmony_ci POWER_HILOGE("Invalid parameter"); 178cb69b360Sopenharmony_ci return EC_INVALID; 179cb69b360Sopenharmony_ci } 180cb69b360Sopenharmony_ci 181cb69b360Sopenharmony_ci BOOL *ret = (BOOL *)owner; 182cb69b360Sopenharmony_ci bool readRet; 183cb69b360Sopenharmony_ci ReadBool(reply, &readRet); 184cb69b360Sopenharmony_ci *ret = readRet ? TRUE : FALSE; 185cb69b360Sopenharmony_ci POWER_HILOGD("Any running lock holding: %d, code: %d", *ret, code); 186cb69b360Sopenharmony_ci return EC_SUCCESS; 187cb69b360Sopenharmony_ci} 188cb69b360Sopenharmony_ci 189cb69b360Sopenharmony_cistatic BOOL IsAnyRunningLockHoldingProxy(IUnknown *iUnknown) 190cb69b360Sopenharmony_ci{ 191cb69b360Sopenharmony_ci BOOL ret; 192cb69b360Sopenharmony_ci PowerManageProxyInterface *proxy = (PowerManageProxyInterface *)iUnknown; 193cb69b360Sopenharmony_ci IpcIo request; 194cb69b360Sopenharmony_ci char buffer[MAX_DATA_LEN]; 195cb69b360Sopenharmony_ci IpcIoInit(&request, buffer, MAX_DATA_LEN, 0); 196cb69b360Sopenharmony_ci proxy->Invoke((IClientProxy *)proxy, POWERMANAGE_FUNCID_ISANYRUNNINGLOCKHOLDING, 197cb69b360Sopenharmony_ci &request, &ret, IsAnyHoldingCallback); 198cb69b360Sopenharmony_ci return ret; 199cb69b360Sopenharmony_ci} 200cb69b360Sopenharmony_ci 201cb69b360Sopenharmony_civoid InitIdentity(RunningLockEntry *entry) 202cb69b360Sopenharmony_ci{ 203cb69b360Sopenharmony_ci if (entry == NULL) { 204cb69b360Sopenharmony_ci return; 205cb69b360Sopenharmony_ci } 206cb69b360Sopenharmony_ci entry->identity.pid = getpid(); 207cb69b360Sopenharmony_ci entry->identity.token = (uint64_t)(uintptr_t)entry; 208cb69b360Sopenharmony_ci} 209cb69b360Sopenharmony_ci 210cb69b360Sopenharmony_ciBOOL AcquireRunningLockEntry(RunningLockEntry *entry, int32_t timeoutMs) 211cb69b360Sopenharmony_ci{ 212cb69b360Sopenharmony_ci int32_t ret = EC_FAILURE; 213cb69b360Sopenharmony_ci PowerManageProxyInterface *intf = GetPowerManageProxyInterface(); 214cb69b360Sopenharmony_ci if ((intf != NULL) && (intf->AcquireRunningLockEntryFunc != NULL)) { 215cb69b360Sopenharmony_ci ret = intf->AcquireRunningLockEntryFunc((IUnknown *)intf, entry, timeoutMs); 216cb69b360Sopenharmony_ci } 217cb69b360Sopenharmony_ci return (ret == EC_SUCCESS) ? TRUE : FALSE; 218cb69b360Sopenharmony_ci} 219cb69b360Sopenharmony_ci 220cb69b360Sopenharmony_ciBOOL ReleaseRunningLockEntry(RunningLockEntry *entry) 221cb69b360Sopenharmony_ci{ 222cb69b360Sopenharmony_ci int32_t ret = EC_FAILURE; 223cb69b360Sopenharmony_ci PowerManageProxyInterface *intf = GetPowerManageProxyInterface(); 224cb69b360Sopenharmony_ci if ((intf != NULL) && (intf->ReleaseRunningLockEntryFunc != NULL)) { 225cb69b360Sopenharmony_ci ret = intf->ReleaseRunningLockEntryFunc((IUnknown *)intf, entry); 226cb69b360Sopenharmony_ci } 227cb69b360Sopenharmony_ci return (ret == EC_SUCCESS) ? TRUE : FALSE; 228cb69b360Sopenharmony_ci} 229cb69b360Sopenharmony_ci 230cb69b360Sopenharmony_ciBOOL IsAnyRunningLockHolding() 231cb69b360Sopenharmony_ci{ 232cb69b360Sopenharmony_ci BOOL ret = FALSE; 233cb69b360Sopenharmony_ci PowerManageProxyInterface *intf = GetPowerManageProxyInterface(); 234cb69b360Sopenharmony_ci if ((intf != NULL) && (intf->IsAnyRunningLockHoldingFunc != NULL)) { 235cb69b360Sopenharmony_ci ret = intf->IsAnyRunningLockHoldingFunc((IUnknown *)intf); 236cb69b360Sopenharmony_ci } 237cb69b360Sopenharmony_ci return ret; 238cb69b360Sopenharmony_ci} 239cb69b360Sopenharmony_ci 240cb69b360Sopenharmony_cistatic void SuspendDeviceProxy(IUnknown *iUnknown, SuspendDeviceType reason, BOOL suspendImmed) 241cb69b360Sopenharmony_ci{ 242cb69b360Sopenharmony_ci IpcIo request; 243cb69b360Sopenharmony_ci char buffer[MAX_DATA_LEN]; 244cb69b360Sopenharmony_ci IpcIoInit(&request, buffer, MAX_DATA_LEN, 0); 245cb69b360Sopenharmony_ci WriteInt32(&request, (int32_t)reason); 246cb69b360Sopenharmony_ci WriteBool(&request, (suspendImmed == TRUE)); 247cb69b360Sopenharmony_ci 248cb69b360Sopenharmony_ci PowerManageProxyInterface *proxy = (PowerManageProxyInterface *)iUnknown; 249cb69b360Sopenharmony_ci proxy->Invoke((IClientProxy *)proxy, POWERMANAGE_FUNCID_SUSPEND, &request, NULL, NULL); 250cb69b360Sopenharmony_ci POWER_HILOGD("Suspend device done, reason: %{public}d", reason); 251cb69b360Sopenharmony_ci} 252cb69b360Sopenharmony_ci 253cb69b360Sopenharmony_cistatic void WakeupDeviceProxy(IUnknown *iUnknown, WakeupDeviceType reason, const char* details) 254cb69b360Sopenharmony_ci{ 255cb69b360Sopenharmony_ci IpcIo request; 256cb69b360Sopenharmony_ci char buffer[MAX_DATA_LEN]; 257cb69b360Sopenharmony_ci IpcIoInit(&request, buffer, MAX_DATA_LEN, 0); 258cb69b360Sopenharmony_ci WriteInt32(&request, (int32_t)reason); 259cb69b360Sopenharmony_ci WriteString(&request, details); 260cb69b360Sopenharmony_ci 261cb69b360Sopenharmony_ci PowerManageProxyInterface *proxy = (PowerManageProxyInterface *)iUnknown; 262cb69b360Sopenharmony_ci proxy->Invoke((IClientProxy *)proxy, POWERMANAGE_FUNCID_WAKEUP, &request, NULL, NULL); 263cb69b360Sopenharmony_ci POWER_HILOGD("Wakeup device done, reason: %{public}d", reason); 264cb69b360Sopenharmony_ci} 265cb69b360Sopenharmony_ci 266cb69b360Sopenharmony_civoid SuspendDevice(SuspendDeviceType reason, BOOL suspendImmed) 267cb69b360Sopenharmony_ci{ 268cb69b360Sopenharmony_ci PowerManageProxyInterface *intf = GetPowerManageProxyInterface(); 269cb69b360Sopenharmony_ci if ((intf != NULL) && (intf->SuspendDeviceFunc != NULL)) { 270cb69b360Sopenharmony_ci intf->SuspendDeviceFunc((IUnknown *)intf, reason, suspendImmed); 271cb69b360Sopenharmony_ci } 272cb69b360Sopenharmony_ci} 273cb69b360Sopenharmony_ci 274cb69b360Sopenharmony_civoid WakeupDevice(WakeupDeviceType reason, const char* details) 275cb69b360Sopenharmony_ci{ 276cb69b360Sopenharmony_ci const char* detailReason = (details != NULL) ? details : "No details"; 277cb69b360Sopenharmony_ci PowerManageProxyInterface *intf = GetPowerManageProxyInterface(); 278cb69b360Sopenharmony_ci if ((intf != NULL) && (intf->WakeupDeviceFunc != NULL)) { 279cb69b360Sopenharmony_ci intf->WakeupDeviceFunc((IUnknown *)intf, reason, detailReason); 280cb69b360Sopenharmony_ci } 281cb69b360Sopenharmony_ci} 282