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