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