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 std::lock_guard<std::mutex> lock(g_mutex);
166 HDF_LOGI("start suspend");
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 #ifdef DRIVER_PERIPHERAL_POWER_SUSPEND_WITH_TAG
245 if (!g_suspendTag.empty()) {
246 return DoSuspendWithTag();
247 }
248 #endif
249
250 UniqueFd suspendStateFd(TEMP_FAILURE_RETRY(open(SUSPEND_STATE_PATH, O_RDWR | O_CLOEXEC)));
251 if (suspendStateFd < 0) {
252 return HDF_FAILURE;
253 }
254 bool ret = SaveStringToFd(suspendStateFd, SUSPEND_STATE);
255 if (!ret) {
256 HDF_LOGE("DoSuspend fail");
257 waitTime_ = std::min(waitTime_ * WAIT_TIME_FACTOR, MAX_WAIT_TIME);
258 return HDF_FAILURE;
259 }
260 waitTime_ = DEFAULT_WAIT_TIME;
261 return HDF_SUCCESS;
262 }
263
NotifyCallback(int code)264 void NotifyCallback(int code)
265 {
266 if (g_callback == nullptr) {
267 return;
268 }
269 switch (code) {
270 case CMD_ON_SUSPEND:
271 g_callback->OnSuspend();
272 break;
273 case CMD_ON_WAKEUP:
274 g_callback->OnWakeup();
275 break;
276 default:
277 break;
278 }
279 }
280
StopSuspend()281 int32_t PowerInterfaceImpl::StopSuspend()
282 {
283 HDF_LOGI("stop suspend");
284 g_suspendRetry = false;
285 g_powerState = PowerHdfState::AWAKE;
286 return HDF_SUCCESS;
287 }
288
ForceSuspend()289 int32_t PowerInterfaceImpl::ForceSuspend()
290 {
291 //force suspend changed into active suspend
292 HDF_LOGI("active suspend");
293 StartSuspend();
294 return HDF_SUCCESS;
295 }
296
Hibernate()297 int32_t PowerInterfaceImpl::Hibernate()
298 {
299 #ifdef DRIVERS_PERIPHERAL_POWER_ENABLE_S4
300 HDF_LOGI("hibernate begin.");
301 return Hibernate::GetInstance().DoHibernate();
302 #else
303 HDF_LOGI("hdf hibernate interface not supported.");
304 return HDF_FAILURE;
305 #endif
306 }
307
SuspendBlock(const std::string & name)308 int32_t PowerInterfaceImpl::SuspendBlock(const std::string &name)
309 {
310 std::lock_guard<std::mutex> lock(g_mutex);
311 if (name.empty()) {
312 return HDF_ERR_INVALID_PARAM;
313 }
314 UniqueFd fd(TEMP_FAILURE_RETRY(open(LOCK_PATH, O_RDWR | O_CLOEXEC)));
315 bool ret = SaveStringToFd(fd, name);
316 if (!ret) {
317 return HDF_FAILURE;
318 }
319 return HDF_SUCCESS;
320 }
321
SuspendUnblock(const std::string & name)322 int32_t PowerInterfaceImpl::SuspendUnblock(const std::string &name)
323 {
324 std::lock_guard<std::mutex> lock(g_mutex);
325 if (name.empty()) {
326 return HDF_ERR_INVALID_PARAM;
327 }
328 UniqueFd fd(TEMP_FAILURE_RETRY(open(UNLOCK_PATH, O_RDWR | O_CLOEXEC)));
329 bool ret = SaveStringToFd(fd, name);
330 if (!ret) {
331 return HDF_FAILURE;
332 }
333 return HDF_SUCCESS;
334 }
335
AddPowerDeathRecipient(const sptr<IPowerHdiCallback> & callback)336 int32_t PowerInterfaceImpl::AddPowerDeathRecipient(const sptr<IPowerHdiCallback> &callback)
337 {
338 HDF_LOGI("AddPowerDeathRecipient");
339 const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IPowerHdiCallback>(callback);
340 bool result = remote->AddDeathRecipient(g_deathRecipient);
341 if (!result) {
342 HDF_LOGI("AddPowerDeathRecipient fail");
343 return HDF_FAILURE;
344 }
345 return HDF_SUCCESS;
346 }
347
RemovePowerDeathRecipient(const sptr<IPowerHdiCallback> & callback)348 int32_t PowerInterfaceImpl::RemovePowerDeathRecipient(const sptr<IPowerHdiCallback> &callback)
349 {
350 HDF_LOGI("RemovePowerDeathRecipient");
351 const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IPowerHdiCallback>(callback);
352 bool result = remote->RemoveDeathRecipient(g_deathRecipient);
353 if (!result) {
354 HDF_LOGI("RemovePowerDeathRecipient fail");
355 return HDF_FAILURE;
356 }
357 return HDF_SUCCESS;
358 }
359
OnRemoteDied(const wptr<IRemoteObject> & object)360 void PowerInterfaceImpl::PowerDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
361 {
362 HDF_LOGI("PowerDeathRecipient OnRemoteDied");
363 powerInterfaceImpl_->UnRegister();
364 RunningLockImpl::Clean();
365 }
366
LoadStringFd(int32_t fd,std::string & content)367 void LoadStringFd(int32_t fd, std::string &content)
368 {
369 if (fd <= 0) {
370 HDF_LOGW("invalid fd: %{public}d", fd);
371 return;
372 }
373
374 const int32_t fileLength = lseek(fd, 0, SEEK_END);
375 if (fileLength > MAX_FILE_LENGTH || fileLength <= 0) {
376 HDF_LOGW("invalid file length(%{public}d)!", fileLength);
377 return;
378 }
379 int32_t loc = lseek(fd, 0, SEEK_SET);
380 if (loc == -1) {
381 HDF_LOGE("lseek file to begin failed!");
382 return;
383 }
384 content.resize(fileLength);
385 const int32_t len = static_cast<int32_t>(read(fd, content.data(), fileLength));
386 if (len <= 0) {
387 HDF_LOGW("the length read from file is failed, len: %{public}d, fileLen: %{public}d", len, fileLength);
388 content.clear();
389 }
390 }
391
ReadWakeCount()392 std::string ReadWakeCount()
393 {
394 if (wakeupCountFd < 0) {
395 wakeupCountFd = UniqueFd(TEMP_FAILURE_RETRY(open(WAKEUP_COUNT_PATH, O_RDWR | O_CLOEXEC)));
396 }
397 std::string wakeupCount;
398 LoadStringFd(wakeupCountFd, wakeupCount);
399
400 return wakeupCount;
401 }
402
WriteWakeCount(const std::string & count)403 bool WriteWakeCount(const std::string &count)
404 {
405 if (wakeupCountFd < 0) {
406 wakeupCountFd = UniqueFd(TEMP_FAILURE_RETRY(open(WAKEUP_COUNT_PATH, O_RDWR | O_CLOEXEC)));
407 }
408 bool ret = SaveStringToFd(wakeupCountFd, count.c_str());
409 return ret;
410 }
411
LoadSystemInfo(const std::string & path,std::string & info)412 static void LoadSystemInfo(const std::string &path, std::string &info)
413 {
414 UniqueFd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDWR | O_CLOEXEC)));
415 std::string str;
416 if (fd >= 0) {
417 bool ret = LoadStringFromFd(fd, str);
418 if (!ret) {
419 str = "# Failed to read";
420 }
421 } else {
422 str = "# Failed to open";
423 }
424 info.append(path);
425 info.append(": " + str + "\n");
426 }
427
PowerDump(std::string & info)428 int32_t PowerInterfaceImpl::PowerDump(std::string &info)
429 {
430 std::string dumpInfo("");
431 LoadSystemInfo(SUSPEND_STATE_PATH, dumpInfo);
432 LoadSystemInfo(LOCK_PATH, dumpInfo);
433 LoadSystemInfo(UNLOCK_PATH, dumpInfo);
434 info = dumpInfo;
435
436 return HDF_SUCCESS;
437 }
438
HoldRunningLock(const RunningLockInfo & info)439 int32_t PowerInterfaceImpl::HoldRunningLock(const RunningLockInfo &info)
440 {
441 return RunningLockImpl::Hold(info, g_powerState);
442 }
443
UnholdRunningLock(const RunningLockInfo & info)444 int32_t PowerInterfaceImpl::UnholdRunningLock(const RunningLockInfo &info)
445 {
446 return RunningLockImpl::Unhold(info);
447 }
448
HoldRunningLockExt(const RunningLockInfo & info,uint64_t lockid,const std::string & bundleName)449 int32_t PowerInterfaceImpl::HoldRunningLockExt(const RunningLockInfo &info,
450 uint64_t lockid, const std::string &bundleName)
451 {
452 HDF_LOGI("Background runningLock active, type=%{public}d name=%{public}s", info.type, info.name.c_str());
453 return RunningLockImpl::HoldLock(info, g_powerState, lockid, bundleName);
454 }
455
UnholdRunningLockExt(const RunningLockInfo & info,uint64_t lockid,const std::string & bundleName)456 int32_t PowerInterfaceImpl::UnholdRunningLockExt(const RunningLockInfo &info,
457 uint64_t lockid, const std::string &bundleName)
458 {
459 HDF_LOGI("Background runningLock inactive, type=%{public}d name=%{public}s", info.type, info.name.c_str());
460 return RunningLockImpl::UnholdLock(info, lockid, bundleName);
461 }
462
GetWakeupReason(std::string & reason)463 int32_t PowerInterfaceImpl::GetWakeupReason(std::string &reason)
464 {
465 #ifdef DRIVER_PERIPHERAL_POWER_WAKEUP_CAUSE_PATH
466 auto& powerConfig = PowerConfig::GetInstance();
467 std::map<std::string, PowerConfig::PowerSceneConfig> sceneConfigMap= powerConfig.GetPowerSceneConfigMap();
468 std::map<std::string, PowerConfig::PowerSceneConfig>::iterator it = sceneConfigMap.find("wakeuo_cause");
469 if (it == sceneConfigMap.end()) {
470 HDF_LOGW("wakeuo_cause getPath does not exist");
471 return HDF_FAILURE;
472 }
473 std::string getPath = (it->second).getPath;
474 HDF_LOGI("getPath = %{public}s", getPath.c_str());
475
476 UniqueFd wakeupCauseFd(TEMP_FAILURE_RETRY(open(getPath.c_str(), O_RDONLY | O_CLOEXEC)));
477 if (wakeupCauseFd < 0) {
478 return HDF_FAILURE;
479 }
480 LoadStringFd(wakeupCauseFd, reason);
481 return HDF_SUCCESS;
482 #else
483 HDF_LOGW("wakrup cause path not config");
484 return HDF_FAILURE;
485 #endif
486 }
487 } // namespace V1_2
488 } // namespace Power
489 } // namespace HDI
490 } // namespace OHOS
491