* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "power_napi.h"
#include "napi_errors.h"
#include "napi_utils.h"
#include "power_common.h"
#include "power_log.h"
#include "power_mgr_client.h"
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <uv.h>
#include "app_manager_utils.h"
#ifdef POWER_API_METRICS_ENABLE
#include "histogram_plugin_macros.h"
#endif
#define SET_REBOOT _IOW(BOOT_DETECTOR_IOCTL_BASE, 109, int)
namespace OHOS {
namespace PowerMgr {
namespace {
constexpr uint32_t REBOOT_SHUTDOWN_MAX_ARGC = 1;
constexpr uint32_t WAKEUP_MAX_ARGC = 1;
constexpr uint32_t SET_MODE_CALLBACK_MAX_ARGC = 2;
constexpr uint32_t SET_MODE_PROMISE_MAX_ARGC = 1;
constexpr uint32_t SUSPEND_MAX_ARGC = 1;
constexpr uint32_t SET_SCREEN_OFFTIME_ARGC = 1;
constexpr uint32_t HIBERNATE_ARGC = 1;
constexpr uint32_t REFRESH_ACTIVITY_ARGC = 1;
constexpr uint32_t POWERRKEY_FILTERING_STRATEGY_ARGC = 1;
constexpr uint32_t SHUTDOWN_CALLBACK_ARGC = 1;
constexpr int32_t INDEX_0 = 0;
constexpr int32_t INDEX_1 = 1;
constexpr int32_t RESTORE_DEFAULT_SCREENOFF_TIME = -1;
constexpr int32_t SHUTDOWN_CALLBACK_TIMEOUT = 5000;
static PowerMgrClient& g_powerMgrClient = PowerMgrClient::GetInstance();
thread_local sptr<PowerShutdownCallback> g_powerShutdownCallback = new (std::nothrow) PowerShutdownCallback();
#ifdef POWER_API_METRICS_ENABLE
constexpr int32_t HISTOGRAM_API_CALL_COUNT = 1;
#endif
}
PowerShutdownCallback::~PowerShutdownCallback()
{
ReleaseCallback();
}
void PowerShutdownCallback::ReleaseCallback()
{
std::lock_guard lock(callbackMutex_);
if (callbackRef_ != nullptr) {
napi_delete_reference(env_, callbackRef_);
}
callbackRef_ = nullptr;
env_ = nullptr;
}
void PowerShutdownCallback::CreateCallback(napi_env env, napi_value jsCallback)
{
std::lock_guard lock(callbackMutex_);
if (napi_ok != napi_create_reference(env, jsCallback, SHUTDOWN_CALLBACK_ARGC, &callbackRef_)) {
POWER_HILOGW(FEATURE_SHUTDOWN, "Failed to create a JS callback reference");
callbackRef_ = nullptr;
}
env_ = env;
}
void PowerShutdownCallback::OnAsyncShutdownOrReboot(bool isReboot)
{
isReboot_ = isReboot;
RETURN_IF(env_ == nullptr);
uv_work_t* work = new (std::nothrow) uv_work_t;
RETURN_IF(work == nullptr);
work->data = reinterpret_cast<void*>(this);
std::shared_ptr<SyncContext> syncContext = std::make_shared<SyncContext>();
auto uvcallback = [work, syncContext]() mutable {
PowerShutdownCallback* callback = reinterpret_cast<PowerShutdownCallback*>(work->data);
if (callback != nullptr) {
callback->OnShutdownOrReboot();
}
delete work;
work = nullptr;
syncContext->NotifyOne();
};
if (napi_send_event(env_, uvcallback, napi_eprio_low, __func__) != napi_status::napi_ok) {
delete work;
work = nullptr;
POWER_HILOGW(FEATURE_SHUTDOWN, "uv_queue_work is failed");
return;
}
if (syncContext->WaitFor(SHUTDOWN_CALLBACK_TIMEOUT)) {
POWER_HILOGI(FEATURE_SHUTDOWN, "OnShutdownOrReboot excuted end");
} else {
POWER_HILOGE(FEATURE_SHUTDOWN, "OnShutdownOrReboot excuted timeout");
}
}
void PowerShutdownCallback::OnShutdownOrReboot()
{
POWER_HILOGI(FEATURE_SHUTDOWN, "OnShutdownOrReboot, isReboot: %{public}d", static_cast<int32_t>(isReboot_));
std::lock_guard lock(callbackMutex_);
RETURN_IF_WITH_LOG(callbackRef_ == nullptr || env_ == nullptr, "js callback ref or env is nullptr");
napi_handle_scope scope = nullptr;
napi_open_handle_scope(env_, &scope);
if (scope == nullptr) {
POWER_HILOGW(FEATURE_SHUTDOWN, "scope is nullptr");
return;
}
napi_value isRebootValue = nullptr;
if (napi_ok != napi_get_boolean(env_, isReboot_, &isRebootValue)) {
POWER_HILOGW(FEATURE_SHUTDOWN, "napi_get_boolean callback failed");
napi_close_handle_scope(env_, scope);
return;
}
napi_value callback = nullptr;
napi_status status = napi_get_reference_value(env_, callbackRef_, &callback);
if (status != napi_ok) {
POWER_HILOGW(FEATURE_SHUTDOWN, "napi_get_reference_value callback failed. status = %{public}d", status);
napi_close_handle_scope(env_, scope);
return;
}
napi_value callResult = nullptr;
status = napi_call_function(env_, nullptr, callback, SHUTDOWN_CALLBACK_ARGC, &isRebootValue, &callResult);
if (status != napi_ok) {
POWER_HILOGW(FEATURE_SHUTDOWN, "napi_call_function callback failed, status = %{public}d", status);
}
napi_close_handle_scope(env_, scope);
}
napi_value PowerNapi::Shutdown(napi_env env, napi_callback_info info)
{
return RebootOrShutdown(env, info, false);
}
napi_value PowerNapi::Reboot(napi_env env, napi_callback_info info)
{
return RebootOrShutdown(env, info, true);
}
napi_value PowerNapi::IsActive(napi_env env, napi_callback_info info)
{
bool isScreen = g_powerMgrClient.IsScreenOn();
napi_value napiValue;
NAPI_CALL(env, napi_get_boolean(env, isScreen, &napiValue));
return napiValue;
}
napi_value PowerNapi::Wakeup(napi_env env, napi_callback_info info)
{
size_t argc = WAKEUP_MAX_ARGC;
napi_value argv[argc];
NapiUtils::GetCallbackInfo(env, info, argc, argv);
NapiErrors error;
if (argc != WAKEUP_MAX_ARGC || !NapiUtils::CheckValueType(env, argv[INDEX_0], napi_string)) {
return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
}
std::string detail = NapiUtils::GetStringFromNapi(env, argv[INDEX_0]);
POWER_HILOGD(FEATURE_WAKEUP, "Wakeup type: APPLICATION, reason: %{public}s", detail.c_str());
int32_t apiVersion = AppManagerUtils::GetApiTargetVersion();
PowerErrors code = g_powerMgrClient.WakeupDevice(
WakeupDeviceType::WAKEUP_DEVICE_APPLICATION, detail, std::to_string(apiVersion));
if (code != PowerErrors::ERR_OK) {
error.ThrowError(env, code);
}
return nullptr;
}
napi_value PowerNapi::Suspend(napi_env env, napi_callback_info info)
{
size_t argc = SUSPEND_MAX_ARGC;
napi_value argv[argc];
NapiUtils::GetCallbackInfo(env, info, argc, argv);
NapiErrors error;
if (argc != SUSPEND_MAX_ARGC || !NapiUtils::CheckValueType(env, argv[INDEX_0], napi_boolean)) {
if (!NapiUtils::CheckValueType(env, argv[INDEX_0], napi_undefined)) {
std::string detail = NapiUtils::GetStringFromNapi(env, argv[INDEX_0]);
if (!detail.empty()) {
return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
}
}
}
bool isForce = false;
napi_get_value_bool(env, argv[0], &isForce);
PowerErrors code;
int32_t apiVersion = AppManagerUtils::GetApiTargetVersion();
if (isForce) {
code = g_powerMgrClient.ForceSuspendDevice(std::to_string(apiVersion));
} else {
code = g_powerMgrClient.SuspendDevice(
SuspendDeviceType::SUSPEND_DEVICE_REASON_APPLICATION, false, std::to_string(apiVersion));
}
if (code != PowerErrors::ERR_OK) {
POWER_HILOGE(FEATURE_WAKEUP, "Suspend Device fail, isForce:%{public}d", isForce);
return error.ThrowError(env, code);
}
return nullptr;
}
napi_value PowerNapi::Hibernate(napi_env env, napi_callback_info info)
{
size_t argc = HIBERNATE_ARGC;
napi_value argv[argc];
NapiUtils::GetCallbackInfo(env, info, argc, argv);
NapiErrors error;
if (argc != HIBERNATE_ARGC || !NapiUtils::CheckValueType(env, argv[INDEX_0], napi_boolean)) {
if (!NapiUtils::CheckValueType(env, argv[INDEX_0], napi_undefined)) {
std::string detail = NapiUtils::GetStringFromNapi(env, argv[INDEX_0]);
if (!detail.empty()) {
return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
}
}
}
bool clearMemory = false;
napi_get_value_bool(env, argv[0], &clearMemory);
int32_t apiVersion = AppManagerUtils::GetApiTargetVersion();
PowerErrors code = g_powerMgrClient.Hibernate(clearMemory, "", std::to_string(apiVersion));
if (code != PowerErrors::ERR_OK) {
POWER_HILOGE(FEATURE_WAKEUP, "Hibernate failed.");
error.ThrowError(env, code);
}
return nullptr;
}
napi_value PowerNapi::SetPowerMode(napi_env env, napi_callback_info info)
{
size_t argc = SET_MODE_CALLBACK_MAX_ARGC;
napi_value argv[argc];
NapiUtils::GetCallbackInfo(env, info, argc, argv);
NapiErrors error;
if (argc != SET_MODE_CALLBACK_MAX_ARGC && argc != SET_MODE_PROMISE_MAX_ARGC) {
return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
}
std::unique_ptr<AsyncCallbackInfo> asyncInfo = std::make_unique<AsyncCallbackInfo>();
RETURN_IF_WITH_RET(asyncInfo == nullptr, nullptr);
if (argc == SET_MODE_CALLBACK_MAX_ARGC) {
POWER_HILOGD(FEATURE_POWER_MODE, "Call setPowerMode callback");
return SetPowerModeCallback(env, argv, asyncInfo);
}
POWER_HILOGD(FEATURE_POWER_MODE, "Call setPowerMode promise");
return SetPowerModePromise(env, argv, asyncInfo);
}
napi_value PowerNapi::GetPowerMode(napi_env env, napi_callback_info info)
{
PowerMode mode = g_powerMgrClient.GetDeviceMode();
napi_value napiValue;
NAPI_CALL(env, napi_create_uint32(env, static_cast<uint32_t>(mode), &napiValue));
return napiValue;
}
napi_value PowerNapi::GetPowerConfig(napi_env env, napi_callback_info info)
{
constexpr size_t maxArgc = 1;
size_t argc = maxArgc;
napi_value argv[argc];
NapiUtils::GetCallbackInfo(env, info, argc, argv);
NapiErrors error;
if (argc != maxArgc || !NapiUtils::CheckValueType(env, argv[0], napi_string)) {
POWER_HILOGW(COMP_FWK, "GetPowerConfig invalid param");
return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
}
std::string sceneName = NapiUtils::GetStringFromNapi(env, argv[0]);
std::string configVal;
PowerErrors code = g_powerMgrClient.GetPowerConfig(sceneName, configVal);
if (code != PowerErrors::ERR_OK) {
POWER_HILOGE(COMP_FWK, "GetPowerConfig failed, code: %{public}d", static_cast<int32_t>(code));
return error.ThrowError(env, code);
}
napi_value napiValue;
NAPI_CALL(env, napi_create_string_utf8(env, configVal.c_str(), NAPI_AUTO_LENGTH, &napiValue));
return napiValue;
}
napi_value PowerNapi::SetPowerConfig(napi_env env, napi_callback_info info)
{
constexpr size_t maxArgc = 2;
size_t argc = maxArgc;
napi_value argv[argc];
NapiUtils::GetCallbackInfo(env, info, argc, argv);
NapiErrors error;
if (argc != maxArgc || !NapiUtils::CheckValueType(env, argv[0], napi_string) ||
!NapiUtils::CheckValueType(env, argv[1], napi_string)) {
POWER_HILOGW(COMP_FWK, "SetPowerConfig invalid param");
return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
}
std::string sceneName = NapiUtils::GetStringFromNapi(env, argv[0]);
std::string configVal = NapiUtils::GetStringFromNapi(env, argv[1]);
PowerErrors code = g_powerMgrClient.SetPowerConfig(sceneName, configVal);
if (code != PowerErrors::ERR_OK) {
POWER_HILOGE(COMP_FWK, "SetPowerConfig failed, code: %{public}d", static_cast<int32_t>(code));
return error.ThrowError(env, code);
}
return nullptr;
}
static void SetFrameworkBootStage(bool isReboot)
{
int fd = open("/dev/bbox", O_WRONLY);
if (fd < 0) {
POWER_HILOGE(FEATURE_SHUTDOWN, "open /dev/bbox failed!");
return;
}
fdsan_exchange_owner_tag(fd, 0, DOMAIN_FEATURE_SHUTDOWN);
POWER_HILOGI(FEATURE_SHUTDOWN, "Set shutdown fw start timeout.");
int rebootFlag = isReboot ? 1 : 0;
int ret = ioctl(fd, SET_REBOOT, &rebootFlag);
if (ret < 0) {
POWER_HILOGE(FEATURE_SHUTDOWN, "set reboot flag failed!");
fdsan_close_with_tag(fd, DOMAIN_FEATURE_SHUTDOWN);
return;
}
int stage = SHUT_STAGE_FRAMEWORK_START;
ret = ioctl(fd, SET_SHUT_STAGE, &stage);
if (ret < 0) {
POWER_HILOGE(FEATURE_SHUTDOWN, "set shut stage failed!");
}
POWER_HILOGI(FEATURE_SHUTDOWN, "Set shutdown timeout mechanism started.");
fdsan_close_with_tag(fd, DOMAIN_FEATURE_SHUTDOWN);
return;
}
napi_value PowerNapi::RebootOrShutdown(napi_env env, napi_callback_info info, bool isReboot)
{
size_t argc = REBOOT_SHUTDOWN_MAX_ARGC;
napi_value argv[argc];
SetFrameworkBootStage(isReboot);
NapiUtils::GetCallbackInfo(env, info, argc, argv);
NapiErrors error;
if (argc != REBOOT_SHUTDOWN_MAX_ARGC || !NapiUtils::CheckValueType(env, argv[INDEX_0], napi_string)) {
return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
}
std::string reason = NapiUtils::GetStringFromNapi(env, argv[INDEX_0]);
POWER_HILOGD(FEATURE_SHUTDOWN, "reboot: %{public}d, reason: %{public}s", isReboot, reason.c_str());
PowerErrors code;
if (isReboot) {
code = g_powerMgrClient.RebootDevice(reason);
} else {
code = g_powerMgrClient.ShutDownDevice(reason);
}
if (code != PowerErrors::ERR_OK && code != PowerErrors::ERR_SKIP_FUNCTION_CALL) {
error.ThrowError(env, code);
}
return nullptr;
}
napi_value PowerNapi::SetPowerModeCallback(
napi_env& env, napi_value argv[], std::unique_ptr<AsyncCallbackInfo>& asyncInfo)
{
bool isNum = NapiUtils::CheckValueType(env, argv[INDEX_0], napi_number);
bool isFunc = NapiUtils::CheckValueType(env, argv[INDEX_1], napi_function);
if (!isNum || !isFunc) {
POWER_HILOGW(FEATURE_POWER_MODE, "isNum: %{public}d, isFunc: %{public}d", isNum, isFunc);
return asyncInfo->GetError().ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
}
asyncInfo->GetData().SetMode(env, argv[INDEX_0]);
asyncInfo->CreateCallback(env, argv[INDEX_1]);
AsyncWork(
env, asyncInfo, "SetPowerModeCallback",
[](napi_env env, void* data) {
AsyncCallbackInfo* asyncInfo = reinterpret_cast<AsyncCallbackInfo*>(data);
RETURN_IF(asyncInfo == nullptr);
PowerErrors error = g_powerMgrClient.SetDeviceMode(asyncInfo->GetData().GetMode());
asyncInfo->GetError().Error(error);
},
[](napi_env env, napi_status status, void* data) {
AsyncCallbackInfo* asyncInfo = reinterpret_cast<AsyncCallbackInfo*>(data);
RETURN_IF(asyncInfo == nullptr);
asyncInfo->CallFunction(env, nullptr);
asyncInfo->Release(env);
delete asyncInfo;
});
return nullptr;
}
napi_value PowerNapi::SetPowerModePromise(
napi_env& env, napi_value argv[], std::unique_ptr<AsyncCallbackInfo>& asyncInfo)
{
bool isNum = NapiUtils::CheckValueType(env, argv[INDEX_0], napi_number);
if (!isNum) {
POWER_HILOGW(FEATURE_POWER_MODE, "isNum: %{public}d", isNum);
return asyncInfo->GetError().ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
}
napi_value promise;
asyncInfo->CreatePromise(env, promise);
RETURN_IF_WITH_RET(promise == nullptr, nullptr);
asyncInfo->GetData().SetMode(env, argv[INDEX_0]);
AsyncWork(
env, asyncInfo, "SetPowerModePromise",
[](napi_env env, void* data) {
AsyncCallbackInfo* asyncInfo = reinterpret_cast<AsyncCallbackInfo*>(data);
RETURN_IF(asyncInfo == nullptr);
PowerErrors error = g_powerMgrClient.SetDeviceMode(asyncInfo->GetData().GetMode());
asyncInfo->GetError().Error(error);
},
[](napi_env env, napi_status status, void* data) {
AsyncCallbackInfo* asyncInfo = reinterpret_cast<AsyncCallbackInfo*>(data);
RETURN_IF(asyncInfo == nullptr);
if (asyncInfo->GetError().IsError()) {
napi_reject_deferred(env, asyncInfo->GetDeferred(), asyncInfo->GetError().GetNapiError(env));
} else {
napi_value undefined;
napi_get_undefined(env, &undefined);
napi_resolve_deferred(env, asyncInfo->GetDeferred(), undefined);
}
asyncInfo->Release(env);
delete asyncInfo;
});
return promise;
}
void PowerNapi::AsyncWork(napi_env& env, std::unique_ptr<AsyncCallbackInfo>& asyncInfo, const std::string& resourceName,
napi_async_execute_callback execute, napi_async_complete_callback complete)
{
napi_value resource = nullptr;
napi_create_string_utf8(env, resourceName.c_str(), NAPI_AUTO_LENGTH, &resource);
napi_create_async_work(env, nullptr, resource, execute, complete,
reinterpret_cast<void*>(asyncInfo.get()), &(asyncInfo->GetAsyncWork()));
NAPI_CALL_RETURN_VOID(env, napi_queue_async_work_with_qos(env, asyncInfo->GetAsyncWork(), napi_qos_utility));
asyncInfo.release();
}
napi_value PowerNapi::SetScreenOffTime(napi_env env, napi_callback_info info)
{
size_t argc = SET_SCREEN_OFFTIME_ARGC;
napi_value argv[argc];
NapiUtils::GetCallbackInfo(env, info, argc, argv);
NapiErrors error;
if (argc != SET_SCREEN_OFFTIME_ARGC || !NapiUtils::CheckValueType(env, argv[INDEX_0], napi_number)) {
POWER_HILOGE(FEATURE_WAKEUP, "check value type failed.");
return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
}
int64_t timeout;
if (napi_ok != napi_get_value_int64(env, argv[INDEX_0], &timeout)) {
POWER_HILOGE(FEATURE_WAKEUP, "napi get int64 value failed.");
return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
}
if (timeout == 0 || (timeout < 0 && timeout != RESTORE_DEFAULT_SCREENOFF_TIME)) {
POWER_HILOGE(FEATURE_WAKEUP, "timeout is not right.");
return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
}
PowerErrors code;
int32_t apiVersion = AppManagerUtils::GetApiTargetVersion();
if (timeout == RESTORE_DEFAULT_SCREENOFF_TIME) {
code = g_powerMgrClient.RestoreScreenOffTime(std::to_string(apiVersion));
} else {
code = g_powerMgrClient.OverrideScreenOffTime(timeout, std::to_string(apiVersion));
}
if (code != PowerErrors::ERR_OK) {
POWER_HILOGE(FEATURE_WAKEUP, "SetScreenOffTime failed.");
return error.ThrowError(env, code);
}
return nullptr;
}
napi_value PowerNapi::IsStandby(napi_env env, napi_callback_info info)
{
#ifdef POWER_API_METRICS_ENABLE
HISTOGRAM_BOOLEAN("BasicServicesKit.PowerManager.isStandby.Boolean", HISTOGRAM_API_CALL_COUNT);
#endif
bool isStandby = false;
PowerErrors code = g_powerMgrClient.IsStandby(isStandby);
if (code == PowerErrors::ERR_OK) {
napi_value napiValue;
NAPI_CALL(env, napi_get_boolean(env, isStandby, &napiValue));
return napiValue;
}
NapiErrors error;
return error.ThrowError(env, code);
}
napi_value PowerNapi::RefreshActivity(napi_env env, napi_callback_info info)
{
size_t argc = REFRESH_ACTIVITY_ARGC;
napi_value argv[argc];
NapiUtils::GetCallbackInfo(env, info, argc, argv);
NapiErrors error;
if (argc != REFRESH_ACTIVITY_ARGC || !NapiUtils::CheckValueType(env, argv[INDEX_0], napi_string)) {
return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
}
std::string reason = NapiUtils::GetStringFromNapi(env, argv[INDEX_0]);
PowerErrors code = g_powerMgrClient.RefreshActivity(UserActivityType::USER_ACTIVITY_TYPE_APPLICATION, reason);
if (code != PowerErrors::ERR_OK) {
POWER_HILOGE(FEATURE_ACTIVITY, "RefreshActivity failed. code:%{public}d", static_cast<int32_t>(code));
return error.ThrowError(env, code);
}
return nullptr;
}
napi_value PowerNapi::SetPowerKeyFilteringStrategy(napi_env env, napi_callback_info info)
{
size_t argc = POWERRKEY_FILTERING_STRATEGY_ARGC;
napi_value argv[argc];
NapiUtils::GetCallbackInfo(env, info, argc, argv);
NapiErrors error;
if (argc != POWERRKEY_FILTERING_STRATEGY_ARGC || !NapiUtils::CheckValueType(env, argv[INDEX_0], napi_number)) {
return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
}
int32_t strategy = 0;
if (napi_ok != napi_get_value_int32(env, argv[INDEX_0], &strategy)) {
POWER_HILOGE(FEATURE_INPUT, "napi get int32 value failed.");
return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
}
if (strategy < 0 || strategy >= static_cast<int32_t>(PowerKeyFilteringStrategy::STRATEGY_MAX)) {
POWER_HILOGE(FEATURE_INPUT, "strategy is not right.");
return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
}
PowerErrors code = g_powerMgrClient.SetPowerKeyFilteringStrategy(static_cast<PowerKeyFilteringStrategy>(strategy));
if (code != PowerErrors::ERR_OK) {
POWER_HILOGE(FEATURE_INPUT, "SetPowerKeyFilteringStrategy failed. code:%{public}d", static_cast<int32_t>(code));
return error.ThrowError(env, code);
}
return nullptr;
}
napi_value PowerNapi::RegisterShutdownCallback(napi_env env, napi_callback_info info)
{
#ifdef POWER_API_METRICS_ENABLE
HISTOGRAM_BOOLEAN("BasicServicesKit.PowerManager.registerShutdownCallback.Boolean", HISTOGRAM_API_CALL_COUNT);
#endif
size_t argc = SHUTDOWN_CALLBACK_ARGC;
napi_value argv[argc];
NapiUtils::GetCallbackInfo(env, info, argc, argv);
NapiErrors errors;
if (argc != SHUTDOWN_CALLBACK_ARGC || !NapiUtils::CheckValueType(env, argv[INDEX_0], napi_function)) {
POWER_HILOGE(FEATURE_SHUTDOWN, "RegisterShutdownCallback ERR_PARAM_INVALID");
return errors.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
}
napi_value result;
napi_get_undefined(env, &result);
if (g_powerShutdownCallback == nullptr) {
POWER_HILOGE(FEATURE_SHUTDOWN, "g_powerShutdownCallback null");
return nullptr;
}
g_powerShutdownCallback->ReleaseCallback();
g_powerShutdownCallback->CreateCallback(env, argv[INDEX_0]);
PowerErrors code = g_powerMgrClient.RegisterAsyncShutdownCallback(g_powerShutdownCallback,
ShutdownPriority::DEFAULT);
if (code != PowerErrors::ERR_OK) {
POWER_HILOGE(FEATURE_SHUTDOWN, "RegisterShutdownCallback failed. code:%{public}d", static_cast<int32_t>(code));
return errors.ThrowError(env, code);
}
return result;
}
napi_value PowerNapi::UnRegisterShutdownCallback(napi_env env, napi_callback_info info)
{
#ifdef POWER_API_METRICS_ENABLE
HISTOGRAM_BOOLEAN("BasicServicesKit.PowerManager.unregisterShutdownCallback.Boolean", HISTOGRAM_API_CALL_COUNT);
#endif
size_t argc = SHUTDOWN_CALLBACK_ARGC;
napi_value argv[argc];
NapiUtils::GetCallbackInfo(env, info, argc, argv);
if (g_powerShutdownCallback == nullptr) {
POWER_HILOGE(FEATURE_SHUTDOWN, "g_powerShutdownCallback null");
return nullptr;
}
NapiErrors errors;
g_powerShutdownCallback->ReleaseCallback();
PowerErrors code = g_powerMgrClient.UnRegisterAsyncShutdownCallback(g_powerShutdownCallback);
if (code != PowerErrors::ERR_OK) {
POWER_HILOGE(FEATURE_SHUTDOWN,
"UnRegisterShutdownCallback failed. code:%{public}d", static_cast<int32_t>(code));
return errors.ThrowError(env, code);
}
RETURN_IF_WITH_RET(argc == INDEX_0, nullptr);
if (argc == SHUTDOWN_CALLBACK_ARGC && NapiUtils::CheckValueType(env, argv[INDEX_0], napi_undefined)) {
POWER_HILOGI(FEATURE_SHUTDOWN, "UnRegisterShutdownCallback end");
return nullptr;
}
if (argc != SHUTDOWN_CALLBACK_ARGC || !NapiUtils::CheckValueType(env, argv[INDEX_0], napi_function)) {
POWER_HILOGE(FEATURE_SHUTDOWN, "UnRegisterShutdownCallback ERR_PARAM_INVALID");
return errors.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
}
napi_value handler = nullptr;
napi_ref handlerRef = nullptr;
napi_create_reference(env, argv[INDEX_0], SHUTDOWN_CALLBACK_ARGC, &handlerRef);
napi_get_reference_value(env, handlerRef, &handler);
napi_delete_reference(env, handlerRef);
napi_value result = nullptr;
if (handler == nullptr) {
POWER_HILOGE(FEATURE_SHUTDOWN, "Handler is nullptr");
return result;
}
napi_get_undefined(env, &result);
napi_status status = napi_call_function(env, nullptr, handler, INDEX_0, nullptr, &result);
if (status != napi_ok) {
POWER_HILOGE(FEATURE_SHUTDOWN, "status=%{public}d", status);
return result;
}
return result;
}
}
}