1 /*
2 * Copyright (c) 2021 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 <cstdio>
17 #include <cstdlib>
18 #include <string>
19 #include "hilog_wrapper.h"
20 #include "napi/native_api.h"
21 #include "napi/native_node_api.h"
22 #include "power_mgr_client.h"
23
24 using namespace OHOS::PowerMgr;
25
26 namespace {
27 constexpr int REASON_MAX = 512;
28 constexpr int RESULT_SIZE = 2;
29 }
30
31 struct PowerAsyncCallbackInfo {
32 napi_env env;
33 napi_async_work asyncWork = nullptr;
34 napi_ref callbackRef = nullptr;
35 napi_deferred deferred = nullptr;
36 bool screenOn = false;
37 };
38
39 static PowerMgrClient &g_powerMgrClient = PowerMgrClient::GetInstance();
40
RebootOrShutdown(napi_env env,napi_callback_info info,bool isReboot)41 static napi_value RebootOrShutdown(napi_env env, napi_callback_info info, bool isReboot)
42 {
43 POWER_HILOGD(MODULE_JS_NAPI, "%{public}s: enter, %{public}s", __func__, isReboot ? "reboot" : "shutdown");
44 size_t argc = 1;
45 napi_value args[1] = { 0 };
46 napi_value jsthis;
47 void *data = nullptr;
48
49 napi_status status = napi_get_cb_info(env, info, &argc, args, &jsthis, &data);
50 NAPI_ASSERT(env, (status == napi_ok) && (argc >= 1), "failed to get cb info");
51 napi_valuetype type = napi_undefined;
52 NAPI_CALL(env, napi_typeof(env, args[0], &type));
53 NAPI_ASSERT(env, type == napi_string, "wrong argument type. string expected.");
54
55 char reason[REASON_MAX] = { 0 };
56 size_t reasonLen = 0;
57 status = napi_get_value_string_utf8(env, args[0], reason, REASON_MAX - 1, &reasonLen);
58 if (status != napi_ok) {
59 POWER_HILOGE(MODULE_JS_NAPI, "%{public}s: get reason failed", __func__);
60 return nullptr;
61 }
62 if (isReboot) {
63 g_powerMgrClient.RebootDevice(std::string(reason));
64 } else {
65 g_powerMgrClient.ShutDownDevice(std::string(reason));
66 }
67 POWER_HILOGD(MODULE_JS_NAPI, "%{public}s: reason %{public}s, exit", __func__, reason);
68 return nullptr;
69 }
70
ShutdownDevice(napi_env env,napi_callback_info info)71 static napi_value ShutdownDevice(napi_env env, napi_callback_info info)
72 {
73 return RebootOrShutdown(env, info, false);
74 }
75
RebootDevice(napi_env env,napi_callback_info info)76 static napi_value RebootDevice(napi_env env, napi_callback_info info)
77 {
78 return RebootOrShutdown(env, info, true);
79 }
80
IsScreenOnCallBack(napi_env env,PowerAsyncCallbackInfo * asyncCallbackInfo)81 static void IsScreenOnCallBack(napi_env env, PowerAsyncCallbackInfo *asyncCallbackInfo)
82 {
83 napi_value resource = nullptr;
84 napi_create_string_utf8(env, "IsScreenOn", NAPI_AUTO_LENGTH, &resource);
85 napi_create_async_work(
86 env,
87 nullptr,
88 resource,
89 [](napi_env env, void *data) {
90 PowerAsyncCallbackInfo *asyncCallbackInfo = (PowerAsyncCallbackInfo *)data;
91 asyncCallbackInfo->screenOn = g_powerMgrClient.IsScreenOn();
92 POWER_HILOGD(MODULE_JS_NAPI, "%{public}s: screen is %{public}s ", __func__,
93 asyncCallbackInfo->screenOn ? "on" : "off");
94 },
95 [](napi_env env, napi_status status, void *data) {
96 PowerAsyncCallbackInfo *asyncCallbackInfo = (PowerAsyncCallbackInfo *)data;
97 napi_value result[RESULT_SIZE] = { 0 };
98 napi_get_boolean(env, asyncCallbackInfo->screenOn, &result[1]);
99 if (asyncCallbackInfo->deferred) {
100 napi_resolve_deferred(env, asyncCallbackInfo->deferred, result[1]);
101 } else {
102 napi_value tmp = nullptr;
103 napi_value callback = nullptr;
104 napi_get_reference_value(env, asyncCallbackInfo->callbackRef, &callback);
105 napi_get_undefined(env, &result[0]);
106 napi_call_function(env, nullptr, callback, RESULT_SIZE, result, &tmp);
107 napi_delete_reference(env, asyncCallbackInfo->callbackRef);
108 }
109 napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
110 delete asyncCallbackInfo;
111 },
112 (void *)asyncCallbackInfo,
113 &asyncCallbackInfo->asyncWork);
114 napi_queue_async_work(env, asyncCallbackInfo->asyncWork);
115 }
116
IsScreenOn(napi_env env,napi_callback_info info)117 static napi_value IsScreenOn(napi_env env, napi_callback_info info)
118 {
119 POWER_HILOGD(MODULE_JS_NAPI, "%{public}s: enter", __func__);
120 size_t argc = 1;
121 napi_value args[1] = { 0 };
122 napi_value jsthis;
123 void *data = nullptr;
124
125 napi_status status = napi_get_cb_info(env, info, &argc, args, &jsthis, &data);
126 NAPI_ASSERT(env, (status == napi_ok), "IsScreenOn: failed to get cb info");
127
128 auto asyncCallbackInfo = new PowerAsyncCallbackInfo();
129 if (asyncCallbackInfo == nullptr) {
130 POWER_HILOGE(MODULE_JS_NAPI, "%{public}s: new asyncCallbackInfo failed", __func__);
131 return nullptr;
132 }
133 asyncCallbackInfo->env = env;
134
135 napi_valuetype type;
136 if (argc == 1) {
137 NAPI_CALL(env, napi_typeof(env, args[0], &type));
138 if (type != napi_function) {
139 POWER_HILOGE(MODULE_JS_NAPI, "%{public}s: wrong argument type. napi_function expected", __func__);
140 delete asyncCallbackInfo;
141 return nullptr;
142 }
143 napi_create_reference(env, args[0], 1, &asyncCallbackInfo->callbackRef);
144 }
145 napi_value result = nullptr;
146 if (asyncCallbackInfo->callbackRef == nullptr) {
147 POWER_HILOGD(MODULE_JS_NAPI, "%{public}s: callbackRef is null", __func__);
148 napi_create_promise(env, &asyncCallbackInfo->deferred, &result);
149 } else {
150 POWER_HILOGD(MODULE_JS_NAPI, "%{public}s: callbackRef is not null", __func__);
151 napi_get_undefined(env, &result);
152 }
153 IsScreenOnCallBack(env, asyncCallbackInfo);
154 POWER_HILOGD(MODULE_JS_NAPI, "%{public}s: exit", __func__);
155 return result;
156 }
157
158 EXTERN_C_START
159 /*
160 * function for module exports
161 */
PowerInit(napi_env env,napi_value exports)162 static napi_value PowerInit(napi_env env, napi_value exports)
163 {
164 POWER_HILOGD(MODULE_JS_NAPI, "%{public}s: enter", __func__);
165 napi_property_descriptor desc[] = {
166 DECLARE_NAPI_FUNCTION("shutdownDevice", ShutdownDevice),
167 DECLARE_NAPI_FUNCTION("rebootDevice", RebootDevice),
168 DECLARE_NAPI_FUNCTION("isScreenOn", IsScreenOn),
169 };
170 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
171 POWER_HILOGD(MODULE_JS_NAPI, "%{public}s: exit", __func__);
172
173 return exports;
174 }
175 EXTERN_C_END
176
177 /*
178 * Module definition
179 */
180 static napi_module g_module = {
181 .nm_version = 1,
182 .nm_flags = 0,
183 .nm_filename = "power",
184 .nm_register_func = PowerInit,
185 .nm_modname = "power",
186 .nm_priv = ((void *)0),
187 .reserved = {0}
188 };
189
190 /*
191 * Module registration
192 */
RegisterPowerModule(void)193 extern "C" __attribute__((constructor)) void RegisterPowerModule(void)
194 {
195 napi_module_register(&g_module);
196 }