Android V4.0/V4.1/V4.2/4.4
[DESCRIPTION]
没有p sensor时要求电话接通5s灭屏
[SOLUTION]
注:
红色标识修改的code.
Android V4.4之前的版本:
1.PhoneGlobals.java
a.添加如下方法: Runnable timeOutTask = new Runnable(){ public void run(){ //mPowerManager.goToSleep(SystemClock.uptimeMillis());
try{ mPowerManagerService.goToSleep(SystemClock.uptimeMillis
(),PowerManager.GO_TO_SLEEP_REASON_PROXIMITY);
}catch(RemoteException e){
}
} };
/************************************************ param: time: milliseconds *************************************************/ void setScreenTimeout(long time) {
if (VDBG) Log.d(LOG_TAG, "setScreenTimeout(" + time + ")..."); // stick with default timeout if we are using the proximity sensor // if (proximitySensorModeEnabled()) { // return; // } mHandler.removeCallbacks(timeOutTask); mHandler.postDelayed(timeOutTask, time); }
/*该方法可根据需要添加到incallscreen.java中的onpause()方法实体的最后*/ void cancelScreenTimeout() {
if (VDBG) Log.d(LOG_TAG, "cancelScreenTimeout()"); mHandler.removeCallbacks(runningtask); }
b.修改如下方法: /* package */
void updateWakeState() { PhoneConstants.State state = mCM.getState(); ...... ...... if (DBG) Log.d(LOG_TAG, "updateWakeState: callscreen " + isShowingCallScreen + ", dialer " + isDialerOpened + ", speaker " + isSpeakerInUse + "...");
// (1) Set the screen timeout. // // Note that the "screen timeout" value we determine here is // meaningless if the screen is forced on (see (2) below.) // if (!isShowingCallScreen || isSpeakerInUse) { // Use the system-wide default timeout. setScreenTimeout(5000); } else { // We're on the in-call screen, and *not* using the speakerphone. if (isDialerOpened) { // The DTMF dialpad is up. This case is special because // the in-call UI has its own "touch lock" mechanism to // disable the dialpad after a very short amount of idle // time (to avoid false touches from the user's face while // in-call.) // // In this case the *physical* screen just uses the // system-wide default timeout. setScreenTimeout(5000); } else { // We're on the in-call screen, and not using the DTMF dialpad. // There's actually no touchable UI onscreen at all in // this state. Also, the user is (most likely) not // looking at the screen at all, since they're probably // holding the phone up to their face. Here we use a // special screen timeout value specific to the in-call // screen, purely to save battery life. setScreenTimeout(5000); } }
// Decide whether to force the screen on or not. // // Force the screen to be on if the phone is ringing or dialing, // or if we're displaying the "Call ended" UI for a connection in // the "disconnected" state. // However, if the phone is disconnected while the user is in the // middle of selecting a quick response message, we should not force // the screen to be on. // boolean isRinging = (state == PhoneConstants.State.RINGING); ...... ...... }
c.修改如下方法: private class PhoneGlobalsBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { ...... String action = intent.getAction(); ...... ...... } else if (action.equals(Intent.ACTION_HEADSET_PLUG)) { if (VDBG) Log.d(LOG_TAG, "mReceiver: ACTION_HEADSET_PLUG"); if (VDBG) Log.d(LOG_TAG, " state: " + intent.getIntExtra("state", 0)); if (VDBG) Log.d(LOG_TAG, " name: " + intent.getStringExtra("name")); mIsHeadsetPlugged = (intent.getIntExtra("state", 0) == 1); mHandler.sendMessage(mHandler.obtainMessage(EVENT_WIRED_HEADSET_PLUG, 0)); pokeUserActivity(); } else if ((action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) && ...... ...... }
2.callNotifier.java a.添加成员变量. public class CallNotifier extends Handler implements CallerInfoAsyncQuery.OnQueryCompleteListener { ...... ...... private Vibrator mVibrator; private Call.State mPreviousCallState = Call.State.IDLE; private Call.State mLastCallState = Call.State.IDLE;
b.修改如下方法: private void onPhoneStateChanged(AsyncResult r) { PhoneConstants.State state = mCM.getState(); if (VDBG) log("onPhoneStateChanged: state = " + state);
...... ...... mApplication.notificationMgr.statusBarHelper .enableNotificationAlerts(state == PhoneConstants.State.IDLE);
Phone fgPhone = mCM.getFgPhone(); Call.State ringCallState =mCM.getRingingPhone().getRingingCall().getState(); Call.State fgCallState = mCM.getActiveFgCallState(); if((ringCallState == Call.State.IDLE && mLastCallState.isRinging())|| (fgCallState == Call.State.ACTIVE && mLastCallState.isDialing())){ PhoneGlobals.getInstance().setScreenTimeout(5000); } mLastCallState = ringCallState.isRinging()?ringCallState:fgCallState; if (fgPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) { if ((fgPhone.getForegroundCall().getState() == Call.State.ACTIVE) && ((mPreviousCdmaCallState == Call.State.DIALING) || (mPreviousCdmaCallState == Call.State.ALERTING))) { if (mIsCdmaRedialCall) { int toneToPlay = InCallTonePlayer.TONE_REDIAL; new InCallTonePlayer(toneToPlay).start(); } // Stop any signal info tone when call moves to ACTIVE state stopSignalInfoTone(); } mPreviousCdmaCallState = fgPhone.getForegroundCall().getState(); } ...... ...... }
Android V4.4及之后版本:
1.PhoneGlobals.java a.添加如下变量和方法: ...... private boolean mTtyEnabled; // Current TTY operating mode selected by user private int mPreferredTtyMode = Phone.TTY_MODE_OFF;
private Call.State mLastCallState = Call.State.IDLE;
Runnable timeOutTask = new Runnable(){ public void run(){
try{ //mPowerManager.goToSleep(SystemClock.uptimeMillis()); mPowerManagerService.goToSleep(SystemClock.uptimeMillis(),PowerManager.GO_TO_SLEEP_REASON_PROXIMITY);
} catch(RemoteException e){
} } };
/** * Set the restore mute state flag. Used when we are setting the mute state * OUTSIDE of user interaction {@link PhoneUtils#startNewCall(Phone)} */ /*package*/void setRestoreMuteOnInCallResume (boolean mode) { PhoneLog.d(LOG_TAG, "setRestoreMuteOnInCallResume, mode = " + mode); mShouldRestoreMuteOnInCallResume = mode; } ...... b.添加如下方法: ...... //开始定时器,定时灭屏 /************************************************ param: time: milliseconds *************************************************/ void setScreenTimeout(long time) { if (VDBG) Log.d(LOG_TAG, "setScreenTimeout(" + time + ")..."); // stick with default timeout if we are using the proximity sensor // if (proximitySensorModeEnabled()) { //return; //} mHandler.removeCallbacks(timeOutTask); mHandler.postDelayed(timeOutTask, time); }
//取消灭屏的定时器,不让灭屏 void cancelScreenTimeout() { if (VDBG) Log.d(LOG_TAG, "cancelScreenTimeout()"); mHandler.removeCallbacks(runningtask); }
public PhoneGlobals(Context context) { super(context); sMe = this; } ......
Note:
以上两方法要在亮屏或灭屏的地方调用,同一进程(默认进程是phone进程)的话,可直接调用,不同的进程,则要通过跨进程的方式才能调用。 c.修改如下方法: /* package */ void updateWakeState() { PhoneConstants.State state = mCM.getState(); Call.State ringCallState = mCM.getRingingPhone().getRingingCall().getState(); Call.State fgCallState = mCM.getActiveFgCallState(); Log.d(LOG_TAG, "updateWakeState,ringCallState ="+ringCallState); Log.d(LOG_TAG, "updateWakeState,fgCallState ="+ringCallState); Log.d(LOG_TAG, "updateWakeState,before of mLastCallState ="+mLastCallState);
if((ringCallState == Call.State.IDLE && mLastCallState.isRinging())|| (fgCallState == Call.State.ACTIVE && mLastCallState.isDialing())){ PhoneGlobals.getInstance().setScreenTimeout(5000);
} mLastCallState = ringCallState.isRinging()?ringCallState:fgCallState; Log.d(LOG_TAG, "updateWakeState,after of mLastCallState ="+mLastCallState);
// True if the speakerphone is in use. (If so, we *always* use // the default timeout. Since the user is obviously not holding // the phone up to his/her face, we don't need to worry about // false touches, and thus don't need to turn the screen off so // aggressively.) // Note that we need to make a fresh call to this method any // time the speaker state changes. (That happens in // PhoneUtils.turnOnSpeaker().) boolean isSpeakerInUse = (state == PhoneConstants.State.OFFHOOK) && PhoneUtils.isSpeakerOn(this); ...... } d.添加如下变量: powermanager.java ...... /** * Go to sleep reason code: Going to sleep due to a screen timeout. * @hide */ public static final int GO_TO_SLEEP_REASON_TIMEOUT = 2;
/** * Go to sleep reason code: Going to sleep due to proximity sensor. * @hide */ public static final int GO_TO_SLEEP_REASON_PROXIMITY = 3;
final Context mContext; ......
e.修改如下方法:
Notifier.java private void sendGoToSleepBroadcast(int reason) { if (DEBUG) { Slog.d(TAG, "Sending go to sleep broadcast."); }
int why = WindowManagerPolicy.OFF_BECAUSE_OF_USER; switch (reason) { case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN: why = WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN; break; case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT: why = WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT; break; case PowerManager.GO_TO_SLEEP_REASON_PROXIMITY: why = WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR; break; }
EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, why, 0, 0); ...... } f.修改如下方法:
PowerManagerService.java
private boolean goToSleepNoUpdateLocked(long eventTime, int reason) { if (mSbPlugState) { if (DEBUG_SPEW) { Slog.d(TAG, "smart book mode: bypass goToSleep request"); } return false; }
if (DEBUG) { ...... switch (reason) { case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN: Slog.i(TAG, "Going to sleep due to device administration policy..."); break; case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT: Slog.i(TAG, "Going to sleep due to screen timeout..."); break; case PowerManager.GO_TO_SLEEP_REASON_PROXIMITY: Slog.i(TAG, "Going to sleep due to proximity sensor..."); break; default: Slog.i(TAG, "Going to sleep by user request..."); reason = PowerManager.GO_TO_SLEEP_REASON_USER; break; }
// MTK: Force enable proximity when talking screen off timeout if (reason == PowerManager.GO_TO_SLEEP_REASON_TIMEOUT) { if (shouldUseProximitySensorLocked()) { ...... }