1 /*
2 * Copyright (c) 2021 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 free(iproxy);
75 }
76
GetPowerManageProxyInterface(void)77 static PowerManageProxyInterface *GetPowerManageProxyInterface(void)
78 {
79 if (g_intf != NULL) {
80 return g_intf;
81 }
82 pthread_mutex_lock(&g_mutex);
83 if (g_intf != NULL) {
84 pthread_mutex_unlock(&g_mutex);
85 return g_intf;
86 }
87
88 SAMGR_RegisterFactory(POWER_MANAGE_SERVICE, POWER_MANAGE_FEATURE, CreatClient, DestroyClient);
89
90 IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(POWER_MANAGE_SERVICE, POWER_MANAGE_FEATURE);
91 if (iUnknown == NULL) {
92 POWER_HILOGE("Failed to get power manage iUnknown");
93 pthread_mutex_unlock(&g_mutex);
94 return NULL;
95 }
96
97 int ret = iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION, (void **)&g_intf);
98 if ((ret != EC_SUCCESS) || (g_intf == NULL)) {
99 POWER_HILOGE("Failed to query power manage interface");
100 pthread_mutex_unlock(&g_mutex);
101 return NULL;
102 }
103 pthread_mutex_unlock(&g_mutex);
104 POWER_HILOGI("Succeed to get power manage proxy interface");
105 return g_intf;
106 }
107
AcquireReleaseCallback(IOwner owner,int32_t code,IpcIo * reply)108 static int32_t AcquireReleaseCallback(IOwner owner, int32_t code, IpcIo *reply)
109 {
110 if ((reply == NULL) || (owner == NULL)) {
111 POWER_HILOGE("Invalid parameter");
112 return EC_INVALID;
113 }
114
115 int32_t *ret = (int32_t *)owner;
116 *ret = IpcIoPopInt32(reply);
117 POWER_HILOGD("Running lock callback: %d, code: %d", *ret, code);
118 return EC_SUCCESS;
119 }
120
AcquireRunningLockEntryProxy(IUnknown * iUnknown,RunningLockEntry * entry,int32_t timeoutMs)121 static int32_t AcquireRunningLockEntryProxy(IUnknown *iUnknown, RunningLockEntry *entry, int32_t timeoutMs)
122 {
123 if (IsValidRunningLockEntry(entry) == FALSE) {
124 POWER_HILOGE("Invalid running lock entry");
125 return EC_INVALID;
126 }
127
128 IpcIo request;
129 char buffer[MAX_DATA_LEN];
130 IpcIoInit(&request, buffer, MAX_DATA_LEN, 0);
131 IpcIoPushFlatObj(&request, entry, sizeof(RunningLockEntry));
132 IpcIoPushInt32(&request, timeoutMs);
133
134 int32_t ret;
135 PowerManageProxyInterface *proxy = (PowerManageProxyInterface *)iUnknown;
136 proxy->Invoke((IClientProxy *)proxy, POWERMANAGE_FUNCID_ACQUIRERUNNINGLOCK, &request, &ret, AcquireReleaseCallback);
137 POWER_HILOGD("Acquire running lock done, name: %s, type: %d", entry->lock.name, entry->lock.type);
138
139 return ret;
140 }
141
ReleaseRunningLockEntryProxy(IUnknown * iUnknown,RunningLockEntry * entry)142 static int32_t ReleaseRunningLockEntryProxy(IUnknown *iUnknown, RunningLockEntry *entry)
143 {
144 if (IsValidRunningLockEntry(entry) == FALSE) {
145 POWER_HILOGE("Invalid running lock entry");
146 return EC_INVALID;
147 }
148
149 IpcIo request;
150 char buffer[MAX_DATA_LEN];
151 IpcIoInit(&request, buffer, MAX_DATA_LEN, 0);
152 IpcIoPushFlatObj(&request, entry, sizeof(RunningLockEntry));
153
154 int32_t ret;
155 PowerManageProxyInterface *proxy = (PowerManageProxyInterface *)iUnknown;
156 proxy->Invoke((IClientProxy *)proxy, POWERMANAGE_FUNCID_RELEASERUNNINGLOCK, &request, &ret, AcquireReleaseCallback);
157 POWER_HILOGD("Release running lock done, name: %s, type: %d", entry->lock.name, entry->lock.type);
158
159 return ret;
160 }
161
IsAnyHoldingCallback(IOwner owner,int32_t code,IpcIo * reply)162 static int32_t IsAnyHoldingCallback(IOwner owner, int32_t code, IpcIo *reply)
163 {
164 if ((reply == NULL) || (owner == NULL)) {
165 POWER_HILOGE("Invalid parameter");
166 return EC_INVALID;
167 }
168
169 BOOL *ret = (BOOL *)owner;
170 *ret = IpcIoPopBool(reply) ? TRUE : FALSE;
171 POWER_HILOGD("Any running lock holding: %d, code: %d", *ret, code);
172 return EC_SUCCESS;
173 }
174
IsAnyRunningLockHoldingProxy(IUnknown * iUnknown)175 static BOOL IsAnyRunningLockHoldingProxy(IUnknown *iUnknown)
176 {
177 BOOL ret;
178 PowerManageProxyInterface *proxy = (PowerManageProxyInterface *)iUnknown;
179 proxy->Invoke((IClientProxy *)proxy, POWERMANAGE_FUNCID_ISANYRUNNINGLOCKHOLDING, NULL, &ret, IsAnyHoldingCallback);
180 return ret;
181 }
182
InitIdentity(RunningLockEntry * entry)183 void InitIdentity(RunningLockEntry *entry)
184 {
185 if (entry == NULL) {
186 return;
187 }
188 entry->identity.pid = getpid();
189 entry->identity.token = (uint64_t)(uintptr_t)entry;
190 }
191
AcquireRunningLockEntry(RunningLockEntry * entry,int32_t timeoutMs)192 BOOL AcquireRunningLockEntry(RunningLockEntry *entry, int32_t timeoutMs)
193 {
194 int32_t ret = EC_FAILURE;
195 PowerManageProxyInterface *intf = GetPowerManageProxyInterface();
196 if ((intf != NULL) && (intf->AcquireRunningLockEntryFunc != NULL)) {
197 ret = intf->AcquireRunningLockEntryFunc((IUnknown *)intf, entry, timeoutMs);
198 }
199 return (ret == EC_SUCCESS) ? TRUE : FALSE;
200 }
201
ReleaseRunningLockEntry(RunningLockEntry * entry)202 BOOL ReleaseRunningLockEntry(RunningLockEntry *entry)
203 {
204 int32_t ret = EC_FAILURE;
205 PowerManageProxyInterface *intf = GetPowerManageProxyInterface();
206 if ((intf != NULL) && (intf->ReleaseRunningLockEntryFunc != NULL)) {
207 ret = intf->ReleaseRunningLockEntryFunc((IUnknown *)intf, entry);
208 }
209 return (ret == EC_SUCCESS) ? TRUE : FALSE;
210 }
211
IsAnyRunningLockHolding()212 BOOL IsAnyRunningLockHolding()
213 {
214 BOOL ret = FALSE;
215 PowerManageProxyInterface *intf = GetPowerManageProxyInterface();
216 if ((intf != NULL) && (intf->IsAnyRunningLockHoldingFunc != NULL)) {
217 ret = intf->IsAnyRunningLockHoldingFunc((IUnknown *)intf);
218 }
219 return ret;
220 }
221
SuspendDeviceProxy(IUnknown * iUnknown,SuspendDeviceType reason,BOOL suspendImmed)222 static void SuspendDeviceProxy(IUnknown *iUnknown, SuspendDeviceType reason, BOOL suspendImmed)
223 {
224 IpcIo request;
225 char buffer[MAX_DATA_LEN];
226 IpcIoInit(&request, buffer, MAX_DATA_LEN, 0);
227 IpcIoPushInt32(&request, reason);
228 IpcIoPushBool(&request, (suspendImmed == TRUE));
229
230 PowerManageProxyInterface *proxy = (PowerManageProxyInterface *)iUnknown;
231 proxy->Invoke((IClientProxy *)proxy, POWERMANAGE_FUNCID_SUSPEND, &request, NULL, NULL);
232 POWER_HILOGD("Suspend device done, reason: %{public}d", reason);
233 }
234
WakeupDeviceProxy(IUnknown * iUnknown,WakeupDeviceType reason,const char * details)235 static void WakeupDeviceProxy(IUnknown *iUnknown, WakeupDeviceType reason, const char* details)
236 {
237 IpcIo request;
238 char buffer[MAX_DATA_LEN];
239 IpcIoInit(&request, buffer, MAX_DATA_LEN, 0);
240 IpcIoPushInt32(&request, reason);
241 IpcIoPushString(&request, details);
242
243 PowerManageProxyInterface *proxy = (PowerManageProxyInterface *)iUnknown;
244 proxy->Invoke((IClientProxy *)proxy, POWERMANAGE_FUNCID_WAKEUP, &request, NULL, NULL);
245 POWER_HILOGD("Wakeup device done, reason: %{public}d", reason);
246 }
247
SuspendDevice(SuspendDeviceType reason,BOOL suspendImmed)248 void SuspendDevice(SuspendDeviceType reason, BOOL suspendImmed)
249 {
250 PowerManageProxyInterface *intf = GetPowerManageProxyInterface();
251 if ((intf != NULL) && (intf->SuspendDeviceFunc != NULL)) {
252 intf->SuspendDeviceFunc((IUnknown *)intf, reason, suspendImmed);
253 }
254 }
255
WakeupDevice(WakeupDeviceType reason,const char * details)256 void WakeupDevice(WakeupDeviceType reason, const char* details)
257 {
258 const char* detailReason = (details != NULL) ? details : "No details";
259 PowerManageProxyInterface *intf = GetPowerManageProxyInterface();
260 if ((intf != NULL) && (intf->WakeupDeviceFunc != NULL)) {
261 intf->WakeupDeviceFunc((IUnknown *)intf, reason, detailReason);
262 }
263 }
264