1 /*
2 * Copyright (c) 2021-2023 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 "runninglock_interface.h"
17
18 #include <cstdint>
19 #include <memory>
20 #include <string>
21
22 #include "power_log.h"
23 #include "power_mgr_client.h"
24 #include "runninglock_entity.h"
25 #ifdef HAS_DFX_HIVIEW_PART
26 #include "xpower_event_js.h"
27 #endif
28
29 namespace OHOS {
30 namespace PowerMgr {
31 namespace {
32 constexpr int RESULT_SIZE = 2;
33 constexpr int RUNNINGLOCK_NAME_MAX = 512;
34 constexpr int CREATRUNNINGLOCK_ARGC = 3;
35 constexpr int ISRUNNINGLOCKTYPESUPPORTED_ARGC = 2;
36 constexpr int32_t INDEX_0 = 0;
37 constexpr int32_t INDEX_1 = 1;
38 constexpr int32_t INDEX_2 = 2;
39 static PowerMgrClient& g_powerMgrClient = PowerMgrClient::GetInstance();
40 }
41
CreateRunningLock(napi_env env,napi_callback_info info,napi_ref & napiRunningLock)42 napi_value RunningLockInterface::CreateRunningLock(napi_env env, napi_callback_info info, napi_ref& napiRunningLock)
43 {
44 size_t argc = CREATRUNNINGLOCK_ARGC;
45 napi_value argv[CREATRUNNINGLOCK_ARGC] = {0};
46 napi_value thisArg = nullptr;
47 void* data = nullptr;
48
49 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisArg, &data);
50 NAPI_ASSERT(env, (status == napi_ok) && (argc >= CREATRUNNINGLOCK_ARGC - 1), "Failed to get cb info");
51
52 std::unique_ptr<RunningLockAsyncInfo> asyncInfo = std::make_unique<RunningLockAsyncInfo>();
53 if (asyncInfo == nullptr) {
54 POWER_HILOGE(FEATURE_RUNNING_LOCK, "asyncInfo is nullptr");
55 return nullptr;
56 }
57 asyncInfo->napiRunningLockIns = napiRunningLock;
58
59 napi_valuetype valueType = napi_undefined;
60 napi_typeof(env, argv[INDEX_0], &valueType);
61 NAPI_ASSERT(env, valueType == napi_string, "The input parameter type is not string");
62 char name[RUNNINGLOCK_NAME_MAX] = {0};
63 napi_get_value_string_utf8(env, argv[INDEX_0], name, RUNNINGLOCK_NAME_MAX + 1, &asyncInfo->nameLen);
64 asyncInfo->name = name;
65
66 napi_typeof(env, argv[INDEX_1], &valueType);
67 NAPI_ASSERT(env, valueType == napi_number, "The input parameter type is not number");
68 int32_t type = static_cast<int32_t>(RunningLockType::RUNNINGLOCK_BUTT);
69 napi_get_value_int32(env, argv[INDEX_1], &type);
70 asyncInfo->type = static_cast<RunningLockType>(type);
71
72 if (argc == CREATRUNNINGLOCK_ARGC) {
73 napi_typeof(env, argv[INDEX_2], &valueType);
74 NAPI_ASSERT(env, valueType == napi_function, "The input parameter type is not function");
75 napi_create_reference(env, argv[INDEX_2], 1, &asyncInfo->callbackRef);
76 }
77 napi_value result = nullptr;
78 if (asyncInfo->callbackRef == nullptr) {
79 POWER_HILOGD(FEATURE_RUNNING_LOCK, "callbackRef is null");
80 napi_create_promise(env, &asyncInfo->deferred, &result);
81 } else {
82 POWER_HILOGD(FEATURE_RUNNING_LOCK, "callbackRef is not null");
83 napi_get_undefined(env, &result);
84 }
85 CreateRunningLockCallBack(env, asyncInfo);
86 return result;
87 }
88
IsRunningLockTypeSupported(napi_env env,napi_callback_info info)89 napi_value RunningLockInterface::IsRunningLockTypeSupported(napi_env env, napi_callback_info info)
90 {
91 size_t argc = ISRUNNINGLOCKTYPESUPPORTED_ARGC;
92 napi_value argv[ISRUNNINGLOCKTYPESUPPORTED_ARGC] = {0};
93 napi_value thisArg = nullptr;
94 void* data = nullptr;
95
96 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisArg, &data);
97 NAPI_ASSERT(env, (status == napi_ok) && (argc >= 1), "Failed to get cb info");
98
99 std::unique_ptr<RunningLockAsyncInfo> asyncInfo = std::make_unique<RunningLockAsyncInfo>();
100 if (asyncInfo == nullptr) {
101 POWER_HILOGE(FEATURE_RUNNING_LOCK, "asyncInfo is nullptr");
102 return nullptr;
103 }
104
105 napi_valuetype valueType = napi_undefined;
106 napi_typeof(env, argv[INDEX_0], &valueType);
107 NAPI_ASSERT(env, valueType == napi_number, "The input parameter type is not number");
108 int32_t type = static_cast<int32_t>(RunningLockType::RUNNINGLOCK_BUTT);
109 napi_get_value_int32(env, argv[INDEX_0], &type);
110 asyncInfo->type = static_cast<RunningLockType>(type);
111
112 if (argc == ISRUNNINGLOCKTYPESUPPORTED_ARGC) {
113 napi_typeof(env, argv[INDEX_1], &valueType);
114 NAPI_ASSERT(env, valueType == napi_function, "The input parameter type is not function");
115 napi_create_reference(env, argv[INDEX_1], 1, &asyncInfo->callbackRef);
116 }
117
118 napi_value result = nullptr;
119 if (asyncInfo->callbackRef == nullptr) {
120 POWER_HILOGD(FEATURE_RUNNING_LOCK, "callbackRef is null");
121 napi_create_promise(env, &asyncInfo->deferred, &result);
122 } else {
123 POWER_HILOGD(FEATURE_RUNNING_LOCK, "callbackRef is not null");
124 napi_get_undefined(env, &result);
125 }
126 IsRunningLockTypeSupportedCallBack(env, asyncInfo);
127 return result;
128 }
129
Lock(napi_env env,napi_callback_info info)130 napi_value RunningLockInterface::Lock(napi_env env, napi_callback_info info)
131 {
132 size_t argc = 1;
133 napi_value args[1] = {0};
134 napi_value thisArg = nullptr;
135 void* data = nullptr;
136
137 napi_status status = napi_get_cb_info(env, info, &argc, args, &thisArg, &data);
138 NAPI_ASSERT(env, (status == napi_ok) && (argc >= 1), "Failed to get cb info");
139 napi_valuetype type = napi_undefined;
140 NAPI_CALL(env, napi_typeof(env, args[0], &type));
141 NAPI_ASSERT(env, type == napi_number, "Wrong argument type. number expected.");
142
143 int32_t timeOut;
144 status = napi_get_value_int32(env, args[0], &timeOut);
145 if (status != napi_ok) {
146 POWER_HILOGE(FEATURE_RUNNING_LOCK, "napi_get_value_uint32 failed");
147 return nullptr;
148 }
149 RunningLockEntity* entity = nullptr;
150 status = napi_unwrap(env, thisArg, (void**)&entity);
151 if (status != napi_ok) {
152 POWER_HILOGE(FEATURE_RUNNING_LOCK, "Cannot unwrap for pointer");
153 return nullptr;
154 }
155 if (entity == nullptr || entity->runningLock == nullptr) {
156 POWER_HILOGE(FEATURE_RUNNING_LOCK, "Entity runningLock is nullptr");
157 return nullptr;
158 }
159 entity->runningLock->Lock(timeOut);
160 #ifdef HAS_DFX_HIVIEW_PART
161 OHOS::HiviewDFX::ReportXPowerJsStackSysEvent(env, "RunningLockNapi::Lock");
162 #endif
163 return nullptr;
164 }
165
IsUsed(napi_env env,napi_callback_info info)166 napi_value RunningLockInterface::IsUsed(napi_env env, napi_callback_info info)
167 {
168 napi_value thisArg = nullptr;
169 napi_value result = nullptr;
170 void* data = nullptr;
171
172 napi_status status = napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, &data);
173 NAPI_ASSERT(env, (status == napi_ok), "Failed to get cb info");
174 napi_get_boolean(env, false, &result);
175 RunningLockEntity* entity = nullptr;
176 status = napi_unwrap(env, thisArg, (void**)&entity);
177 if (status != napi_ok) {
178 POWER_HILOGE(FEATURE_RUNNING_LOCK, "Cannot unwrap for pointer");
179 return result;
180 }
181 if (entity == nullptr || entity->runningLock == nullptr) {
182 POWER_HILOGE(FEATURE_RUNNING_LOCK, "Entity runningLock is nullptr");
183 return result;
184 }
185 bool isUsed = entity->runningLock->IsUsed();
186 napi_get_boolean(env, isUsed, &result);
187 return result;
188 }
189
Unlock(napi_env env,napi_callback_info info)190 napi_value RunningLockInterface::Unlock(napi_env env, napi_callback_info info)
191 {
192 napi_value thisArg = nullptr;
193 void* data = nullptr;
194
195 napi_status status = napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, &data);
196 NAPI_ASSERT(env, (status == napi_ok), "Unlock: failed to get cb info");
197
198 RunningLockEntity* entity = nullptr;
199 status = napi_unwrap(env, thisArg, (void**)&entity);
200 if (status != napi_ok) {
201 POWER_HILOGE(FEATURE_RUNNING_LOCK, "Cannot unwrap for pointer");
202 return nullptr;
203 }
204 if (entity == nullptr || entity->runningLock == nullptr) {
205 POWER_HILOGE(FEATURE_RUNNING_LOCK, "Entity runningLock is nullptr");
206 return nullptr;
207 }
208 entity->runningLock->UnLock();
209 return nullptr;
210 }
211
CreateInstanceForRunningLock(napi_env env,RunningLockAsyncInfo * asyncInfo)212 napi_value RunningLockInterface::CreateInstanceForRunningLock(napi_env env, RunningLockAsyncInfo* asyncInfo)
213 {
214 napi_value cons = nullptr;
215 napi_value instance = nullptr;
216 napi_status callBackStatus;
217 RunningLockEntity* entity = nullptr;
218
219 if (asyncInfo->runningLock == nullptr) {
220 POWER_HILOGE(FEATURE_RUNNING_LOCK, "RunningLock is nullptr");
221 return nullptr;
222 }
223 callBackStatus = napi_get_reference_value(env, asyncInfo->napiRunningLockIns, &cons);
224 if (callBackStatus != napi_ok) {
225 POWER_HILOGE(FEATURE_RUNNING_LOCK, "NAPI failed to create a reference value");
226 return nullptr;
227 }
228 callBackStatus = napi_new_instance(env, cons, 0, nullptr, &instance);
229 if (callBackStatus != napi_ok || instance == nullptr) {
230 POWER_HILOGE(FEATURE_RUNNING_LOCK, "NAPI failed to create a reference");
231 return nullptr;
232 }
233 callBackStatus = napi_unwrap(env, instance, (void**)&entity);
234 if (callBackStatus != napi_ok || entity == nullptr) {
235 POWER_HILOGE(FEATURE_RUNNING_LOCK, "Cannot unwrap entity from instance");
236 return nullptr;
237 }
238 entity->runningLock = asyncInfo->runningLock;
239 return instance;
240 }
241
CreateRunningLockCallBack(napi_env env,std::unique_ptr<RunningLockAsyncInfo> & asyncInfo)242 void RunningLockInterface::CreateRunningLockCallBack(napi_env env, std::unique_ptr<RunningLockAsyncInfo>& asyncInfo)
243 {
244 napi_value resource = nullptr;
245 napi_create_string_utf8(env, "createRunningLock", NAPI_AUTO_LENGTH, &resource);
246 napi_create_async_work(
247 env, nullptr, resource,
248 [](napi_env env, void* data) {
249 auto* asyncInfo = reinterpret_cast<RunningLockAsyncInfo*>(data);
250 if (!IsTypeSupported(asyncInfo->type)) {
251 auto type = static_cast<uint32_t>(asyncInfo->type);
252 POWER_HILOGW(FEATURE_RUNNING_LOCK, "type=%{public}u not supported", type);
253 return;
254 }
255 asyncInfo->runningLock = g_powerMgrClient.CreateRunningLock(std::string(asyncInfo->name), asyncInfo->type);
256 },
257 [](napi_env env, napi_status status, void* data) {
258 auto* asyncInfo = reinterpret_cast<RunningLockAsyncInfo*>(data);
259 napi_value result[RESULT_SIZE] = {0};
260 result[1] = CreateInstanceForRunningLock(env, asyncInfo);
261 if (result[1] == nullptr) {
262 napi_value message = nullptr;
263 napi_create_string_utf8(env, "runningLock create failed", NAPI_AUTO_LENGTH, &message);
264 napi_create_error(env, nullptr, message, &result[0]);
265 }
266 if (asyncInfo->deferred) {
267 if (result[1] != nullptr) {
268 napi_resolve_deferred(env, asyncInfo->deferred, result[1]);
269 } else {
270 napi_reject_deferred(env, asyncInfo->deferred, result[0]);
271 }
272 } else {
273 napi_value tmp = nullptr;
274 napi_value callback = nullptr;
275 napi_get_undefined(env, &result[0]);
276 napi_get_reference_value(env, asyncInfo->callbackRef, &callback);
277 napi_call_function(env, nullptr, callback, RESULT_SIZE, result, &tmp);
278 napi_delete_reference(env, asyncInfo->callbackRef);
279 }
280 napi_delete_async_work(env, asyncInfo->asyncWork);
281 delete asyncInfo;
282 },
283 reinterpret_cast<void*>(asyncInfo.get()), &asyncInfo->asyncWork);
284 if (napi_ok == napi_queue_async_work_with_qos(env, asyncInfo->asyncWork, napi_qos_utility)) {
285 asyncInfo.release();
286 }
287 }
288
IsRunningLockTypeSupportedCallBack(napi_env env,std::unique_ptr<RunningLockAsyncInfo> & asyncInfo)289 void RunningLockInterface::IsRunningLockTypeSupportedCallBack(
290 napi_env env, std::unique_ptr<RunningLockAsyncInfo>& asyncInfo)
291 {
292 napi_value resource = nullptr;
293 napi_create_string_utf8(env, "isRunningLockTypeSupported", NAPI_AUTO_LENGTH, &resource);
294 napi_create_async_work(
295 env, nullptr, resource,
296 [](napi_env env, void* data) {
297 auto* asyncInfo = reinterpret_cast<RunningLockAsyncInfo*>(data);
298 asyncInfo->isSupported = IsTypeSupported(asyncInfo->type);
299 POWER_HILOGD(FEATURE_RUNNING_LOCK, "type=%{public}u, isSupported=%{public}s",
300 static_cast<uint32_t>(asyncInfo->type), asyncInfo->isSupported ? "true" : "false");
301 },
302 [](napi_env env, napi_status status, void* data) {
303 auto* asyncInfo = reinterpret_cast<RunningLockAsyncInfo*>(data);
304 napi_value result[RESULT_SIZE] = {0};
305 napi_get_boolean(env, asyncInfo->isSupported, &result[1]);
306 if (asyncInfo->deferred) {
307 napi_resolve_deferred(env, asyncInfo->deferred, result[1]);
308 } else {
309 napi_value tmp = nullptr;
310 napi_value callback = nullptr;
311 napi_get_reference_value(env, asyncInfo->callbackRef, &callback);
312 napi_get_undefined(env, &result[0]);
313 napi_call_function(env, nullptr, callback, RESULT_SIZE, result, &tmp);
314 napi_delete_reference(env, asyncInfo->callbackRef);
315 }
316 napi_delete_async_work(env, asyncInfo->asyncWork);
317 delete asyncInfo;
318 },
319 reinterpret_cast<void*>(asyncInfo.get()), &asyncInfo->asyncWork);
320 if (napi_ok == napi_queue_async_work_with_qos(env, asyncInfo->asyncWork, napi_qos_utility)) {
321 asyncInfo.release();
322 }
323 }
324
IsTypeSupported(RunningLockType type)325 bool RunningLockInterface::IsTypeSupported(RunningLockType type)
326 {
327 return type == RunningLockType::RUNNINGLOCK_BACKGROUND ||
328 type == RunningLockType::RUNNINGLOCK_PROXIMITY_SCREEN_CONTROL;
329 }
330 } // namespace PowerMgr
331 } // namespace OHOS
332