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