今天追了一下来电接通状态下手机贴近脸的情况下进入睡眠
问题是进入睡眠以后将p sensor的电也断掉了,导致无法唤醒
首先看锁在哪里上的
InCallPresenter.java里
public void onUiShowing(boolean showing)这个函数里有一句话
if (mProximitySensor != null) {
mProximitySensor.onInCallShowing(showing);
}
这里调用了onInCallShowing
在ProximitySensor.java里
/**
* Used to save when the UI goes in and out of the foreground.
*/
public void onInCallShowing(boolean showing) {
if (showing) {
mUiShowing = true;
// We only consider the UI not showing for instances where another app took the foreground.
// If we stopped showing because the screen is off, we still consider that showing.
} else if (mPowerManager.isScreenOn()) {
mUiShowing = false;
}
updateProximitySensorMode();
}
这里调用了
updateProximitySensorMode();
/**
* Updates the wake lock used to control proximity sensor behavior,
* based on the current state of the phone.
*
* On devices that have a proximity sensor, to avoid false touches
* during a call, we hold a PROXIMITY_SCREEN_OFF_WAKE_LOCK wake lock
* whenever the phone is off hook. (When held, that wake lock causes
* the screen to turn off automatically when the sensor detects an
* object close to the screen.)
*
* This method is a no-op for devices that don't have a proximity
* sensor.
*
* Proximity wake lock will *not* be held if any one of the
* conditions is true while on a call:
* 1) If the audio is routed via Bluetooth
* 2) If a wired headset is connected
* 3) if the speaker is ON
* 4) If the slider is open(i.e. the hardkeyboard is *not* hidden)
*/
private synchronized void updateProximitySensorMode() {
final int audioMode = mAudioModeProvider.getAudioMode();
// turn proximity sensor off and turn screen on immediately if
// we are using a headset, the keyboard is open, or the device
// is being held in a horizontal position.
boolean screenOnImmediately = (AudioState.ROUTE_WIRED_HEADSET == audioMode
|| AudioState.ROUTE_SPEAKER == audioMode
|| AudioState.ROUTE_BLUETOOTH == audioMode
|| mIsHardKeyboardOpen);
// We do not keep the screen off when the user is outside in-call screen and we are
// horizontal, but we do not force it on when we become horizontal until the
// proximity sensor goes negative.
final boolean horizontal =
(mOrientation == AccelerometerListener.ORIENTATION_HORIZONTAL);
screenOnImmediately |= !mUiShowing && horizontal;
// We do not keep the screen off when dialpad is visible, we are horizontal, and
// the in-call screen is being shown.
// At that moment we're pretty sure users want to use it, instead of letting the
// proximity sensor turn off the screen by their hands.
screenOnImmediately |= mDialpadVisible && horizontal;
Log.v(this, "screenonImmediately: ", screenOnImmediately);
Log.i(this, Objects.toStringHelper(this)
.add("keybrd", mIsHardKeyboardOpen ? 1 : 0)
.add("dpad", mDialpadVisible ? 1 : 0)
.add("offhook", mIsPhoneOffhook ? 1 : 0)
.add("hor", horizontal ? 1 : 0)
.add("ui", mUiShowing ? 1 : 0)
.add("aud", AudioState.audioRouteToString(audioMode))
.toString());
if (mIsPhoneOffhook && !screenOnImmediately) {
Log.d(this, "Turning on proximity sensor");
// Phone is in use! Arrange for the screen to turn off
// automatically when the sensor detects a close object.
TelecomAdapter.getInstance().turnOnProximitySensor();
} else {
Log.d(this, "Turning off proximity sensor");
// Phone is either idle, or ringing. We don't want any special proximity sensor
// behavior in either case.
TelecomAdapter.getInstance().turnOffProximitySensor(screenOnImmediately);
}
}
}
然后看turnOnProximitySensor这个函数
在TelecomAdapter.java
void turnOnProximitySensor() {
if (mPhone != null) {
mPhone.setProximitySensorOn();
} else {
Log.e(this, "error setProximitySensorOn, mPhone is null");
}
}
void turnOffProximitySensor(boolean screenOnImmediately) {
if (mPhone != null) {
mPhone.setProximitySensorOff(screenOnImmediately);
} else {
Log.e(this, "error setProximitySensorOff, mPhone is null");
}
}
在Phone.java
public final void setProximitySensorOn() {
mInCallAdapter.turnProximitySensorOn();
}
/**
* Turns the proximity sensor off. When this request is made, the proximity sensor will
* become inactive, and no longer affect the touch screen and display. This operation is a
* no-op on devices that do not have a proximity sensor.
*
* @param screenOnImmediately If true, the screen will be turned on immediately if it was
* previously off. Otherwise, the screen will only be turned on after the proximity sensor
* is no longer triggered.
*/
public final void setProximitySensorOff(boolean screenOnImmediately) {
mInCallAdapter.turnProximitySensorOff(screenOnImmediately);
}
在InCallAdapter.java
@Override
public void turnOnProximitySensor() {
Log.n(TAG, "turnOnProximitySensor(): send MSG_TURN_ON_PROXIMITY_SENSOR");
mHandler.obtainMessage(MSG_TURN_ON_PROXIMITY_SENSOR).sendToTarget();
}
@Override
public void turnOffProximitySensor(boolean screenOnImmediately) {
Log.n(TAG, "turnOffProximitySensor(): screenOnImmediately " + screenOnImmediately);
Log.n(TAG, "turnOffProximitySensor(): send MSG_TURN_OFF_PROXIMITY_SENSOR");
mHandler.obtainMessage(MSG_TURN_OFF_PROXIMITY_SENSOR, screenOnImmediately).sendToTarget();
}
然后看同文件下的public void handleMessage(Message msg)
case MSG_TURN_ON_PROXIMITY_SENSOR:
Log.n(TAG, "InCallAdapterHandler: MSG_TURN_ON_PROXIMITY_SENSOR");
mCallsManager.turnOnProximitySensor();
break;
case MSG_TURN_OFF_PROXIMITY_SENSOR:
Log.n(TAG, "InCallAdapterHandler: MSG_TURN_OFF_PROXIMITY_SENSOR " + ((boolean) msg.obj));
mCallsManager.turnOffProximitySensor((boolean) msg.obj);
然后看CallsManager.java
/** Called by the in-call UI to turn the proximity sensor on. */
void turnOnProximitySensor() {
Log.n(TAG, "turnOnProximitySensor()");
mProximitySensorManager.turnOn();
}
/**
* Called by the in-call UI to turn the proximity sensor off.
* @param screenOnImmediately If true, the screen will be turned on immediately. Otherwise,
* the screen will be kept off until the proximity sensor goes negative.
*/
void turnOffProximitySensor(boolean screenOnImmediately) {
Log.n(TAG, "turnOffProximitySensor(): screenOnImmediately " + screenOnImmediately);
mProximitySensorManager.turnOff(screenOnImmediately);
}
最后看ProximitySensorManager.java
/**
* Turn the proximity sensor on.
*/
void turnOn() {
if (CallsManager.getInstance().getCalls().isEmpty()) {
Log.n(TAG, "turnOn(): Asking to turn on prox sensor without a call? I don't think so.");
return;
}
if (mProximityWakeLock == null) {
Log.n(TAG, "turnOn(): mProximityWakeLock null => return");
return;
}
if (!mProximityWakeLock.isHeld()) {
Log.n(TAG, "turnOn(): Acquiring proximity wake lock: acquiring...");
mProximityWakeLock.acquire();
} else {
Log.n(TAG, "turnOn(): Proximity wake lock already acquired");
}
}
/**
* Turn the proximity sensor off.
* @param screenOnImmediately
*/
void turnOff(boolean screenOnImmediately) {
if (mProximityWakeLock == null) {
Log.n(TAG, "turnOff(): mProximityWakeLock null => return");
return;
}
int audioState = CallsManager.getInstance().getAudioState().route;
boolean audio = AudioState.ROUTE_WIRED_HEADSET == audioState
|| AudioState.ROUTE_SPEAKER == audioState
|| AudioState.ROUTE_BLUETOOTH == audioState;
Log.n(TAG, "turnOff(): mProximityScreen = " + mProximityScreen + " ,audio = " + audio);
if(mProximityScreen || audio) {
if (mProximityWakeLock.isHeld()) {
Log.n(TAG, "turnOff(): Releasing proximity wake lock: releasing...");
int flags =
(screenOnImmediately ? 0 : PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY);
mProximityWakeLock.release(flags);
} else {
Log.n(TAG, "turnOff(): Proximity wake lock already released");
}
stopCountDownToReleaseProximity();
}
}