您的位置:首页 > 移动开发 > Android开发

android power--wakelock framework

2015-10-28 20:23 399 查看
在开始前,先看一个图,这是android power的架构图:



wakelock是一种阻止系统进入睡眠等低功耗模式的机制,Android改动较大的另一处是增加了wakelock机制。实现在wakelock.c和userwakelock.c中。wakelock可以阻止处于正常运行(active)或者空闲(idle)状态的系统进入睡眠等低功耗状态。直到所持有的wakelock全部被释放,系统才能进入睡眠等低功耗的状态。

我们接下来看一看wake lock的机制是怎么运行和起作用的,主要关注 wakelock.c(wake_lock)文件就可以了。

1) wake lock 有加锁和解锁两种状态,加锁的方式有两种:

• 第一种是永久的锁住,这样的锁除非显示的放开,是不会解锁的,所以这种锁的使用是非常小心的。

• 第二种是超时锁,这种锁会锁定系统唤醒一段时间,如果这个时间过去了,这个锁会自动解除。

2) 锁有两种类型:

• WAKE_LOCK_SUSPEND:这种锁会防止系统进入睡眠(suspend)。

• WAKE_LOCK_IDLE:这种锁不会影响系统的休眠,用于阻止系统在持有锁的过程中进入低功耗状态。即直到wake_lock被释放,系统才会从idle状态进入低功耗状态,此低功耗状态将使中断延迟或禁用一组中断。

内核维护了:

a).两个链表,active_wake_locks[WAKE_LOCK_TYPE_COUNT]

active_wake_locks[0]维护的是suspend lock.

active_wake_locks[1]维护的是idle lock.

b).一个链表,inactive_locks来记录所有处于inactive状态的锁.

如果申请了partial wakelock,那么即使按Power键,系统也不会进Sleep,如Music播放时 如果申请了其它的wakelocks,按Power键,系统还是会进Sleep

3) 在wake lock中, 会有3个地方让系统直接开始suspend(), 分别是:

• 在wake_unlock()中, 如果发现解锁以后没有任何其他的wake lock了,就开始休眠

• 在定时器都到时间以后,定时器的回调函数会查看是否有其他的wake lock,如果没有,就在这里让系统进入睡眠。

• 在wake_lock() 中,对一个wake lock加锁以后,会再次检查一下有没有锁, 我想这里的检查是没有必要的, 更好的方法是使加锁的这个操作原子化,而不是繁冗的检查,而且这样的检查也有可能漏掉。



下面讲述wakelock是如何上层申请到传到kernel里面的:



首先应用服务在获取申请wakelock权限需要在对应服务文件夹下面的AndroidManifest.xml 里面加上以下一句话:

<uses-permission android:name="android.permission.WAKE_LOCK" />
Android 提供了现成 android.os.PowerManager 类 ,类中提供 newWakeLock(int flags, String tag)方法来取得相应层次的锁, 此函数的定义frameworks/base/core/java/android/os/PowerManager.java

public WakeLock newWakeLock(int levelAndFlags, String tag) {
validateWakeLockParameters(levelAndFlags, tag);
return new WakeLock(levelAndFlags, tag, mContext.getOpPackageName());
}


应用程序在申请wakelock时就会调用到上面这个函数,例如:

mWakeLock = ((PowerManager)mContext.getSystemService(Context.POWER_SERVICE)).
newWakeLock( PowerManager.PARTIAL_WAKE_LOCK, TAG );//PARTIAL_WAKE_LOCK是wakelock的类型,具体有以下几种类型PARTIAL_WAKE_LOCK:保持CPU 运转,屏幕和键盘灯有可能是关闭的。
//SCREEN_DIM_WAKE_LOCK:保持CPU 运转,允许保持屏幕显示但有可能是灰的,允许关闭键盘灯
//SCREEN_BRIGHT_WAKE_LOCK:保持CPU 运转,保持屏幕高亮显示,允许关闭键盘灯
//FULL_WAKE_LOCK:保持CPU 运转,保持屏幕高亮显示,键盘灯也保持亮度
//ACQUIRE_CAUSES_WAKEUP:不会唤醒设备,强制屏幕马上高亮显示,键盘灯开启。有一个例外,如果有notification弹出的话,会唤醒设备。
//ON_AFTER_RELEASE:WakeLock 被释放后,维持屏幕亮度一小段时间,减少WakeLock 循环时的闪烁情况
//如果申请了partial wakelock,那么即使按Power键,系统也不会进Sleep,如Music播放时 如果申请了其它的wakelocks,按Power键,系统还是会进Sleep

            mWakeLock.acquire();//申请锁这个里面会调用PowerManagerService里面acquireWakeLock()
…………
mWakeLock.release();//释放锁,显示的释放,如果申请的锁不在此释放系统就不会进入休眠<pre name="code" class="cpp">这个里面会调用PowerManagerService里面releaseWakeLock。




先说mWakeLock.acquire()或者acquire(timeout),这里会调用到PowerManager.java里面的acquire()(永久锁)或者acquire(long timeout)(超时锁):

public void acquire() {
synchronized (mToken) {
acquireLocked();
}
}

public void acquire(long timeout) {
synchronized (mToken) {
acquireLocked();
mHandler.postDelayed(mReleaser, timeout);
}
}
这里都会调用到acquireLocked()函数:

private void acquireLocked() {
if (!mRefCounted || mCount++ == 0) {
mHandler.removeCallbacks(mReleaser);
Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, mTraceName, 0);
try {
mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource,
mHistoryTag);
} catch (RemoteException e) {
}
mHeld = true;
}
}
mWakeLock.release()则会调用到PowerManager.java里面的release():

public void release() {
release(0);
}

public void release(int flags) {
synchronized (mToken) {
if (!mRefCounted || --mCount == 0) {
mHandler.removeCallbacks(mReleaser);
if (mHeld) {
Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);
try {
mService.releaseWakeLock(mToken, flags);
} catch (RemoteException e) {
}
mHeld = false;
}
}
if (mCount < 0) {
throw new RuntimeException("WakeLock under-locked " + mTag);
}
}
}


这里会继续往下调用获取锁会调用mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource,mHistoryTag),释放锁则会调用public void releaseWakeLock(IBinder lock, int flags) ,这里的mService是一个IPowerManager接口类,PowerManager的实现通过IPowerManager来调用Power服务的接口,IPowerManager实现了acquireWakeLock,
releaseWakeLock, shutdown, reboot等power相关的接口。

24 interface IPowerManager
25 {
26     // WARNING: The first five methods must remain the first five methods because their
27     // transaction numbers must not change unless IPowerManager.cpp is also updated.
28     void acquireWakeLock(IBinder lock, int flags, String tag, String packageName, in WorkSource ws,
29             String historyTag);
30     void acquireWakeLockWithUid(IBinder lock, int flags, String tag, String packageName,
31             int uidtoblame);
32     void releaseWakeLock(IBinder lock, int flags);
33     void updateWakeLockUids(IBinder lock, in int[] uids);
34     oneway void powerHint(int hintId, int data);
35
36     void updateWakeLockWorkSource(IBinder lock, in WorkSource ws, String historyTag);
37     boolean isWakeLockLevelSupported(int level);
38
39     void userActivity(long time, int event, int flags);
40     void wakeUp(long time);
41     void goToSleep(long time, int reason, int flags);
42
43     void startBacklight(int msec);
44     void stopBacklight();
45
46     void wakeUpByReason(long time, int reason);
47     void setSmartBookScreen(boolean on);
48
49     void nap(long time);
50     boolean isInteractive();
51     boolean isPowerSaveMode();
52     boolean setPowerSaveMode(boolean mode);
53
54     void reboot(boolean confirm, String reason, boolean wait);
55     void shutdown(boolean confirm, boolean wait);
56     void crash(String message);
57
58     void setStayOnSetting(int val);
59     void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs);
60
61     // temporarily overrides the screen brightness settings to allow the user to
62     // see the effect of a settings change without applying it immediately
63     void setTemporaryScreenBrightnessSettingOverride(int brightness);
64     void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj);
65
66     void setBacklightOffForWfd(boolean enable);
67     void setBlNotify();
68
69     // sets the attention light (used by phone app only)
70     void setAttentionLight(boolean on, int color);
71
72     //+[framework] add for cpu wakelock
73     void acquireHtcCpuCtrl(int flags, IBinder lock, String tag, in WorkSource ws, int level, String packageName);
74     void releaseHtcCpuCtrl(IBinder lock, int flags);
75     //-[framework]
76
77     //+ [framework] Add feature to improve battery life on phone offhook, menghui_wu
78     void customizeScreenOffDelay_Once(int screenOffDelay, boolean calcRemaining);
79     void customizeScreenOffDelay_Always(int screenOffDelay, boolean calcRemaining);
80     void customizeScreenOffDelay_System(int screenOffDelay, boolean calcRemaining);
81     //- [framework] Add feature to improve battery life on phone offhook, menghui_wu
82
83     // ++ [framework] overload method to IPowerManager for HtcShutdownThread
84     void lowLevelShutdown_system();
85     void lowLevelReboot_system(String reason);
86     // -- [framework] overload method to IPowerManager for HtcShutdownThread
87
88     // ++ [framework] Add system wipe API
89     boolean wipeSystem(in byte[] imei, in byte[] encMsg);
90     // -- [framework] Add system wipe API
91
92     //++[framework] For max auto brightness feature
93     void setTemporaryScreenAutoBrightnessPercentageSettingOverride(int percentage);
94     //--[framework] For max auto brightness feature
95
96     // ++ [framework] to determine actual screen state.
97     boolean isActualScreenOn();
98     // -- [framework] to determine actual screen state.
99
100     //++[framework] If the OOBE still keep in 1st page, then shutdown the devicePower
101     void informOOBEStatusChange(boolean status);
102     //--[framework] If the OOBE still keep in 1st page, then shutdown the devicePower
103
104     //++[framework] To check if P-sensor wake lock is held
105     boolean getProximityWakeLockIsHeld();
106     //--[framework] To check if P-sensor wake lock is held
107
108     //+[framework] to get power key screen on event
109     void wakeUpFromPowerKey(long time);
110     //-[framework] to get power key screen on event
111 }


这里只要获得Power服务的IBinder,获取锁通过反射调用PowerManagerService.java的函数acquireWakeLock(IBinder lock, int flags, String tag, String packageName,WorkSource ws, String historyTag)函数,释放锁则通过反射调用public void releaseWakeLock(IBinder lock, int flags) :

public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,
WorkSource ws, String historyTag) {
if (lock == null) {
throw new IllegalArgumentException("lock must not be null");
}
if (packageName == null) {
throw new IllegalArgumentException("packageName must not be null");
}
PowerManager.validateWakeLockParameters(flags, tag);

mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
if ((flags & PowerManager.DOZE_WAKE_LOCK) != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
}
if (ws != null && ws.size() != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.UPDATE_DEVICE_STATS, null);
} else {
ws = null;
}

final int uid = Binder.getCallingUid();
final int pid = Binder.getCallingPid();
final long ident = Binder.clearCallingIdentity();
try {
acquireWakeLockInternal(lock, flags, tag, packageName, ws, historyTag, uid, pid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}

        public void releaseWakeLock(IBinder lock, int flags) {
            if (lock == null) {
                throw new IllegalArgumentException("lock must not be null");
            }

            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);

            final long ident = Binder.clearCallingIdentity();
            try {
                releaseWakeLockInternal(lock, flags);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        } 
acquireWakeLock最后调用了acquireWakeLockInternal函数,releaseWakeLock最后调用了releaseWakeLockInternal函数:

private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName,
WorkSource ws, String historyTag, int uid, int pid){
synchronized (mLock) {
if (DEBUG_SPEW) {
Slog.d(TAG, "acquireWakeLockInternal: lock=" + Objects.hashCode(lock)
+ ", flags=0x" + Integer.toHexString(flags)
+ ", tag=\"" + tag + "\", ws=" + ws + ", uid=" + uid + ", pid=" + pid);
}

WakeLock wakeLock;
int index = findWakeLockIndexLocked(lock);
boolean notifyAcquire;
if (index >= 0) {
wakeLock = mWakeLocks.get(index);
if (!wakeLock.hasSameProperties(flags, tag, ws, uid, pid)) {
// Update existing wake lock.  This shouldn't happen but is harmless.
notifyWakeLockChangingLocked(wakeLock, flags, tag, packageName,
uid, pid, ws, historyTag);
wakeLock.updateProperties(flags, tag, packageName, ws, historyTag, uid, pid);
}
notifyAcquire = false;
} else {
wakeLock = new WakeLock(lock, flags, tag, packageName, ws, historyTag, uid, pid);
try {
lock.linkToDeath(wakeLock, 0);
} catch (RemoteException ex) {
throw new IllegalArgumentException("Wake lock is already dead.");
}
mWakeLocks.add(wakeLock);
notifyAcquire = true;
wakeLock.mActiveSince = SystemClock.uptimeMillis();

// ++ [HTC SSD Power] WLD implemented some policy to detect abnormal wakelock
if (mHtcWakeLockDetector != null) {
try {
mHtcWakeLockDetector.addWakeLock(wakeLock.mLock,
wakeLock.mFlags,
wakeLock.mTag,
wakeLock.mPackageName,
wakeLock.mWorkSource,
wakeLock.mOwnerUid,
wakeLock.mOwnerPid);
} catch (Exception e) {
Slog.w(TAG, "[HtcWLD] addWakeLock Exception : ", e);
}
}
// -- [HTC SSD Power] WLD implemented some policy to detect abnormal wakelock
}

// ++ [framework] Change dim timeout during Mirror or Miracast mode
if (isScreenLock(wakeLock)) {
updateUserActivityEventLocked();
}
// -- [framework] Change dim timeout during Mirror or Miracast mode

//++[framework] Add protection to avoid the p-sensor is always Near.
if ((wakeLock.mFlags & PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) != 0) {
cancelPsensorNearMonitorMsg();
}
//--[framework] Add protection to avoid the p-sensor is always Near.

applyWakeLockFlagsOnAcquireLocked(wakeLock, uid);

//+[framework] add for cpu wakelock
if ((flags & PowerManager.WAKE_LOCK_LEVEL_MASK) == PowerManager.CPU_PERF_WAKE_LOCK) {
mCpuPerfCount++;
// ++ [framework] Rework CPU_PERF_WAKE_LOCK to use new kernel API
updateHtcCpuCtrlLevel(PowerManager.CPU_PERF_WAKE_LOCK);
// -- [framework] Rework CPU_PERF_WAKE_LOCK to use new kernel API
}
//-[framework] add for cpu wakelock
// ++ [framework] Monitor wake lock behaviors
if (mHtcWakeLockMonitor != null) {
mHtcWakeLockMonitor.addRecord(wakeLock.mFlags, wakeLock.mTag, wakeLock.mOwnerUid, wakeLock.mOwnerPid, wakeLock.mLock);
}
// -- [framework] Monitor wake lock behaviors

// ++ [framework] Add WakeLock related logs to determine issue root cause more easily.
if (HtcPMSExtension.canPrintWakeLockLog(flags, tag)) {
// ++ [framework] Encrypt tag if neccessary in release rom.
String new_tag = tag;
if (!DEBUG_SECURITY_ON) {
if (new_tag.contains("@")) {
new_tag = "encrypted_tag"; // To prevent leak user account into debug logs.
}
}
// -- [framework] Encrypt tag if neccessary in release rom.

String typeInfo = HtcPMSExtension.getWakeLockTypeInfo(flags);
String flagInfo = wakeLock.getLockFlagsString();
Formatter f;
if (!wakeLock.hasSameProperties(flags, tag, ws, uid, pid)) {
f = new Formatter();
//+[framework] add worksource for debug
f.format("releaseWL(%x): %s %s %s 0x%x %s",
wakeLock.hashCode(), typeInfo, flagInfo, new_tag, flags, ws);
//-[framework] add worksource for debug
Slog.d(TAG, f.toString());
}
f = new Formatter();
//+[framework] add worksource for debug
f.format("acquireWL(%x): %s %s %s 0x%x %d %d %s",
wakeLock.hashCode(), typeInfo, flagInfo, new_tag, flags, pid, uid, ws);
//-[framework] add worksource for debug
Slog.d(TAG, f.toString());
}
// -- [framework] Add WakeLock related logs to determine issue root cause more easily.

mDirty |= DIRTY_WAKE_LOCKS;
updatePowerStateLocked();
if (notifyAcquire) {
// This needs to be done last so we are sure we have acquired the
// kernel wake lock.  Otherwise we have a race where the system may
// go to sleep between the time we start the accounting in battery
// stats and when we actually get around to telling the kernel to
// stay awake.
notifyWakeLockAcquiredLocked(wakeLock);
}
}
}

private void releaseWakeLockInternal(IBinder lock, int flags) {
        synchronized (mLock) {
            int index = findWakeLockIndexLocked(lock);
            if (index < 0) {
                if (DEBUG_SPEW) {
                    Slog.d(TAG, "releaseWakeLockInternal: lock=" + Objects.hashCode(lock)
                            + " [not found], flags=0x" + Integer.toHexString(flags));
                }
                // ++ [framework] Monitor wake lock behaviors
                // No such wakelock, stop dead record here. GB30 Menghui Wu
                if (mHtcWakeLockMonitor != null) {
                    mHtcWakeLockMonitor.stopDeadRecord(lock);
                }
                // -- [framework] Monitor wake lock behaviors
                return;
            }

            WakeLock wakeLock = mWakeLocks.get(index);
            wakeLock.mTotalTime = SystemClock.uptimeMillis() - wakeLock.mActiveSince;

            // ++ [HTC SSD Power] WLD implemented some policy to detect abnormal wakelock
            if (mHtcWakeLockDetector != null) {
                try {
                    mHtcWakeLockDetector.removeWakeLock(wakeLock.mLock);
                } catch (Exception e) {
                    Slog.w(TAG, "[HtcWLD] removeWakeLock Exception : ", e);
                }
            }
            // -- [HTC SSD Power] WLD implemented some policy to detect abnormal wakelock

            // ++ [framework] Add WakeLock related logs to determine issue root cause more easily.
            if (HtcPMSExtension.canPrintWakeLockLog(wakeLock.mFlags, wakeLock.mTag)) {
                // ++ [framework] Encrypt tag if neccessary in release rom.
                String new_tag = wakeLock.mTag;
                if (!DEBUG_SECURITY_ON) {
                    if (new_tag.contains("@")) {
                        new_tag = "encrypted_tag"; // To prevent leak user account into debug logs.
                    }
                }
                // -- [framework] Encrypt tag if neccessary in release rom.

                String typeInfo = HtcPMSExtension.getWakeLockTypeInfo(wakeLock.mFlags);
                String flagInfo = wakeLock.getLockFlagsString();
                Formatter f = new Formatter();
                f.format("releaseWL(%x): %s %s %s 0x%x %s", wakeLock.hashCode(), typeInfo, flagInfo, new_tag, wakeLock.mFlags, wakeLock.mWorkSource);
                Slog.d(TAG, f.toString());
            }
            // -- [framework] Add WakeLock related logs to determine issue root cause more easily.

            if ((flags & PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY) != 0) {
                mRequestWaitForNegativeProximity = true;
            }

            //++[framework] Add protection to avoid the p-sensor is always Near.
            if ((wakeLock.mFlags & PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) != 0) {
                if (mProximityPositive) {
                    sendPsensorNearMonitorMsg();
                }
            }
            //--[framework] Add protection to avoid the p-sensor is always Near.

            //+[framework] add for cpu wakelock
            if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) == PowerManager.CPU_PERF_WAKE_LOCK) {
                mCpuPerfCount--;
                // ++ [framework] Rework CPU_PERF_WAKE_LOCK to use new kernel API
                if (mCpuPerfCount == 0) {
                    if (mCpuFreqMinCount == 0) {
                        nativeReleaseCpuFreqMinWakeLock();
                    }
                    if (mCpuNumMinCount == 0) {
                        nativeReleaseCpuNumMinWakeLock();
                    }
                    if (mCpuFreqMinCount != 0 || mCpuNumMinCount != 0) {
                        updateHtcCpuCtrlLevel(PowerManager.CPU_PERF_WAKE_LOCK);
                    }
                } else {
                    updateHtcCpuCtrlLevel(PowerManager.CPU_PERF_WAKE_LOCK);
                }
                // -- [framework] Rework CPU_PERF_WAKE_LOCK to use new kernel API
            }
            //-[framework] add for cpu wakelock

            // ++ [framework] Monitor wake lock behaviors
            if (mHtcWakeLockMonitor != null) {
                mHtcWakeLockMonitor.stopRecord(wakeLock.mTag, wakeLock.mLock);
            }
            // -- [framework] Monitor wake lock behaviors
            wakeLock.mLock.unlinkToDeath(wakeLock, 0);
            removeWakeLockLocked(wakeLock, index);
        }
    }


releaseWakeLockInternal最后调用了removeWakeLockLocked,removeWakeLockLocked和acquireWakeLockInternal最后调用了updatePowerStateLocked函数:

private void removeWakeLockLocked(WakeLock wakeLock, int index) {
        mWakeLocks.remove(index);
        notifyWakeLockReleasedLocked(wakeLock);

        applyWakeLockFlagsOnReleaseLocked(wakeLock);
        mDirty |= DIRTY_WAKE_LOCKS;
        updatePowerStateLocked();
    }

private void updatePowerStateLocked(){
// ++ [framework] Add debug log.
if (DEBUG_ON && mHtcPMSExtension != null) {
Formatter f = new Formatter();
try {
final String logKey = "udpatePowerStateLocked-arg_check";
f.format("updatePSL(0x%x,%b)", mDirty, mSystemReady);
mHtcPMSExtension.reduceLog(logKey, TAG, f.toString());
} catch (Exception e) {
if (f != null) {
Slog.d(TAG, " - " + f.toString());
}
}
}
// -- [framework] Add debug log.

if (!mSystemReady || mDirty == 0) {
return;
}
if (!Thread.holdsLock(mLock)) {
Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");
}

Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");
try {
// Phase 0: Basic state updates.
updateIsPoweredLocked(mDirty);
updateStayOnLocked(mDirty);

// Phase 1: Update wakefulness.
// Loop because the wake lock and user activity computations are influenced
// by changes in wakefulness.
final long now = SystemClock.uptimeMillis();
int dirtyPhase2 = 0;
for (;;) {
int dirtyPhase1 = mDirty;
dirtyPhase2 |= dirtyPhase1;
mDirty = 0;

updateWakeLockSummaryLocked(dirtyPhase1);
updateUserActivitySummaryLocked(now, dirtyPhase1);
if (!updateWakefulnessLocked(dirtyPhase1)) {
break;
}
}

// Phase 2: Update display power state.
boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);

// Phase 3: Update dream state (depends on display ready signal).
updateDreamLocked(dirtyPhase2, displayBecameReady);

// Phase 4: Send notifications, if needed.
if (mDisplayReady) {
finishInteractiveStateChangeLocked();
}

// Phase 5: Update suspend blocker.
// Because we might release the last suspend blocker here, we need to make sure
// we finished everything else first!
updateSuspendBlockerLocked();
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
updatePowerStateLocked最后调用updateSuspendBlockerLocked函数:

private void updateSuspendBlockerLocked() {
final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);
final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked();
final boolean autoSuspend = !needDisplaySuspendBlocker;

// Disable auto-suspend if needed.
if (!autoSuspend) {
if (mDecoupleHalAutoSuspendModeFromDisplayConfig) {
setHalAutoSuspendModeLocked(false);
}
if (mDecoupleHalInteractiveModeFromDisplayConfig) {
setHalInteractiveModeLocked(true);
}
}

// First acquire suspend blockers if needed.
if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {
mWakeLockSuspendBlocker.acquire();
mHoldingWakeLockSuspendBlocker = true;
}
if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {
if (DEBUG_ON) {
Slog.d(TAG, "acq wl D");
}
mDisplaySuspendBlocker.acquire();
mHoldingDisplaySuspendBlocker = true;
}

// Then release suspend blockers if needed.
if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {
mWakeLockSuspendBlocker.release();
mHoldingWakeLockSuspendBlocker = false;
}
if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) {
if (DEBUG_ON) {
Slog.d(TAG, "rel wl D");
}
mDisplaySuspendBlocker.release();
mHoldingDisplaySuspendBlocker = false;
}

// Enable auto-suspend if needed.
if (autoSuspend) {
if (mDecoupleHalInteractiveModeFromDisplayConfig) {
setHalInteractiveModeLocked(false);
}
if (mDecoupleHalAutoSuspendModeFromDisplayConfig) {
setHalAutoSuspendModeLocked(true);
}
}
}
这里如果是获取锁会调用SuspendBlocker类的acquire方法,释放锁则会调用SuspendBlocker类的release方法:

public void acquire() {
synchronized (this) {
mReferenceCount += 1;
if (mReferenceCount == 1) {
if (DEBUG_SPEW) {
Slog.d(TAG, "Acquiring suspend blocker \"" + mName + "\".");
}
Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, mTraceName, 0);
nativeAcquireSuspendBlocker(mName);
}
}
}

public void release() {
synchronized (this) {
mReferenceCount -= 1;
if (mReferenceCount == 0) {
if (DEBUG_SPEW) {
Slog.d(TAG, "Releasing suspend blocker \"" + mName + "\".");
}
nativeReleaseSuspendBlocker(mName);
Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);
} else if (mReferenceCount < 0) {
Slog.wtf(TAG, "Suspend blocker \"" + mName
+ "\" was released without being acquired!", new Throwable());
mReferenceCount = 0;
}
}
}
这里的acquire和release方法分别通过JNI层的映射转换,分别会调用到JNI层com_android_server_power_PowerManagerService.cpp的nativeAcquireSuspendBlocker和nativeReleaseSuspendBlocker方法:

static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {
ScopedUtfChars name(env, nameStr);
acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
}

static void nativeReleaseSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {
ScopedUtfChars name(env, nameStr);
release_wake_lock(name.c_str());
}
nativeAcquireSuspendBlocker和nativeReleaseSuspendBlocker则会调用到HAL层hardware/libhardware_legacy/power/power.c的acquire_wake_lock和release_wake_lock方法:

acquire_wake_lock(int lock, const char* id)
{
initialize_fds();

//    ALOGI("acquire_wake_lock lock=%d id='%s'\n", lock, id);

if (g_error) return -g_error;

int fd;

if (lock == PARTIAL_WAKE_LOCK) {
fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];
}
else {
return -EINVAL;
}

return write(fd, id, strlen(id));
}

int
release_wake_lock(const char* id)
{
initialize_fds();

//    ALOGI("release_wake_lock id='%s'\n", id);

if (g_error) return -g_error;

ssize_t len = write(g_fds[RELEASE_WAKE_LOCK], id, strlen(id));
return len >= 0;
}
到这里wakelock framework层内容就讲完了,下一篇将介绍kernel的wakelock!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: