• 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 #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