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 里面加上以下一句话:
应用程序在申请wakelock时就会调用到上面这个函数,例如:
先说mWakeLock.acquire()或者acquire(timeout),这里会调用到PowerManager.java里面的acquire()(永久锁)或者acquire(long timeout)(超时锁):
这里会继续往下调用获取锁会调用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相关的接口。
这里只要获得Power服务的IBinder,获取锁通过反射调用PowerManagerService.java的函数acquireWakeLock(IBinder lock, int flags, String tag, String packageName,WorkSource ws, String historyTag)函数,释放锁则通过反射调用public void releaseWakeLock(IBinder lock, int flags) :
releaseWakeLockInternal最后调用了removeWakeLockLocked,removeWakeLockLocked和acquireWakeLockInternal最后调用了updatePowerStateLocked函数:
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!
相关文章推荐
- Ubuntu 下载 & 编译 Android5.1 源码
- android 动画效果大全
- Android中长TextView实现跑马灯效果
- Android ORM数据库框架之-greenDao(二)
- Android中实现两次点击返回键退出本程序
- Android--Fragment的懒加载
- 008android初级篇之jni中数组的传递
- Android Studio 教程(干货)
- Android 自定义View
- 如何使用Android蓝牙开发
- Android设置屏幕亮度
- Android中Activity出现与退出的自定义动画
- 【教程】Microsoft Visual Studio 2015 安装Android SDK
- [Android高级知识][1] 如何调用支付宝接口
- VS2015配置安卓Android和iOS开发环境
- 【Android】自定义dialog的布局样式
- android中使用百度定位sdk实时的计算移动距离
- Android通过广播实现灭屏和唤醒
- 定义XML菜单文件
- Android实战简易教程-第六十六枪(结合SharedPreferenced实现自动登录功能)