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 27namespace OHOS { 28namespace PowerMgr { 29namespace { 30constexpr uint32_t CREATE_PROMISE_MAX_ARGC = 2; 31constexpr uint32_t CREATE_CALLBACK_MAX_ARGC = 3; 32constexpr uint32_t ISSUPPORTED_MAX_ARGC = 1; 33constexpr uint32_t HOLD_MAX_ARGC = 1; 34constexpr int32_t INDEX_0 = 0; 35constexpr int32_t INDEX_1 = 1; 36constexpr int32_t INDEX_2 = 2; 37} 38 39napi_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 62napi_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 85napi_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 110napi_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 122napi_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 136napi_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 170napi_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 209void 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 220std::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