Android DisplayManagerService--0

2023-11-29  本文已影响0人  DarcyZhou

本文转载自:Android R DisplayManagerService(5) Proximity Sensor灭屏原理

本文基于Android 11.0源码分析

1.概述

  在PMS灭屏流程中可以通过距离传感器的灭屏,它和正常灭屏原理上不同。像按Power键灭屏这类正常灭屏来说,会将PMS部分的系统状态和DMS中整体状态全部更新(PMS中唤醒状态mWakefulness会设置为ASLEEP、DOZING,DMS中display状态会设置为STATE_OFF、STATE_DOZING、STATE_DOZING_SUSPEND)。而如果是PSensor灭屏,只会将Display状态设置为STATE_OFF,同时关闭屏幕亮度,PMS中的系统状态依旧保持Awake状态。这篇文章就对PSensor亮灭屏流程和原理进行分析。

2.注册PSensor

  DMS中,通过申请PROXIMITY_SCREEN_OFF_WAKE_LOCK类型WakeLock锁来注册PSensor:

mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = mPowerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK,"TAG");
mWakeLock.acquire();  // 申请
mWakeLock.release(/*PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY*/);  // 释放

当PMS中申请该类型WakeLock后,在向DisplayMS发起请求时,DisplayPowerRequest.useProximitySensor 属性将会设置为true,表示需要使用PSensor。DisplayPowerController中收到请求后,将在updatePowerState()方法中,将针对该属性进行处理PSensor注册:

// frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
    private void updatePowerState() {
        ......
        // Apply the proximity sensor.
        if (mProximitySensor != null) {
            // 如果持有PROXIMITY_SCREEN_OFF_WAKE_LOCK类型WakeLock锁,且请求Display状态不为OFF
            if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {
                // 注册PSensor
                setProximitySensorEnabled(true);
                // PSensor收到靠近事件时,设置mScreenOffBecauseOfProximity为true,表示由于PSensor导致的灭屏
                if (!mScreenOffBecauseOfProximity
                        && mProximity == PROXIMITY_POSITIVE) {
                    mScreenOffBecauseOfProximity = true;
                    // 回调通知PMS收到靠近事件
                    sendOnProximityPositiveWithWakelock();
                }
            // 如果mWaitingForNegativeProximity为true,且此时PSensor状态为靠近,继续保持PSensor监听
            } else if (mWaitingForNegativeProximity
                    && mScreenOffBecauseOfProximity
                    && mProximity == PROXIMITY_POSITIVE
                    && state != Display.STATE_OFF) {
                setProximitySensorEnabled(true);
            // 解除PSensor监听
            } else {
                setProximitySensorEnabled(false);
                mWaitingForNegativeProximity = false;
            }
            // 表示收到远离事件,重置mScreenOffBecauseOfProximity
            if (mScreenOffBecauseOfProximity
                    && mProximity != PROXIMITY_POSITIVE) {
                mScreenOffBecauseOfProximity = false;
                // 回调通知PMS收到远离事件
                sendOnProximityNegativeWithWakelock();
            }
        } else {
            mWaitingForNegativeProximity = false;
        }
        // 如果PSensor收到上报靠近事件,将Display状态设置为OFF进行灭屏
        if (mScreenOffBecauseOfProximity) {
            state = Display.STATE_OFF;
        }
        .......
        // 设置状态
        animateScreenStateChange(state, performScreenOffTransition);
        ......

在DisplayPowerController#updatePowerState()方法的以上代码片段中,处理PSensor相关逻辑,包括PSensor监听的注册、解除、事件处理:

  1. 当请求对象mPowerRequest.useProximitySensor为true,且当前Display状态处于非OFF时,通过setProximitySensorEnabled()方法设置PSensor监听;

  2. 当PSensor上报靠近事件时,将mScreenOffBecauseOfProximity设置为true,并执行sendOnProximityPositiveWithWakelock()方法通知PMS收到靠近事件;

  3. 当请求对象mPowerRequest.useProximitySensor为false,说明PMS中相关WakeLock已经释放,如果释放时带有RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY标记,则mWaitingForNegativeProximity变量为true,若此时PSensor监听状态依然处于靠近状态,则不会立即解除PSensor监听;

  4. 如果释放WakeLock时,不带有RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY标记,则解除PSensor监听,并将将mScreenOffBecauseOfProximity重置;

  5. 当PSensor上报远离事件时,将mScreenOffBecauseOfProximity重置为false,并执行sendOnProximityNegativeWithWakelock()方法通知PMS收到远离事件;

  通过setProximitySensorEnabled()方法进行PSensor监听的注册与解除:

// frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
    private void setProximitySensorEnabled(boolean enable) {
        if (enable) {
            // 注册
            if (!mProximitySensorEnabled) {
                mProximitySensorEnabled = true;
                mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,
                        SensorManager.SENSOR_DELAY_NORMAL, mHandler);
            }
        // 解除
        } else {
            if (mProximitySensorEnabled) {
                mProximitySensorEnabled = false;
                // 重置PSensor监听状态
                mProximity = PROXIMITY_UNKNOWN;
                mPendingProximity = PROXIMITY_UNKNOWN;
                mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
                mSensorManager.unregisterListener(mProximitySensorListener);
                // 
                clearPendingProximityDebounceTime(); 
            }
        }
    }

3.PSensor事件处理

  注册成功后,mProximitySensorListener将用来接收PSensor上报的数据:

// frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
    private final SensorEventListener mProximitySensorListener = new SensorEventListener() {
        @Override
        public void onSensorChanged(SensorEvent event) {
            if (mProximitySensorEnabled) {
                final long time = SystemClock.uptimeMillis();
                // 获取上报值
                final float distance = event.values[0];
                // 判断是否是靠近事件
                boolean positive = distance >= 0.0f && distance < mProximityThreshold;
                // 处理上报事件
                handleProximitySensorEvent(time, positive);
            }
        }
    };

这个方法中,会得到PSensor上报的事件值,如果 0.0f <= distance < mProximityThreshold,说明上报了靠近事件,distance >= mProximityThreshold则说明上报了远离事件。然后调用handleProximitySensorEvent()方法,根据上报事件值来进行灭屏和亮屏流程:

// frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java

    private void handleProximitySensorEvent(long time, boolean positive) {
        if (mProximitySensorEnabled) {
            // 两次上报事件均为远离事件时,不做处理
            if (mPendingProximity == PROXIMITY_NEGATIVE && !positive) {
                return; // no change
            }
            // 两次上报事件均为靠近事件时,不做处理
            if (mPendingProximity == PROXIMITY_POSITIVE && positive) {
                return; // no change
            }

            mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
            // 上报靠近事件
            if (positive) {
                // 表示接下来设置靠近事件
                mPendingProximity = PROXIMITY_POSITIVE;
                // 设置防抖动时长,PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY为0
                setPendingProximityDebounceTime(
                        time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY); // acquire wake lock
            // 上报远离事件
            } else {
                mPendingProximity = PROXIMITY_NEGATIVE;
                setPendingProximityDebounceTime(
                        time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY); // acquire wake lock
            }
            // 防抖动操作
            debounceProximitySensor();
        }
    }

这个方法中,首先设置mPendingProximity变量,然后调用setPendingProximityDebounceTime()方法,设置PSensor事件的防抖动时长:

// frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
private void setPendingProximityDebounceTime(long debounceTime) {
    if (mPendingProximityDebounceTime < 0) {
        // 向PMS中申请一个SuspendBlocker锁
        mCallbacks.acquireSuspendBlocker();    
    }
    // 更新防抖动时长
    mPendingProximityDebounceTime = debounceTime;    
}

最后执行debounceProximitySensor()方法,进行防抖动处理,原生流程中靠近事件和远离时间的防抖时长分别为0ms和250ms,也就是说,如果是靠近事件则立即处理,如果是远离时间,则在250ms后处理,避免由于频繁的靠近远离操作而频繁地亮灭屏。该方法如下:

// frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
private void debounceProximitySensor() {
    if (mProximitySensorEnabled
            && mPendingProximity != PROXIMITY_UNKNOWN
            && mPendingProximityDebounceTime >= 0) {   
        final long now = SystemClock.uptimeMillis();
        // 说明当前时间已经超过规定去抖动时间
        if (mPendingProximityDebounceTime <= now) {  
            // 更新Psensor监听状态
            mProximity = mPendingProximity;   
            // 更新全局状态
            updatePowerState();    
            // 清除防抖动时长,并释放SuspendBlcoker锁
            clearPendingProximityDebounceTime(); 
        // 说明还到达规定的防抖动时间
        } else {   
            Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED);
            mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime);
        }
    }
}

如果当前时间还不满足规定去抖动时长,则会用Handler设置一个定时操作,到达时间后再执行一次debounceProximitySensor(),完成mProximity属性的更新,然后调用updatePowerState()开始进行全局更新。

  在这次更新时,将根据PSensor监听状态mProximity的值进行判断,靠近时,设置Display状态为Display.STATE_OFF,亮度也会被设置为0。

4.PMS中的工作

  当PSensor监听状态发生变化时,会调用sendOnProximityPositiveWithWakelock()方法和sendOnProximityNegativeWithWakelock()方法,回调到PMS中:

// frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
private void sendOnProximityPositiveWithWakelock() {
    // 申请SuspendBlocker锁
    mCallbacks.acquireSuspendBlocker();   
    mHandler.post(mOnProximityPositiveRunnable);
}

private final Runnable mOnProximityPositiveRunnable = new Runnable() {
    @Override
    public void run() {
        // 回调PMS.onProximityPositive()
        mCallbacks.onProximityPositive();    
        // 释放SuspendBlocker
        mCallbacks.releaseSuspendBlocker();  
    }
};

private void sendOnProximityNegativeWithWakelock() {
    // 申请SuspendBlocker
    mCallbacks.acquireSuspendBlocker();   
    mHandler.post(mOnProximityNegativeRunnable);
}

private final Runnable mOnProximityNegativeRunnable = new Runnable() {
    @Override
    public void run() {
        // 回调PMS.onProximityNegative()
        mCallbacks.onProximityNegative(); 
        // 释放SuspendBlocker
        mCallbacks.releaseSuspendBlocker();   
    }
};

mCallbacks对象来自PMS中,所以接下来将执行到PMS中以下两个回调方法:

// frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
@Override
public void onProximityPositive() {
    synchronized (mLock) {
        // 表示接收到靠近事件
        mProximityPositive = true;    
        mDirty |= DIRTY_PROXIMITY_POSITIVE;
        // 更新全局Power状态
        updatePowerStateLocked();    
    }
}

@Override
public void onProximityNegative() {
    synchronized (mLock) {
        // 表示接收到远离事件
        mProximityPositive = false;   
        mDirty |= DIRTY_PROXIMITY_POSITIVE;
        // 更新用户活动时间
        userActivityNoUpdateLocked(SystemClock.uptimeMillis(),
                PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);   
        // 更新全局Power状态
        updatePowerStateLocked();   
    }
}

当DisplayPowerController中PSensor状态发生变化时,会通知PMS中更新mProximityPositive,而且如果是远离事件,还会更新用户活动时间。这个值有何作用?发现在下面isBeingKeptAwakeLocked()方法中用到了:

private boolean isBeingKeptAwakeLocked() {
    return mStayOn
            || mProximityPositive
            || (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0
            || (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
                    | USER_ACTIVITY_SCREEN_DIM)) != 0
            || mScreenBrightnessBoostInProgress;
}

只要任意条件为ture,那么就不会进行自动灭屏。因此,在PSensor收到靠近事件灭屏后,PMS中会一直保持唤醒状态,即使到达自动休眠时间,也不会执行自动灭屏流程。

5.总结

  从整个分析来看,相比正常亮灭屏有几个特点:

  以上流程时序图如下:

DMS5-1.png
上一篇 下一篇

猜你喜欢

热点阅读