Merge "Add ability to enable/disable navigation features from In-Call UI" into klp-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index fe71d4c..9dc1072 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -40,6 +40,7 @@
     <protected-broadcast android:name="com.android.internal.telephony.data-restart-trysetup" />
     <protected-broadcast android:name="com.android.internal.telephony.data-stall" />
 
+    <uses-permission android:name="android.permission.BIND_CALL_SERVICE" />
     <uses-permission android:name="android.permission.BROADCAST_STICKY" />
     <uses-permission android:name="android.permission.CALL_PHONE" />
     <uses-permission android:name="android.permission.CALL_PRIVILEGED" />
diff --git a/src/com/android/phone/BluetoothManager.java b/src/com/android/phone/BluetoothManager.java
index c2b4f7d..ffce465 100644
--- a/src/com/android/phone/BluetoothManager.java
+++ b/src/com/android/phone/BluetoothManager.java
@@ -71,7 +71,6 @@
         mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
 
         init(mContext);
-        // TODO(klp): Listen for changes to the call list/state.
     }
 
     /* package */ boolean isBluetoothHeadsetAudioOn() {
diff --git a/src/com/android/phone/CallCard.java b/src/com/android/phone/CallCard.java
index 22215c0..bfb14ac 100644
--- a/src/com/android/phone/CallCard.java
+++ b/src/com/android/phone/CallCard.java
@@ -764,14 +764,6 @@
             case INCOMING:
             case WAITING:
                 callStateLabel = context.getString(R.string.card_title_incoming_call);
-
-                // Also, display a special icon (alongside the "Incoming call"
-                // label) if there's an incoming call and audio will be routed
-                // to bluetooth when you answer it.
-                // TODO(klp): Add bluetooth label to new UI screen for incoming calls.
-                //if (mApplication.showBluetoothIndication()) {
-                //    bluetoothIconId = R.drawable.ic_incoming_call_bluetooth;
-                //}
                 break;
 
             case DISCONNECTING:
diff --git a/src/com/android/phone/CallCommandService.java b/src/com/android/phone/CallCommandService.java
index 60c5802..212ce45 100644
--- a/src/com/android/phone/CallCommandService.java
+++ b/src/com/android/phone/CallCommandService.java
@@ -58,7 +58,7 @@
     }
 
     /**
-     * TODO(klp): Add a confirmation callback parameter.
+     * TODO: Add a confirmation callback parameter.
      */
     @Override
     public void answerCall(int callId) {
@@ -73,7 +73,7 @@
     }
 
     /**
-     * TODO(klp): Add a confirmation callback parameter.
+     * TODO: Add a confirmation callback parameter.
      */
     @Override
     public void rejectCall(int callId, boolean rejectWithMessage, String message) {
@@ -205,7 +205,6 @@
     @Override
     public void speaker(boolean onOff) {
         try {
-            // TODO(klp): add bluetooth logic from InCallScreen.toggleSpeaker()
             PhoneUtils.turnOnSpeaker(mContext, onOff, true);
         } catch (Exception e) {
             Log.e(TAG, "Error during speaker().", e);
diff --git a/src/com/android/phone/CallHandlerServiceProxy.java b/src/com/android/phone/CallHandlerServiceProxy.java
index 0681fb4..2f71457 100644
--- a/src/com/android/phone/CallHandlerServiceProxy.java
+++ b/src/com/android/phone/CallHandlerServiceProxy.java
@@ -16,12 +16,14 @@
 
 package com.android.phone;
 
+import android.Manifest;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -338,7 +340,21 @@
                 final PackageManager packageManger = mContext.getPackageManager();
                 final List<ResolveInfo> services = packageManger.queryIntentServices(serviceIntent,
                         0);
-                if (services.size() == 0) {
+
+                ServiceInfo serviceInfo = null;
+
+                for (int i = 0; i < services.size(); i++) {
+                    final ResolveInfo info = services.get(i);
+                    if (info.serviceInfo != null) {
+                        if (Manifest.permission.BIND_CALL_SERVICE.equals(
+                                info.serviceInfo.permission)) {
+                            serviceInfo = info.serviceInfo;
+                            break;
+                        }
+                    }
+                }
+
+                if (serviceInfo == null) {
                     // Service not found, retry again after some delay
                     // This can happen if the service is being installed by the package manager.
                     // Between deletes and installs, bindService could get a silent service not
@@ -357,6 +373,11 @@
                     return;
                 }
 
+                // Bind to the first service that has a permission
+                // TODO: Add UI to allow us to select between services
+
+                serviceIntent.setComponent(new ComponentName(serviceInfo.packageName,
+                        serviceInfo.name));
                 if (DBG) {
                     Log.d(TAG, "binding to service " + serviceIntent);
                 }
diff --git a/src/com/android/phone/CallModeler.java b/src/com/android/phone/CallModeler.java
index 7af2416..75da0be 100644
--- a/src/com/android/phone/CallModeler.java
+++ b/src/com/android/phone/CallModeler.java
@@ -70,7 +70,7 @@
  * the telephony layer. We use Connection references as identifiers for a call;
  * new reference = new call.
  *
- * TODO(klp): Create a new Call class to replace the simple call Id ints
+ * TODO: Create a new Call class to replace the simple call Id ints
  * being used currently.
  *
  * The new Call models are parcellable for transfer via the CallHandlerService
@@ -110,7 +110,9 @@
     public void handleMessage(Message msg) {
         switch(msg.what) {
             case CallStateMonitor.PHONE_NEW_RINGING_CONNECTION:
-                onNewRingingConnection((Connection) ((AsyncResult) msg.obj).result);
+                // We let the CallNotifier handle the new ringing connection first. When the custom
+                // ringtone and send_to_voicemail settings are retrieved, CallNotifier will directly
+                // call CallModeler's onNewRingingConnection.
                 break;
             case CallStateMonitor.PHONE_DISCONNECT:
                 onDisconnect((Connection) ((AsyncResult) msg.obj).result);
@@ -282,15 +284,15 @@
         }
     }
 
-    private Call onNewRingingConnection(Connection conn) {
+    /* package */ Call onNewRingingConnection(Connection conn) {
         Log.i(TAG, "onNewRingingConnection");
         final Call call = getCallFromMap(mCallMap, conn, true);
 
-        updateCallFromConnection(call, conn, false);
+        if (call != null) {
+            updateCallFromConnection(call, conn, false);
 
-        for (int i = 0; i < mListeners.size(); ++i) {
-            if (call != null) {
-              mListeners.get(i).onIncoming(call);
+            for (int i = 0; i < mListeners.size(); ++i) {
+                mListeners.get(i).onIncoming(call);
             }
         }
 
@@ -318,9 +320,6 @@
 
             mCallMap.remove(conn);
         }
-
-        // TODO(klp): Do a final check to see if there are any active calls.
-        // If there are not, totally cancel all calls
     }
 
     /**
@@ -592,7 +591,7 @@
         boolean canMute = false;
 
         final boolean supportHold = PhoneUtils.okToSupportHold(mCallManager);
-        final boolean canHold = PhoneUtils.okToHoldCall(mCallManager);
+        final boolean canHold = (supportHold ? PhoneUtils.okToHoldCall(mCallManager) : false);
         final boolean genericConf = isForConference &&
                 (connection.getCall().getPhone().getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA);
 
diff --git a/src/com/android/phone/CallNotifier.java b/src/com/android/phone/CallNotifier.java
index c7db763..bbffbd2 100644
--- a/src/com/android/phone/CallNotifier.java
+++ b/src/com/android/phone/CallNotifier.java
@@ -277,7 +277,7 @@
                 break;
 
             case RINGER_CUSTOM_RINGTONE_QUERY_TIMEOUT:
-                onCustomRingtoneQueryTimeout((String) msg.obj);
+                onCustomRingtoneQueryTimeout((Connection) msg.obj);
                 break;
 
             case PHONE_MWI_CHANGED:
@@ -333,9 +333,6 @@
                     int toneToPlay = InCallTonePlayer.TONE_VOICE_PRIVACY;
                     new InCallTonePlayer(toneToPlay).start();
                     mVoicePrivacyState = true;
-                    // Update the VP icon:
-                    if (DBG) log("- updating notification for VP state...");
-                    mApplication.notificationMgr.updateInCallNotification();
                 }
                 break;
 
@@ -345,9 +342,6 @@
                     int toneToPlay = InCallTonePlayer.TONE_VOICE_PRIVACY;
                     new InCallTonePlayer(toneToPlay).start();
                     mVoicePrivacyState = false;
-                    // Update the VP icon:
-                    if (DBG) log("- updating notification for VP state...");
-                    mApplication.notificationMgr.updateInCallNotification();
                 }
                 break;
 
@@ -359,10 +353,6 @@
                 onResendMute();
                 break;
 
-            case UPDATE_IN_CALL_NOTIFICATION:
-                mApplication.notificationMgr.updateInCallNotification();
-                break;
-
             default:
                 // super.handleMessage(msg);
         }
@@ -456,10 +446,11 @@
                 mCallWaitingTonePlayer = new InCallTonePlayer(InCallTonePlayer.TONE_CALL_WAITING);
                 mCallWaitingTonePlayer.start();
             }
+
             // in this case, just fall through like before, and call
             // showIncomingCall().
             if (DBG) log("- showing incoming call (this is a WAITING call)...");
-            showIncomingCall();
+            notifyCallModelerOfNewRingingCall(c);
         }
 
         // Note we *don't* post a status bar notification here, since
@@ -572,20 +563,20 @@
 
             // query the callerinfo to try to get the ringer.
             PhoneUtils.CallerInfoToken cit = PhoneUtils.startGetCallerInfo(
-                    mApplication, c, this, this);
+                    mApplication, c, this, c);
 
             // if this has already been queried then just ring, otherwise
             // we wait for the alloted time before ringing.
             if (cit.isFinal) {
                 if (VDBG) log("- CallerInfo already up to date, using available data");
-                onQueryComplete(0, this, cit.currentInfo);
+                onQueryComplete(0, c, cit.currentInfo);
             } else {
                 if (VDBG) log("- Starting query, posting timeout message.");
 
                 // Phone number (via getAddress()) is stored in the message to remember which
                 // number is actually used for the look up.
                 sendMessageDelayed(
-                        Message.obtain(this, RINGER_CUSTOM_RINGTONE_QUERY_TIMEOUT, c.getAddress()),
+                        Message.obtain(this, RINGER_CUSTOM_RINGTONE_QUERY_TIMEOUT, c),
                         RINGTONE_QUERY_WAIT_TIME);
             }
             // The call to showIncomingCall() will happen after the
@@ -603,7 +594,7 @@
             // in this case, just fall through like before, and call
             // showIncomingCall().
             if (DBG) log("- showing incoming call (couldn't start query)...");
-            showIncomingCall();
+            notifyCallModelerOfNewRingingCall(c);
         }
     }
 
@@ -624,7 +615,7 @@
      * (We still tell the Ringer to start, but it's going to use the
      * default ringtone.)
      */
-    private void onCustomRingQueryComplete() {
+    private void onCustomRingQueryComplete(Connection c) {
         boolean isQueryExecutionTimeExpired = false;
         synchronized (mCallerInfoQueryStateGuard) {
             if (mCallerInfoQueryState == CALLERINFO_QUERYING) {
@@ -658,13 +649,19 @@
             return;
         }
 
-        // Ring, either with the queried ringtone or default one.
-        if (VDBG) log("RINGING... (onCustomRingQueryComplete)");
-        mRinger.ring();
+        // If the ringing call still does not have any connection anymore, do not send the
+        // notification to the CallModeler.
+        final Call ringingCall = mCM.getFirstActiveRingingCall();
 
-        // ...and display the incoming call to the user:
-        if (DBG) log("- showing incoming call (custom ring query complete)...");
-        showIncomingCall();
+        if (ringingCall != null && ringingCall.getLatestConnection() == c) {
+            // Ring, either with the queried ringtone or default one.
+            if (VDBG) log("RINGING... (onCustomRingQueryComplete)");
+            mRinger.ring();
+
+            // ...and display the incoming call to the user:
+            if (DBG) log("- showing incoming call (custom ring query complete)...");
+            notifyCallModelerOfNewRingingCall(c);
+        }
     }
 
     private void onUnknownConnectionAppeared(AsyncResult r) {
@@ -673,52 +670,15 @@
         if (state == PhoneConstants.State.OFFHOOK) {
             // basically do onPhoneStateChanged + display the incoming call UI
             onPhoneStateChanged(r);
+
             if (DBG) log("- showing incoming call (unknown connection appeared)...");
-            showIncomingCall();
+            final Connection c = (Connection) r.result;
+            notifyCallModelerOfNewRingingCall(c);
         }
     }
 
-    /**
-     * Informs the user about a new incoming call.
-     *
-     * In most cases this means "bring up the full-screen incoming call
-     * UI".  However, if an immersive activity is running, the system
-     * NotificationManager will instead pop up a small notification window
-     * on top of the activity.
-     *
-     * Watch out: be sure to call this method only once per incoming call,
-     * or otherwise we may end up launching the InCallScreen multiple
-     * times (which can lead to slow responsiveness and/or visible
-     * glitches.)
-     *
-     * Note this method handles only the onscreen UI for incoming calls;
-     * the ringer and/or vibrator are started separately (see the various
-     * calls to Ringer.ring() in this class.)
-     *
-     * @see NotificationMgr#updateNotificationAndLaunchIncomingCallUi()
-     */
-    private void showIncomingCall() {
-        log("showIncomingCall()...  phone state = " + mCM.getState());
-
-        // Before bringing up the "incoming call" UI, force any system
-        // dialogs (like "recent tasks" or the power dialog) to close first.
-        try {
-            ActivityManagerNative.getDefault().closeSystemDialogs("call");
-        } catch (RemoteException e) {
-        }
-
-        // Go directly to the in-call screen.
-        // (No need to do anything special if we're already on the in-call
-        // screen; it'll notice the phone state change and update itself.)
-        mApplication.requestWakeState(PhoneGlobals.WakeState.FULL);
-
-        // Post the "incoming call" notification *and* include the
-        // fullScreenIntent that'll launch the incoming-call UI.
-        // (This will usually take us straight to the incoming call
-        // screen, but if an immersive activity is running it'll just
-        // appear as a notification.)
-        if (DBG) log("- updating notification from showIncomingCall()...");
-        mApplication.notificationMgr.updateNotificationAndLaunchIncomingCallUi();
+    private void notifyCallModelerOfNewRingingCall(Connection c) {
+        mCallModeler.onNewRingingConnection(c);
     }
 
     /**
@@ -759,7 +719,7 @@
         // There's no need to force a UI update since we update the
         // in-call notification ourselves (below), and the InCallScreen
         // listens for phone state changes itself.
-        // TODO(klp): Have BluetoothManager listen to CallModeler instead of relying on
+        // TODO: Have BluetoothManager listen to CallModeler instead of relying on
         // CallNotifier
         mBluetoothManager.updateBluetoothIndication();
 
@@ -792,26 +752,6 @@
             // remove it!
             if (DBG) log("stopRing()... (OFFHOOK state)");
             mRinger.stopRing();
-
-            // Post a request to update the "in-call" status bar icon.
-            //
-            // We don't call NotificationMgr.updateInCallNotification()
-            // directly here, for two reasons:
-            // (1) a single phone state change might actually trigger multiple
-            //   onPhoneStateChanged() callbacks, so this prevents redundant
-            //   updates of the notification.
-            // (2) we suppress the status bar icon while the in-call UI is
-            //   visible (see updateInCallNotification()).  But when launching
-            //   an outgoing call the phone actually goes OFFHOOK slightly
-            //   *before* the InCallScreen comes up, so the delay here avoids a
-            //   brief flicker of the icon at that point.
-
-            if (DBG) log("- posting UPDATE_IN_CALL_NOTIFICATION request...");
-            // Remove any previous requests in the queue
-            removeMessages(UPDATE_IN_CALL_NOTIFICATION);
-            final int IN_CALL_NOTIFICATION_UPDATE_DELAY = 1000;  // msec
-            sendEmptyMessageDelayed(UPDATE_IN_CALL_NOTIFICATION,
-                                    IN_CALL_NOTIFICATION_UPDATE_DELAY);
         }
 
         if (fgPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
@@ -885,7 +825,8 @@
             mApplication.notificationMgr.notifyMissedCall(ci.name, ci.phoneNumber,
                     ci.phoneLabel, ci.cachedPhoto, ci.cachedPhotoIcon,
                     ((Long) cookie).longValue());
-        } else if (cookie instanceof CallNotifier) {
+        } else if (cookie instanceof Connection) {
+            final Connection c = (Connection) cookie;
             if (VDBG) log("CallerInfo query complete (for CallNotifier), "
                     + "updating state for incoming call..");
 
@@ -905,18 +846,21 @@
                 // send directly to voicemail.
                 if (ci.shouldSendToVoicemail) {
                     if (DBG) log("send to voicemail flag detected. hanging up.");
-                    PhoneUtils.hangupRingingCall(mCM.getFirstActiveRingingCall());
-                    return;
+                    final Call ringingCall = mCM.getFirstActiveRingingCall();
+                    if (ringingCall != null && ringingCall.getLatestConnection() == c) {
+                        PhoneUtils.hangupRingingCall(ringingCall);
+                        return;
+                    }
                 }
 
                 // set the ringtone uri to prepare for the ring.
                 if (ci.contactRingtoneUri != null) {
                     if (DBG) log("custom ringtone found, setting up ringer.");
-                    Ringer r = ((CallNotifier) cookie).mRinger;
+                    Ringer r = mRinger;
                     r.setCustomRingtoneUri(ci.contactRingtoneUri);
                 }
                 // ring, and other post-ring actions.
-                onCustomRingQueryComplete();
+                onCustomRingQueryComplete(c);
             }
         }
     }
@@ -932,7 +876,7 @@
      * @param number The phone number used for the async query. This method will take care of
      * formatting or normalization of the number.
      */
-    private void onCustomRingtoneQueryTimeout(String number) {
+    private void onCustomRingtoneQueryTimeout(Connection c) {
         // First of all, this case itself should be rare enough, though we cannot avoid it in
         // some situations (e.g. IPC is slow due to system overload, database is in sync, etc.)
         Log.w(LOG_TAG, "CallerInfo query took too long; look up local fallback cache.");
@@ -940,29 +884,34 @@
         // This method is intentionally verbose for now to detect possible bad side-effect for it.
         // TODO: Remove the verbose log when it looks stable and reliable enough.
 
-        final CallerInfoCache.CacheEntry entry =
-                mApplication.callerInfoCache.getCacheEntry(number);
-        if (entry != null) {
-            if (entry.sendToVoicemail) {
-                log("send to voicemail flag detected (in fallback cache). hanging up.");
-                PhoneUtils.hangupRingingCall(mCM.getFirstActiveRingingCall());
-                return;
-            }
 
-            if (entry.customRingtone != null) {
-                log("custom ringtone found (in fallback cache), setting up ringer: "
-                        + entry.customRingtone);
-                this.mRinger.setCustomRingtoneUri(Uri.parse(entry.customRingtone));
+        if (c != null) {
+            final CallerInfoCache.CacheEntry entry =
+                    mApplication.callerInfoCache.getCacheEntry(c.getAddress());
+            if (entry != null) {
+                if (entry.sendToVoicemail) {
+                    log("send to voicemail flag detected (in fallback cache). hanging up.");
+                    if (mCM.getFirstActiveRingingCall().getLatestConnection() == c) {
+                        PhoneUtils.hangupRingingCall(mCM.getFirstActiveRingingCall());
+                        return;
+                    }
+                }
+
+                if (entry.customRingtone != null) {
+                    log("custom ringtone found (in fallback cache), setting up ringer: "
+                            + entry.customRingtone);
+                    this.mRinger.setCustomRingtoneUri(Uri.parse(entry.customRingtone));
+                }
+            } else {
+                // In this case we call onCustomRingQueryComplete(), just
+                // like if the query had completed normally.  (But we're
+                // going to get the default ringtone, since we never got
+                // the chance to call Ringer.setCustomRingtoneUri()).
+                log("Failed to find fallback cache. Use default ringer tone.");
             }
-        } else {
-            // In this case we call onCustomRingQueryComplete(), just
-            // like if the query had completed normally.  (But we're
-            // going to get the default ringtone, since we never got
-            // the chance to call Ringer.setCustomRingtoneUri()).
-            log("Failed to find fallback cache. Use default ringer tone.");
         }
 
-        onCustomRingQueryComplete();
+        onCustomRingQueryComplete(c);
     }
 
     private void onDisconnect(AsyncResult r) {
@@ -1645,13 +1594,6 @@
         mApplication.cdmaPhoneCallState.setCurrentCallState(
                 CdmaPhoneCallState.PhoneCallState.SINGLE_ACTIVE);
 
-        // Display the incoming call to the user if the InCallScreen isn't
-        // already in the foreground.
-        if (!mApplication.isShowingCallScreen()) {
-            if (DBG) log("- showing incoming call (CDMA call waiting)...");
-            showIncomingCall();
-        }
-
         // Start timer for CW display
         mCallWaitingTimeOut = false;
         sendEmptyMessageDelayed(CALLWAITING_CALLERINFO_DISPLAY_DONE,
diff --git a/src/com/android/phone/InCallScreen.java b/src/com/android/phone/InCallScreen.java
index 8b67b77..53cd40d 100644
--- a/src/com/android/phone/InCallScreen.java
+++ b/src/com/android/phone/InCallScreen.java
@@ -494,10 +494,6 @@
 
         updateExpandedViewState();
 
-        // ...and update the in-call notification too, since the status bar
-        // icon needs to be hidden while we're the foreground activity:
-        mApp.notificationMgr.updateInCallNotification();
-
         // Listen for broadcast intents that might affect the onscreen UI.
         registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_HEADSET_PLUG));
 
@@ -760,8 +756,6 @@
 
         updateExpandedViewState();
 
-        // ...and the in-call notification too:
-        mApp.notificationMgr.updateInCallNotification();
         // ...and *always* reset the system bar back to its normal state
         // when leaving the in-call UI.
         // (While we're the foreground activity, we disable navigation in
@@ -2685,12 +2679,6 @@
         boolean newSpeakerState = !PhoneUtils.isSpeakerOn(this);
         log("toggleSpeaker(): newSpeakerState = " + newSpeakerState);
 
-        // TODO(klp): Add bluetooth query back in for AudioRouter.
-        /*
-         if (newSpeakerState && isBluetoothAvailable() && isBluetoothAudioConnected()) {
-            disconnectBluetoothAudio();
-        }
-        */
         PhoneUtils.turnOnSpeaker(this, newSpeakerState, true);
 
         // And update the InCallTouchUi widget (since the "audio mode"
@@ -2708,16 +2696,6 @@
         PhoneUtils.setMute(newMuteState);
     }
 
-    public void toggleBluetooth() {
-        // TODO(klp) this still here to avoid compile errors until remove
-        // the UI from services/Telephony completely.
-    }
-
-    public void switchInCallAudio(InCallAudioMode newMode) {
-        // TODO(klp) this still here to avoid compile errors until remove
-        // the UI from services/Telephony completely.
-    }
-
     /**
      * Handle a click on the "Open/Close dialpad" button.
      *
diff --git a/src/com/android/phone/InCallTouchUi.java b/src/com/android/phone/InCallTouchUi.java
index 1d08671..9cb2a52 100644
--- a/src/com/android/phone/InCallTouchUi.java
+++ b/src/com/android/phone/InCallTouchUi.java
@@ -868,7 +868,6 @@
         MenuItem earpieceItem = menu.findItem(R.id.audio_mode_earpiece);
         MenuItem wiredHeadsetItem = menu.findItem(R.id.audio_mode_wired_headset);
 
-        // TODO(klp): This is a compile stop-gap.  This will all be deleted
         final boolean usingHeadset = false; //mApp.isHeadsetPlugged();
 
         earpieceItem.setVisible(!usingHeadset);
@@ -938,16 +937,16 @@
 
         switch (item.getItemId()) {
             case R.id.audio_mode_speaker:
-                mInCallScreen.switchInCallAudio(InCallScreen.InCallAudioMode.SPEAKER);
+//                mInCallScreen.switchInCallAudio(InCallScreen.InCallAudioMode.SPEAKER);
                 break;
             case R.id.audio_mode_earpiece:
             case R.id.audio_mode_wired_headset:
                 // InCallAudioMode.EARPIECE means either the handset earpiece,
                 // or the wired headset (if connected.)
-                mInCallScreen.switchInCallAudio(InCallScreen.InCallAudioMode.EARPIECE);
+//                mInCallScreen.switchInCallAudio(InCallScreen.InCallAudioMode.EARPIECE);
                 break;
             case R.id.audio_mode_bluetooth:
-                mInCallScreen.switchInCallAudio(InCallScreen.InCallAudioMode.BLUETOOTH);
+//                mInCallScreen.switchInCallAudio(InCallScreen.InCallAudioMode.BLUETOOTH);
                 break;
             default:
                 Log.wtf(LOG_TAG,
diff --git a/src/com/android/phone/NotificationMgr.java b/src/com/android/phone/NotificationMgr.java
index 5c33ab4..7771fa9 100644
--- a/src/com/android/phone/NotificationMgr.java
+++ b/src/com/android/phone/NotificationMgr.java
@@ -67,7 +67,7 @@
  *
  * @see PhoneGlobals.notificationMgr
  */
-public class NotificationMgr implements CallerInfoAsyncQuery.OnQueryCompleteListener{
+public class NotificationMgr {
     private static final String LOG_TAG = "NotificationMgr";
     private static final boolean DBG =
             (PhoneGlobals.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1);
@@ -112,8 +112,6 @@
     // used to track the missed call counter, default to 0.
     private int mNumberMissedCalls = 0;
 
-    private boolean mHasInCallNotification = false;
-
     // used to track the notification of selected network unavailable
     private boolean mSelectedUnavailableNotify = false;
 
@@ -278,10 +276,6 @@
         mQueryHandler.startQuery(CALL_LOG_TOKEN, null, Calls.CONTENT_URI,  CALL_LOG_PROJECTION,
                 where.toString(), null, Calls.DEFAULT_SORT_ORDER);
 
-        // Update (or cancel) the in-call notification
-        if (DBG) log("- updating in-call notification at startup...");
-        updateInCallNotification();
-
         // Depend on android.app.StatusBarManager to be set to
         // disable(DISABLE_NONE) upon startup.  This will be the
         // case even if the phone app crashes.
@@ -705,229 +699,11 @@
     }
 
     /**
-     * Updates the phone app's status bar notification based on the
-     * current telephony state, or cancels the notification if the phone
-     * is totally idle.
-     *
-     * This method will never actually launch the incoming-call UI.
-     * (Use updateNotificationAndLaunchIncomingCallUi() for that.)
-     */
-    public void updateInCallNotification() {
-        // allowFullScreenIntent=false means *don't* allow the incoming
-        // call UI to be launched.
-        updateInCallNotification(false);
-    }
-
-    /**
-     * Updates the phone app's status bar notification *and* launches the
-     * incoming call UI in response to a new incoming call.
-     *
-     * This is just like updateInCallNotification(), with one exception:
-     * If an incoming call is ringing (or call-waiting), the notification
-     * will also include a "fullScreenIntent" that will cause the
-     * InCallScreen to be launched immediately, unless the current
-     * foreground activity is marked as "immersive".
-     *
-     * (This is the mechanism that actually brings up the incoming call UI
-     * when we receive a "new ringing connection" event from the telephony
-     * layer.)
-     *
-     * Watch out: this method should ONLY be called directly from the code
-     * path in CallNotifier that handles the "new ringing connection"
-     * event from the telephony layer.  All other places that update the
-     * in-call notification (like for phone state changes) should call
-     * updateInCallNotification() instead.  (This ensures that we don't
-     * end up launching the InCallScreen multiple times for a single
-     * incoming call, which could cause slow responsiveness and/or visible
-     * glitches.)
-     *
-     * Also note that this method is safe to call even if the phone isn't
-     * actually ringing (or, more likely, if an incoming call *was*
-     * ringing briefly but then disconnected).  In that case, we'll simply
-     * update or cancel the in-call notification based on the current
-     * phone state.
-     *
-     * @see #updateInCallNotification(boolean)
-     */
-    public void updateNotificationAndLaunchIncomingCallUi() {
-        // Set allowFullScreenIntent=true to indicate that we *should*
-        // launch the incoming call UI if necessary.
-        updateInCallNotification(true);
-    }
-
-    /**
-     * Helper method for updateInCallNotification() and
-     * updateNotificationAndLaunchIncomingCallUi(): Update the phone app's
-     * status bar notification based on the current telephony state, or
-     * cancels the notification if the phone is totally idle.
-     *
-     * @param allowFullScreenIntent If true, *and* an incoming call is
-     *   ringing, the notification will include a "fullScreenIntent"
-     *   pointing at the InCallScreen (which will cause the InCallScreen
-     *   to be launched.)
-     *   Watch out: This should be set to true *only* when directly
-     *   handling the "new ringing connection" event from the telephony
-     *   layer (see updateNotificationAndLaunchIncomingCallUi().)
-     */
-    private void updateInCallNotification(boolean allowFullScreenIntent) {
-        if (DBG) log("updateInCallNotification(allowFullScreenIntent = "
-                     + allowFullScreenIntent + ")...");
-
-        // Never display the "ongoing call" notification on
-        // non-voice-capable devices, even if the phone is actually
-        // offhook (like during a non-interactive OTASP call.)
-        if (!PhoneGlobals.sVoiceCapable) {
-            if (DBG) log("- non-voice-capable device; suppressing notification.");
-            return;
-        }
-
-        // If the phone is idle, completely clean up all call-related
-        // notifications.
-        if (mCM.getState() == PhoneConstants.State.IDLE) {
-            cancelInCall();
-            cancelMute();
-            cancelSpeakerphone();
-            return;
-        }
-
-        final boolean hasRingingCall = mCM.hasActiveRingingCall();
-        if (DBG) {
-            log("  - hasRingingCall = " + hasRingingCall);
-        }
-
-        // Suppress the in-call notification if the InCallScreen is the
-        // foreground activity, since it's already obvious that you're on a
-        // call.  (The status bar icon is needed only if you navigate *away*
-        // from the in-call UI.)
-        boolean suppressNotification = mApp.isShowingCallScreen();
-        // if (DBG) log("- suppressNotification: initial value: " + suppressNotification);
-
-        // ...except for a couple of cases where we *never* suppress the
-        // notification:
-        //
-        //   - If there's an incoming ringing call: always show the
-        //     notification, since the in-call notification is what actually
-        //     launches the incoming call UI in the first place (see
-        //     notification.fullScreenIntent below.)  This makes sure that we'll
-        //     correctly handle the case where a new incoming call comes in but
-        //     the InCallScreen is already in the foreground.
-        if (hasRingingCall) suppressNotification = false;
-
-        //   - If "voice privacy" mode is active: always show the notification,
-        //     since that's the only "voice privacy" indication we have.
-        boolean enhancedVoicePrivacy = mApp.notifier.getVoicePrivacyState();
-        // if (DBG) log("updateInCallNotification: enhancedVoicePrivacy = " + enhancedVoicePrivacy);
-        if (enhancedVoicePrivacy) suppressNotification = false;
-
-        if (suppressNotification) {
-            if (DBG) log("- suppressNotification = true; reducing clutter in status bar...");
-            cancelInCall();
-            // Suppress the mute and speaker status bar icons too
-            // (also to reduce clutter in the status bar.)
-            cancelSpeakerphone();
-            cancelMute();
-            return;
-        }
-
-        mHasInCallNotification = true;
-
-        // Activate a couple of special Notification features if an
-        // incoming call is ringing:
-        if (hasRingingCall) {
-            if (DBG) log("- Using hi-pri notification for ringing call!");
-
-            if (allowFullScreenIntent) {
-
-                // Ugly hack alert:
-                //
-                // The NotificationManager has the (undocumented) behavior
-                // that it will *ignore* the fullScreenIntent field if you
-                // post a new Notification that matches the ID of one that's
-                // already active.  Unfortunately this is exactly what happens
-                // when you get an incoming call-waiting call:  the
-                // "ongoing call" notification is already visible, so the
-                // InCallScreen won't get launched in this case!
-                // (The result: if you bail out of the in-call UI while on a
-                // call and then get a call-waiting call, the incoming call UI
-                // won't come up automatically.)
-                //
-                // The workaround is to just notice this exact case (this is a
-                // call-waiting call *and* the InCallScreen is not in the
-                // foreground) and manually cancel the in-call notification
-                // before (re)posting it.
-                //
-                // TODO: there should be a cleaner way of avoiding this
-                // problem (see discussion in bug 3184149.)
-                Call ringingCall = mCM.getFirstActiveRingingCall();
-                if ((ringingCall.getState() == Call.State.WAITING) && !mApp.isShowingCallScreen()) {
-                    Log.i(LOG_TAG, "updateInCallNotification: call-waiting! force relaunch...");
-                    // Cancel the IN_CALL_NOTIFICATION immediately before
-                    // (re)posting it; this seems to force the
-                    // NotificationManager to launch the fullScreenIntent.
-                    mNotificationManager.cancel(IN_CALL_NOTIFICATION);
-                }
-            }
-        }
-
-        // Finally, refresh the mute and speakerphone notifications (since
-        // some phone state changes can indirectly affect the mute and/or
-        // speaker state).
-        updateSpeakerNotification();
-        updateMuteNotification();
-    }
-
-    /**
-     * Implemented for CallerInfoAsyncQuery.OnQueryCompleteListener interface.
-     * refreshes the contentView when called.
-     */
-    @Override
-    public void onQueryComplete(int token, Object cookie, CallerInfo ci){
-        if (DBG) log("CallerInfo query complete (for NotificationMgr), "
-                     + "updating in-call notification..");
-        if (DBG) log("- cookie: " + cookie);
-        if (DBG) log("- ci: " + ci);
-
-        if (cookie == this) {
-            // Ok, this is the caller-id query we fired off in
-            // updateInCallNotification(), presumably when an incoming call
-            // first appeared.  If the caller-id info matched any contacts,
-            // compactName should now be a real person name rather than a raw
-            // phone number:
-            if (DBG) log("- compactName is now: "
-                         + PhoneUtils.getCompactNameFromCallerInfo(ci, mContext));
-
-            // Now that our CallerInfo object has been fully filled-in,
-            // refresh the in-call notification.
-            if (DBG) log("- updating notification after query complete...");
-            updateInCallNotification();
-        } else {
-            Log.w(LOG_TAG, "onQueryComplete: caller-id query from unknown source! "
-                  + "cookie = " + cookie);
-        }
-    }
-
-    /**
-     * Take down the in-call notification.
-     * @see updateInCallNotification()
-     */
-    private void cancelInCall() {
-        if (DBG) log("cancelInCall()...");
-        mNotificationManager.cancel(IN_CALL_NOTIFICATION);
-        mHasInCallNotification = false;
-    }
-
-    /**
      * Completely take down the in-call notification *and* the mute/speaker
      * notifications as well, to indicate that the phone is now idle.
      */
     /* package */ void cancelCallInProgressNotifications() {
-        if (DBG) log("cancelCallInProgressNotifications()...");
-        if (!mHasInCallNotification) {
-            return;
-        }
-
         if (DBG) log("cancelCallInProgressNotifications");
-        cancelInCall();
         cancelMute();
         cancelSpeakerphone();
     }
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index 49a3427..b70b159 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -105,7 +105,6 @@
     // Message codes; see mHandler below.
     private static final int EVENT_SIM_NETWORK_LOCKED = 3;
     private static final int EVENT_SIM_STATE_CHANGED = 8;
-    private static final int EVENT_UPDATE_INCALL_NOTIFICATION = 9;
     private static final int EVENT_DATA_ROAMING_DISCONNECTED = 10;
     private static final int EVENT_DATA_ROAMING_OK = 11;
     private static final int EVENT_UNSOL_CDMA_INFO_RECORD = 12;
@@ -301,16 +300,6 @@
                     }
                     break;
 
-                case EVENT_UPDATE_INCALL_NOTIFICATION:
-                    // Tell the NotificationMgr to update the "ongoing
-                    // call" icon in the status bar, if necessary.
-                    // Currently, this is triggered by a bluetooth headset
-                    // state change (since the status bar icon needs to
-                    // turn blue when bluetooth is active.)
-                    if (DBG) Log.d (LOG_TAG, "- updating in-call notification from handler...");
-                    notificationMgr.updateInCallNotification();
-                    break;
-
                 case EVENT_DATA_ROAMING_DISCONNECTED:
                     notificationMgr.showDataDisconnectedRoaming();
                     break;
diff --git a/src/com/android/phone/RejectWithTextMessageManager.java b/src/com/android/phone/RejectWithTextMessageManager.java
index fda8f78..232de8e 100644
--- a/src/com/android/phone/RejectWithTextMessageManager.java
+++ b/src/com/android/phone/RejectWithTextMessageManager.java
@@ -250,7 +250,6 @@
             return true;
         } else {
             Log.v(TAG, "Choosing from one of the apps");
-            // TODO(klp): Add an app picker.
             final Intent intent = new Intent(Intent.ACTION_VIEW, null);
             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                     Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |