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