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