1 /*
2 * Copyright (c) 2021 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_service.h"
17
18 #include <algorithm>
19 #include <atomic>
20 #include <future>
21 #include <thread>
22 #include <cinttypes>
23 #include <common_event_data.h>
24 #include <common_event_manager.h>
25 #include <common_event_publish_info.h>
26 #include <common_event_support.h>
27
28 #include "hilog_wrapper.h"
29 #include "power_mgr_factory.h"
30
31 using namespace OHOS::AAFwk;
32 using namespace OHOS::EventFwk;
33 using namespace std;
34
35 namespace OHOS {
36 namespace PowerMgr {
37 namespace {
38 const time_t MAX_TIMEOUT_SEC = 30;
39 }
ShutdownService()40 ShutdownService::ShutdownService() : started_(false)
41 {
42 devicePowerAction_ = PowerMgrFactory::GetDevicePowerAction();
43 highCallbackMgr_ = new CallbackManager();
44 defaultCallbackMgr_ = new CallbackManager();
45 lowCallbackMgr_ = new CallbackManager();
46 }
47
Reboot(const std::string & reason)48 void ShutdownService::Reboot(const std::string& reason)
49 {
50 RebootOrShutdown(reason, true);
51 }
52
Shutdown(const std::string & reason)53 void ShutdownService::Shutdown(const std::string& reason)
54 {
55 RebootOrShutdown(reason, false);
56 }
57
AddShutdownCallback(IShutdownCallback::ShutdownPriority priority,const sptr<IShutdownCallback> & callback)58 void ShutdownService::AddShutdownCallback(IShutdownCallback::ShutdownPriority priority,
59 const sptr<IShutdownCallback>& callback)
60 {
61 switch (priority) {
62 case IShutdownCallback::ShutdownPriority::POWER_SHUTDOWN_PRIORITY_HIGH:
63 highCallbackMgr_->AddCallback(callback);
64 break;
65 case IShutdownCallback::ShutdownPriority::POWER_SHUTDOWN_PRIORITY_DEFAULT:
66 defaultCallbackMgr_->AddCallback(callback);
67 break;
68 case IShutdownCallback::ShutdownPriority::POWER_SHUTDOWN_PRIORITY_LOW:
69 lowCallbackMgr_->AddCallback(callback);
70 break;
71 default:
72 return;
73 }
74 }
75
DelShutdownCallback(const sptr<IShutdownCallback> & callback)76 void ShutdownService::DelShutdownCallback(const sptr<IShutdownCallback>& callback)
77 {
78 highCallbackMgr_->RemoveCallback(callback);
79 defaultCallbackMgr_->RemoveCallback(callback);
80 lowCallbackMgr_->RemoveCallback(callback);
81 }
82
IsShuttingDown()83 bool ShutdownService::IsShuttingDown()
84 {
85 POWER_HILOGE(MODULE_SERVICE, "IsShuttingDown");
86 return started_;
87 }
88
RebootOrShutdown(const std::string & reason,bool isReboot)89 void ShutdownService::RebootOrShutdown(const std::string& reason, bool isReboot)
90 {
91 if (started_) {
92 POWER_HILOGE(MODULE_SERVICE, "Shutdown is already running.");
93 return;
94 }
95 started_ = true;
96 make_unique<thread>([=] {
97 Prepare();
98 POWER_HILOGD(MODULE_SERVICE, "reason = %{public}s, reboot = %{public}d", reason.c_str(), isReboot);
99 if (devicePowerAction_ != nullptr) {
100 isReboot ? devicePowerAction_->Reboot(reason) : devicePowerAction_->Shutdown(reason);
101 }
102 started_ = false;
103 })->detach();
104 }
105
Prepare()106 void ShutdownService::Prepare()
107 {
108 PublishShutdownEvent();
109 highCallbackMgr_->WaitingCallback();
110 defaultCallbackMgr_->WaitingCallback();
111 lowCallbackMgr_->WaitingCallback();
112 }
113
PublishShutdownEvent() const114 void ShutdownService::PublishShutdownEvent() const
115 {
116 POWER_HILOGD(MODULE_SERVICE, "Start of publishing shutdown event");
117 CommonEventPublishInfo publishInfo;
118 publishInfo.SetOrdered(false);
119 IntentWant shutdownWant;
120 shutdownWant.SetAction(CommonEventSupport::COMMON_EVENT_SHUTDOWN);
121 CommonEventData event(shutdownWant);
122 if (!CommonEventManager::PublishCommonEvent(event, publishInfo, nullptr)) {
123 POWER_HILOGE(MODULE_SERVICE, "Failed to publish the shutdown event!");
124 return;
125 }
126 POWER_HILOGD(MODULE_SERVICE, "End of publishing shutdown event");
127 }
128
AddCallback(const sptr<IShutdownCallback> & callback)129 void ShutdownService::CallbackManager::AddCallback(const sptr<IShutdownCallback>& callback)
130 {
131 unique_lock<mutex> lock(mutex_);
132 RETURN_IF((callback == nullptr) || (callback->AsObject() == nullptr));
133 auto object = callback->AsObject();
134 auto retIt = callbacks_.insert(object);
135 if (retIt.second) {
136 object->AddDeathRecipient(this);
137 }
138 POWER_HILOGI(MODULE_SERVICE, "object = %{public}p, callback = %{public}p, callbacks.size = %{public}zu,"
139 " insertOk = %{public}d", object.GetRefPtr(),
140 callback.GetRefPtr(), callbacks_.size(), retIt.second);
141 }
142
RemoveCallback(const sptr<IShutdownCallback> & callback)143 void ShutdownService::CallbackManager::RemoveCallback(const sptr<IShutdownCallback>& callback)
144 {
145 unique_lock<mutex> lock(mutex_);
146 RETURN_IF((callback == nullptr) || (callback->AsObject() == nullptr));
147 auto object = callback->AsObject();
148 auto it = find(callbacks_.begin(), callbacks_.end(), object);
149 if (it != callbacks_.end()) {
150 callbacks_.erase(it);
151 object->RemoveDeathRecipient(this);
152 }
153 POWER_HILOGI(MODULE_SERVICE, "object = %{public}p, callback = %{public}p, callbacks.size = %{public}zu,",
154 object.GetRefPtr(), callback.GetRefPtr(), callbacks_.size());
155 }
156
OnRemoteDied(const wptr<IRemoteObject> & remote)157 void ShutdownService::CallbackManager::OnRemoteDied(const wptr<IRemoteObject>& remote)
158 {
159 RETURN_IF(remote.promote() == nullptr);
160 RemoveCallback(iface_cast<IShutdownCallback>(remote.promote()));
161 }
162
WaitingCallback()163 void ShutdownService::CallbackManager::WaitingCallback()
164 {
165 POWER_HILOGD(MODULE_SERVICE, "Shutdown callback started.");
166 auto callbackStart = [&]() {
167 unique_lock<mutex> lock(mutex_);
168 for (auto &obj : callbacks_) {
169 sptr<IShutdownCallback> callback = iface_cast<IShutdownCallback>(obj);
170 if (callback != nullptr) {
171 callback->ShutdownCallback();
172 }
173 }
174 };
175
176 packaged_task<void()> callbackTask(callbackStart);
177 future<void> fut = callbackTask.get_future();
178 make_unique<thread>(std::move(callbackTask))->detach();
179
180 POWER_HILOGI(MODULE_SERVICE, "Waiting for the callback execution is complete...");
181 future_status status = fut.wait_for(std::chrono::seconds(MAX_TIMEOUT_SEC));
182 if (status == future_status::timeout) {
183 POWER_HILOGW(MODULE_SERVICE, "Shutdown callback execution timedout!");
184 }
185 POWER_HILOGI(MODULE_SERVICE, "The callback execution is complete. ");
186 }
187 } // namespace PowerMgr
188 } // namespace OHOS
189