Merge 5785a88195339f631b88ef663375c1201caf9285 on remote branch

Change-Id: I7d10a0562df8f66f300cad150a374d8758b76114
diff --git a/src/com/android/bluetooth/a2dp/A2dpService.java b/src/com/android/bluetooth/a2dp/A2dpService.java
index b232568..2d2f34a 100755
--- a/src/com/android/bluetooth/a2dp/A2dpService.java
+++ b/src/com/android/bluetooth/a2dp/A2dpService.java
@@ -716,21 +716,27 @@
     }
 
     private void storeActiveDeviceVolume() {
-        // Make sure volume has been stored before been removed from active.
-        if (mFactory.getAvrcpTargetService() != null && mActiveDevice != null) {
-            mFactory.getAvrcpTargetService().storeVolumeForDevice(mActiveDevice);
+        BluetoothDevice activeDevice;
+        synchronized (mStateMachines) {
+            activeDevice = mActiveDevice;
         }
-        if (mActiveDevice != null && mAvrcp_ext != null) {
-            mAvrcp_ext.storeVolumeForDevice(mActiveDevice);
+        // Make sure volume has been stored before been removed from active.
+        if (mFactory.getAvrcpTargetService() != null && activeDevice != null) {
+            mFactory.getAvrcpTargetService().storeVolumeForDevice(activeDevice);
+        }
+        synchronized (mBtAvrcpLock) {
+            if (activeDevice != null && mAvrcp_ext != null) {
+                mAvrcp_ext.storeVolumeForDevice(activeDevice);
+            }
         }
     }
 
     private void removeActiveDevice(boolean forceStopPlayingAudio) {
         BluetoothDevice previousActiveDevice = mActiveDevice;
-        synchronized (mBtA2dpLock) {
-            // Make sure volume has been store before device been remove from active.
-            storeActiveDeviceVolume();
 
+        // Make sure volume has been store before device been remove from active.
+        storeActiveDeviceVolume();
+        synchronized (mBtA2dpLock) {
             // This needs to happen before we inform the audio manager that the device
             // disconnected. Please see comment in updateAndBroadcastActiveDevice() for why.
             updateAndBroadcastActiveDevice(null);
diff --git a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java
index d3219e2..dede1a7 100644
--- a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java
+++ b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java
@@ -40,6 +40,9 @@
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
+
 /**
  * Provides Bluetooth AVRCP Controller profile, as a service in the Bluetooth application.
  */
@@ -329,6 +332,11 @@
         StackEvent event =
                 StackEvent.connectionStateChanged(remoteControlConnected, browsingConnected);
         AvrcpControllerStateMachine stateMachine = getOrCreateStateMachine(device);
+        if (stateMachine == null) {
+            Log.e(TAG, "onConnectionStateChanged: mAvrcpCtSm is null, return");
+            return;
+        }
+
         if (remoteControlConnected || browsingConnected) {
             stateMachine.connect(event);
         } else {
@@ -343,9 +351,17 @@
         mCaPsm = caPsm;
         BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
         AvrcpControllerStateMachine stateMachine = getStateMachine(device);
-        if (stateMachine != null) {
+        if (stateMachine == null) {
+            Log.e(TAG, "getRcFeatures: AvrcpControllerStateMachine is null for device: " + device);
+            return;
+        }
+
+        try {
             stateMachine.sendMessage(
                     AvrcpControllerStateMachine.MESSAGE_PROCESS_RC_FEATURES, features, caPsm, device);
+        } catch(Exception ee) {
+            Log.i(TAG, "getRcFeatures exception occured.");
+            ee.printStackTrace();
         }
     }
 
@@ -718,7 +734,10 @@
         if (stateMachine == null) {
             stateMachine = newStateMachine(device);
             mDeviceStateMap.put(device, stateMachine);
+            Log.d(TAG, "AvrcpControllerStateMachine start() called: " + device);
             stateMachine.start();
+            Log.d(TAG, "AvrcpcontrollerSM started for device: " + device);
+            stateMachine.registerReceiver(device);
         }
         return stateMachine;
     }
diff --git a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
index 03d8f48..92a67db 100644
--- a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
+++ b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
@@ -140,6 +140,7 @@
 
     AvrcpControllerStateMachine(BluetoothDevice device, AvrcpControllerService service) {
         super(TAG);
+        setDbg(DBG);
         mDevice = device;
         mDeviceAddress = Utils.getByteAddress(mDevice);
         mService = service;
@@ -164,12 +165,11 @@
 
         mAudioManager = (AudioManager) service.getSystemService(Context.AUDIO_SERVICE);
         mIsVolumeFixed = mAudioManager.isVolumeFixed();
-        IntentFilter filter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION);
-        mService.registerReceiver(mBroadcastReceiver, filter);
 
         mCoveArtUtils = new CoverArtUtils();
         mBipStateMachine = AvrcpControllerBipStateMachine.make(this, getHandler(), service);
 
+        Log.d(TAG, "Setting initial state: Disconnected: " + mDevice);
         setInitialState(mDisconnected);
     }
 
@@ -285,7 +285,7 @@
     protected class Disconnected extends State {
         @Override
         public void enter() {
-            logD("Enter Disconnected");
+            logD("Enter Disconnected mDevice:" + mDevice);
             if (mMostRecentState != BluetoothProfile.STATE_DISCONNECTED) {
                 sendMessage(CLEANUP);
             }
@@ -817,6 +817,14 @@
         }
     };
 
+    void registerReceiver(BluetoothDevice device) {
+        if (DBG) {
+            Log.d(TAG, " Register receiver for device: " + device);
+        }
+        IntentFilter filter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION);
+        mService.registerReceiver(mBroadcastReceiver, filter);
+    }
+
     void doQuit() {
         Log.d(TAG, "doQuit()");
         try {
diff --git a/src/com/android/bluetooth/opp/BluetoothOppService.java b/src/com/android/bluetooth/opp/BluetoothOppService.java
old mode 100644
new mode 100755
index 1324619..77af4a7
--- a/src/com/android/bluetooth/opp/BluetoothOppService.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppService.java
@@ -204,6 +204,7 @@
             @Override
             public void run() {
                 trimDatabase(contentResolver);
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_START_UPDATE_THREAD));
             }
         }.start();
 
@@ -232,12 +233,6 @@
         if (D) {
             Log.v(TAG, "start()");
         }
-        mObserver = new BluetoothShareContentObserver();
-        getContentResolver().registerContentObserver(BluetoothShare.CONTENT_URI, true, mObserver);
-        mNotifier = new BluetoothOppNotification(this);
-        mNotifier.mNotificationMgr.cancelAll();
-        mNotifier.updateNotification();
-        updateFromProvider();
         setBluetoothOppService(this);
         return true;
     }
@@ -318,6 +313,8 @@
 
     private static final int STOP_LISTENER = 200;
 
+    private static final int MSG_START_UPDATE_THREAD = 300;
+
     private Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
@@ -468,6 +465,17 @@
                         }
                     }
                     break;
+                case MSG_START_UPDATE_THREAD:
+                    mObserver = new BluetoothShareContentObserver();
+                    getContentResolver().registerContentObserver(BluetoothShare.CONTENT_URI,
+                            true, mObserver);
+
+                    mNotifier = new BluetoothOppNotification(BluetoothOppService.this);
+                    mNotifier.mNotificationMgr.cancelAll();
+                    mNotifier.updateNotification();
+
+                    updateFromProvider();
+                    break;
             }
         }
     };