当前位置: 首页 > 工具软件 > Proximity > 使用案例 >

android P-sensor (Proximity Sensor)

徐峰
2023-12-01

P-sensor (Proximity Sensor)
手机接听电话时,贴近屏幕时,屏幕会灭屏,以防止脸部触碰屏幕引起误操作。当我们的脸离开屏幕时,屏幕会自动亮屏.
 
phone app(maybe incallUI) 会申请 wakeLock( PROXIMITY_SCREEN_OFF_WAKE_LOCK
 
    wakeLock =context.getSystemService(PowerManager.class)
                .newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, TAG);
    wakeLock.acquire();   //通话时候会acquire 这个wakeLock, framework会enable p-sensor
    wakeLock.release();  //通话结束时会释放这个wakeLock, framework 会 disable p-sensor

 
主要code:
base\services\core\java\com\android\server\display\DisplayPowerController.java
base\services\core\java\com\android\server\power\PowerManagerService.java
 
 
大致的工作流程是:
 
 
acquire()                         --PowerManager.java
acquireLocked()
acquireWakeLock()                 --PowerManagerService.java 
acquireWakeLockInternal()  
updatePowerStateLocked()
updateDisplayPowerStateLocked()
 
    private boolean updateDisplayPowerStateLocked(int dirty) {
        ......
             //p-sensor wakeLock acquire后,useProximitySensor为true; release后useProximitySensor为false
            mDisplayPowerRequest. useProximitySensor = shouldUseProximitySensorLocked();
        ......
            mDisplayReady = mDisplayManagerInternal. requestPowerState(mDisplayPowerRequest,
                    mRequestWaitForNegativeProximity);
 
requestPowerState()                --DisplayManagerService.java
requestPowerState()                --DisplayPowerController.java
sendUpdatePowerStateLocked() MSG_UPDATE_POWER_STATE
handleMessage()                     
updatePowerState()
 
    private void updatePowerState() { // 更新屏幕状态
        ......
         // 根据当前状态enable/disable p-Sensor
        // Apply the proximity sensor.
        if (mProximitySensor != null) {
            if (mPowerRequest. useProximitySensor && state != Display.STATE_OFF) {
                setProximitySensorEnabled(true); //enable p-Sensor
                if (!mScreenOffBecauseOfProximity
                        && mProximity == PROXIMITY_POSITIVE) { 
                    mScreenOffBecauseOfProximity = true//p-Sensor 遮挡, 屏幕暗掉
                    sendOnProximityPositiveWithWakelock();
                }
            } else if (mWaitingForNegativeProximity
                    && mScreenOffBecauseOfProximity
                    && mProximity == PROXIMITY_POSITIVE
                    && state != Display.STATE_OFF) {
                setProximitySensorEnabled(true); //enable on p-Sensor
            } else {
                setProximitySensorEnabled(false); // disable off p-Sensor, 屏幕亮起
                mWaitingForNegativeProximity = false;
            }
            if (mScreenOffBecauseOfProximity
                    && mProximity != PROXIMITY_POSITIVE) {
                mScreenOffBecauseOfProximity = false;  // p-Sensor 没用遮挡, 起作用
                sendOnProximityNegativeWithWakelock();
            }
        } else {
            mWaitingForNegativeProximity = false;
        }
 
        if ( mScreenOffBecauseOfProximity) {   // p_Sensor 遮挡, screen off
            state = Display.STATE_OFF;
        }
 
        // Use zero brightness when screen is off.
        if ( state == Display.STATE_OFF) {
            brightness = PowerManager.BRIGHTNESS_OFF;
        }
 
        ......
            if ((state == Display.STATE_ON
                    && mSkipRampState == RAMP_STATE_SKIP_NONE
                    || state == Display.STATE_DOZE)
                    && !wasOrWillBeInVr) {
                animateScreenBrightness(brightness,
                        slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
            } else {
                animateScreenBrightness(brightness, 0);
            }
 
}
 
    private void setProximitySensorEnabled(boolean enable) {
        if (enable) {
            if (!mProximitySensorEnabled) {
                // Register the listener.
                // Proximity sensor state already cleared initially.

                mProximitySensorEnabled = true;
                mSensorManager.registerListener( mProximitySensorListener, mProximitySensor,
                        SensorManager.SENSOR_DELAY_NORMAL, mHandler);
            }
        } else {
            if (mProximitySensorEnabled) {
                 // Unregister the listener.
                // Clear the proximity sensor state for next time.

                mProximitySensorEnabled = false;
                mProximity = PROXIMITY_UNKNOWN;
                mPendingProximity = PROXIMITY_UNKNOWN;
                mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
                mSensorManager.unregisterListener(mProximitySensorListener);
                clearPendingProximityDebounceTime(); // release wake lock (must be last)
            }
        }
    }
    //监听p-Sensor, p-Sensor变化后,收到onSensorChanged,判断是否发生遮挡,
    //然后调用updatePowerState()办法更新屏幕状态
    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);
            }
        }
 
    handleProximitySensorEvent()
    debounceProximitySensor()
    updatePowerState() // 更新屏幕状态
 
 
 
[Z20] ARIMA00015441 GST-PV<7947_Driver_pSensor>-<The screen will light when tap power key many times after cover P-sensor area in calling.>
 
這題,加下面這段code 應該可以fix
    PowerManagerService.java (base\services\core\java\com\android\server\power)
    private void goToSleepInternal(long eventTime, int reason, int flags, int uid) {
        synchronized (mLock) {
           
            if (mProximityPositive && reason == PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON) {
                Slog.d(TAG, "Proximity positive sleep and do not sleep by power button");
                return;
            }

          
            if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) {
                updatePowerStateLocked();
            }
        }
    }
從code分析,我覺得這個應該是android的原始行為:
in call的時候,p-sensor起作用, p-sensor遮住時,只是屏幕滅掉,手機並沒有進sleep模式
這時候,按power key, 手機會進入sleep 模式, p-sensor 會被關閉
    private void updatePowerState() {
         ......
        // Apply the proximity sensor.
        if (mProximitySensor != null) {
            if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {
                setProximitySensorEnabled(true);
                if (!mScreenOffBecauseOfProximity
                        && mProximity == PROXIMITY_POSITIVE) {
                    mScreenOffBecauseOfProximity = true;
                    sendOnProximityPositiveWithWakelock();
                }
            } else if (mWaitingForNegativeProximity
                    && mScreenOffBecauseOfProximity
                    && mProximity == PROXIMITY_POSITIVE
                    && state != Display.STATE_OFF) {
                setProximitySensorEnabled(true);
            } else {
                setProximitySensorEnabled(false); // 按power key的時候,p-sensor 會被關閉
                mWaitingForNegativeProximity = false;
            }
應為p-sensor已經被關閉了,所以再按一次power key, 手機會亮起來
 
 
 
 
 
 
通过dumpsys display 可以查看p-sensor的状态
 
adb shell dumpsys display > d:\display.txt
 
Display Power Controller Thread State:
  mPowerRequest=policy=BRIGHT, useProximitySensor=true, screenBrightness=128, screenAutoBrightnessAdjustment=0.0, screenLowPowerBrightnessFactor=0.5, brightnessSetByUser=true, useAutoBrightness=false, blockScreenOn=false, lowPowerMode=false, boostScreenBrightness=false, dozeScreenBrightness=-1, dozeScreenState=UNKNOWN
  mWaitingForNegativeProximity=false
  mProximitySensor={Sensor name="EPL259x ALS/PS EPL259x", vendor="Eminent", version=2, type=8, maxRange=5.000305, resolution=0.0010070801, power=0.32, minDelay=0}
  mProximitySensorEnabled=true
  mProximityThreshold=5.0
  mProximity=Positive
  mPendingProximity=Positive
  mPendingProximityDebounceTime=-1 (4802060 ms ago)
  mScreenOffBecauseOfProximity=true
  mAppliedAutoBrightness=false
  mAppliedDimming=false
  mAppliedLowPower=false
  mPendingScreenOnUnblocker=null
  mPendingScreenOff=false
  mReportedToPolicy=REPORTED_TO_POLICY_SCREEN_ON
  mScreenBrightnessRampAnimator.isAnimating()=false
  mColorFadeOnAnimator.isStarted()=false
  mColorFadeOffAnimator.isStarted()=false
 
 
 
 
 
 
      
 
 
 
 类似资料:

相关阅读

相关文章

相关问答