Psensor功耗异常-config_suspendWhenScreenOffDueToProximity默认false情况

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无法正常休眠。

public class MainActivity extends Activity implements SensorEventListener{ public static final String TAG = "SensorTest"; private SensorManager sensorManager; private TextView tv; private PowerManager localPowerManager = null;// 电源管理对象 private WakeLock localWakeLock = null;// 电源锁 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); tv = (TextView) findViewById(R.id.tv); localPowerManager = (PowerManager) getSystemService(POWER_SERVICE); // 获取PowerManager.WakeLock对象,后面的参数|表示同时传入两个值,最后的是LogCat里用的Tag localWakeLock = this.localPowerManager.newWakeLock(32, "hahaha");// 第一个参数为电源锁级别,第二个是日志tag } @Override protected void onResume() { sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY), SensorManager.SENSOR_DELAY_UI); super.onResume(); } @Override protected void onPause() { sensorManager.unregisterListener(this); super.onPause(); } @Override public void onSensorChanged(SensorEvent event) { // TODO Auto-generated method stub float[] values = event.values; switch (event.sensor.getType()) { case Sensor.TYPE_PROXIMITY: tv.setText(values[0] + ""); if (values[0] == 0.0) {// 贴近手机 System.out.println("hands up"); Log.d(TAG, "hands up in calling activity"); if (localWakeLock.isHeld()) { return; } else { localWakeLock.acquire();// 申请设备电源锁 } } else {// 远离手机 System.out.println("hands moved"); Log.d(TAG, "hands moved in calling activity"); if (localWakeLock.isHeld()) { return; } else { localWakeLock.setReferenceCounted(false); localWakeLock.release(); // 释放设备电源锁 } break; } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

法迪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值