Android 8.1 DisplayPowerController(二) Proximity Sensor的亮灭屏

概述

P-Sensor亮屏和按Power键亮屏流程还是有些不同之处,如开始调用位置、PowerManagerService中的流程等,由于在平常遇到过许多PSensor亮屏相关Bug,因此这里独立地进行下分析。

流程

在DisplayPowerController中,实例化了一个SensorEventListener对PSensor事件进行监听:

private final SensorEventListener mProximitySensorListener = new SensorEventListener() {
   
    @Override
    public void onSensorChanged(SensorEvent event) {
   
        if (mProximitySensorEnabled) {
   
            //获取当前系统时间
            final long time = SystemClock.uptimeMillis();
            //获取distance值,表示距离
            final float distance = event.values[0];
            //如果distance>=0.0f
            boolean positive = distance >= 0.0f && distance < mProximityThreshold;
            //处理PSensor上报事件
            handleProximitySensorEvent(time, positive);
        }
    }

SensorEventListener是一个用于接收Sensor新数据的接口,只有两个方法:

  • onSensorChanged(SensorEvent event):当有新Sensor事件时进行回调;
  • onAccuracyChanged(Sensor, int accuracy):Sensor注册的精度值发生改变时调用;

在DisplayPowerController中,重写了onSensorChanged()方法,因此,在接收到PSensor新事件时,会回调该方法。在这个方法中可以看到,只有mProximitySensorEnabled这个全局变量为true时,才会进入该方法体,这个值表示PSensor是否可用,由屏幕状态和PMS中的请求参数useProximitySensor共同决定,只有满足useProximitySensor=true && state!=Display.STATE_OFF时,该值才会为true,而useProximitySensor=true的条件是当前系统持有PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK类型的锁。

现在进入方法体中,它记录了当前系统时间,并根据SensorEvent判断是否是靠近还是远离后,将time和distance作为参数传给了handleProximitySensorEvent()方法,该方法如下:

private void handleProximitySensorEvent(long time, boolean positive) {
   
    //PSensor是否可用,由setProximitySensorEnabled()方法根据PMS中请求的参数
//useProximitySensor和STATE_OFF决定
    if (mProximitySensorEnabled) {
   
        //mPendingProximity表示"将要进行的PSensor状态",初始值为
    // PROXIMITY_UNKNOWN,PROXIMITY_NEGATIVE&&positive=false都表示远离,
    // 所以没有值变化,直接返回,下同
        if (mPendingProximity == PROXIMITY_NEGATIVE && !positive) {
   
            return; // no change
        }
        if (mPendingProximity == PROXIMITY_POSITIVE && positive) {
   
            return; // no change
        }
        //取消延迟处理Psensor事件的Handler
        mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
        //如果是靠近
        if (positive) {
   
            //设置mPendingProximity 值,PROXIMITY_POSITIVE表示靠近设备
            mPendingProximity = PROXIMITY_POSITIVE;
            //设置PSensor去抖动时间(或转换延迟时间),会申请一个Display锁
            // 靠近时立即灭屏
            setPendingProximityDebounceTime(
                    time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY); 
        } else {
   
            mPendingProximity = PROXIMITY_NEGATIVE;
            //设置去抖动时间,远离时会稍等会再亮屏
            setPendingProximityDebounceTime(
                    time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY); 
        }
        // Debounce the new sensor reading.
        //读取新Psensor数据
        debounceProximitySensor();
    }
}

在这个方法中,如果PSensor数据没有改变,则直接返回。如果上报值发生了改变,则首先设置mPendingProximity,表示“将要、打算进行的PSensor事件”,如果是靠近则设置该变量值为PROXIMITY_POSITIVE,远离则设置该变量值为PROXIMITY_NEGATIVE,同时调用setPendingProximityDebounceTime()方法,该方法用来设置PSensor的转换延迟时间,并会通过DisplayPowerCallback向PMS中申请一个Display锁,如果是靠近,延迟时间为0,也即不会进行延迟;如果是远离,默认延迟时间为250。该方法如下:

private void setPendingProximityDebounceTime(long debounceTime) {
   
    if (mPendingProximityDebounceTime < 0) {
   
        //申请一个PowerManagerService.Display的SuspendBlocker锁
        mCallbacks.acquireSuspendBlocker(); // acquire wake lock
    }
    //PSensor转换延迟时间
    mPendingProximityDebounceTime = debounceTime;
}

当设置完毕mPendingProximity和mPendingProximityDebounceTime后,会调用debounceProximitySensor()方法,读取新的PSensor数据,该方法如下:


                
  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
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
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值