android P-sensor (Proximity Sensor)
16lz
2021-01-25
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>- 這題,加下面這段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
.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>-
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
更多相关文章
- Android控件之ImageButton
- android状态机机制StateMachine
- Android(安卓)进入后台触发的事件,一般用于APP屏幕解锁
- Android:Xmpp协议的简单分析
- android获取屏幕的尺寸,宽度和高度
- Android状态栏上添加按钮(程序部分)
- Android(安卓)OpenGL ES 开发教程(10):绘制线段Line Segment
- Android进阶之路 - 软键盘顶起解决方案
- Android之dialog实现底部出现对话框