• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "power_napi.h"
17 
18 #include "napi_errors.h"
19 #include "napi_utils.h"
20 #include "power_common.h"
21 #include "power_log.h"
22 #include "power_mgr_client.h"
23 #include <fcntl.h>
24 #include <sys/ioctl.h>
25 #include <unistd.h>
26 #include "app_manager_utils.h"
27 
28 #define SET_REBOOT _IOW(BOOT_DETECTOR_IOCTL_BASE, 109, int)
29 
30 namespace OHOS {
31 namespace PowerMgr {
32 namespace {
33 constexpr uint32_t REBOOT_SHUTDOWN_MAX_ARGC = 1;
34 constexpr uint32_t WAKEUP_MAX_ARGC = 1;
35 constexpr uint32_t SET_MODE_CALLBACK_MAX_ARGC = 2;
36 constexpr uint32_t SET_MODE_PROMISE_MAX_ARGC = 1;
37 constexpr uint32_t SUSPEND_MAX_ARGC = 1;
38 constexpr uint32_t SET_SCREEN_OFFTIME_ARGC = 1;
39 constexpr uint32_t HIBERNATE_ARGC = 1;
40 constexpr int32_t INDEX_0 = 0;
41 constexpr int32_t INDEX_1 = 1;
42 constexpr int32_t RESTORE_DEFAULT_SCREENOFF_TIME = -1;
43 static PowerMgrClient& g_powerMgrClient = PowerMgrClient::GetInstance();
44 } // namespace
Shutdown(napi_env env,napi_callback_info info)45 napi_value PowerNapi::Shutdown(napi_env env, napi_callback_info info)
46 {
47     return RebootOrShutdown(env, info, false);
48 }
49 
Reboot(napi_env env,napi_callback_info info)50 napi_value PowerNapi::Reboot(napi_env env, napi_callback_info info)
51 {
52     return RebootOrShutdown(env, info, true);
53 }
54 
IsActive(napi_env env,napi_callback_info info)55 napi_value PowerNapi::IsActive(napi_env env, napi_callback_info info)
56 {
57     bool isScreen = g_powerMgrClient.IsScreenOn();
58     napi_value napiValue;
59     NAPI_CALL(env, napi_get_boolean(env, isScreen, &napiValue));
60     return napiValue;
61 }
62 
Wakeup(napi_env env,napi_callback_info info)63 napi_value PowerNapi::Wakeup(napi_env env, napi_callback_info info)
64 {
65     size_t argc = WAKEUP_MAX_ARGC;
66     napi_value argv[argc];
67     NapiUtils::GetCallbackInfo(env, info, argc, argv);
68 
69     NapiErrors error;
70     if (argc != WAKEUP_MAX_ARGC || !NapiUtils::CheckValueType(env, argv[INDEX_0], napi_string)) {
71         return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
72     }
73 
74     std::string detail = NapiUtils::GetStringFromNapi(env, argv[INDEX_0]);
75     POWER_HILOGD(FEATURE_WAKEUP, "Wakeup type: APPLICATION, reason: %{public}s", detail.c_str());
76     int32_t apiVersion = AppManagerUtils::GetApiTargetVersion();
77     PowerErrors code = g_powerMgrClient.WakeupDevice(
78         WakeupDeviceType::WAKEUP_DEVICE_APPLICATION, detail, std::to_string(apiVersion));
79     if (code != PowerErrors::ERR_OK) {
80         error.ThrowError(env, code);
81     }
82     return nullptr;
83 }
84 
Suspend(napi_env env,napi_callback_info info)85 napi_value PowerNapi::Suspend(napi_env env, napi_callback_info info)
86 {
87     size_t argc = SUSPEND_MAX_ARGC;
88     napi_value argv[argc];
89     NapiUtils::GetCallbackInfo(env, info, argc, argv);
90 
91     NapiErrors error;
92     if (argc != SUSPEND_MAX_ARGC || !NapiUtils::CheckValueType(env, argv[INDEX_0], napi_boolean)) {
93         if (!NapiUtils::CheckValueType(env, argv[INDEX_0], napi_undefined)) {
94             std::string detail = NapiUtils::GetStringFromNapi(env, argv[INDEX_0]);
95             if (!detail.empty()) {
96                 return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
97             }
98         }
99     }
100 
101     bool isForce = false;
102     napi_get_value_bool(env, argv[0], &isForce);
103 
104     PowerErrors code;
105     int32_t apiVersion = AppManagerUtils::GetApiTargetVersion();
106     if (isForce) {
107         code = g_powerMgrClient.ForceSuspendDevice(std::to_string(apiVersion));
108     } else {
109         code = g_powerMgrClient.SuspendDevice(
110             SuspendDeviceType::SUSPEND_DEVICE_REASON_APPLICATION, false, std::to_string(apiVersion));
111     }
112     if (code != PowerErrors::ERR_OK) {
113         POWER_HILOGE(FEATURE_WAKEUP, "Suspend Device fail, isForce:%{public}d", isForce);
114         return error.ThrowError(env, code);
115     }
116     return nullptr;
117 }
118 
Hibernate(napi_env env,napi_callback_info info)119 napi_value PowerNapi::Hibernate(napi_env env, napi_callback_info info)
120 {
121     size_t argc = HIBERNATE_ARGC;
122     napi_value argv[argc];
123     NapiUtils::GetCallbackInfo(env, info, argc, argv);
124 
125     NapiErrors error;
126     if (argc != HIBERNATE_ARGC || !NapiUtils::CheckValueType(env, argv[INDEX_0], napi_boolean)) {
127         if (!NapiUtils::CheckValueType(env, argv[INDEX_0], napi_undefined)) {
128             std::string detail = NapiUtils::GetStringFromNapi(env, argv[INDEX_0]);
129             if (!detail.empty()) {
130                 return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
131             }
132         }
133     }
134 
135     bool clearMemory = false;
136     napi_get_value_bool(env, argv[0], &clearMemory);
137 
138     int32_t apiVersion = AppManagerUtils::GetApiTargetVersion();
139     PowerErrors code = g_powerMgrClient.Hibernate(clearMemory, std::to_string(apiVersion));
140     if (code != PowerErrors::ERR_OK) {
141         POWER_HILOGE(FEATURE_WAKEUP, "Hibernate failed.");
142         error.ThrowError(env, code);
143     }
144     return nullptr;
145 }
146 
SetPowerMode(napi_env env,napi_callback_info info)147 napi_value PowerNapi::SetPowerMode(napi_env env, napi_callback_info info)
148 {
149     size_t argc = SET_MODE_CALLBACK_MAX_ARGC;
150     napi_value argv[argc];
151     NapiUtils::GetCallbackInfo(env, info, argc, argv);
152 
153     NapiErrors error;
154     if (argc != SET_MODE_CALLBACK_MAX_ARGC && argc != SET_MODE_PROMISE_MAX_ARGC) {
155         return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
156     }
157 
158     std::unique_ptr<AsyncCallbackInfo> asyncInfo = std::make_unique<AsyncCallbackInfo>();
159     RETURN_IF_WITH_RET(asyncInfo == nullptr, nullptr);
160     // callback
161     if (argc == SET_MODE_CALLBACK_MAX_ARGC) {
162         POWER_HILOGD(FEATURE_POWER_MODE, "Call setPowerMode callback");
163         return SetPowerModeCallback(env, argv, asyncInfo);
164     }
165 
166     // promise
167     POWER_HILOGD(FEATURE_POWER_MODE, "Call setPowerMode promise");
168     return SetPowerModePromise(env, argv, asyncInfo);
169 }
170 
GetPowerMode(napi_env env,napi_callback_info info)171 napi_value PowerNapi::GetPowerMode(napi_env env, napi_callback_info info)
172 {
173     PowerMode mode = g_powerMgrClient.GetDeviceMode();
174     napi_value napiValue;
175     NAPI_CALL(env, napi_create_uint32(env, static_cast<uint32_t>(mode), &napiValue));
176     return napiValue;
177 }
178 
SetFrameworkBootStage(bool isReboot)179 static void SetFrameworkBootStage(bool isReboot)
180 {
181     int fd = open("/dev/bbox", O_WRONLY);
182     if (fd < 0) {
183         POWER_HILOGE(FEATURE_SHUTDOWN, "open /dev/bbox failed!");
184         return;
185     }
186     int rebootFlag = isReboot ? 1 : 0;
187     int ret = ioctl(fd, SET_REBOOT, &rebootFlag);
188     if (ret < 0) {
189         POWER_HILOGE(FEATURE_SHUTDOWN, "set reboot flag failed!");
190         close(fd);
191         return;
192     }
193     int stage = SHUT_STAGE_FRAMEWORK_START;
194     ret = ioctl(fd, SET_SHUT_STAGE, &stage);
195     if (ret < 0) {
196         POWER_HILOGE(FEATURE_SHUTDOWN, "set shut stage failed!");
197     }
198     close(fd);
199     return;
200 }
201 
RebootOrShutdown(napi_env env,napi_callback_info info,bool isReboot)202 napi_value PowerNapi::RebootOrShutdown(napi_env env, napi_callback_info info, bool isReboot)
203 {
204     size_t argc = REBOOT_SHUTDOWN_MAX_ARGC;
205     napi_value argv[argc];
206     SetFrameworkBootStage(isReboot);
207     NapiUtils::GetCallbackInfo(env, info, argc, argv);
208 
209     NapiErrors error;
210     if (argc != REBOOT_SHUTDOWN_MAX_ARGC || !NapiUtils::CheckValueType(env, argv[INDEX_0], napi_string)) {
211         return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
212     }
213 
214     std::string reason = NapiUtils::GetStringFromNapi(env, argv[INDEX_0]);
215     POWER_HILOGD(FEATURE_SHUTDOWN, "reboot: %{public}d, reason: %{public}s", isReboot, reason.c_str());
216 
217     PowerErrors code;
218     if (isReboot) {
219         code = g_powerMgrClient.RebootDevice(reason);
220     } else {
221         code = g_powerMgrClient.ShutDownDevice(reason);
222     }
223     if (code != PowerErrors::ERR_OK) {
224         error.ThrowError(env, code);
225     }
226 
227     return nullptr;
228 }
229 
SetPowerModeCallback(napi_env & env,napi_value argv[],std::unique_ptr<AsyncCallbackInfo> & asyncInfo)230 napi_value PowerNapi::SetPowerModeCallback(
231     napi_env& env, napi_value argv[], std::unique_ptr<AsyncCallbackInfo>& asyncInfo)
232 {
233     bool isNum = NapiUtils::CheckValueType(env, argv[INDEX_0], napi_number);
234     bool isFunc = NapiUtils::CheckValueType(env, argv[INDEX_1], napi_function);
235     if (!isNum || !isFunc) {
236         POWER_HILOGW(FEATURE_POWER_MODE, "isNum: %{public}d, isFunc: %{public}d", isNum, isFunc);
237         return asyncInfo->GetError().ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
238     }
239 
240     asyncInfo->GetData().SetMode(env, argv[INDEX_0]);
241     asyncInfo->CreateCallback(env, argv[INDEX_1]);
242 
243     AsyncWork(
244         env, asyncInfo, "SetPowerModeCallback",
245         [](napi_env env, void* data) {
246             AsyncCallbackInfo* asyncInfo = reinterpret_cast<AsyncCallbackInfo*>(data);
247             RETURN_IF(asyncInfo == nullptr);
248             PowerErrors error = g_powerMgrClient.SetDeviceMode(asyncInfo->GetData().GetMode());
249             asyncInfo->GetError().Error(error);
250         },
251         [](napi_env env, napi_status status, void* data) {
252             AsyncCallbackInfo* asyncInfo = reinterpret_cast<AsyncCallbackInfo*>(data);
253             RETURN_IF(asyncInfo == nullptr);
254             asyncInfo->CallFunction(env, nullptr);
255             asyncInfo->Release(env);
256             delete asyncInfo;
257         });
258     return nullptr;
259 }
260 
SetPowerModePromise(napi_env & env,napi_value argv[],std::unique_ptr<AsyncCallbackInfo> & asyncInfo)261 napi_value PowerNapi::SetPowerModePromise(
262     napi_env& env, napi_value argv[], std::unique_ptr<AsyncCallbackInfo>& asyncInfo)
263 {
264     bool isNum = NapiUtils::CheckValueType(env, argv[INDEX_0], napi_number);
265     if (!isNum) {
266         POWER_HILOGW(FEATURE_POWER_MODE, "isNum: %{public}d", isNum);
267         return asyncInfo->GetError().ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
268     }
269     napi_value promise;
270     asyncInfo->CreatePromise(env, promise);
271     RETURN_IF_WITH_RET(promise == nullptr, nullptr);
272     asyncInfo->GetData().SetMode(env, argv[INDEX_0]);
273 
274     AsyncWork(
275         env, asyncInfo, "SetPowerModePromise",
276         [](napi_env env, void* data) {
277             AsyncCallbackInfo* asyncInfo = reinterpret_cast<AsyncCallbackInfo*>(data);
278             RETURN_IF(asyncInfo == nullptr);
279             PowerErrors error = g_powerMgrClient.SetDeviceMode(asyncInfo->GetData().GetMode());
280             asyncInfo->GetError().Error(error);
281         },
282         [](napi_env env, napi_status status, void* data) {
283             AsyncCallbackInfo* asyncInfo = reinterpret_cast<AsyncCallbackInfo*>(data);
284             RETURN_IF(asyncInfo == nullptr);
285             if (asyncInfo->GetError().IsError()) {
286                 napi_reject_deferred(env, asyncInfo->GetDeferred(), asyncInfo->GetError().GetNapiError(env));
287             } else {
288                 napi_value undefined;
289                 napi_get_undefined(env, &undefined);
290                 napi_resolve_deferred(env, asyncInfo->GetDeferred(), undefined);
291             }
292             asyncInfo->Release(env);
293             delete asyncInfo;
294         });
295     return promise;
296 }
297 
AsyncWork(napi_env & env,std::unique_ptr<AsyncCallbackInfo> & asyncInfo,const std::string & resourceName,napi_async_execute_callback execute,napi_async_complete_callback complete)298 void PowerNapi::AsyncWork(napi_env& env, std::unique_ptr<AsyncCallbackInfo>& asyncInfo, const std::string& resourceName,
299     napi_async_execute_callback execute, napi_async_complete_callback complete)
300 {
301     napi_value resource = nullptr;
302     napi_create_string_utf8(env, resourceName.c_str(), NAPI_AUTO_LENGTH, &resource);
303     napi_create_async_work(env, nullptr, resource, execute, complete,
304         reinterpret_cast<void*>(asyncInfo.get()), &(asyncInfo->GetAsyncWork()));
305     NAPI_CALL_RETURN_VOID(env, napi_queue_async_work_with_qos(env, asyncInfo->GetAsyncWork(), napi_qos_utility));
306     asyncInfo.release();
307 }
308 
SetScreenOffTime(napi_env env,napi_callback_info info)309 napi_value PowerNapi::SetScreenOffTime(napi_env env, napi_callback_info info)
310 {
311     size_t argc = SET_SCREEN_OFFTIME_ARGC;
312     napi_value argv[argc];
313     NapiUtils::GetCallbackInfo(env, info, argc, argv);
314 
315     NapiErrors error;
316     if (argc != SET_SCREEN_OFFTIME_ARGC || !NapiUtils::CheckValueType(env, argv[INDEX_0], napi_number)) {
317         POWER_HILOGE(FEATURE_WAKEUP, "check value type failed.");
318         return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
319     }
320 
321     int64_t timeout;
322     if (napi_ok != napi_get_value_int64(env, argv[INDEX_0], &timeout)) {
323         POWER_HILOGE(FEATURE_WAKEUP, "napi get int64 value failed.");
324         return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
325     }
326 
327     if (timeout == 0 || (timeout < 0 && timeout != RESTORE_DEFAULT_SCREENOFF_TIME)) {
328         POWER_HILOGE(FEATURE_WAKEUP, "timeout is not right.");
329         return error.ThrowError(env, PowerErrors::ERR_PARAM_INVALID);
330     }
331 
332     PowerErrors code;
333     int32_t apiVersion = AppManagerUtils::GetApiTargetVersion();
334     if (timeout == RESTORE_DEFAULT_SCREENOFF_TIME) {
335         code = g_powerMgrClient.RestoreScreenOffTime(std::to_string(apiVersion));
336     } else {
337         code = g_powerMgrClient.OverrideScreenOffTime(timeout, std::to_string(apiVersion));
338     }
339     if (code != PowerErrors::ERR_OK) {
340         POWER_HILOGE(FEATURE_WAKEUP, "SetScreenOffTime failed.");
341         return error.ThrowError(env, code);
342     }
343     return nullptr;
344 }
345 
IsStandby(napi_env env,napi_callback_info info)346 napi_value PowerNapi::IsStandby(napi_env env, napi_callback_info info)
347 {
348     bool isStandby = false;
349     PowerErrors code = g_powerMgrClient.IsStandby(isStandby);
350     if (code == PowerErrors::ERR_OK) {
351         napi_value napiValue;
352         NAPI_CALL(env, napi_get_boolean(env, isStandby, &napiValue));
353         return napiValue;
354     }
355     NapiErrors error;
356     return error.ThrowError(env, code);
357 }
358 } // namespace PowerMgr
359 } // namespace OHOS
360