Explicitly stop existing objects before creating new ones to avoid leaks

Its not okay to rely on preunbind and disconnected events being called
before connected is called with our service listener. To avoid cases
where we leak broadcast receivers (owned by objects created when the
service connects) we need to explicitly stop() each one. We can do this
by calling destroyUser(), effectively removing the entire user context
safely, before initializing a new one off the new proxy objects.

Bug: b/144080122
Test: Build, flash, interoperability testing with device, atest,
automated reconnection tests (adapter toggle, user switch and reboot)

Change-Id: Id7717ef5c22b8733766677980a1778dc94f86f05
Merged-In: Id7717ef5c22b8733766677980a1778dc94f86f05
diff --git a/service/src/com/android/car/CarBluetoothService.java b/service/src/com/android/car/CarBluetoothService.java
index b27e0a5..54d15a1 100644
--- a/service/src/com/android/car/CarBluetoothService.java
+++ b/service/src/com/android/car/CarBluetoothService.java
@@ -98,7 +98,13 @@
         public void onServiceConnected(ICarUserService carUserService) {
             logd("Connected to PerUserCarService");
             synchronized (mPerUserLock) {
+                // Explicitly clear out existing per-user objects since we can't rely on the
+                // onServiceDisconnected and onPreUnbind calls to always be called before this
+                destroyUser();
+
                 mCarUserService = carUserService;
+
+                // Create new objects with our new set of profile proxies
                 initializeUser();
             }
         }
@@ -112,9 +118,7 @@
         @Override
         public void onServiceDisconnected() {
             logd("Disconnected from PerUserCarService");
-            synchronized (mPerUserLock) {
-                mCarUserService = null;
-            }
+            destroyUser();
         }
     };
 
@@ -250,8 +254,16 @@
                 return;
             }
             for (int profileId : sManagedProfiles) {
-                BluetoothProfileDeviceManager deviceManager = BluetoothProfileDeviceManager.create(
-                        mContext, mUserId, mCarBluetoothUserService, profileId);
+                BluetoothProfileDeviceManager deviceManager = mProfileDeviceManagers.get(profileId);
+                if (deviceManager != null) {
+                    deviceManager.stop();
+                    mProfileDeviceManagers.remove(profileId);
+                    logd("Existing device manager removed for profile "
+                            + Utils.getProfileName(profileId));
+                }
+
+                deviceManager = BluetoothProfileDeviceManager.create(mContext, mUserId,
+                        mCarBluetoothUserService, profileId);
                 if (deviceManager == null) {
                     logd("Failed to create profile device manager for "
                             + Utils.getProfileName(profileId));