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