• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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