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 51namespace OHOS { 52namespace HDI { 53namespace Power { 54namespace V1_2 { 55static constexpr const int32_t MAX_FILE_LENGTH = 32 * 1024 * 1024; 56static constexpr const char * const SUSPEND_STATE = "mem"; 57static constexpr const char * const SUSPEND_STATE_PATH = "/sys/power/state"; 58static constexpr const char * const LOCK_PATH = "/sys/power/wake_lock"; 59static constexpr const char * const UNLOCK_PATH = "/sys/power/wake_unlock"; 60static constexpr const char * const WAKEUP_COUNT_PATH = "/sys/power/wakeup_count"; 61#ifdef FASTER_RETRY_OF_SLEEP 62static constexpr std::chrono::milliseconds DEFAULT_WAIT_TIME(100); // 100ms for phone and tablet 63#elif defined(SLOWER_RETRY_OF_SLEEP) 64static constexpr std::chrono::milliseconds DEFAULT_WAIT_TIME(500); // 500ms for PC 65#else 66static constexpr std::chrono::milliseconds DEFAULT_WAIT_TIME(1000); // 1000ms 67#endif 68static constexpr std::chrono::milliseconds MAX_WAIT_TIME(1000 * 60); // 1min 69static constexpr int32_t WAIT_TIME_FACTOR = 2; 70static std::chrono::milliseconds waitTime_(DEFAULT_WAIT_TIME); 71static std::mutex g_mutex; 72static std::mutex g_suspendMutex; 73static std::condition_variable g_suspendCv; 74static std::unique_ptr<std::thread> g_daemon; 75static std::atomic_bool g_suspending; 76static std::atomic_bool g_suspendRetry; 77static sptr<IPowerHdiCallback> g_callback; 78static UniqueFd wakeupCountFd; 79static PowerHdfState g_powerState {PowerHdfState::AWAKE}; 80static void AutoSuspendLoop(); 81static int32_t DoSuspend(); 82static void LoadStringFd(int32_t fd, std::string &content); 83static std::string ReadWakeCount(); 84static bool WriteWakeCount(const std::string &count); 85static void NotifyCallback(int code); 86namespace { 87sptr<PowerInterfaceImpl::PowerDeathRecipient> g_deathRecipient = nullptr; 88bool g_isHdiStart = false; 89} // namespace 90 91extern "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 106int32_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 119int32_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 139int32_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 148int32_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 158int32_t PowerInterfaceImpl::UnRegisterRunningLockCallback() 159{ 160 RunningLockImpl::UnRegisterRunningLockCallback(); 161 return HDF_SUCCESS; 162} 163 164int32_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 180void 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 207static constexpr const int32_t MAX_RETRY_COUNT = 5; 208static int32_t g_ulsr_loop = 0; 209static std::string g_suspendTag; 210int32_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 218int32_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 244int32_t PowerInterfaceImpl::SetSuspendTag(const std::string &tag) 245{ 246 return HDF_SUCCESS; 247} 248#endif 249 250int32_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 274void 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 291int32_t PowerInterfaceImpl::StopSuspend() 292{ 293 HDF_LOGI("stop suspend"); 294 g_suspendRetry = false; 295 g_powerState = PowerHdfState::AWAKE; 296 return HDF_SUCCESS; 297} 298 299int32_t PowerInterfaceImpl::ForceSuspend() 300{ 301 //force suspend changed into active suspend 302 HDF_LOGI("active suspend"); 303 StartSuspend(); 304 return HDF_SUCCESS; 305} 306 307int32_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 318int32_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 332int32_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 346int32_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 358int32_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 370void PowerInterfaceImpl::PowerDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object) 371{ 372 HDF_LOGI("PowerDeathRecipient OnRemoteDied"); 373 powerInterfaceImpl_->UnRegister(); 374 RunningLockImpl::Clean(); 375} 376 377void 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 402std::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 413bool 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 422static 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 438int32_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 449int32_t PowerInterfaceImpl::HoldRunningLock(const RunningLockInfo &info) 450{ 451 Power::PowerXCollie powerXcollie("Power_HoldRunningLock"); 452 return RunningLockImpl::Hold(info, g_powerState); 453} 454 455int32_t PowerInterfaceImpl::UnholdRunningLock(const RunningLockInfo &info) 456{ 457 Power::PowerXCollie powerXcollie("Power_UnholdRunningLock"); 458 return RunningLockImpl::Unhold(info); 459} 460 461int32_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 468int32_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 475int32_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