P-sensor (Proximity Sensor)
手机接听电话时,贴近屏幕时,屏幕会灭屏,以防止脸部触碰屏幕引起误操作。当我们的脸离开屏幕时,屏幕会自动亮屏.
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