1 /*
2 * Copyright (c) 2025 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 "ohos.power.proj.hpp"
17 #include "ohos.power.impl.hpp"
18 #include "taihe/runtime.hpp"
19 #include "stdexcept"
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 using namespace taihe;
31 using namespace ohos::power;
32 using namespace OHOS::PowerMgr;
33
34 namespace {
35 std::map<PowerErrors, std::string> g_errorTable = {
36 {PowerErrors::ERR_CONNECTION_FAIL, "Failed to connect to the service."},
37 {PowerErrors::ERR_PERMISSION_DENIED, "Permission is denied" },
38 {PowerErrors::ERR_SYSTEM_API_DENIED, "System permission is denied" },
39 {PowerErrors::ERR_PARAM_INVALID, "Invalid input parameter." }
40 };
41 static PowerMgrClient& g_powerMgrClient = PowerMgrClient::GetInstance();
42 constexpr int32_t RESTORE_DEFAULT_SCREENOFF_TIME = -1;
43
SetFrameworkBootStage(bool isReboot)44 static void SetFrameworkBootStage(bool isReboot)
45 {
46 int fd = open("/dev/bbox", O_WRONLY);
47 if (fd < 0) {
48 POWER_HILOGE(FEATURE_SHUTDOWN, "open /dev/bbox failed!");
49 return;
50 }
51
52 fdsan_exchange_owner_tag(fd, 0, DOMAIN_FEATURE_SHUTDOWN);
53 POWER_HILOGI(FEATURE_SHUTDOWN, "Set shutdown fw start timeout.");
54
55 int rebootFlag = isReboot ? 1 : 0;
56 int ret = ioctl(fd, SET_REBOOT, &rebootFlag);
57 if (ret < 0) {
58 POWER_HILOGE(FEATURE_SHUTDOWN, "set reboot flag failed!");
59 fdsan_close_with_tag(fd, DOMAIN_FEATURE_SHUTDOWN);
60 return;
61 }
62
63 int stage = SHUT_STAGE_FRAMEWORK_START;
64 ret = ioctl(fd, SET_SHUT_STAGE, &stage);
65 if (ret < 0) {
66 POWER_HILOGE(FEATURE_SHUTDOWN, "set shut stage failed!");
67 }
68
69 POWER_HILOGI(FEATURE_SHUTDOWN, "Set shutdown timeout mechanism started.");
70 fdsan_close_with_tag(fd, DOMAIN_FEATURE_SHUTDOWN);
71
72 return;
73 }
74
Shutdown(string_view reason)75 void Shutdown(string_view reason)
76 {
77 SetFrameworkBootStage(false);
78 POWER_HILOGD(FEATURE_SHUTDOWN, "reboot: %{public}d, reason: %{public}s", false, reason.c_str());
79 PowerErrors code = g_powerMgrClient.ShutDownDevice(std::string(reason));
80 if (code != PowerErrors::ERR_OK && code != PowerErrors::ERR_FAILURE) {
81 taihe::set_business_error(static_cast<int32_t>(code), g_errorTable[code]);
82 }
83 }
84
Reboot(string_view reason)85 void Reboot(string_view reason)
86 {
87 SetFrameworkBootStage(true);
88 POWER_HILOGD(FEATURE_SHUTDOWN, "reboot: %{public}d, reason: %{public}s", true, reason.c_str());
89 PowerErrors code = g_powerMgrClient.RebootDevice(std::string(reason));
90 if (code != PowerErrors::ERR_OK && code != PowerErrors::ERR_FAILURE) {
91 taihe::set_business_error(static_cast<int32_t>(code), g_errorTable[code]);
92 }
93 }
94
IsActive()95 bool IsActive()
96 {
97 return g_powerMgrClient.IsScreenOn();
98 }
99
Wakeup(string_view detail)100 void Wakeup(string_view detail)
101 {
102 POWER_HILOGD(FEATURE_WAKEUP, "Wakeup type: APPLICATION, reason: %{public}s", detail.c_str());
103 int32_t apiVersion = AppManagerUtils::GetApiTargetVersion();
104 PowerErrors code = g_powerMgrClient.WakeupDevice(
105 WakeupDeviceType::WAKEUP_DEVICE_APPLICATION, std::string(detail), std::to_string(apiVersion));
106 if (code != PowerErrors::ERR_OK && code != PowerErrors::ERR_FAILURE) {
107 taihe::set_business_error(static_cast<int32_t>(code), g_errorTable[code]);
108 }
109 }
110
Suspend(optional_view<bool> isImmediate)111 void Suspend(optional_view<bool> isImmediate)
112 {
113 bool isForce = isImmediate.value_or(false);
114
115 PowerErrors code;
116 int32_t apiVersion = AppManagerUtils::GetApiTargetVersion();
117 if (isForce) {
118 code = g_powerMgrClient.ForceSuspendDevice(std::to_string(apiVersion));
119 } else {
120 code = g_powerMgrClient.SuspendDevice(
121 SuspendDeviceType::SUSPEND_DEVICE_REASON_APPLICATION, false, std::to_string(apiVersion));
122 }
123 if (code != PowerErrors::ERR_OK && code != PowerErrors::ERR_FAILURE) {
124 POWER_HILOGE(FEATURE_SUSPEND, "Suspend Device fail, isForce:%{public}d", isForce);
125 taihe::set_business_error(static_cast<int32_t>(code), g_errorTable[code]);
126 }
127 }
128
GetPowerMode()129 DevicePowerMode GetPowerMode()
130 {
131 PowerMode mode = g_powerMgrClient.GetDeviceMode();
132 DevicePowerMode deviceMode(DevicePowerMode::key_t::MODE_NORMAL);
133 switch (mode) {
134 case PowerMode::NORMAL_MODE:
135 deviceMode = DevicePowerMode::key_t::MODE_NORMAL;
136 break;
137 case PowerMode::POWER_SAVE_MODE:
138 deviceMode = DevicePowerMode::key_t::MODE_POWER_SAVE;
139 break;
140 case PowerMode::PERFORMANCE_MODE:
141 deviceMode = DevicePowerMode::key_t::MODE_PERFORMANCE;
142 break;
143 case PowerMode::EXTREME_POWER_SAVE_MODE:
144 deviceMode = DevicePowerMode::key_t::MODE_EXTREME_POWER_SAVE;
145 break;
146 default:
147 POWER_HILOGE(FEATURE_POWER_MODE, "Unknown mode");
148 }
149 return deviceMode;
150 }
151
SetPowerModeSync(DevicePowerMode mode)152 void SetPowerModeSync(DevicePowerMode mode)
153 {
154 PowerErrors code = g_powerMgrClient.SetDeviceMode(PowerMode(static_cast<uint32_t>(mode)));
155 if (code != PowerErrors::ERR_OK && code != PowerErrors::ERR_FAILURE) {
156 taihe::set_business_error(static_cast<int32_t>(code), g_errorTable[code]);
157 }
158 }
159
IsStandby()160 bool IsStandby()
161 {
162 bool isStandby = false;
163 PowerErrors code = g_powerMgrClient.IsStandby(isStandby);
164 if (code != PowerErrors::ERR_OK && code != PowerErrors::ERR_FAILURE) {
165 taihe::set_business_error(static_cast<int32_t>(code), g_errorTable[code]);
166 }
167 return isStandby;
168 }
169
Hibernate(bool clearMemory)170 void Hibernate(bool clearMemory)
171 {
172 int32_t apiVersion = AppManagerUtils::GetApiTargetVersion();
173 PowerErrors code = g_powerMgrClient.Hibernate(clearMemory, "", std::to_string(apiVersion));
174 if (code != PowerErrors::ERR_OK && code != PowerErrors::ERR_FAILURE) {
175 POWER_HILOGE(FEATURE_WAKEUP, "Hibernate failed.");
176 taihe::set_business_error(static_cast<int32_t>(code), g_errorTable[code]);
177 }
178 }
179
SetScreenOffTime(int64_t timeout)180 void SetScreenOffTime(int64_t timeout)
181 {
182 if (timeout == 0 || (timeout < 0 && timeout != RESTORE_DEFAULT_SCREENOFF_TIME)) {
183 POWER_HILOGE(FEATURE_WAKEUP, "timeout is not right.");
184 taihe::set_business_error(
185 static_cast<int32_t>(PowerErrors::ERR_PARAM_INVALID), g_errorTable[PowerErrors::ERR_PARAM_INVALID]);
186 }
187
188 PowerErrors code;
189 int32_t apiVersion = AppManagerUtils::GetApiTargetVersion();
190 if (timeout == RESTORE_DEFAULT_SCREENOFF_TIME) {
191 code = g_powerMgrClient.RestoreScreenOffTime(std::to_string(apiVersion));
192 } else {
193 code = g_powerMgrClient.OverrideScreenOffTime(timeout, std::to_string(apiVersion));
194 }
195 if (code != PowerErrors::ERR_OK && code != PowerErrors::ERR_FAILURE) {
196 POWER_HILOGE(FEATURE_WAKEUP, "SetScreenOffTime failed.");
197 taihe::set_business_error(static_cast<int32_t>(code), g_errorTable[code]);
198 }
199 }
200 } // namespace
201
202 // Since these macros are auto-generate, lint will cause false positive
203 // NOLINTBEGIN
204 TH_EXPORT_CPP_API_Shutdown(Shutdown);
205 TH_EXPORT_CPP_API_Reboot(Reboot);
206 TH_EXPORT_CPP_API_IsActive(IsActive);
207 TH_EXPORT_CPP_API_Wakeup(Wakeup);
208 TH_EXPORT_CPP_API_Suspend(Suspend);
209 TH_EXPORT_CPP_API_GetPowerMode(GetPowerMode);
210 TH_EXPORT_CPP_API_SetPowerModeSync(SetPowerModeSync);
211 TH_EXPORT_CPP_API_IsStandby(IsStandby);
212 TH_EXPORT_CPP_API_Hibernate(Hibernate);
213 TH_EXPORT_CPP_API_SetScreenOffTime(SetScreenOffTime);
214 // NOLINTEND