原生Android 4.0来电按钮消失的问题


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();
         }
     }

结束!

相关内容