Fix data race

Fixes a race in BluetoothControllerImpl that could lead
to a ConcurrentModificationException, by moving the manipulation
of the callbacks array to the handler.

Change-Id: I7c3be74d239d4706f55357f54e539b7b6439e76d
Fixes: 29390132
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
index 6439bea..014cc49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
@@ -40,7 +40,6 @@
     private static final String TAG = "BluetoothController";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
-    private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
     private final LocalBluetoothManager mLocalBluetoothManager;
     private final UserManager mUserManager;
     private final int mCurrentUser;
@@ -78,7 +77,7 @@
         pw.print("  mEnabled="); pw.println(mEnabled);
         pw.print("  mConnectionState="); pw.println(stateToString(mConnectionState));
         pw.print("  mLastDevice="); pw.println(mLastDevice);
-        pw.print("  mCallbacks.size="); pw.println(mCallbacks.size());
+        pw.print("  mCallbacks.size="); pw.println(mHandler.mCallbacks.size());
         pw.println("  Bluetooth Devices:");
         for (CachedBluetoothDevice device :
                 mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy()) {
@@ -106,13 +105,13 @@
 
     @Override
     public void addStateChangedCallback(Callback cb) {
-        mCallbacks.add(cb);
+        mHandler.obtainMessage(H.MSG_ADD_CALLBACK, cb).sendToTarget();
         mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
     }
 
     @Override
     public void removeStateChangedCallback(Callback cb) {
-        mCallbacks.remove(cb);
+        mHandler.obtainMessage(H.MSG_REMOVE_CALLBACK, cb).sendToTarget();
     }
 
     @Override
@@ -236,8 +235,12 @@
     }
 
     private final class H extends Handler {
+        private final ArrayList<BluetoothController.Callback> mCallbacks = new ArrayList<>();
+
         private static final int MSG_PAIRED_DEVICES_CHANGED = 1;
         private static final int MSG_STATE_CHANGED = 2;
+        private static final int MSG_ADD_CALLBACK = 3;
+        private static final int MSG_REMOVE_CALLBACK = 4;
 
         @Override
         public void handleMessage(Message msg) {
@@ -248,6 +251,12 @@
                 case MSG_STATE_CHANGED:
                     fireStateChange();
                     break;
+                case MSG_ADD_CALLBACK:
+                    mCallbacks.add((BluetoothController.Callback) msg.obj);
+                    break;
+                case MSG_REMOVE_CALLBACK:
+                    mCallbacks.remove((BluetoothController.Callback) msg.obj);
+                    break;
             }
         }