1 /*
2 * Copyright (c) 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 "shutdown_controller.h"
17
18 #include "ipc_skeleton.h"
19 #include "iremote_broker.h"
20 #include "power_common.h"
21 #include "power_mgr_factory.h"
22 #include "screen_manager_lite.h"
23 #include "parameters.h"
24
25 #include <algorithm>
26 #include <cinttypes>
27 #include <common_event_data.h>
28 #include <common_event_manager.h>
29 #include <common_event_publish_info.h>
30 #include <common_event_support.h>
31 #include <datetime_ex.h>
32 #include <future>
33 #include <hisysevent.h>
34 #include <thread>
35 #include <dlfcn.h>
36
37 #ifdef POWER_MANAGER_POWEROFF_CHARGE
38 #include "battery_srv_client.h"
39 #endif
40
41 using namespace OHOS::AAFwk;
42 using namespace OHOS::EventFwk;
43 using namespace std;
44
45 namespace OHOS {
46 namespace PowerMgr {
47 namespace {
48 const time_t MAX_TIMEOUT_SEC = 30;
49 const std::string REASON_POWEROFF_CHARGE_DISABLE = "POWEROFF_CHARGE_DISABLE";
50 }
ShutdownController()51 ShutdownController::ShutdownController() : started_(false)
52 {
53 POWER_HILOGD(FEATURE_SHUTDOWN, "Instance create");
54 devicePowerAction_ = PowerMgrFactory::GetDevicePowerAction();
55 deviceStateAction_ = PowerMgrFactory::GetDeviceStateAction();
56 takeoverShutdownCallbackHolder_ = new ShutdownCallbackHolder();
57 asyncShutdownCallbackHolder_ = new ShutdownCallbackHolder();
58 syncShutdownCallbackHolder_ = new ShutdownCallbackHolder();
59 }
60
Reboot(const std::string & reason)61 void ShutdownController::Reboot(const std::string& reason)
62 {
63 RebootOrShutdown(reason, true);
64 }
65
Shutdown(const std::string & reason)66 void ShutdownController::Shutdown(const std::string& reason)
67 {
68 RebootOrShutdown(reason, false);
69 }
70
IsShuttingDown()71 bool ShutdownController::IsShuttingDown()
72 {
73 return started_;
74 }
75
76 #ifdef POWER_MANAGER_POWEROFF_CHARGE
IsNeedWritePoweroffChargeFlag(const std::string & reason)77 static bool IsNeedWritePoweroffChargeFlag(const std::string& reason)
78 {
79 if (reason == REASON_POWEROFF_CHARGE_DISABLE) {
80 return false;
81 }
82 auto& batterySvcClient = BatterySrvClient::GetInstance();
83 const auto pluggedType = batterySvcClient.GetPluggedType();
84 POWER_HILOGI(FEATURE_SHUTDOWN, "pluggedType : %{public}u", pluggedType);
85 return (pluggedType == BatteryPluggedType::PLUGGED_TYPE_AC) ||
86 (pluggedType == BatteryPluggedType::PLUGGED_TYPE_USB) ||
87 (pluggedType == BatteryPluggedType::PLUGGED_TYPE_WIRELESS);
88 }
89
90 static const char* POWER_CHARGE_EXTENSION_PATH = "system/lib64/libpower_charge_ext.z.so";
91 static const char* WRITE_POWER_OFF_CHARGE_FLAG_FUNC = "WritePoweroffChargeFlag";
92 typedef void(*Func)();
93
WritePoweroffChargeFlag()94 static void WritePoweroffChargeFlag()
95 {
96 POWER_HILOGI(FEATURE_SHUTDOWN, "enter WritePoweroffChargeFlag");
97 void *handler = dlopen(POWER_CHARGE_EXTENSION_PATH, RTLD_LAZY | RTLD_NODELETE);
98 if (handler == nullptr) {
99 POWER_HILOGE(FEATURE_SHUTDOWN, "Dlopen failed, reason : %{public}s", dlerror());
100 return;
101 }
102
103 Func writePoweroffChargeFlag = (Func)dlsym(handler, WRITE_POWER_OFF_CHARGE_FLAG_FUNC);
104 if (writePoweroffChargeFlag == nullptr) {
105 POWER_HILOGE(FEATURE_SHUTDOWN, "find function failed, reason : %{public}s", dlerror());
106 dlclose(handler);
107 return;
108 }
109 writePoweroffChargeFlag();
110 dlclose(handler);
111 }
112 #endif
113
RebootOrShutdown(const std::string & reason,bool isReboot)114 void ShutdownController::RebootOrShutdown(const std::string& reason, bool isReboot)
115 {
116 if (started_) {
117 POWER_HILOGW(FEATURE_SHUTDOWN, "Shutdown is already running");
118 return;
119 }
120 started_ = true;
121 bool isTakeOver = TriggerTakeOverShutdownCallback(isReboot);
122 if (isTakeOver) {
123 started_ = false;
124 return;
125 }
126 POWER_HILOGI(FEATURE_SHUTDOWN, "Start to detach shutdown thread");
127 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER, "STATE", HiviewDFX::HiSysEvent::EventType::STATISTIC,
128 "STATE", static_cast<uint32_t>(PowerState::SHUTDOWN));
129 PublishShutdownEvent();
130 TriggerSyncShutdownCallback(isReboot);
131 TurnOffScreen();
132 make_unique<thread>([=] {
133 Prepare(isReboot);
134 POWER_HILOGI(FEATURE_SHUTDOWN, "reason = %{public}s, reboot = %{public}d", reason.c_str(), isReboot);
135
136 #ifdef POWER_MANAGER_POWEROFF_CHARGE
137 if (IsNeedWritePoweroffChargeFlag(reason)) {
138 WritePoweroffChargeFlag();
139 }
140 #endif
141
142 if (devicePowerAction_ != nullptr) {
143 isReboot ? devicePowerAction_->Reboot(reason) : devicePowerAction_->Shutdown(reason);
144 }
145 started_ = false;
146 })->detach();
147 }
148
Prepare(bool isReboot)149 void ShutdownController::Prepare(bool isReboot)
150 {
151 auto callbackStart = [&]() {
152 TriggerAsyncShutdownCallback(isReboot);
153 };
154
155 packaged_task<void()> callbackTask(callbackStart);
156 future<void> fut = callbackTask.get_future();
157 make_unique<thread>(std::move(callbackTask))->detach();
158
159 POWER_HILOGI(FEATURE_SHUTDOWN, "Waiting for the callback execution complete...");
160 future_status status = fut.wait_for(std::chrono::seconds(MAX_TIMEOUT_SEC));
161 if (status == future_status::timeout) {
162 POWER_HILOGW(FEATURE_SHUTDOWN, "Shutdown callback execution timeout");
163 }
164 POWER_HILOGI(FEATURE_SHUTDOWN, "The callback execution is complete");
165 }
166
PublishShutdownEvent() const167 void ShutdownController::PublishShutdownEvent() const
168 {
169 POWER_HILOGD(FEATURE_SHUTDOWN, "Start of publishing shutdown event");
170 CommonEventPublishInfo publishInfo;
171 publishInfo.SetOrdered(false);
172 IntentWant shutdownWant;
173 shutdownWant.SetAction(CommonEventSupport::COMMON_EVENT_SHUTDOWN);
174 CommonEventData event(shutdownWant);
175 if (!CommonEventManager::PublishCommonEvent(event, publishInfo, nullptr)) {
176 POWER_HILOGE(FEATURE_SHUTDOWN, "Publish the shutdown event fail");
177 return;
178 }
179 POWER_HILOGD(FEATURE_SHUTDOWN, "End of publishing shutdown event");
180 }
181
TurnOffScreen()182 void ShutdownController::TurnOffScreen()
183 {
184 POWER_HILOGD(FEATURE_SHUTDOWN, "Turn off screen before shutdown");
185 bool ret = Rosen::ScreenManagerLite::GetInstance().SetScreenPowerForAll(Rosen::ScreenPowerState::POWER_OFF,
186 Rosen::PowerStateChangeReason::STATE_CHANGE_REASON_SHUT_DOWN);
187 POWER_HILOGI(FEATURE_SHUTDOWN, "Turn off screen before shutting down, ret = %{public}d", ret);
188 }
189
AddCallback(const sptr<ITakeOverShutdownCallback> & callback,ShutdownPriority priority)190 void ShutdownController::AddCallback(const sptr<ITakeOverShutdownCallback>& callback, ShutdownPriority priority)
191 {
192 RETURN_IF(callback->AsObject() == nullptr)
193 takeoverShutdownCallbackHolder_->AddCallback(callback->AsObject(), priority);
194 POWER_HILOGI(FEATURE_SHUTDOWN,
195 "takeover shutdown callback added, priority=%{public}u, pid=%{public}d, uid=%{public}d", priority,
196 IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
197 }
198
AddCallback(const sptr<IAsyncShutdownCallback> & callback,ShutdownPriority priority)199 void ShutdownController::AddCallback(const sptr<IAsyncShutdownCallback>& callback, ShutdownPriority priority)
200 {
201 RETURN_IF(callback->AsObject() == nullptr)
202 asyncShutdownCallbackHolder_->AddCallback(callback->AsObject(), priority);
203 POWER_HILOGI(FEATURE_SHUTDOWN,
204 "async shutdown callback added, priority=%{public}u, pid=%{public}d, uid=%{public}d", priority,
205 IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
206 }
207
AddCallback(const sptr<ISyncShutdownCallback> & callback,ShutdownPriority priority)208 void ShutdownController::AddCallback(const sptr<ISyncShutdownCallback>& callback, ShutdownPriority priority)
209 {
210 RETURN_IF(callback->AsObject() == nullptr)
211 syncShutdownCallbackHolder_->AddCallback(callback->AsObject(), priority);
212 POWER_HILOGI(FEATURE_SHUTDOWN,
213 "sync shutdown callback added, priority=%{public}u, pid=%{public}d, uid=%{public}d", priority,
214 IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
215 }
216
RemoveCallback(const sptr<ITakeOverShutdownCallback> & callback)217 void ShutdownController::RemoveCallback(const sptr<ITakeOverShutdownCallback>& callback)
218 {
219 RETURN_IF(callback->AsObject() == nullptr)
220 takeoverShutdownCallbackHolder_->RemoveCallback(callback->AsObject());
221 POWER_HILOGI(FEATURE_SHUTDOWN, "takeover shutdown callback removed, pid=%{public}d, uid=%{public}d",
222 IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
223 }
224
RemoveCallback(const sptr<IAsyncShutdownCallback> & callback)225 void ShutdownController::RemoveCallback(const sptr<IAsyncShutdownCallback>& callback)
226 {
227 RETURN_IF(callback->AsObject() == nullptr)
228 asyncShutdownCallbackHolder_->RemoveCallback(callback->AsObject());
229 POWER_HILOGI(FEATURE_SHUTDOWN, "async shutdown callback removed, pid=%{public}d, uid=%{public}d",
230 IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
231 }
232
RemoveCallback(const sptr<ISyncShutdownCallback> & callback)233 void ShutdownController::RemoveCallback(const sptr<ISyncShutdownCallback>& callback)
234 {
235 RETURN_IF(callback->AsObject() == nullptr)
236 syncShutdownCallbackHolder_->RemoveCallback(callback->AsObject());
237 POWER_HILOGI(FEATURE_SHUTDOWN, "sync shutdown callback removed, pid=%{public}d, uid=%{public}d",
238 IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
239 }
240
TriggerTakeOverShutdownCallback(bool isReboot)241 bool ShutdownController::TriggerTakeOverShutdownCallback(bool isReboot)
242 {
243 bool isTakeover = false;
244 auto highPriorityCallbacks = takeoverShutdownCallbackHolder_->GetHighPriorityCallbacks();
245 isTakeover = TriggerTakeOverShutdownCallbackInner(highPriorityCallbacks, isReboot);
246 RETURN_IF_WITH_RET(isTakeover, true);
247 auto defaultPriorityCallbacks = takeoverShutdownCallbackHolder_->GetDefaultPriorityCallbacks();
248 isTakeover = TriggerTakeOverShutdownCallbackInner(defaultPriorityCallbacks, isReboot);
249 RETURN_IF_WITH_RET(isTakeover, true);
250 auto lowPriorityCallbacks = takeoverShutdownCallbackHolder_->GetLowPriorityCallbacks();
251 isTakeover = TriggerTakeOverShutdownCallbackInner(lowPriorityCallbacks, isReboot);
252 return isTakeover;
253 }
254
TriggerTakeOverShutdownCallbackInner(std::set<sptr<IRemoteObject>> & callbacks,bool isReboot)255 bool ShutdownController::TriggerTakeOverShutdownCallbackInner(std::set<sptr<IRemoteObject>>& callbacks, bool isReboot)
256 {
257 bool isTakeover = false;
258 for (const auto& obj : callbacks) {
259 auto callback = iface_cast<ITakeOverShutdownCallback>(obj);
260 isTakeover = callback->OnTakeOverShutdown(isReboot);
261 }
262 return isTakeover;
263 }
264
TriggerAsyncShutdownCallback(bool isReboot)265 void ShutdownController::TriggerAsyncShutdownCallback(bool isReboot)
266 {
267 auto highPriorityCallbacks = asyncShutdownCallbackHolder_->GetHighPriorityCallbacks();
268 TriggerAsyncShutdownCallbackInner(highPriorityCallbacks, isReboot);
269 auto defaultPriorityCallbacks = asyncShutdownCallbackHolder_->GetDefaultPriorityCallbacks();
270 TriggerAsyncShutdownCallbackInner(defaultPriorityCallbacks, isReboot);
271 auto lowPriorityCallbacks = asyncShutdownCallbackHolder_->GetLowPriorityCallbacks();
272 TriggerAsyncShutdownCallbackInner(lowPriorityCallbacks, isReboot);
273 }
274
TriggerAsyncShutdownCallbackInner(std::set<sptr<IRemoteObject>> & callbacks,bool isReboot)275 void ShutdownController::TriggerAsyncShutdownCallbackInner(std::set<sptr<IRemoteObject>>& callbacks, bool isReboot)
276 {
277 for (auto &obj : callbacks) {
278 sptr<IAsyncShutdownCallback> callback = iface_cast<IAsyncShutdownCallback>(obj);
279 if (callback != nullptr) {
280 int64_t start = GetTickCount();
281 callback->OnAsyncShutdown();
282 callback->OnAsyncShutdownOrReboot(isReboot);
283 int64_t cost = GetTickCount() - start;
284 POWER_HILOGD(FEATURE_SHUTDOWN, "Callback finished, cost=%{public}" PRId64 "", cost);
285 }
286 }
287 }
288
TriggerSyncShutdownCallback(bool isReboot)289 void ShutdownController::TriggerSyncShutdownCallback(bool isReboot)
290 {
291 auto highPriorityCallbacks = syncShutdownCallbackHolder_->GetHighPriorityCallbacks();
292 TriggerSyncShutdownCallbackInner(highPriorityCallbacks, isReboot);
293 auto defaultPriorityCallbacks = syncShutdownCallbackHolder_->GetDefaultPriorityCallbacks();
294 TriggerSyncShutdownCallbackInner(defaultPriorityCallbacks, isReboot);
295 auto lowPriorityCallbacks = syncShutdownCallbackHolder_->GetLowPriorityCallbacks();
296 TriggerSyncShutdownCallbackInner(lowPriorityCallbacks, isReboot);
297 }
298
TriggerSyncShutdownCallbackInner(std::set<sptr<IRemoteObject>> & callbacks,bool isReboot)299 void ShutdownController::TriggerSyncShutdownCallbackInner(std::set<sptr<IRemoteObject>>& callbacks, bool isReboot)
300 {
301 for (auto &obj : callbacks) {
302 sptr<ISyncShutdownCallback> callback = iface_cast<ISyncShutdownCallback>(obj);
303 if (callback != nullptr) {
304 int64_t start = GetTickCount();
305 callback->OnSyncShutdown();
306 callback->OnSyncShutdownOrReboot(isReboot);
307 int64_t cost = GetTickCount() - start;
308 POWER_HILOGD(FEATURE_SHUTDOWN, "Callback finished, cost=%{public}" PRId64 "", cost);
309 }
310 }
311 }
312 } // namespace PowerMgr
313 } // namespace OHOS
314