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