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
23 #include <algorithm>
24 #include <cinttypes>
25 #include <common_event_data.h>
26 #include <common_event_manager.h>
27 #include <common_event_publish_info.h>
28 #include <common_event_support.h>
29 #include <datetime_ex.h>
30 #include <future>
31 #include <thread>
32
33 #ifdef POWER_MANAGER_POWEROFF_CHARGE
34 #include "battery_srv_client.h"
35 #include "v1_0/ifactory_interface.h"
36 #endif
37
38 using namespace OHOS::AAFwk;
39 using namespace OHOS::EventFwk;
40 using namespace std;
41
42 namespace OHOS {
43 namespace PowerMgr {
44 namespace {
45 const time_t MAX_TIMEOUT_SEC = 30;
46 }
ShutdownController()47 ShutdownController::ShutdownController() : started_(false)
48 {
49 POWER_HILOGD(FEATURE_SHUTDOWN, "Instance create");
50 devicePowerAction_ = PowerMgrFactory::GetDevicePowerAction();
51 deviceStateAction_ = PowerMgrFactory::GetDeviceStateAction();
52 takeoverShutdownCallbackHolder_ = new ShutdownCallbackHolder();
53 asyncShutdownCallbackHolder_ = new ShutdownCallbackHolder();
54 syncShutdownCallbackHolder_ = new ShutdownCallbackHolder();
55 }
56
Reboot(const std::string & reason)57 void ShutdownController::Reboot(const std::string& reason)
58 {
59 RebootOrShutdown(reason, true);
60 }
61
Shutdown(const std::string & reason)62 void ShutdownController::Shutdown(const std::string& reason)
63 {
64 RebootOrShutdown(reason, false);
65 }
66
IsShuttingDown()67 bool ShutdownController::IsShuttingDown()
68 {
69 return started_;
70 }
71
72 #ifdef POWER_MANAGER_POWEROFF_CHARGE
IsNeedWritePoweroffChargeFlag()73 static bool IsNeedWritePoweroffChargeFlag()
74 {
75 auto& batterySvcClient = BatterySrvClient::GetInstance();
76 const auto pluggedType = batterySvcClient.GetPluggedType();
77 POWER_HILOGI(FEATURE_SHUTDOWN, "pluggedType : %{public}u", pluggedType);
78 return (pluggedType == BatteryPluggedType::PLUGGED_TYPE_AC) ||
79 (pluggedType == BatteryPluggedType::PLUGGED_TYPE_USB) ||
80 (pluggedType == BatteryPluggedType::PLUGGED_TYPE_WIRELESS);
81 }
82
83 static const unsigned int OEMINFO_REUSED_ID_204_8K_VALID_SIZE_64_BYTE = 204;
84 static const unsigned int OEMINFO_SHUTFLAG_SUBID = 4;
85 static const char POWEROFF_CHARGE_FLAG[] = {0xAA, 0x55, 0x00, 0x00};
86
WritePoweroffChargeFlag()87 static void WritePoweroffChargeFlag()
88 {
89 auto factoryInterfaceImpl = OHOS::HDI::Factory::V1_0::IFactoryInterface::Get("factory_interface_service", false);
90 if (factoryInterfaceImpl == nullptr) {
91 POWER_HILOGE(FEATURE_SHUTDOWN, "get factory_interface_service failed");
92 return;
93 }
94
95 int ret = factoryInterfaceImpl->OeminfoWriteReused(OEMINFO_REUSED_ID_204_8K_VALID_SIZE_64_BYTE,
96 OEMINFO_SHUTFLAG_SUBID, sizeof(POWEROFF_CHARGE_FLAG), POWEROFF_CHARGE_FLAG);
97 POWER_HILOGI(FEATURE_SHUTDOWN, "write oem flag:0x55AA, result:%{public}d", ret);
98 }
99 #endif
100
RebootOrShutdown(const std::string & reason,bool isReboot)101 void ShutdownController::RebootOrShutdown(const std::string& reason, bool isReboot)
102 {
103 if (started_) {
104 POWER_HILOGW(FEATURE_SHUTDOWN, "Shutdown is already running");
105 return;
106 }
107 started_ = true;
108 bool isTakeOver = TriggerTakeOverShutdownCallback(isReboot);
109 if (isTakeOver) {
110 started_ = false;
111 return;
112 }
113 POWER_HILOGI(FEATURE_SHUTDOWN, "Start to detach shutdown thread");
114 PublishShutdownEvent();
115 TriggerSyncShutdownCallback();
116 TurnOffScreen();
117 make_unique<thread>([=] {
118 Prepare();
119 POWER_HILOGD(FEATURE_SHUTDOWN, "reason = %{public}s, reboot = %{public}d", reason.c_str(), isReboot);
120
121 #ifdef POWER_MANAGER_POWEROFF_CHARGE
122 if (IsNeedWritePoweroffChargeFlag()) {
123 WritePoweroffChargeFlag();
124 }
125 #endif
126
127 if (devicePowerAction_ != nullptr) {
128 isReboot ? devicePowerAction_->Reboot(reason) : devicePowerAction_->Shutdown(reason);
129 }
130 started_ = false;
131 })->detach();
132 }
133
Prepare()134 void ShutdownController::Prepare()
135 {
136 auto callbackStart = [&]() {
137 TriggerAsyncShutdownCallback();
138 };
139
140 packaged_task<void()> callbackTask(callbackStart);
141 future<void> fut = callbackTask.get_future();
142 make_unique<thread>(std::move(callbackTask))->detach();
143
144 POWER_HILOGI(FEATURE_SHUTDOWN, "Waiting for the callback execution complete...");
145 future_status status = fut.wait_for(std::chrono::seconds(MAX_TIMEOUT_SEC));
146 if (status == future_status::timeout) {
147 POWER_HILOGW(FEATURE_SHUTDOWN, "Shutdown callback execution timeout");
148 }
149 POWER_HILOGI(FEATURE_SHUTDOWN, "The callback execution is complete");
150 }
151
PublishShutdownEvent() const152 void ShutdownController::PublishShutdownEvent() const
153 {
154 POWER_HILOGD(FEATURE_SHUTDOWN, "Start of publishing shutdown event");
155 CommonEventPublishInfo publishInfo;
156 publishInfo.SetOrdered(false);
157 IntentWant shutdownWant;
158 shutdownWant.SetAction(CommonEventSupport::COMMON_EVENT_SHUTDOWN);
159 CommonEventData event(shutdownWant);
160 if (!CommonEventManager::PublishCommonEvent(event, publishInfo, nullptr)) {
161 POWER_HILOGE(FEATURE_SHUTDOWN, "Publish the shutdown event fail");
162 return;
163 }
164 POWER_HILOGD(FEATURE_SHUTDOWN, "End of publishing shutdown event");
165 }
166
TurnOffScreen()167 void ShutdownController::TurnOffScreen()
168 {
169 POWER_HILOGD(FEATURE_SHUTDOWN, "Turn off screen before shutdown");
170 deviceStateAction_->SetDisplayState(DisplayState::DISPLAY_OFF, StateChangeReason::STATE_CHANGE_REASON_INIT);
171 }
172
AddCallback(const sptr<ITakeOverShutdownCallback> & callback,ShutdownPriority priority)173 void ShutdownController::AddCallback(const sptr<ITakeOverShutdownCallback>& callback, ShutdownPriority priority)
174 {
175 RETURN_IF(callback->AsObject() == nullptr)
176 takeoverShutdownCallbackHolder_->AddCallback(callback->AsObject(), priority);
177 POWER_HILOGI(FEATURE_SHUTDOWN,
178 "takeover shutdown callback added, priority=%{public}u, pid=%{public}d, uid=%{public}d", priority,
179 IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
180 }
181
AddCallback(const sptr<IAsyncShutdownCallback> & callback,ShutdownPriority priority)182 void ShutdownController::AddCallback(const sptr<IAsyncShutdownCallback>& callback, ShutdownPriority priority)
183 {
184 RETURN_IF(callback->AsObject() == nullptr)
185 asyncShutdownCallbackHolder_->AddCallback(callback->AsObject(), priority);
186 POWER_HILOGI(FEATURE_SHUTDOWN,
187 "async shutdown callback added, priority=%{public}u, pid=%{public}d, uid=%{public}d", priority,
188 IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
189 }
190
AddCallback(const sptr<ISyncShutdownCallback> & callback,ShutdownPriority priority)191 void ShutdownController::AddCallback(const sptr<ISyncShutdownCallback>& callback, ShutdownPriority priority)
192 {
193 RETURN_IF(callback->AsObject() == nullptr)
194 syncShutdownCallbackHolder_->AddCallback(callback->AsObject(), priority);
195 POWER_HILOGI(FEATURE_SHUTDOWN,
196 "sync shutdown callback added, priority=%{public}u, pid=%{public}d, uid=%{public}d", priority,
197 IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
198 }
199
RemoveCallback(const sptr<ITakeOverShutdownCallback> & callback)200 void ShutdownController::RemoveCallback(const sptr<ITakeOverShutdownCallback>& callback)
201 {
202 RETURN_IF(callback->AsObject() == nullptr)
203 takeoverShutdownCallbackHolder_->RemoveCallback(callback->AsObject());
204 POWER_HILOGI(FEATURE_SHUTDOWN, "takeover shutdown callback removed, pid=%{public}d, uid=%{public}d",
205 IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
206 }
207
RemoveCallback(const sptr<IAsyncShutdownCallback> & callback)208 void ShutdownController::RemoveCallback(const sptr<IAsyncShutdownCallback>& callback)
209 {
210 RETURN_IF(callback->AsObject() == nullptr)
211 asyncShutdownCallbackHolder_->RemoveCallback(callback->AsObject());
212 POWER_HILOGI(FEATURE_SHUTDOWN, "async shutdown callback removed, pid=%{public}d, uid=%{public}d",
213 IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
214 }
215
RemoveCallback(const sptr<ISyncShutdownCallback> & callback)216 void ShutdownController::RemoveCallback(const sptr<ISyncShutdownCallback>& callback)
217 {
218 RETURN_IF(callback->AsObject() == nullptr)
219 syncShutdownCallbackHolder_->RemoveCallback(callback->AsObject());
220 POWER_HILOGI(FEATURE_SHUTDOWN, "sync shutdown callback removed, pid=%{public}d, uid=%{public}d",
221 IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid());
222 }
223
TriggerTakeOverShutdownCallback(bool isReboot)224 bool ShutdownController::TriggerTakeOverShutdownCallback(bool isReboot)
225 {
226 bool isTakeover = false;
227 auto highPriorityCallbacks = takeoverShutdownCallbackHolder_->GetHighPriorityCallbacks();
228 isTakeover = TriggerTakeOverShutdownCallbackInner(highPriorityCallbacks, isReboot);
229 RETURN_IF_WITH_RET(isTakeover, true);
230 auto defaultPriorityCallbacks = takeoverShutdownCallbackHolder_->GetDefaultPriorityCallbacks();
231 isTakeover = TriggerTakeOverShutdownCallbackInner(defaultPriorityCallbacks, isReboot);
232 RETURN_IF_WITH_RET(isTakeover, true);
233 auto lowPriorityCallbacks = takeoverShutdownCallbackHolder_->GetLowPriorityCallbacks();
234 isTakeover = TriggerTakeOverShutdownCallbackInner(lowPriorityCallbacks, isReboot);
235 return isTakeover;
236 }
237
TriggerTakeOverShutdownCallbackInner(std::set<sptr<IRemoteObject>> & callbacks,bool isReboot)238 bool ShutdownController::TriggerTakeOverShutdownCallbackInner(std::set<sptr<IRemoteObject>>& callbacks, bool isReboot)
239 {
240 bool isTakeover = false;
241 for (const auto& obj : callbacks) {
242 auto callback = iface_cast<ITakeOverShutdownCallback>(obj);
243 isTakeover = callback->OnTakeOverShutdown(isReboot);
244 }
245 return isTakeover;
246 }
247
TriggerAsyncShutdownCallback()248 void ShutdownController::TriggerAsyncShutdownCallback()
249 {
250 auto highPriorityCallbacks = asyncShutdownCallbackHolder_->GetHighPriorityCallbacks();
251 TriggerAsyncShutdownCallbackInner(highPriorityCallbacks);
252 auto defaultPriorityCallbacks = asyncShutdownCallbackHolder_->GetDefaultPriorityCallbacks();
253 TriggerAsyncShutdownCallbackInner(defaultPriorityCallbacks);
254 auto lowPriorityCallbacks = asyncShutdownCallbackHolder_->GetLowPriorityCallbacks();
255 TriggerAsyncShutdownCallbackInner(lowPriorityCallbacks);
256 }
257
TriggerAsyncShutdownCallbackInner(std::set<sptr<IRemoteObject>> & callbacks)258 void ShutdownController::TriggerAsyncShutdownCallbackInner(std::set<sptr<IRemoteObject>>& callbacks)
259 {
260 for (auto &obj : callbacks) {
261 sptr<IAsyncShutdownCallback> callback = iface_cast<IAsyncShutdownCallback>(obj);
262 if (callback != nullptr) {
263 int64_t start = GetTickCount();
264 callback->OnAsyncShutdown();
265 int64_t cost = GetTickCount() - start;
266 POWER_HILOGD(FEATURE_SHUTDOWN, "Callback finished, cost=%{public}" PRId64 "", cost);
267 }
268 }
269 }
270
TriggerSyncShutdownCallback()271 void ShutdownController::TriggerSyncShutdownCallback()
272 {
273 auto highPriorityCallbacks = syncShutdownCallbackHolder_->GetHighPriorityCallbacks();
274 TriggerSyncShutdownCallbackInner(highPriorityCallbacks);
275 auto defaultPriorityCallbacks = syncShutdownCallbackHolder_->GetDefaultPriorityCallbacks();
276 TriggerSyncShutdownCallbackInner(defaultPriorityCallbacks);
277 auto lowPriorityCallbacks = syncShutdownCallbackHolder_->GetLowPriorityCallbacks();
278 TriggerSyncShutdownCallbackInner(lowPriorityCallbacks);
279 }
280
TriggerSyncShutdownCallbackInner(std::set<sptr<IRemoteObject>> & callbacks)281 void ShutdownController::TriggerSyncShutdownCallbackInner(std::set<sptr<IRemoteObject>>& callbacks)
282 {
283 for (auto &obj : callbacks) {
284 sptr<ISyncShutdownCallback> callback = iface_cast<ISyncShutdownCallback>(obj);
285 if (callback != nullptr) {
286 int64_t start = GetTickCount();
287 callback->OnSyncShutdown();
288 int64_t cost = GetTickCount() - start;
289 POWER_HILOGD(FEATURE_SHUTDOWN, "Callback finished, cost=%{public}" PRId64 "", cost);
290 }
291 }
292 }
293 } // namespace PowerMgr
294 } // namespace OHOS
295