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 "power_hdf_log.h"
27 #include "power_xcollie.h"
28 #include "v1_2/power_types.h"
29 #include <atomic>
30 #include <chrono>
31 #include <condition_variable>
32 #include <cstdlib>
33 #include <file_ex.h>
34 #include <hdf_base.h>
35 #include <iproxy_broker.h>
36 #include <iremote_object.h>
37 #include <mutex>
38 #include <sys/eventfd.h>
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <thread>
42 #include <unistd.h>
43
44 #ifdef DRIVER_PERIPHERAL_POWER_WAKEUP_CAUSE_PATH
45 #include "power_config.h"
46 #endif
47 #ifdef DRIVERS_PERIPHERAL_POWER_ENABLE_S4
48 #include "hibernate.h"
49 #endif
50
51 namespace OHOS {
52 namespace HDI {
53 namespace Power {
54 namespace V1_2 {
55 static constexpr const int32_t MAX_FILE_LENGTH = 32 * 1024 * 1024;
56 static constexpr const char * const SUSPEND_STATE = "mem";
57 static constexpr const char * const SUSPEND_STATE_PATH = "/sys/power/state";
58 static constexpr const char * const LOCK_PATH = "/sys/power/wake_lock";
59 static constexpr const char * const UNLOCK_PATH = "/sys/power/wake_unlock";
60 static constexpr const char * const WAKEUP_COUNT_PATH = "/sys/power/wakeup_count";
61 #ifdef FASTER_RETRY_OF_SLEEP
62 static constexpr std::chrono::milliseconds DEFAULT_WAIT_TIME(100); // 100ms for phone and tablet
63 #elif defined(SLOWER_RETRY_OF_SLEEP)
64 static constexpr std::chrono::milliseconds DEFAULT_WAIT_TIME(500); // 500ms for PC
65 #else
66 static constexpr std::chrono::milliseconds DEFAULT_WAIT_TIME(1000); // 1000ms
67 #endif
68 static constexpr std::chrono::milliseconds MAX_WAIT_TIME(1000 * 60); // 1min
69 static constexpr int32_t WAIT_TIME_FACTOR = 2;
70 static std::chrono::milliseconds waitTime_(DEFAULT_WAIT_TIME);
71 static std::mutex g_mutex;
72 static std::mutex g_suspendMutex;
73 static std::condition_variable g_suspendCv;
74 static std::unique_ptr<std::thread> g_daemon;
75 static std::atomic_bool g_suspending;
76 static std::atomic_bool g_suspendRetry;
77 static sptr<IPowerHdiCallback> g_callback;
78 static UniqueFd wakeupCountFd;
79 static PowerHdfState g_powerState {PowerHdfState::AWAKE};
80 static void AutoSuspendLoop();
81 static int32_t DoSuspend();
82 static void LoadStringFd(int32_t fd, std::string &content);
83 static std::string ReadWakeCount();
84 static bool WriteWakeCount(const std::string &count);
85 static void NotifyCallback(int code);
86 namespace {
87 sptr<PowerInterfaceImpl::PowerDeathRecipient> g_deathRecipient = nullptr;
88 bool g_isHdiStart = false;
89 } // namespace
90
PowerInterfaceImplGetInstance(void)91 extern "C" IPowerInterface *PowerInterfaceImplGetInstance(void)
92 {
93 using OHOS::HDI::Power::V1_2::PowerInterfaceImpl;
94 PowerInterfaceImpl *service = new (std::nothrow) PowerInterfaceImpl();
95 if (service == nullptr) {
96 return nullptr;
97 }
98
99 if (service->Init() != HDF_SUCCESS) {
100 delete service;
101 return nullptr;
102 }
103 return service;
104 }
105
Init()106 int32_t PowerInterfaceImpl::Init()
107 {
108 #ifdef DRIVER_PERIPHERAL_POWER_WAKEUP_CAUSE_PATH
109 auto& powerConfig = PowerConfig::GetInstance();
110 powerConfig.ParseConfig();
111 #endif
112
113 #ifdef DRIVERS_PERIPHERAL_POWER_ENABLE_S4
114 Hibernate::GetInstance().Init();
115 #endif
116 return HDF_SUCCESS;
117 }
118
RegisterCallback(const sptr<IPowerHdiCallback> &ipowerHdiCallback)119 int32_t PowerInterfaceImpl::RegisterCallback(const sptr<IPowerHdiCallback> &ipowerHdiCallback)
120 {
121 std::lock_guard<std::mutex> lock(g_mutex);
122 if (!g_isHdiStart) {
123 g_callback = ipowerHdiCallback;
124 if (g_callback == nullptr) {
125 UnRegister();
126 return HDF_SUCCESS;
127 }
128 g_deathRecipient = new PowerDeathRecipient(this);
129 if (g_deathRecipient == nullptr) {
130 return HDF_FAILURE;
131 }
132 AddPowerDeathRecipient(g_callback);
133 g_isHdiStart = true;
134 }
135
136 return HDF_SUCCESS;
137 }
138
UnRegister()139 int32_t PowerInterfaceImpl::UnRegister()
140 {
141 HDF_LOGI("UnRegister");
142 RemovePowerDeathRecipient(g_callback);
143 g_callback = nullptr;
144 g_isHdiStart = false;
145 return HDF_SUCCESS;
146 }
147
RegisterRunningLockCallback(const sptr<IPowerRunningLockCallback> &iPowerRunningLockCallback)148 int32_t PowerInterfaceImpl::RegisterRunningLockCallback(const sptr<IPowerRunningLockCallback>
149 &iPowerRunningLockCallback)
150 {
151 if (iPowerRunningLockCallback != nullptr) {
152 UnRegisterRunningLockCallback();
153 }
154 RunningLockImpl::RegisterRunningLockCallback(iPowerRunningLockCallback);
155 return HDF_SUCCESS;
156 }
157
UnRegisterRunningLockCallback()158 int32_t PowerInterfaceImpl::UnRegisterRunningLockCallback()
159 {
160 RunningLockImpl::UnRegisterRunningLockCallback();
161 return HDF_SUCCESS;
162 }
163
StartSuspend()164 int32_t PowerInterfaceImpl::StartSuspend()
165 {
166 HDF_LOGI("start suspend");
167 std::lock_guard<std::mutex> lock(g_mutex);
168 g_suspendRetry = true;
169 if (g_suspending) {
170 g_powerState = PowerHdfState::INACTIVE;
171 g_suspendCv.notify_one();
172 return HDF_SUCCESS;
173 }
174 g_suspending = true;
175 g_daemon = std::make_unique<std::thread>(&AutoSuspendLoop);
176 g_daemon->detach();
177 return HDF_SUCCESS;
178 }
179
AutoSuspendLoop()180 void AutoSuspendLoop()
181 {
182 auto suspendLock = std::unique_lock(g_suspendMutex);
183 while (true) {
184 std::this_thread::sleep_for(waitTime_);
185 const std::string wakeupCount = ReadWakeCount();
186 if (wakeupCount.empty()) {
187 continue;
188 }
189 if (!g_suspendRetry) {
190 g_suspendCv.wait(suspendLock);
191 }
192 if (!WriteWakeCount(wakeupCount)) {
193 continue;
194 }
195
196 NotifyCallback(CMD_ON_SUSPEND);
197 g_powerState = PowerHdfState::SLEEP;
198 DoSuspend();
199 g_powerState = PowerHdfState::AWAKE;
200 NotifyCallback(CMD_ON_WAKEUP);
201 }
202 g_suspending = false;
203 g_suspendRetry = false;
204 }
205
206 #ifdef DRIVER_PERIPHERAL_POWER_SUSPEND_WITH_TAG
207 static constexpr const int32_t MAX_RETRY_COUNT = 5;
208 static int32_t g_ulsr_loop = 0;
209 static std::string g_suspendTag;
SetSuspendTag(const std::string &tag)210 int32_t PowerInterfaceImpl::SetSuspendTag(const std::string &tag)
211 {
212 HDF_LOGI("Set suspend tag: %{public}s", tag.c_str());
213 g_suspendTag = tag;
214 g_ulsr_loop = 0;
215 return HDF_SUCCESS;
216 }
217
DoSuspendWithTag()218 int32_t DoSuspendWithTag()
219 {
220 UniqueFd suspendStateFd(TEMP_FAILURE_RETRY(open(SUSPEND_STATE_PATH, O_RDWR | O_CLOEXEC)));
221 if (suspendStateFd < 0) {
222 return HDF_FAILURE;
223 }
224
225 g_ulsr_loop++;
226 bool ret = SaveStringToFd(suspendStateFd, g_suspendTag);
227 if (!ret) {
228 waitTime_ = std::min(waitTime_ * WAIT_TIME_FACTOR, MAX_WAIT_TIME);
229 HDF_LOGE("SaveStringToFd fail, tag:%{public}s loop:%{public}d", g_suspendTag.c_str(), g_ulsr_loop);
230 if (g_ulsr_loop >= MAX_RETRY_COUNT) {
231 HDF_LOGE("DoSuspendWithTag fail: %{public}s", g_suspendTag.c_str());
232 g_suspendTag.clear();
233 waitTime_ = DEFAULT_WAIT_TIME;
234 return HDF_FAILURE;
235 }
236 return HDF_SUCCESS;
237 }
238 HDF_LOGI("Do Suspend %{public}d: echo %{public}s > /sys/power/state", g_ulsr_loop, g_suspendTag.c_str());
239 g_suspendTag.clear();
240 waitTime_ = DEFAULT_WAIT_TIME;
241 return HDF_SUCCESS;
242 }
243 #else
SetSuspendTag(const std::string &tag)244 int32_t PowerInterfaceImpl::SetSuspendTag(const std::string &tag)
245 {
246 return HDF_SUCCESS;
247 }
248 #endif
249
DoSuspend()250 int32_t DoSuspend()
251 {
252 std::lock_guard<std::mutex> lock(g_mutex);
253
254 #ifdef DRIVER_PERIPHERAL_POWER_SUSPEND_WITH_TAG
255 if (!g_suspendTag.empty()) {
256 return DoSuspendWithTag();
257 }
258 #endif
259
260 UniqueFd suspendStateFd(TEMP_FAILURE_RETRY(open(SUSPEND_STATE_PATH, O_RDWR | O_CLOEXEC)));
261 if (suspendStateFd < 0) {
262 return HDF_FAILURE;
263 }
264 bool ret = SaveStringToFd(suspendStateFd, SUSPEND_STATE);
265 if (!ret) {
266 HDF_LOGE("DoSuspend fail");
267 waitTime_ = std::min(waitTime_ * WAIT_TIME_FACTOR, MAX_WAIT_TIME);
268 return HDF_FAILURE;
269 }
270 waitTime_ = DEFAULT_WAIT_TIME;
271 return HDF_SUCCESS;
272 }
273
NotifyCallback(int code)274 void NotifyCallback(int code)
275 {
276 if (g_callback == nullptr) {
277 return;
278 }
279 switch (code) {
280 case CMD_ON_SUSPEND:
281 g_callback->OnSuspend();
282 break;
283 case CMD_ON_WAKEUP:
284 g_callback->OnWakeup();
285 break;
286 default:
287 break;
288 }
289 }
290
StopSuspend()291 int32_t PowerInterfaceImpl::StopSuspend()
292 {
293 HDF_LOGI("stop suspend");
294 g_suspendRetry = false;
295 g_powerState = PowerHdfState::AWAKE;
296 return HDF_SUCCESS;
297 }
298
ForceSuspend()299 int32_t PowerInterfaceImpl::ForceSuspend()
300 {
301 //force suspend changed into active suspend
302 HDF_LOGI("active suspend");
303 StartSuspend();
304 return HDF_SUCCESS;
305 }
306
Hibernate()307 int32_t PowerInterfaceImpl::Hibernate()
308 {
309 #ifdef DRIVERS_PERIPHERAL_POWER_ENABLE_S4
310 HDF_LOGI("hibernate begin.");
311 return Hibernate::GetInstance().DoHibernate();
312 #else
313 HDF_LOGI("hdf hibernate interface not supported.");
314 return HDF_FAILURE;
315 #endif
316 }
317
SuspendBlock(const std::string &name)318 int32_t PowerInterfaceImpl::SuspendBlock(const std::string &name)
319 {
320 std::lock_guard<std::mutex> lock(g_mutex);
321 if (name.empty()) {
322 return HDF_ERR_INVALID_PARAM;
323 }
324 UniqueFd fd(TEMP_FAILURE_RETRY(open(LOCK_PATH, O_RDWR | O_CLOEXEC)));
325 bool ret = SaveStringToFd(fd, name);
326 if (!ret) {
327 return HDF_FAILURE;
328 }
329 return HDF_SUCCESS;
330 }
331
SuspendUnblock(const std::string &name)332 int32_t PowerInterfaceImpl::SuspendUnblock(const std::string &name)
333 {
334 std::lock_guard<std::mutex> lock(g_mutex);
335 if (name.empty()) {
336 return HDF_ERR_INVALID_PARAM;
337 }
338 UniqueFd fd(TEMP_FAILURE_RETRY(open(UNLOCK_PATH, O_RDWR | O_CLOEXEC)));
339 bool ret = SaveStringToFd(fd, name);
340 if (!ret) {
341 return HDF_FAILURE;
342 }
343 return HDF_SUCCESS;
344 }
345
AddPowerDeathRecipient(const sptr<IPowerHdiCallback> &callback)346 int32_t PowerInterfaceImpl::AddPowerDeathRecipient(const sptr<IPowerHdiCallback> &callback)
347 {
348 HDF_LOGI("AddPowerDeathRecipient");
349 const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IPowerHdiCallback>(callback);
350 bool result = remote->AddDeathRecipient(g_deathRecipient);
351 if (!result) {
352 HDF_LOGI("AddPowerDeathRecipient fail");
353 return HDF_FAILURE;
354 }
355 return HDF_SUCCESS;
356 }
357
RemovePowerDeathRecipient(const sptr<IPowerHdiCallback> &callback)358 int32_t PowerInterfaceImpl::RemovePowerDeathRecipient(const sptr<IPowerHdiCallback> &callback)
359 {
360 HDF_LOGI("RemovePowerDeathRecipient");
361 const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IPowerHdiCallback>(callback);
362 bool result = remote->RemoveDeathRecipient(g_deathRecipient);
363 if (!result) {
364 HDF_LOGI("RemovePowerDeathRecipient fail");
365 return HDF_FAILURE;
366 }
367 return HDF_SUCCESS;
368 }
369
OnRemoteDied(const wptr<IRemoteObject> &object)370 void PowerInterfaceImpl::PowerDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
371 {
372 HDF_LOGI("PowerDeathRecipient OnRemoteDied");
373 powerInterfaceImpl_->UnRegister();
374 RunningLockImpl::Clean();
375 }
376
LoadStringFd(int32_t fd, std::string &content)377 void LoadStringFd(int32_t fd, std::string &content)
378 {
379 if (fd <= 0) {
380 HDF_LOGW("invalid fd: %{public}d", fd);
381 return;
382 }
383
384 const int32_t fileLength = lseek(fd, 0, SEEK_END);
385 if (fileLength > MAX_FILE_LENGTH || fileLength <= 0) {
386 HDF_LOGW("invalid file length(%{public}d)!", fileLength);
387 return;
388 }
389 int32_t loc = lseek(fd, 0, SEEK_SET);
390 if (loc == -1) {
391 HDF_LOGE("lseek file to begin failed!");
392 return;
393 }
394 content.resize(fileLength);
395 const int32_t len = static_cast<int32_t>(read(fd, content.data(), fileLength));
396 if (len <= 0) {
397 HDF_LOGW("the length read from file is failed, len: %{public}d, fileLen: %{public}d", len, fileLength);
398 content.clear();
399 }
400 }
401
ReadWakeCount()402 std::string ReadWakeCount()
403 {
404 if (wakeupCountFd < 0) {
405 wakeupCountFd = UniqueFd(TEMP_FAILURE_RETRY(open(WAKEUP_COUNT_PATH, O_RDWR | O_CLOEXEC)));
406 }
407 std::string wakeupCount;
408 LoadStringFd(wakeupCountFd, wakeupCount);
409
410 return wakeupCount;
411 }
412
WriteWakeCount(const std::string &count)413 bool WriteWakeCount(const std::string &count)
414 {
415 if (wakeupCountFd < 0) {
416 wakeupCountFd = UniqueFd(TEMP_FAILURE_RETRY(open(WAKEUP_COUNT_PATH, O_RDWR | O_CLOEXEC)));
417 }
418 bool ret = SaveStringToFd(wakeupCountFd, count.c_str());
419 return ret;
420 }
421
LoadSystemInfo(const std::string &path, std::string &info)422 static void LoadSystemInfo(const std::string &path, std::string &info)
423 {
424 UniqueFd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDWR | O_CLOEXEC)));
425 std::string str;
426 if (fd >= 0) {
427 bool ret = LoadStringFromFd(fd, str);
428 if (!ret) {
429 str = "# Failed to read";
430 }
431 } else {
432 str = "# Failed to open";
433 }
434 info.append(path);
435 info.append(": " + str + "\n");
436 }
437
PowerDump(std::string &info)438 int32_t PowerInterfaceImpl::PowerDump(std::string &info)
439 {
440 std::string dumpInfo("");
441 LoadSystemInfo(SUSPEND_STATE_PATH, dumpInfo);
442 LoadSystemInfo(LOCK_PATH, dumpInfo);
443 LoadSystemInfo(UNLOCK_PATH, dumpInfo);
444 info = dumpInfo;
445
446 return HDF_SUCCESS;
447 }
448
HoldRunningLock(const RunningLockInfo &info)449 int32_t PowerInterfaceImpl::HoldRunningLock(const RunningLockInfo &info)
450 {
451 Power::PowerXCollie powerXcollie("Power_HoldRunningLock");
452 return RunningLockImpl::Hold(info, g_powerState);
453 }
454
UnholdRunningLock(const RunningLockInfo &info)455 int32_t PowerInterfaceImpl::UnholdRunningLock(const RunningLockInfo &info)
456 {
457 Power::PowerXCollie powerXcollie("Power_UnholdRunningLock");
458 return RunningLockImpl::Unhold(info);
459 }
460
HoldRunningLockExt(const RunningLockInfo &info, uint64_t lockid, const std::string &bundleName)461 int32_t PowerInterfaceImpl::HoldRunningLockExt(const RunningLockInfo &info,
462 uint64_t lockid, const std::string &bundleName)
463 {
464 Power::PowerXCollie powerXcollie("Power_HoldRunningLockExt");
465 return RunningLockImpl::HoldLock(info, g_powerState, lockid, bundleName);
466 }
467
UnholdRunningLockExt(const RunningLockInfo &info, uint64_t lockid, const std::string &bundleName)468 int32_t PowerInterfaceImpl::UnholdRunningLockExt(const RunningLockInfo &info,
469 uint64_t lockid, const std::string &bundleName)
470 {
471 Power::PowerXCollie powerXcollie("Power_UnholdRunningLockExt");
472 return RunningLockImpl::UnholdLock(info, lockid, bundleName);
473 }
474
GetWakeupReason(std::string &reason)475 int32_t PowerInterfaceImpl::GetWakeupReason(std::string &reason)
476 {
477 #ifdef DRIVER_PERIPHERAL_POWER_WAKEUP_CAUSE_PATH
478 auto& powerConfig = PowerConfig::GetInstance();
479 std::map<std::string, PowerConfig::PowerSceneConfig> sceneConfigMap= powerConfig.GetPowerSceneConfigMap();
480 std::map<std::string, PowerConfig::PowerSceneConfig>::iterator it = sceneConfigMap.find("wakeuo_cause");
481 if (it == sceneConfigMap.end()) {
482 HDF_LOGW("wakeuo_cause getPath does not exist");
483 return HDF_FAILURE;
484 }
485 std::string getPath = (it->second).getPath;
486 HDF_LOGI("getPath = %{public}s", getPath.c_str());
487
488 UniqueFd wakeupCauseFd(TEMP_FAILURE_RETRY(open(getPath.c_str(), O_RDONLY | O_CLOEXEC)));
489 if (wakeupCauseFd < 0) {
490 return HDF_FAILURE;
491 }
492 LoadStringFd(wakeupCauseFd, reason);
493 return HDF_SUCCESS;
494 #else
495 HDF_LOGW("wakrup cause path not config");
496 return HDF_FAILURE;
497 #endif
498 }
499 } // namespace V1_2
500 } // namespace Power
501 } // namespace HDI
502 } // namespace OHOS
503