1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "AWakeLock"
19#include <utils/Log.h>
20
21#include "ADebug.h"
22#include "AWakeLock.h"
23
24#include <binder/IPCThreadState.h>
25#include <binder/IServiceManager.h>
26#include <powermanager/PowerManager.h>
27
28
29namespace android {
30
31AWakeLock::AWakeLock() :
32    mPowerManager(NULL),
33    mWakeLockToken(NULL),
34    mWakeLockCount(0),
35    mDeathRecipient(new PMDeathRecipient(this)) {}
36
37AWakeLock::~AWakeLock() {
38    if (mPowerManager != NULL) {
39        sp<IBinder> binder = IInterface::asBinder(mPowerManager);
40        binder->unlinkToDeath(mDeathRecipient);
41    }
42    clearPowerManager();
43}
44
45bool AWakeLock::acquire() {
46    if (mWakeLockCount == 0) {
47        CHECK(mWakeLockToken == NULL);
48        if (mPowerManager == NULL) {
49            // use checkService() to avoid blocking if power service is not up yet
50            sp<IBinder> binder =
51                defaultServiceManager()->checkService(String16("power"));
52            if (binder == NULL) {
53                ALOGW("could not get the power manager service");
54            } else {
55                mPowerManager = interface_cast<IPowerManager>(binder);
56                binder->linkToDeath(mDeathRecipient);
57            }
58        }
59        if (mPowerManager != NULL) {
60            sp<IBinder> binder = new BBinder();
61            int64_t token = IPCThreadState::self()->clearCallingIdentity();
62            status_t status = mPowerManager->acquireWakeLock(
63                    POWERMANAGER_PARTIAL_WAKE_LOCK,
64                    binder, String16("AWakeLock"), String16("media"));
65            IPCThreadState::self()->restoreCallingIdentity(token);
66            if (status == NO_ERROR) {
67                mWakeLockToken = binder;
68                mWakeLockCount++;
69                return true;
70            }
71        }
72    } else {
73        mWakeLockCount++;
74        return true;
75    }
76    return false;
77}
78
79void AWakeLock::release(bool force) {
80    if (mWakeLockCount == 0) {
81        return;
82    }
83    if (force) {
84        // Force wakelock release below by setting reference count to 1.
85        mWakeLockCount = 1;
86    }
87    if (--mWakeLockCount == 0) {
88        CHECK(mWakeLockToken != NULL);
89        if (mPowerManager != NULL) {
90            int64_t token = IPCThreadState::self()->clearCallingIdentity();
91            mPowerManager->releaseWakeLock(mWakeLockToken, 0 /* flags */);
92            IPCThreadState::self()->restoreCallingIdentity(token);
93        }
94        mWakeLockToken.clear();
95    }
96}
97
98void AWakeLock::clearPowerManager() {
99    release(true);
100    mPowerManager.clear();
101}
102
103void AWakeLock::PMDeathRecipient::binderDied(const wp<IBinder>& who __unused) {
104    if (mWakeLock != NULL) {
105        mWakeLock->clearPowerManager();
106    }
107}
108
109}  // namespace android
110