• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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