1 /*
2 * Copyright (c) 2022-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_napi.h"
17
18 #include <memory>
19
20 #include "napi_errors.h"
21 #include "napi_utils.h"
22 #include "power_common.h"
23 #include "power_log.h"
24 #include "runninglock_entity.h"
25 #include "xpower_event_js.h"
26
27 namespace OHOS {
28 namespace PowerMgr {
29 namespace {
30 constexpr uint32_t CREATE_PROMISE_MAX_ARGC = 2;
31 constexpr uint32_t CREATE_CALLBACK_MAX_ARGC = 3;
32 constexpr uint32_t ISSUPPORTED_MAX_ARGC = 1;
33 constexpr uint32_t HOLD_MAX_ARGC = 1;
34 constexpr int32_t INDEX_0 = 0;
35 constexpr int32_t INDEX_1 = 1;
36 constexpr int32_t INDEX_2 = 2;
37 }
38
Create(napi_env & env,napi_callback_info & info,napi_ref & napiRunningLockIns)39 napi_value RunningLockNapi::Create(napi_env& env, napi_callback_info& info, napi_ref& napiRunningLockIns)
40 {
41 size_t argc = CREATE_CALLBACK_MAX_ARGC;
42 napi_value argv[argc];
43 NapiUtils::GetCallbackInfo(env, info, argc, argv);
44
45 NapiErrors error;
46 if (argc != CREATE_CALLBACK_MAX_ARGC && argc != CREATE_PROMISE_MAX_ARGC) {
47 return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
48 }
49
50 std::unique_ptr<AsyncCallbackInfo> asyncInfo = std::make_unique<AsyncCallbackInfo>();
51 RETURN_IF_WITH_RET(asyncInfo == nullptr, nullptr);
52 asyncInfo->GetData().SetRunningLockInstance(napiRunningLockIns);
53 // callback
54 if (argc == CREATE_CALLBACK_MAX_ARGC) {
55 return CreateAsyncCallback(env, argv, asyncInfo);
56 }
57
58 // promise
59 return CreatePromise(env, argv, asyncInfo);
60 }
61
IsSupported(napi_env env,napi_callback_info info)62 napi_value RunningLockNapi::IsSupported(napi_env env, napi_callback_info info)
63 {
64 size_t argc = ISSUPPORTED_MAX_ARGC;
65 napi_value argv[argc];
66 NapiUtils::GetCallbackInfo(env, info, argc, argv);
67
68 NapiErrors error;
69 if (argc != ISSUPPORTED_MAX_ARGC || !NapiUtils::CheckValueType(env, argv[INDEX_0], napi_number)) {
70 return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
71 }
72
73 int32_t numType;
74 napi_get_value_int32(env, argv[INDEX_0], &numType);
75 RunningLockType type = static_cast<RunningLockType>(numType);
76
77 bool isSupported = (type == RunningLockType::RUNNINGLOCK_BACKGROUND) ||
78 (type == RunningLockType::RUNNINGLOCK_PROXIMITY_SCREEN_CONTROL);
79
80 napi_value result;
81 napi_get_boolean(env, isSupported, &result);
82 return result;
83 }
84
Hold(napi_env env,napi_callback_info info)85 napi_value RunningLockNapi::Hold(napi_env env, napi_callback_info info)
86 {
87 size_t argc = HOLD_MAX_ARGC;
88 napi_value argv[argc];
89 napi_value thisArg = NapiUtils::GetCallbackInfo(env, info, argc, argv);
90 NapiErrors error;
91 if (argc != HOLD_MAX_ARGC || !NapiUtils::CheckValueType(env, argv[INDEX_0], napi_number)) {
92 return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
93 }
94
95 int32_t timeOut;
96 if (napi_ok != napi_get_value_int32(env, argv[INDEX_0], &timeOut)) {
97 POWER_HILOGE(FEATURE_RUNNING_LOCK, "napi_get_value_uint32 failed");
98 return nullptr;
99 }
100 auto runningLock = UnwrapRunningLock(env, thisArg);
101 RETURN_IF_WITH_RET(runningLock == nullptr, nullptr);
102 ErrCode code = runningLock->Lock(timeOut);
103 if (code == E_PERMISSION_DENIED) {
104 return error.ThrowError(env, PowerErrors::ERR_PERMISSION_DENIED);
105 }
106 OHOS::HiviewDFX::ReportXPowerJsStackSysEvent(env, "RunningLockNapi::Hold");
107 return nullptr;
108 }
109
IsHolding(napi_env env,napi_callback_info info)110 napi_value RunningLockNapi::IsHolding(napi_env env, napi_callback_info info)
111 {
112 size_t argc = 0;
113 napi_value thisArg = NapiUtils::GetCallbackInfo(env, info, argc, nullptr);
114 auto runningLock = UnwrapRunningLock(env, thisArg);
115 RETURN_IF_WITH_RET(runningLock == nullptr, nullptr);
116 bool isUsed = runningLock->IsUsed();
117 napi_value result;
118 napi_get_boolean(env, isUsed, &result);
119 return result;
120 }
121
UnHold(napi_env env,napi_callback_info info)122 napi_value RunningLockNapi::UnHold(napi_env env, napi_callback_info info)
123 {
124 size_t argc = 0;
125 napi_value thisArg = NapiUtils::GetCallbackInfo(env, info, argc, nullptr);
126 auto runningLock = UnwrapRunningLock(env, thisArg);
127 RETURN_IF_WITH_RET(runningLock == nullptr, nullptr);
128 ErrCode code = runningLock->UnLock();
129 NapiErrors error;
130 if (code == E_PERMISSION_DENIED) {
131 return error.ThrowError(env, PowerErrors::ERR_PERMISSION_DENIED);
132 }
133 return nullptr;
134 }
135
CreateAsyncCallback(napi_env & env,napi_value argv[],std::unique_ptr<AsyncCallbackInfo> & asyncInfo)136 napi_value RunningLockNapi::CreateAsyncCallback(
137 napi_env& env, napi_value argv[], std::unique_ptr<AsyncCallbackInfo>& asyncInfo)
138 {
139 bool isStr = NapiUtils::CheckValueType(env, argv[INDEX_0], napi_string);
140 bool isNum = NapiUtils::CheckValueType(env, argv[INDEX_1], napi_number);
141 bool isFunc = NapiUtils::CheckValueType(env, argv[INDEX_2], napi_function);
142 if (!isStr || !isNum || !isFunc) {
143 POWER_HILOGD(
144 FEATURE_RUNNING_LOCK, "isStr: %{public}d, isNum: %{public}d, isFunc: %{public}d", isStr, isNum, isFunc);
145 return asyncInfo->GetError().ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
146 }
147 asyncInfo->GetData().SetName(env, argv[INDEX_0]);
148 asyncInfo->GetData().SetType(env, argv[INDEX_1]);
149 asyncInfo->CreateCallback(env, argv[INDEX_2]);
150
151 AsyncWork(
152 env, asyncInfo, "CreateAsyncCallback",
153 [](napi_env env, void* data) {
154 AsyncCallbackInfo* asyncInfo = reinterpret_cast<AsyncCallbackInfo*>(data);
155 RETURN_IF(asyncInfo == nullptr);
156 auto error = asyncInfo->GetData().CreateRunningLock();
157 asyncInfo->GetError().Error(error);
158 },
159 [](napi_env env, napi_status status, void* data) {
160 AsyncCallbackInfo* asyncInfo = reinterpret_cast<AsyncCallbackInfo*>(data);
161 RETURN_IF(asyncInfo == nullptr);
162 napi_value result = asyncInfo->GetData().CreateInstanceForRunningLock(env);
163 asyncInfo->CallFunction(env, result);
164 asyncInfo->Release(env);
165 delete asyncInfo;
166 });
167 return nullptr;
168 }
169
CreatePromise(napi_env & env,napi_value argv[],std::unique_ptr<AsyncCallbackInfo> & asyncInfo)170 napi_value RunningLockNapi::CreatePromise(
171 napi_env& env, napi_value argv[], std::unique_ptr<AsyncCallbackInfo>& asyncInfo)
172 {
173 bool isStr = NapiUtils::CheckValueType(env, argv[INDEX_0], napi_string);
174 bool isNum = NapiUtils::CheckValueType(env, argv[INDEX_1], napi_number);
175 if (!isStr || !isNum) {
176 POWER_HILOGW(FEATURE_RUNNING_LOCK, "isStr: %{public}d, isNum: %{public}d", isStr, isNum);
177 return asyncInfo->GetError().ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
178 }
179
180 napi_value promise;
181 asyncInfo->CreatePromise(env, promise);
182 RETURN_IF_WITH_RET(promise == nullptr, nullptr);
183 asyncInfo->GetData().SetName(env, argv[INDEX_0]);
184 asyncInfo->GetData().SetType(env, argv[INDEX_1]);
185
186 AsyncWork(
187 env, asyncInfo, "CreatePromise",
188 [](napi_env env, void* data) {
189 AsyncCallbackInfo* asyncInfo = reinterpret_cast<AsyncCallbackInfo*>(data);
190 RETURN_IF(asyncInfo == nullptr);
191 auto error = asyncInfo->GetData().CreateRunningLock();
192 asyncInfo->GetError().Error(error);
193 },
194 [](napi_env env, napi_status status, void* data) {
195 AsyncCallbackInfo* asyncInfo = reinterpret_cast<AsyncCallbackInfo*>(data);
196 RETURN_IF(asyncInfo == nullptr);
197 if (asyncInfo->GetError().IsError()) {
198 napi_reject_deferred(env, asyncInfo->GetDeferred(), asyncInfo->GetError().GetNapiError(env));
199 } else {
200 napi_value result = asyncInfo->GetData().CreateInstanceForRunningLock(env);
201 napi_resolve_deferred(env, asyncInfo->GetDeferred(), result);
202 }
203 asyncInfo->Release(env);
204 delete asyncInfo;
205 });
206 return promise;
207 }
208
AsyncWork(napi_env & env,std::unique_ptr<AsyncCallbackInfo> & asyncInfo,const std::string & resourceName,napi_async_execute_callback execute,napi_async_complete_callback complete)209 void RunningLockNapi::AsyncWork(napi_env& env, std::unique_ptr<AsyncCallbackInfo>& asyncInfo,
210 const std::string& resourceName, napi_async_execute_callback execute, napi_async_complete_callback complete)
211 {
212 napi_value resource = nullptr;
213 napi_create_string_utf8(env, resourceName.c_str(), NAPI_AUTO_LENGTH, &resource);
214 napi_create_async_work(env, nullptr, resource, execute, complete,
215 reinterpret_cast<void*>(asyncInfo.get()), &asyncInfo->GetAsyncWork());
216 NAPI_CALL_RETURN_VOID(env, napi_queue_async_work_with_qos(env, asyncInfo->GetAsyncWork(), napi_qos_utility));
217 asyncInfo.release();
218 }
219
UnwrapRunningLock(napi_env & env,napi_value & thisArg)220 std::shared_ptr<RunningLock> RunningLockNapi::UnwrapRunningLock(napi_env& env, napi_value& thisArg)
221 {
222 RunningLockEntity* entity = nullptr;
223 if (napi_ok != napi_unwrap(env, thisArg, (void**)&entity)) {
224 POWER_HILOGE(FEATURE_RUNNING_LOCK, "Cannot unwrap for pointer");
225 return nullptr;
226 }
227 if (entity == nullptr || entity->runningLock == nullptr) {
228 POWER_HILOGE(FEATURE_RUNNING_LOCK, "Entity runningLock is nullptr");
229 return nullptr;
230 }
231 return entity->runningLock;
232 }
233 } // namespace PowerMgr
234 } // namespace OHOS
235