namespace V1_0 {
static const char kSleepState[] = "mem";
+// TODO(b/128923994): we only need /sys/power/wake_[un]lock to export debugging info via
+// /sys/kernel/debug/wakeup_sources.
+static constexpr char kSysPowerWakeLock[] = "/sys/power/wake_lock";
+static constexpr char kSysPowerWakeUnlock[] = "/sys/power/wake_unlock";
// This function assumes that data in fd is small enough that it can be read in one go.
// We use this function instead of the ones available in libbase because it doesn't block
return std::chrono::duration_cast<std::chrono::microseconds>(timeSinceEpoch).count();
}
-WakeLock::WakeLock(SystemSuspend* systemSuspend, const WakeLockIdType& id)
- : mReleased(), mSystemSuspend(systemSuspend), mId(id) {
- mSystemSuspend->incSuspendCounter();
+WakeLock::WakeLock(SystemSuspend* systemSuspend, const WakeLockIdType& id, const string& name)
+ : mReleased(), mSystemSuspend(systemSuspend), mId(id), mName(name) {
+ mSystemSuspend->incSuspendCounter(mName);
}
WakeLock::~WakeLock() {
void WakeLock::releaseOnce() {
std::call_once(mReleased, [this]() {
- mSystemSuspend->decSuspendCounter();
+ mSystemSuspend->decSuspendCounter(mName);
mSystemSuspend->deleteWakeLockStatsEntry(mId);
});
}
SystemSuspend::SystemSuspend(unique_fd wakeupCountFd, unique_fd stateFd, size_t maxStatsEntries,
std::chrono::milliseconds baseSleepTime,
- const sp<SuspendControlService>& controlService)
+ const sp<SuspendControlService>& controlService,
+ bool useSuspendCounter)
: mSuspendCounter(0),
mWakeupCountFd(std::move(wakeupCountFd)),
mStateFd(std::move(stateFd)),
mMaxStatsEntries(maxStatsEntries),
mBaseSleepTime(baseSleepTime),
mSleepTime(baseSleepTime),
- mControlService(controlService) {
+ mControlService(controlService),
+ mUseSuspendCounter(useSuspendCounter),
+ mWakeLockFd(-1),
+ mWakeUnlockFd(-1) {
mControlService->setSuspendService(this);
+
+ if (!mUseSuspendCounter) {
+ mWakeLockFd.reset(TEMP_FAILURE_RETRY(open(kSysPowerWakeLock, O_CLOEXEC | O_RDWR)));
+ if (mWakeLockFd < 0) {
+ PLOG(ERROR) << "error opening " << kSysPowerWakeLock;
+ }
+ mWakeUnlockFd.reset(TEMP_FAILURE_RETRY(open(kSysPowerWakeUnlock, O_CLOEXEC | O_RDWR)));
+ if (mWakeUnlockFd < 0) {
+ PLOG(ERROR) << "error opening " << kSysPowerWakeUnlock;
+ }
+ }
}
bool SystemSuspend::enableAutosuspend() {
const hidl_string& name) {
auto pid = getCallingPid();
auto wlId = getWakeLockId(pid, name);
- IWakeLock* wl = new WakeLock{this, wlId};
+ IWakeLock* wl = new WakeLock{this, wlId, name};
{
auto l = std::lock_guard(mStatsLock);
return Void();
}
-void SystemSuspend::incSuspendCounter() {
+void SystemSuspend::incSuspendCounter(const string& name) {
auto l = std::lock_guard(mCounterLock);
- mSuspendCounter++;
+ if (mUseSuspendCounter) {
+ mSuspendCounter++;
+ } else {
+ if (!WriteStringToFd(name, mWakeLockFd)) {
+ PLOG(ERROR) << "error writing " << name << " to " << kSysPowerWakeLock;
+ }
+ }
}
-void SystemSuspend::decSuspendCounter() {
+void SystemSuspend::decSuspendCounter(const string& name) {
auto l = std::lock_guard(mCounterLock);
- if (--mSuspendCounter == 0) {
- mCounterCondVar.notify_one();
+ if (mUseSuspendCounter) {
+ if (--mSuspendCounter == 0) {
+ mCounterCondVar.notify_one();
+ }
+ } else {
+ if (!WriteStringToFd(name, mWakeUnlockFd)) {
+ PLOG(ERROR) << "error writing " << name << " to " << kSysPowerWakeUnlock;
+ }
}
}
class WakeLock : public IWakeLock {
public:
- WakeLock(SystemSuspend* systemSuspend, const WakeLockIdType& id);
+ WakeLock(SystemSuspend* systemSuspend, const WakeLockIdType& id, const std::string& name);
~WakeLock();
Return<void> release();
SystemSuspend* mSystemSuspend;
WakeLockIdType mId;
+ std::string mName;
};
class SystemSuspend : public ISystemSuspend {
public:
SystemSuspend(unique_fd wakeupCountFd, unique_fd stateFd, size_t maxStatsEntries,
std::chrono::milliseconds baseSleepTime,
- const sp<SuspendControlService>& controlService);
+ const sp<SuspendControlService>& controlService, bool useSuspendCounter = true);
Return<sp<IWakeLock>> acquireWakeLock(WakeLockType type, const hidl_string& name) override;
Return<void> debug(const hidl_handle& handle, const hidl_vec<hidl_string>& options) override;
- void incSuspendCounter();
- void decSuspendCounter();
+ void incSuspendCounter(const std::string& name);
+ void decSuspendCounter(const std::string& name);
void deleteWakeLockStatsEntry(WakeLockIdType id);
bool enableAutosuspend();
void updateSleepTime(bool success);
sp<SuspendControlService> mControlService;
+
+ // If true, use mSuspendCounter to keep track of native wake locks. Otherwise, rely on
+ // /sys/power/wake_lock interface to block suspend.
+ // TODO(b/128923994): remove dependency on /sys/power/wake_lock interface.
+ bool mUseSuspendCounter;
+ unique_fd mWakeLockFd;
+ unique_fd mWakeUnlockFd;
};
} // namespace V1_0