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