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