auto import from //branches/cupcake/...@137197
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index a254081..9948322 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -196,6 +196,11 @@
     ClientState mCurClient;
     
     /**
+     * The last window token that gained focus.
+     */
+    IBinder mCurFocusedWindow;
+    
+    /**
      * The input context last provided by the current client.
      */
     IInputContext mCurInputContext;
@@ -557,7 +562,7 @@
          }
     }
     
-    void unbindCurrentInputLocked() {
+    void unbindCurrentClientLocked() {
         if (mCurClient != null) {
             if (DEBUG) Log.v(TAG, "unbindCurrentInputLocked: client = "
                     + mCurClient.client.asBinder());
@@ -658,7 +663,7 @@
         if (mCurClient != cs) {
             // If the client is changing, we need to switch over to the new
             // one.
-            unbindCurrentInputLocked();
+            unbindCurrentClientLocked();
             if (DEBUG) Log.v(TAG, "switching to client: client = "
                     + cs.client.asBinder());
 
@@ -721,21 +726,7 @@
             throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
         }
         
-        if (mHaveConnection) {
-            mContext.unbindService(this);
-            mHaveConnection = false;
-        }
-        
-        if (mCurToken != null) {
-            try {
-                if (DEBUG) Log.v(TAG, "Removing window token: " + mCurToken);
-                mIWindowManager.removeWindowToken(mCurToken);
-            } catch (RemoteException e) {
-            }
-            mCurToken = null;
-        }
-        
-        clearCurMethod();
+        unbindCurrentMethodLocked(false);
         
         mCurIntent = new Intent(InputMethod.SERVICE_INTERFACE);
         mCurIntent.setComponent(info.getComponent());
@@ -814,7 +805,30 @@
         }
     }
     
-    void clearCurMethod() {
+    void unbindCurrentMethodLocked(boolean reportToClient) {
+        if (mHaveConnection) {
+            mContext.unbindService(this);
+            mHaveConnection = false;
+        }
+        
+        if (mCurToken != null) {
+            try {
+                if (DEBUG) Log.v(TAG, "Removing window token: " + mCurToken);
+                mIWindowManager.removeWindowToken(mCurToken);
+            } catch (RemoteException e) {
+            }
+            mCurToken = null;
+        }
+        
+        clearCurMethodLocked();
+        
+        if (reportToClient && mCurClient != null) {
+            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
+                    MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
+        }
+    }
+    
+    void clearCurMethodLocked() {
         if (mCurMethod != null) {
             for (ClientState cs : mClients.values()) {
                 cs.sessionRequested = false;
@@ -831,7 +845,7 @@
                     + " mCurIntent=" + mCurIntent);
             if (mCurMethod != null && mCurIntent != null
                     && name.equals(mCurIntent.getComponent())) {
-                clearCurMethod();
+                clearCurMethodLocked();
                 // We consider this to be a new bind attempt, since the system
                 // should now try to restart the service for us.
                 mLastBindTime = SystemClock.uptimeMillis();
@@ -871,14 +885,22 @@
     }
 
     void updateFromSettingsLocked() {
+        // We are assuming that whoever is changing DEFAULT_INPUT_METHOD and
+        // ENABLED_INPUT_METHODS is taking care of keeping them correctly in
+        // sync, so we will never have a DEFAULT_INPUT_METHOD that is not
+        // enabled.
         String id = Settings.Secure.getString(mContext.getContentResolver(),
             Settings.Secure.DEFAULT_INPUT_METHOD);
-        if (id != null) {
+        if (id != null && id.length() > 0) {
             try {
                 setInputMethodLocked(id);
             } catch (IllegalArgumentException e) {
                 Log.w(TAG, "Unknown input method from prefs: " + id, e);
+                unbindCurrentMethodLocked(true);
             }
+        } else {
+            // There is no longer an input method set, so stop any current one.
+            unbindCurrentMethodLocked(true);
         }
     }
     
@@ -903,7 +925,7 @@
                 intent.putExtra("input_method_id", id);
                 mContext.sendBroadcast(intent);
             }
-            unbindCurrentInputLocked();
+            unbindCurrentClientLocked();
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -1023,7 +1045,7 @@
         return res;
     }
     
-    public void windowGainedFocus(IInputMethodClient client,
+    public void windowGainedFocus(IInputMethodClient client, IBinder windowToken,
             boolean viewHasFocus, boolean isTextEditor, int softInputMode,
             boolean first, int windowFlags) {
         long ident = Binder.clearCallingIdentity();
@@ -1043,13 +1065,19 @@
                         // focus in the window manager, to allow this call to
                         // be made before input is started in it.
                         if (!mIWindowManager.inputMethodClientHasFocus(client)) {
-                            Log.w(TAG, "Ignoring focus gain of: " + client);
+                            Log.w(TAG, "Client not active, ignoring focus gain of: " + client);
                             return;
                         }
                     } catch (RemoteException e) {
                     }
                 }
     
+                if (mCurFocusedWindow == windowToken) {
+                    Log.w(TAG, "Window already focused, ignoring focus gain of: " + client);
+                    return;
+                }
+                mCurFocusedWindow = windowToken;
+                
                 switch (softInputMode&WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) {
                     case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
                         if (!isTextEditor || (softInputMode &
@@ -1558,7 +1586,8 @@
             p.println("  mInputMethodData=" + mInputMethodData);
             p.println("  mCurrentMethod=" + mCurMethodId);
             client = mCurClient;
-            p.println("  mCurSeq=" + mCurSeq + " mCurClient=" + client);
+            p.println("  mCurClient=" + client + " mCurSeq=" + mCurSeq);
+            p.println("  mCurFocusedWindow=" + mCurFocusedWindow);
             p.println("  mCurId=" + mCurId + " mHaveConnect=" + mHaveConnection
                     + " mBoundToMethod=" + mBoundToMethod);
             p.println("  mCurToken=" + mCurToken);
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index eece581..e298f49 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -22,9 +22,9 @@
 import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING;
 import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;
 
-import android.app.ActivityManagerNative;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
+import android.bluetooth.BluetoothA2dp;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -1491,6 +1491,12 @@
                     return;
                 }
                 mPluggedType = pluggedType;
+            } else if (action.equals(BluetoothA2dp.SINK_STATE_CHANGED_ACTION)) {
+                boolean isBluetoothPlaying =
+                        intent.getIntExtra(
+                                BluetoothA2dp.SINK_STATE,
+                                BluetoothA2dp.STATE_DISCONNECTED) == BluetoothA2dp.STATE_PLAYING;
+                mWifiStateTracker.setBluetoothScanMode(isBluetoothPlaying);
             } else {
                 return;
             }
@@ -1603,13 +1609,11 @@
 
     private void registerForBroadcasts() {
         IntentFilter intentFilter = new IntentFilter();
-        if (isAirplaneSensitive()) {
-            intentFilter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
-        }
         intentFilter.addAction(Intent.ACTION_SCREEN_ON);
         intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
         intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
         intentFilter.addAction(ACTION_DEVICE_IDLE);
+        intentFilter.addAction(BluetoothA2dp.SINK_STATE_CHANGED_ACTION);
         mContext.registerReceiver(mReceiver, intentFilter);
     }