Google原生Android 4.0有個bug:來電時,如果用戶進行一定操作,來電按鈕會消失掉,以致用戶無法接聽電話.
在我們的項目中,對該問題的修復是通過修改以下幾個文件來完成的:
packages/apps/Phone/src/com/android/phone/InCallScreen.java
packages/apps/Phone/src/com/android/phone/InCallTouchUi.java
packages/apps/Phone/src/com/android/phone/RespondViaSmsManager.java
InCallTouchUi.java文件的修改如下:
@@ -226,12 +226,19 @@ public class InCallTouchUi extends FrameLayout
View.OnTouchListener smallerHitTargetTouchListener = new SmallerHitTarg
mEndButton.setOnTouchListener(smallerHitTargetTouchListener);
}
+ /**
+ * Updates the visibility and/or state of our UI elements, based on
+ * the current state of the phone.
+ */
+ final void updateState(CallManager cm) {
+ updateState(cm,false);
+ }
/**
* Updates the visibility and/or state of our UI elements, based on
* the current state of the phone.
*/
- void updateState(CallManager cm) {
+ void updateState(CallManager cm, boolean force) {
if (mInCallScreen == null) {
log("- updateState: mInCallScreen has been destroyed; bailing out..")
return;
@@ -270,7 +277,7 @@ public class InCallTouchUi extends FrameLayout
// within the last 500 msec, *don't* show the incoming call
// UI even if the phone is still in the RINGING state.
long now = SystemClock.uptimeMillis();
- if (now < mLastIncomingCallActionTime + 500) {
+ if ((!force) && (now < mLastIncomingCallActionTime + 500)) {
log("updateState: Too soon after last action; not drawing!");
showIncomingCallControls = false;
}
InCallScreen.java文件的主要修改如下:
@@ -156,8 +156,9 @@ public class InCallScreen extends Activity
private static final int EVENT_PAUSE_DIALOG_COMPLETE = 120;
private static final int EVENT_HIDE_PROVIDER_OVERLAY = 121; // Time to rem
private static final int REQUEST_UPDATE_SCREEN = 122;
- private static final int PHONE_INCOMING_RING = 123;
- private static final int PHONE_NEW_RINGING_CONNECTION = 124;
+ private static final int REQUEST_FORCE_UPDATE_SCREEN = 123;
+ private static final int PHONE_INCOMING_RING = 124;
+ private static final int PHONE_NEW_RINGING_CONNECTION = 125;
// When InCallScreenMode is UNDEFINED set the default action
// to ACTION_UNDEFINED so if we are resumed the activity will
@@ -417,6 +418,9 @@ public class InCallScreen extends Activity
updateScreen();
break;
+ case REQUEST_FORCE_UPDATE_SCREEN:
+ updateScreen(true);
+ break;
case PHONE_INCOMING_RING:
onIncomingRing();
break;
@@ -2172,7 +2176,21 @@ public class InCallScreen extends Activity
mWildPromptText.requestFocus();
}
-
+ /**
+ * Updates the state of the in-call UI based on the current state of
+ * the Phone. This call has no effect if we're not currently the
+ * foreground activity.
+ *
+ * This method is only allowed to be called from the UI thread (since it
+ * manipulates our View hierarchy). If you need to update the screen from
+ * some other thread, or if you just want to "post a request" for the scree
+ * to be updated (rather than doing it synchronously), call
+ * requestUpdateScreen() instead.
+ */
+ final private void updateScreen()
+ {
+ updateScreen(false);
+ }
/**
* Updates the state of the in-call UI based on the current state of
* the Phone. This call has no effect if we're not currently the
@@ -2184,7 +2202,7 @@ public class InCallScreen extends Activity
* to be updated (rather than doing it synchronously), call
* requestUpdateScreen() instead.
*/
- private void updateScreen() {
+ private void updateScreen(boolean force) {
if (DBG) log("updateScreen()...");
final InCallScreenMode inCallScreenMode = mApp.inCallUiState.inCallScre
if (VDBG) {
@@ -2245,7 +2263,7 @@ public class InCallScreen extends Activity
// Note we update the InCallTouchUi widget before the CallCard,
// since the CallCard adjusts its size based on how much vertical
// space the InCallTouchUi widget needs.
- updateInCallTouchUi();
+ updateInCallTouchUi(force);
mCallCard.updateState(mCM);
updateDialpadVisibility();
updateProviderOverlay();
@@ -3925,13 +3943,18 @@ public class InCallScreen extends Activity
mRespondViaSmsManager = new RespondViaSmsManager();
mRespondViaSmsManager.setInCallScreenInstance(this);
}
-
/**
* Updates the state of the in-call touch UI.
*/
- private void updateInCallTouchUi() {
+ final private void updateInCallTouchUi() {
+ updateInCallTouchUi(false);
+ }
+ /**
+ * Updates the state of the in-call touch UI.
+ */
+ private void updateInCallTouchUi(boolean force) {
if (mInCallTouchUi != null) {
- mInCallTouchUi.updateState(mCM);
+ mInCallTouchUi.updateState(mCM,force);
}
}
@@ -3941,7 +3964,6 @@ public class InCallScreen extends Activity
/* package */ InCallTouchUi getInCallTouchUi() {
return mInCallTouchUi;
}
-
/**
* Posts a handler message telling the InCallScreen to refresh the
* onscreen in-call UI.
@@ -3958,7 +3980,23 @@ public class InCallScreen extends Activity
mHandler.removeMessages(REQUEST_UPDATE_SCREEN);
mHandler.sendEmptyMessage(REQUEST_UPDATE_SCREEN);
}
-
+ /**
+ * Posts a handler message telling the InCallScreen to force refresh the
+ * onscreen in-call UI.
+ *
+ * This is just a wrapper around updateScreen(true), for use by the
+ * rest of the phone app or from a thread other than the UI thread.
+ *
+ * updateScreen() is a no-op if the InCallScreen is not the foreground
+ * activity, so it's safe to call this whether or not the InCallScreen
+ * is currently visible.
+ */
+ /* package */ void requestForceUpdateScreen() {
+ if (DBG) log("requestForceUpdateScreen()...");
+ mHandler.removeMessages(REQUEST_UPDATE_SCREEN);
+ mHandler.removeMessages(REQUEST_FORCE_UPDATE_SCREEN);
+ mHandler.sendEmptyMessage(REQUEST_FORCE_UPDATE_SCREEN);
+ }
/**
* @return true if it's OK to display the in-call touch UI, given the
* current state of the InCallScreen.
RespondViaSmsManager.java文件的修改如下:
@@ -281,7 +281,7 @@ public class RespondViaSmsManager {
// update itself based on the current telephony state.
// (Assuming the incoming call is still ringing, this will
// cause the incoming call widget to reappear.)
- mInCallScreen.requestUpdateScreen();
+ mInCallScreen.requestForceUpdateScreen();
}
}
結束!