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_time.h"
22 #include "power_mgr_factory.h"
23 #include "screen_manager_lite.h"
24 #include "parameters.h"
25
26 #include <algorithm>
27 #include <cinttypes>
28 #include <common_event_data.h>
29 #include <common_event_manager.h>
30 #include <common_event_publish_info.h>
31 #include <common_event_support.h>
32 #include <datetime_ex.h>
33 #include <future>
34 #ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
35 #include <hisysevent.h>
36 #endif
37 #include <thread>
38 #include <dlfcn.h>
39 #include <fcntl.h>
40 #include <sys/ioctl.h>
41 #include <vector>
42
43 #ifdef POWER_MANAGER_POWEROFF_CHARGE
44 #include "battery_srv_client.h"
45 #endif
46
47 using namespace OHOS::AAFwk;
48 using namespace OHOS::EventFwk;
49 using namespace std;
50
51 namespace OHOS {
52 namespace PowerMgr {
53 namespace {
54 const time_t MAX_TIMEOUT_SEC = 30;
55 const std::string REASON_POWEROFF_CHARGE_DISABLE = "POWEROFF_CHARGE_DISABLE";
56 #ifdef POWER_MANAGER_ENABLE_JUDGING_TAKEOVER_SHUTDOWN
57 const vector<string> REASONS_DISABLE_TAKE_OVER = {"LowCapacity", "HibernateFail"};
58 #endif
59
60 enum PowerEventType {
61 DEFAULT = 0,
62 REBOOT = 1,
63 SHUTDOWN = 2,
64 SUSPEND = 3,
65 HIBERNATE = 4
66 };
67 }
68
ShutdownController()69 ShutdownController::ShutdownController() : started_(false)
70 {
71 POWER_HILOGD(FEATURE_SHUTDOWN, "Instance create");
72 devicePowerAction_ = PowerMgrFactory::GetDevicePowerAction();
73 deviceStateAction_ = PowerMgrFactory::GetDeviceStateAction();
74 takeoverShutdownCallbackHolder_ = new ShutdownCallbackHolder();
75 asyncShutdownCallbackHolder_ = new ShutdownCallbackHolder();
76 syncShutdownCallbackHolder_ = new ShutdownCallbackHolder();
77 }
78
Reboot(const std::string & reason)79 void ShutdownController::Reboot(const std::string& reason)
80 {
81 RebootOrShutdown(reason, true);
82 }
83
Shutdown(const std::string & reason)84 void ShutdownController::Shutdown(const std::string& reason)
85 {
86 RebootOrShutdown(reason, false);
87 }
88
IsShuttingDown()89 bool ShutdownController::IsShuttingDown()
90 {
91 return started_;
92 }
93
94 #ifdef POWER_MANAGER_POWEROFF_CHARGE
IsNeedWritePoweroffChargeFlag(const std::string & reason)95 static bool IsNeedWritePoweroffChargeFlag(const std::string& reason)
96 {
97 if (reason == REASON_POWEROFF_CHARGE_DISABLE) {
98 return false;
99 }
100 auto& batterySvcClient = BatterySrvClient::GetInstance();
101 const auto pluggedType = batterySvcClient.GetPluggedType();
102 POWER_HILOGI(FEATURE_SHUTDOWN, "pluggedType : %{public}u", pluggedType);
103 return (pluggedType == BatteryPluggedType::PLUGGED_TYPE_AC) ||
104 (pluggedType == BatteryPluggedType::PLUGGED_TYPE_USB) ||
105 (pluggedType == BatteryPluggedType::PLUGGED_TYPE_WIRELESS);
106 }
107
108 static const char* POWER_CHARGE_EXTENSION_PATH = "libpower_charge_ext.z.so";
109 static const char* WRITE_POWER_OFF_CHARGE_FLAG_FUNC = "WritePoweroffChargeFlag";
110 typedef void(*Func)();
111
WritePoweroffChargeFlag()112 static void WritePoweroffChargeFlag()
113 {
114 POWER_HILOGI(FEATURE_SHUTDOWN, "enter WritePoweroffChargeFlag");
115 void *handler = dlopen(POWER_CHARGE_EXTENSION_PATH, RTLD_LAZY | RTLD_NODELETE);
116 if (handler == nullptr) {
117 POWER_HILOGE(FEATURE_SHUTDOWN, "Dlopen failed, reason : %{public}s", dlerror());
118 return;
119 }
120
121 Func writePoweroffChargeFlag = (Func)dlsym(handler, WRITE_POWER_OFF_CHARGE_FLAG_FUNC);
122 if (writePoweroffChargeFlag == nullptr) {
123 POWER_HILOGE(FEATURE_SHUTDOWN, "find function failed, reason : %{public}s", dlerror());
124 dlclose(handler);
125 return;
126 }
127 writePoweroffChargeFlag();
128 dlclose(handler);
129 }
130 #endif
131
SetFrameworkFinishBootStage(void)132 static void SetFrameworkFinishBootStage(void)
133 {
134 int fd = open("/dev/bbox", O_WRONLY);
135 if (fd < 0) {
136 POWER_HILOGE(FEATURE_SHUTDOWN, "open /dev/bbox failed!");
137 return;
138 }
139 int stage = SHUT_STAGE_FRAMEWORK_FINISH;
140 int ret = ioctl(fd, SET_SHUT_STAGE, &stage);
141 if (ret < 0) {
142 POWER_HILOGE(FEATURE_SHUTDOWN, "set shut stage failed!");
143 }
144 close(fd);
145 return;
146 }
147
RebootOrShutdown(const std::string & reason,bool isReboot)148 void ShutdownController::RebootOrShutdown(const std::string& reason, bool isReboot)
149 {
150 if (started_) {
151 POWER_HILOGW(FEATURE_SHUTDOWN, "Shutdown is already running");
152 return;
153 }
154 started_ = true;
155 bool isTakeOver = TakeOverShutdownAction(reason, isReboot);
156 if (isTakeOver) {
157 started_ = false;
158 return;
159 }
160 POWER_KHILOGI(FEATURE_SHUTDOWN, "Start to detach shutdown thread");
161 if (reason != "test_case") {
162 SetFrameworkFinishBootStage();
163 }
164 #ifdef HAS_HIVIEWDFX_HISYSEVENT_PART
165 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::POWER, "STATE", HiviewDFX::HiSysEvent::EventType::STATISTIC,
166 "STATE", static_cast<uint32_t>(PowerState::SHUTDOWN));
167 #endif
168 PublishShutdownEvent();
169 std::string actionTimeStr = std::to_string(GetCurrentRealTimeMs());
170 PowerEventType eventType = isReboot ? PowerEventType::REBOOT : PowerEventType::SHUTDOWN;
171 system::SetParameter("persist.dfx.eventtype", to_string(eventType));
172 TriggerSyncShutdownCallback(isReboot);
173 actionTimeStr = actionTimeStr + "," + std::to_string(GetCurrentRealTimeMs());
174 TurnOffScreen();
175 actionTimeStr = actionTimeStr + "," + std::to_string(GetCurrentRealTimeMs());
176 system::SetParameter("persist.dfx.shutdownactiontime", actionTimeStr);
177 make_unique<thread>([=] {
178 Prepare(isReboot);
179 POWER_HILOGI(FEATURE_SHUTDOWN, "reason = %{public}s, reboot = %{public}d", reason.c_str(), isReboot);
180
181 #ifdef POWER_MANAGER_POWEROFF_CHARGE
182 if (IsNeedWritePoweroffChargeFlag(reason)) {
183 WritePoweroffChargeFlag();
184 }
185 #endif
186
187 if (devicePowerAction_ != nullptr) {
188 std::string shutdownDeviceTime = std::to_string(GetCurrentRealTimeMs());
189 system::SetParameter("persist.dfx.shutdowncompletetime", shutdownDeviceTime);
190 isReboot ? devicePowerAction_->Reboot(reason) : devicePowerAction_->Shutdown(reason);
191 }
192 started_ = false;
193 })->detach();
194 }
195
Prepare(bool isReboot)196 void ShutdownController::Prepare(bool isReboot)
197 {
198 auto callbackStart = [&]() {
199 TriggerAsyncShutdownCallback(isReboot);
200 };
201
202 packaged_task<void()> callbackTask(callbackStart);
203 future<void> fut = callbackTask.get_future();
204 make_unique<thread>(std::move(callbackTask))->detach();
205
206 POWER_HILOGI(FEATURE_SHUTDOWN, "Waiting for the callback execution complete...");
207 future_status status = fut.wait_for(std::chrono::seconds(MAX_TIMEOUT_SEC));
208 if (status == future_status::timeout) {
209 POWER_HILOGW(FEATURE_SHUTDOWN, "Shutdown callback execution timeout");
210 }
211 POWER_HILOGI(FEATURE_SHUTDOWN, "The callback execution is complete");
212 }
213
PublishShutdownEvent() const214 void ShutdownController::PublishShutdownEvent() const
215 {
216 POWER_KHILOGI(FEATURE_SHUTDOWN, "Start of publishing shutdown event");
217 CommonEventPublishInfo publishInfo;
218 publishInfo.SetOrdered(false);
219 IntentWant shutdownWant;
220 shutdownWant.SetAction(CommonEventSupport::COMMON_EVENT_SHUTDOWN);
221 CommonEventData event(shutdownWant);
222 if (!CommonEventManager::PublishCommonEvent(event, publishInfo, nullptr)) {
223 POWER_KHILOGE(FEATURE_SHUTDOWN, "Publish the shutdown event fail");
224 return;
225 }
226 POWER_KHILOGI(FEATURE_SHUTDOWN, "End of publishing shutdown event");
227 }
228
TurnOffScreen()229 void ShutdownController::TurnOffScreen()
230 {
231 POWER_HILOGD(FEATURE_SHUTDOWN, "Turn off screen before shutdown");
232 bool ret = Rosen::ScreenManagerLite::GetInstance().SetScreenPowerForAll(Rosen::ScreenPowerState::POWER_OFF,
233 Rosen::PowerStateChangeReason::STATE_CHANGE_REASON_SHUT_DOWN);
234 POWER_HILOGI(FEATURE_SHUTDOWN, "Turn off screen before shutting down, ret = %{public}d", ret);
235 }
236
AddCallback(const sptr<ITakeOverShutdownCallback> & callback,ShutdownPriority priority)237 void ShutdownController::AddCallback(const sptr<ITakeOverShutdownCallback>& callback, ShutdownPriority priority)
238 {
239 RETURN_IF(callback->AsObject() == nullptr)
240 takeoverShutdownCallbackHolder_->AddCallback(callback->AsObject(), priority);
241 POWER_HILOGI(FEATURE_SHUTDOWN,
242 "takeover shutdown callback added, priority=%{public}u, pid=%{public}d, uid=%{public}d", priority,
243 IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
244 }
245
AddCallback(const sptr<IAsyncShutdownCallback> & callback,ShutdownPriority priority)246 void ShutdownController::AddCallback(const sptr<IAsyncShutdownCallback>& callback, ShutdownPriority priority)
247 {
248 RETURN_IF(callback->AsObject() == nullptr)
249 asyncShutdownCallbackHolder_->AddCallback(callback->AsObject(), priority);
250 POWER_HILOGI(FEATURE_SHUTDOWN,
251 "async shutdown callback added, priority=%{public}u, pid=%{public}d, uid=%{public}d", priority,
252 IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
253 }
254
AddCallback(const sptr<ISyncShutdownCallback> & callback,ShutdownPriority priority)255 void ShutdownController::AddCallback(const sptr<ISyncShutdownCallback>& callback, ShutdownPriority priority)
256 {
257 RETURN_IF(callback->AsObject() == nullptr)
258 syncShutdownCallbackHolder_->AddCallback(callback->AsObject(), priority);
259 POWER_HILOGI(FEATURE_SHUTDOWN,
260 "sync shutdown callback added, priority=%{public}u, pid=%{public}d, uid=%{public}d", priority,
261 IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
262 }
263
RemoveCallback(const sptr<ITakeOverShutdownCallback> & callback)264 void ShutdownController::RemoveCallback(const sptr<ITakeOverShutdownCallback>& callback)
265 {
266 RETURN_IF(callback->AsObject() == nullptr)
267 takeoverShutdownCallbackHolder_->RemoveCallback(callback->AsObject());
268 POWER_HILOGI(FEATURE_SHUTDOWN, "takeover shutdown callback removed, pid=%{public}d, uid=%{public}d",
269 IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
270 }
271
RemoveCallback(const sptr<IAsyncShutdownCallback> & callback)272 void ShutdownController::RemoveCallback(const sptr<IAsyncShutdownCallback>& callback)
273 {
274 RETURN_IF(callback->AsObject() == nullptr)
275 asyncShutdownCallbackHolder_->RemoveCallback(callback->AsObject());
276 POWER_HILOGI(FEATURE_SHUTDOWN, "async shutdown callback removed, pid=%{public}d, uid=%{public}d",
277 IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
278 }
279
RemoveCallback(const sptr<ISyncShutdownCallback> & callback)280 void ShutdownController::RemoveCallback(const sptr<ISyncShutdownCallback>& callback)
281 {
282 RETURN_IF(callback->AsObject() == nullptr)
283 syncShutdownCallbackHolder_->RemoveCallback(callback->AsObject());
284 POWER_HILOGI(FEATURE_SHUTDOWN, "sync shutdown callback removed, pid=%{public}d, uid=%{public}d",
285 IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
286 }
287
TriggerTakeOverShutdownCallback(const TakeOverInfo & info)288 bool ShutdownController::TriggerTakeOverShutdownCallback(const TakeOverInfo& info)
289 {
290 bool isTakeover = false;
291 auto highPriorityCallbacks = takeoverShutdownCallbackHolder_->GetHighPriorityCallbacks();
292 isTakeover = TriggerTakeOverShutdownCallbackInner(highPriorityCallbacks, info);
293 RETURN_IF_WITH_RET(isTakeover, true);
294 auto defaultPriorityCallbacks = takeoverShutdownCallbackHolder_->GetDefaultPriorityCallbacks();
295 isTakeover = TriggerTakeOverShutdownCallbackInner(defaultPriorityCallbacks, info);
296 RETURN_IF_WITH_RET(isTakeover, true);
297 auto lowPriorityCallbacks = takeoverShutdownCallbackHolder_->GetLowPriorityCallbacks();
298 isTakeover = TriggerTakeOverShutdownCallbackInner(lowPriorityCallbacks, info);
299 return isTakeover;
300 }
301
TriggerTakeOverHibernateCallback(const TakeOverInfo & info)302 bool ShutdownController::TriggerTakeOverHibernateCallback(const TakeOverInfo& info)
303 {
304 bool isTakeover = false;
305 auto highPriorityCallbacks = takeoverShutdownCallbackHolder_->GetHighPriorityCallbacks();
306 isTakeover = TriggerTakeOverHibernateCallbackInner(highPriorityCallbacks, info);
307 RETURN_IF_WITH_RET(isTakeover, true);
308 auto defaultPriorityCallbacks = takeoverShutdownCallbackHolder_->GetDefaultPriorityCallbacks();
309 isTakeover = TriggerTakeOverHibernateCallbackInner(defaultPriorityCallbacks, info);
310 RETURN_IF_WITH_RET(isTakeover, true);
311 auto lowPriorityCallbacks = takeoverShutdownCallbackHolder_->GetLowPriorityCallbacks();
312 isTakeover = TriggerTakeOverHibernateCallbackInner(lowPriorityCallbacks, info);
313 return isTakeover;
314 }
315
TriggerTakeOverShutdownCallbackInner(std::set<sptr<IRemoteObject>> & callbacks,const TakeOverInfo & info)316 bool ShutdownController::TriggerTakeOverShutdownCallbackInner(
317 std::set<sptr<IRemoteObject>>& callbacks, const TakeOverInfo& info)
318 {
319 bool isTakeover = false;
320 for (const auto& obj : callbacks) {
321 auto callback = iface_cast<ITakeOverShutdownCallback>(obj);
322 isTakeover = callback->OnTakeOverShutdown(info);
323 }
324 return isTakeover;
325 }
326
TriggerTakeOverHibernateCallbackInner(std::set<sptr<IRemoteObject>> & callbacks,const TakeOverInfo & info)327 bool ShutdownController::TriggerTakeOverHibernateCallbackInner(
328 std::set<sptr<IRemoteObject>>& callbacks, const TakeOverInfo& info)
329 {
330 bool isTakeover = false;
331 for (const auto& obj : callbacks) {
332 auto callback = iface_cast<ITakeOverShutdownCallback>(obj);
333 isTakeover = callback->OnTakeOverHibernate(info);
334 }
335 return isTakeover;
336 }
337
TriggerAsyncShutdownCallback(bool isReboot)338 void ShutdownController::TriggerAsyncShutdownCallback(bool isReboot)
339 {
340 auto highPriorityCallbacks = asyncShutdownCallbackHolder_->GetHighPriorityCallbacks();
341 TriggerAsyncShutdownCallbackInner(highPriorityCallbacks, isReboot);
342 auto defaultPriorityCallbacks = asyncShutdownCallbackHolder_->GetDefaultPriorityCallbacks();
343 TriggerAsyncShutdownCallbackInner(defaultPriorityCallbacks, isReboot);
344 auto lowPriorityCallbacks = asyncShutdownCallbackHolder_->GetLowPriorityCallbacks();
345 TriggerAsyncShutdownCallbackInner(lowPriorityCallbacks, isReboot);
346 }
347
TriggerAsyncShutdownCallbackInner(std::set<sptr<IRemoteObject>> & callbacks,bool isReboot)348 void ShutdownController::TriggerAsyncShutdownCallbackInner(std::set<sptr<IRemoteObject>>& callbacks, bool isReboot)
349 {
350 for (auto &obj : callbacks) {
351 sptr<IAsyncShutdownCallback> callback = iface_cast<IAsyncShutdownCallback>(obj);
352 if (callback != nullptr) {
353 int64_t start = GetTickCount();
354 callback->OnAsyncShutdown();
355 callback->OnAsyncShutdownOrReboot(isReboot);
356 int64_t cost = GetTickCount() - start;
357 POWER_HILOGD(FEATURE_SHUTDOWN, "Callback finished, cost=%{public}" PRId64 "", cost);
358 }
359 }
360 }
361
TriggerSyncShutdownCallback(bool isReboot)362 void ShutdownController::TriggerSyncShutdownCallback(bool isReboot)
363 {
364 auto highPriorityCallbacks = syncShutdownCallbackHolder_->GetHighPriorityCallbacks();
365 TriggerSyncShutdownCallbackInner(highPriorityCallbacks, isReboot);
366 auto defaultPriorityCallbacks = syncShutdownCallbackHolder_->GetDefaultPriorityCallbacks();
367 TriggerSyncShutdownCallbackInner(defaultPriorityCallbacks, isReboot);
368 auto lowPriorityCallbacks = syncShutdownCallbackHolder_->GetLowPriorityCallbacks();
369 TriggerSyncShutdownCallbackInner(lowPriorityCallbacks, isReboot);
370 }
371
TriggerSyncShutdownCallbackInner(std::set<sptr<IRemoteObject>> & callbacks,bool isReboot)372 void ShutdownController::TriggerSyncShutdownCallbackInner(std::set<sptr<IRemoteObject>>& callbacks, bool isReboot)
373 {
374 for (auto &obj : callbacks) {
375 auto pidUid = syncShutdownCallbackHolder_->FindCallbackPidUid(obj);
376 sptr<ISyncShutdownCallback> callback = iface_cast<ISyncShutdownCallback>(obj);
377 if (callback != nullptr) {
378 int64_t start = GetTickCount();
379 POWER_KHILOGI(
380 FEATURE_SHUTDOWN, "calling callback pid=%{public}d uid=%{public}d", pidUid.first, pidUid.second);
381 callback->OnSyncShutdown();
382 callback->OnSyncShutdownOrReboot(isReboot);
383 int64_t cost = GetTickCount() - start;
384 POWER_KHILOGI(FEATURE_SHUTDOWN, "Callback finished, cost=%{public}" PRId64 "", cost);
385 }
386 }
387 }
388
TakeOverShutdownAction(const std::string & reason,bool isReboot)389 bool ShutdownController::TakeOverShutdownAction(const std::string& reason, bool isReboot)
390 {
391 if (AllowedToBeTakenOver(reason)) {
392 return TriggerTakeOverShutdownCallback(TakeOverInfo(reason, isReboot));
393 }
394 return false;
395 }
396
AllowedToBeTakenOver(const std::string & reason) const397 bool ShutdownController::AllowedToBeTakenOver(const std::string& reason) const
398 {
399 #ifdef POWER_MANAGER_ENABLE_JUDGING_TAKEOVER_SHUTDOWN
400 if (find(REASONS_DISABLE_TAKE_OVER.cbegin(), REASONS_DISABLE_TAKE_OVER.cend(), reason)
401 != REASONS_DISABLE_TAKE_OVER.cend()) {
402 POWER_HILOGI(FEATURE_SHUTDOWN, "forbid to takeover shutdown, reason:%{public}s", reason.c_str());
403 return false;
404 }
405 return true;
406 #endif
407 (void)reason;
408 return true;
409 }
410 } // namespace PowerMgr
411 } // namespace OHOS
412