• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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