1. 现象
正常情况下使用Psenor待机是不影响功耗的,即即使申请了psenor的锁,也不会影响CPU进入休眠状态,但是在功耗分析中,我们遇到了psensor上层持锁导致的功耗异常。即config_suspendWhenScreenOffDueToProximity默认false情况下,调用上层调用psensor,必现无法休眠的现象
测试用例 | 平均电流 |
---|---|
飞行模式 | 5 mA |
飞行模式+psensor正常 | 5mA |
飞行模式+psensor异常 | 18mA |
2. 上层apk 调用psenor demo
mProximityWakeLock = mPowerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, "TAG_suhuazhi" + "#"
+ getClass().getName());
private void turnOnProximitySensor() {
Log.d("suhuazhi", "turnOnProximitySensor");
if (mProximityWakeLock != null) {
if (!mProximityWakeLock.isHeld()) {
mProximityWakeLock.acquire();
Log.d("suhuazhi", "turnOnProximitySensor acquire");
Toast.makeText(this, "acquire psensor", Toast.LENGTH_SHORT);
}
}
}
3. 功耗异常日志
当上层apk持 PROXIMITY_SCREEN_OFF_WAKE_LOCK flag时,手动按Power键灭屏,待机电流正常,但是遮挡手机,触发psensor远近监听事件,从而屏幕自动灭屏事件,发现待机电流一直处于 18 mA,即手机无法进入休眠状态。对应的日志如下
正常psenro开启,灭屏后一般只打印一次如下关键字,异常情况下,会出现频繁打印的情况
PowerManagerService.Display
4. 查看源码
这里主要看acquire函数是否被调用,如果找到相关调用信息,打印调用所需条件对比正常机器即可。因为有时候并不是逻辑出现问题了,可能是某些参数没有配置好导致。或者仅只是为了分析效率高些
4.1 PowerManagerService.Display
681 synchronized (mLock) {
682 mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
683 mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
684 mDisplaySuspendBlocker.acquire();
4.2 PowerManagerService. updateSuspendBlockerLocked()
2710 if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {
// display 类型持锁
2711 mDisplaySuspendBlocker.acquire();
2712 mHoldingDisplaySuspendBlocker = true;
2713 }
4.3 needDisplaySuspendBlocker
/**
2748 * Return true if we must keep a suspend blocker active on behalf of the display.
2749 * We do so if the screen is on or is in transition between states.
2750 */
2751 private boolean needDisplaySuspendBlockerLocked() {
2752 if (!mDisplayReady) {
2753 return true;
2754 }
2755 if (mDisplayPowerRequest.isBrightOrDim()) {
2756 // If we asked for the screen to be on but it is off due to the proximity
2757 // sensor then we may suspend but only if the configuration allows it.
2758 // On some hardware it may not be safe to suspend because the proximity
2759 // sensor may not be correctly configured as a wake-up source.
2760 if (!mDisplayPowerRequest.useProximitySensor || !mProximityPositive
2761 || !mSuspendWhenScreenOffDueToProximityConfig) {
// 阻止进入CPU suspend 休眠状态
2762 return true;
2763 }
2764 }
2765 if (mScreenBrightnessBoostInProgress) {
2766 return true;
2767 }
2768 // Let the system suspend if the screen is off or dozing.
2769 return false;
2770 }
4.4 mSuspendWhenScreenOffDueToProximityConfig
<!-- Indicate whether to allow the device to suspend when the screen is off
927 due to the proximity sensor. This resource should only be set to true
928 if the sensor HAL correctly handles the proximity sensor as a wake-up source.
929 Otherwise, the device may fail to wake out of suspend reliably.
930 The default is false. -->
931 <bool name="config_suspendWhenScreenOffDueToProximity">false</bool>//修改为true即可
5 解决方案
原因 config_suspendWhenScreenOffDueToProximity 没有设置ture导致,对比其他正常项目,该配置值在proximity sendor 调试ok后,一般要将上层对应的config属性设置ture,不然在PMS中会进行needDisplaySuspendBlockerLocked,导致DisplaySuspendBlocker.acquire()被调用,导致CPU无法正常休眠。