• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 "power_interface_impl.h"
17 
18 #include "errors.h"
19 #include "hdf_device_desc.h"
20 #include "hdf_remote_service.h"
21 #include "hdf_sbuf.h"
22 #include "pubdef.h"
23 #include "running_lock_impl.h"
24 #include "securec.h"
25 #include "unique_fd.h"
26 #include "hdf_log.h"
27 #include "v1_1/power_types.h"
28 #include <atomic>
29 #include <chrono>
30 #include <condition_variable>
31 #include <cstdlib>
32 #include <file_ex.h>
33 #include <hdf_base.h>
34 #include <iproxy_broker.h>
35 #include <iremote_object.h>
36 #include <mutex>
37 #include <sys/eventfd.h>
38 #include <sys/stat.h>
39 #include <sys/types.h>
40 #include <thread>
41 #include <unistd.h>
42 
43 namespace OHOS {
44 namespace HDI {
45 namespace Power {
46 namespace V1_1 {
47 static constexpr const int32_t MAX_FILE_LENGTH = 32 * 1024 * 1024;
48 static constexpr const char * const SUSPEND_STATE = "mem";
49 static constexpr const char * const SUSPEND_STATE_PATH = "/sys/power/state";
50 static constexpr const char * const LOCK_PATH = "/sys/power/wake_lock";
51 static constexpr const char * const UNLOCK_PATH = "/sys/power/wake_unlock";
52 static constexpr const char * const WAKEUP_COUNT_PATH = "/sys/power/wakeup_count";
53 static std::chrono::milliseconds waitTime_(100); // {100ms};
54 static std::mutex g_mutex;
55 static std::mutex g_suspendMutex;
56 static std::condition_variable g_suspendCv;
57 static std::unique_ptr<std::thread> g_daemon;
58 static std::atomic_bool g_suspending;
59 static std::atomic_bool g_suspendRetry;
60 static sptr<IPowerHdiCallback> g_callback;
61 static UniqueFd wakeupCountFd;
62 static PowerHdfState g_powerState {PowerHdfState::AWAKE};
63 static void AutoSuspendLoop();
64 static int32_t DoSuspend();
65 static void LoadStringFd(int32_t fd, std::string &content);
66 static std::string ReadWakeCount();
67 static bool WriteWakeCount(const std::string &count);
68 static void NotifyCallback(int code);
69 namespace {
70 sptr<PowerInterfaceImpl::PowerDeathRecipient> g_deathRecipient = nullptr;
71 bool g_isHdiStart = false;
72 } // namespace
73 
PowerInterfaceImplGetInstance(void)74 extern "C" IPowerInterface *PowerInterfaceImplGetInstance(void)
75 {
76     return new (std::nothrow) PowerInterfaceImpl();
77 }
78 
RegisterCallback(const sptr<IPowerHdiCallback> & ipowerHdiCallback)79 int32_t PowerInterfaceImpl::RegisterCallback(const sptr<IPowerHdiCallback> &ipowerHdiCallback)
80 {
81     std::lock_guard<std::mutex> lock(g_mutex);
82     if (!g_isHdiStart) {
83         g_callback = ipowerHdiCallback;
84         if (g_callback == nullptr) {
85             UnRegister();
86             return HDF_SUCCESS;
87         }
88         g_deathRecipient = new PowerDeathRecipient(this);
89         if (g_deathRecipient == nullptr) {
90             return HDF_FAILURE;
91         }
92         AddPowerDeathRecipient(g_callback);
93         g_isHdiStart = true;
94     }
95     return HDF_SUCCESS;
96 }
97 
UnRegister()98 int32_t PowerInterfaceImpl::UnRegister()
99 {
100     HDF_LOGI("UnRegister");
101     RemovePowerDeathRecipient(g_callback);
102     g_callback = nullptr;
103     g_isHdiStart = false;
104     return HDF_SUCCESS;
105 }
106 
StartSuspend()107 int32_t PowerInterfaceImpl::StartSuspend()
108 {
109     std::lock_guard<std::mutex> lock(g_mutex);
110     g_suspendRetry = true;
111     if (g_suspending) {
112         g_powerState = PowerHdfState::INACTIVE;
113         g_suspendCv.notify_one();
114         return HDF_SUCCESS;
115     }
116     g_suspending = true;
117     g_daemon = std::make_unique<std::thread>(&AutoSuspendLoop);
118     g_daemon->detach();
119     return HDF_SUCCESS;
120 }
121 
AutoSuspendLoop()122 void AutoSuspendLoop()
123 {
124     auto suspendLock = std::unique_lock(g_suspendMutex);
125     while (true) {
126         std::this_thread::sleep_for(waitTime_);
127 
128         const std::string wakeupCount = ReadWakeCount();
129         if (wakeupCount.empty()) {
130             continue;
131         }
132         if (!g_suspendRetry) {
133             g_suspendCv.wait(suspendLock);
134         }
135         if (!WriteWakeCount(wakeupCount)) {
136             continue;
137         }
138 
139         NotifyCallback(CMD_ON_SUSPEND);
140         g_powerState = PowerHdfState::SLEEP;
141         DoSuspend();
142         g_powerState = PowerHdfState::AWAKE;
143         NotifyCallback(CMD_ON_WAKEUP);
144     }
145     g_suspending = false;
146     g_suspendRetry = false;
147 }
148 
DoSuspend()149 int32_t DoSuspend()
150 {
151     std::lock_guard<std::mutex> lock(g_mutex);
152     UniqueFd suspendStateFd(TEMP_FAILURE_RETRY(open(SUSPEND_STATE_PATH, O_RDWR | O_CLOEXEC)));
153     if (suspendStateFd < 0) {
154         return HDF_FAILURE;
155     }
156     bool ret = SaveStringToFd(suspendStateFd, SUSPEND_STATE);
157     if (!ret) {
158         HDF_LOGE("DoSuspend fail");
159         return HDF_FAILURE;
160     }
161     return HDF_SUCCESS;
162 }
163 
NotifyCallback(int code)164 void NotifyCallback(int code)
165 {
166     if (g_callback == nullptr) {
167         return;
168     }
169     switch (code) {
170         case CMD_ON_SUSPEND:
171             g_callback->OnSuspend();
172             break;
173         case CMD_ON_WAKEUP:
174             g_callback->OnWakeup();
175             break;
176         default:
177             break;
178     }
179 }
180 
StopSuspend()181 int32_t PowerInterfaceImpl::StopSuspend()
182 {
183     g_suspendRetry = false;
184     g_powerState = PowerHdfState::AWAKE;
185     return HDF_SUCCESS;
186 }
187 
ForceSuspend()188 int32_t PowerInterfaceImpl::ForceSuspend()
189 {
190     g_suspendRetry = false;
191 
192     NotifyCallback(CMD_ON_SUSPEND);
193     g_powerState = PowerHdfState::SLEEP;
194     DoSuspend();
195     g_powerState = PowerHdfState::AWAKE;
196     NotifyCallback(CMD_ON_WAKEUP);
197     return HDF_SUCCESS;
198 }
199 
SuspendBlock(const std::string & name)200 int32_t PowerInterfaceImpl::SuspendBlock(const std::string &name)
201 {
202     std::lock_guard<std::mutex> lock(g_mutex);
203     if (name.empty()) {
204         return HDF_ERR_INVALID_PARAM;
205     }
206     UniqueFd fd(TEMP_FAILURE_RETRY(open(LOCK_PATH, O_RDWR | O_CLOEXEC)));
207     bool ret = SaveStringToFd(fd, name);
208     if (!ret) {
209         return HDF_FAILURE;
210     }
211     return HDF_SUCCESS;
212 }
213 
SuspendUnblock(const std::string & name)214 int32_t PowerInterfaceImpl::SuspendUnblock(const std::string &name)
215 {
216     std::lock_guard<std::mutex> lock(g_mutex);
217     if (name.empty()) {
218         return HDF_ERR_INVALID_PARAM;
219     }
220     UniqueFd fd(TEMP_FAILURE_RETRY(open(UNLOCK_PATH, O_RDWR | O_CLOEXEC)));
221     bool ret = SaveStringToFd(fd, name);
222     if (!ret) {
223         return HDF_FAILURE;
224     }
225     return HDF_SUCCESS;
226 }
227 
AddPowerDeathRecipient(const sptr<IPowerHdiCallback> & callback)228 int32_t PowerInterfaceImpl::AddPowerDeathRecipient(const sptr<IPowerHdiCallback> &callback)
229 {
230     HDF_LOGI("AddPowerDeathRecipient");
231     const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IPowerHdiCallback>(callback);
232     bool result = remote->AddDeathRecipient(g_deathRecipient);
233     if (!result) {
234         HDF_LOGI("AddPowerDeathRecipient fail");
235         return HDF_FAILURE;
236     }
237     return HDF_SUCCESS;
238 }
239 
RemovePowerDeathRecipient(const sptr<IPowerHdiCallback> & callback)240 int32_t PowerInterfaceImpl::RemovePowerDeathRecipient(const sptr<IPowerHdiCallback> &callback)
241 {
242     HDF_LOGI("RemovePowerDeathRecipient");
243     const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IPowerHdiCallback>(callback);
244     bool result = remote->RemoveDeathRecipient(g_deathRecipient);
245     if (!result) {
246         HDF_LOGI("RemovePowerDeathRecipient fail");
247         return HDF_FAILURE;
248     }
249     return HDF_SUCCESS;
250 }
251 
OnRemoteDied(const wptr<IRemoteObject> & object)252 void PowerInterfaceImpl::PowerDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
253 {
254     powerInterfaceImpl_->UnRegister();
255 }
256 
LoadStringFd(int32_t fd,std::string & content)257 void LoadStringFd(int32_t fd, std::string &content)
258 {
259     if (fd <= 0) {
260         HDF_LOGW("invalid fd: %{public}d", fd);
261         return;
262     }
263 
264     const int32_t fileLength = lseek(fd, 0, SEEK_END);
265     if (fileLength > MAX_FILE_LENGTH || fileLength <= 0) {
266         HDF_LOGW("invalid file length(%{public}d)!", fileLength);
267         return;
268     }
269     int32_t loc = lseek(fd, 0, SEEK_SET);
270     if (loc == -1) {
271         HDF_LOGE("lseek file to begin failed!");
272         return;
273     }
274     content.resize(fileLength);
275     const int32_t len = static_cast<int32_t>(read(fd, content.data(), fileLength));
276     if (len <= 0) {
277         HDF_LOGW("the length read from file is failed, len: %{public}d, fileLen: %{public}d", len, fileLength);
278         content.clear();
279     }
280 }
281 
ReadWakeCount()282 std::string ReadWakeCount()
283 {
284     if (wakeupCountFd < 0) {
285         wakeupCountFd = UniqueFd(TEMP_FAILURE_RETRY(open(WAKEUP_COUNT_PATH, O_RDWR | O_CLOEXEC)));
286     }
287     std::string wakeupCount;
288     LoadStringFd(wakeupCountFd, wakeupCount);
289 
290     return wakeupCount;
291 }
292 
WriteWakeCount(const std::string & count)293 bool WriteWakeCount(const std::string &count)
294 {
295     if (wakeupCountFd < 0) {
296         wakeupCountFd = UniqueFd(TEMP_FAILURE_RETRY(open(WAKEUP_COUNT_PATH, O_RDWR | O_CLOEXEC)));
297     }
298     bool ret = SaveStringToFd(wakeupCountFd, count.c_str());
299     return ret;
300 }
301 
LoadSystemInfo(const std::string & path,std::string & info)302 static void LoadSystemInfo(const std::string &path, std::string &info)
303 {
304     UniqueFd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDWR | O_CLOEXEC)));
305     std::string str;
306     if (fd >= 0) {
307         bool ret = LoadStringFromFd(fd, str);
308         if (!ret) {
309             str = "# Failed to read";
310         }
311     } else {
312         str = "# Failed to open";
313     }
314     info.append(path);
315     info.append(": " + str + "\n");
316 }
317 
PowerDump(std::string & info)318 int32_t PowerInterfaceImpl::PowerDump(std::string &info)
319 {
320     std::string dumpInfo("");
321     LoadSystemInfo(SUSPEND_STATE_PATH, dumpInfo);
322     LoadSystemInfo(LOCK_PATH, dumpInfo);
323     LoadSystemInfo(UNLOCK_PATH, dumpInfo);
324     info = dumpInfo;
325 
326     return HDF_SUCCESS;
327 }
328 
HoldRunningLock(const RunningLockInfo & info)329 int32_t PowerInterfaceImpl::HoldRunningLock(const RunningLockInfo &info)
330 {
331     return RunningLockImpl::Hold(info, g_powerState);
332 }
333 
UnholdRunningLock(const RunningLockInfo & info)334 int32_t PowerInterfaceImpl::UnholdRunningLock(const RunningLockInfo &info)
335 {
336     return RunningLockImpl::Unhold(info);
337 }
338 } // namespace V1_1
339 } // namespace Power
340 } // namespace HDI
341 } // namespace OHOS
342