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