Kick Bluetooth stack after user is unlocked.

If Bluetooth was enabled at boot time, but the actual Bluetooth
package wasn't encryption aware, we need to kick off another enabled
pass once the user is unlocked.

Bug: 27326711
Change-Id: I511c4fd8567792e5bc4d49fa95929fd87edd0fbf
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index f65dbb6..e241a4a 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -89,14 +89,15 @@
     private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40;
     private static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41;
     private static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42;
-    private static final int MESSAGE_BLUETOOTH_STATE_CHANGE=60;
-    private static final int MESSAGE_TIMEOUT_BIND =100;
-    private static final int MESSAGE_TIMEOUT_UNBIND =101;
+    private static final int MESSAGE_BLUETOOTH_STATE_CHANGE = 60;
+    private static final int MESSAGE_TIMEOUT_BIND = 100;
+    private static final int MESSAGE_TIMEOUT_UNBIND = 101;
     private static final int MESSAGE_USER_SWITCHED = 300;
+    private static final int MESSAGE_USER_UNLOCKED = 301;
     private static final int MESSAGE_ADD_PROXY_DELAYED = 400;
     private static final int MESSAGE_BIND_PROFILE_SERVICE = 401;
-    private static final int MAX_SAVE_RETRIES=3;
-    private static final int MAX_ERROR_RESTART_RETRIES=6;
+    private static final int MAX_SAVE_RETRIES = 3;
+    private static final int MAX_ERROR_RESTART_RETRIES = 6;
 
     // Bluetooth persisted setting is off
     private static final int BLUETOOTH_OFF=0;
@@ -767,8 +768,16 @@
      * Called when switching to a different foreground user.
      */
     public void handleOnSwitchUser(int userHandle) {
-        if (DBG) Slog.d(TAG, "Bluetooth user switched");
-        mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0));
+        if (DBG) Slog.d(TAG, "User " + userHandle + " switched");
+        mHandler.obtainMessage(MESSAGE_USER_SWITCHED, userHandle, 0).sendToTarget();
+    }
+
+    /**
+     * Called when user is unlocked.
+     */
+    public void handleOnUnlockUser(int userHandle) {
+        if (DBG) Slog.d(TAG, "User " + userHandle + " unlocked");
+        mHandler.obtainMessage(MESSAGE_USER_UNLOCKED, userHandle, 0).sendToTarget();
     }
 
     /**
@@ -1308,12 +1317,10 @@
                     break;
                 }
 
-                case MESSAGE_USER_SWITCHED:
-                {
-                    if (DBG) {
-                        Slog.d(TAG, "MESSAGE_USER_SWITCHED");
-                    }
+                case MESSAGE_USER_SWITCHED: {
+                    if (DBG) Slog.d(TAG, "MESSAGE_USER_SWITCHED");
                     mHandler.removeMessages(MESSAGE_USER_SWITCHED);
+
                     /* disable and enable BT when detect a user switch */
                     if (mEnable && mBluetooth != null) {
                         synchronized (mConnection) {
@@ -1381,6 +1388,20 @@
                     }
                     break;
                 }
+                case MESSAGE_USER_UNLOCKED: {
+                    if (DBG) Slog.d(TAG, "MESSAGE_USER_UNLOCKED");
+                    mHandler.removeMessages(MESSAGE_USER_SWITCHED);
+
+                    synchronized (mConnection) {
+                        if (mEnable && !mBinding && (mBluetooth == null)) {
+                            // We should be connected, but we gave up for some
+                            // reason; maybe the Bluetooth service wasn't encryption
+                            // aware, so try binding again.
+                            if (DBG) Slog.d(TAG, "Enabled but not bound; retrying after unlock");
+                            handleEnable(mQuietEnable);
+                        }
+                    }
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/BluetoothService.java b/services/core/java/com/android/server/BluetoothService.java
index 019d03d..1bf4e3a 100644
--- a/services/core/java/com/android/server/BluetoothService.java
+++ b/services/core/java/com/android/server/BluetoothService.java
@@ -18,10 +18,8 @@
 
 import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
-import android.util.Log;
 
 class BluetoothService extends SystemService {
-    private static final String TAG = "BluetoothService";
     private BluetoothManagerService mBluetoothManagerService;
 
     public BluetoothService(Context context) {
@@ -36,17 +34,20 @@
     @Override
     public void onBootPhase(int phase) {
         if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
-            Log.d(TAG, "onBootPhase: PHASE_SYSTEM_SERVICES_READY");
-            publishBinderService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, mBluetoothManagerService);
+            publishBinderService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE,
+                    mBluetoothManagerService);
         } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
-            Log.d(TAG, "onBootPhase: PHASE_ACTIVITY_MANAGER_READY");
             mBluetoothManagerService.handleOnBootPhase();
         }
     }
 
     @Override
     public void onSwitchUser(int userHandle) {
-        Log.d(TAG, "onSwitchUser: switching to user " + userHandle);
         mBluetoothManagerService.handleOnSwitchUser(userHandle);
     }
+
+    @Override
+    public void onUnlockUser(int userHandle) {
+        mBluetoothManagerService.handleOnUnlockUser(userHandle);
+    }
 }