Fix Connect State message in Device details for Hearing Aids

In the Device details of Settings App and when using two Hearing Aids
devices (left and right sides), this will fix the connect state messages
for these two devices. Also added Robo tests for the changes.

Bug: 116317072
Bug: 117074814
Test: Manual tests and also ran RunSettingsLibRoboTests and RunSettingsRoboTests.
Change-Id: Ia9df6facd99ae91ebb4a819f61ea27551ce35efe
Merged-In: Id2dc364dfa815e72db91b92bcee9745e6c40d34a
Merged-In: Ia9df6facd99ae91ebb4a819f61ea27551ce35efe
(cherry picked from commit 3d8dd1ae2c5b7aad91594062e53ef3bc2db7212e)
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 0370f20..1a8e24f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -143,8 +143,8 @@
 
     void onProfileStateChanged(LocalBluetoothProfile profile, int newProfileState) {
         if (Utils.D) {
-            Log.d(TAG, "onProfileStateChanged: profile " + profile +
-                    " newProfileState " + newProfileState);
+            Log.d(TAG, "onProfileStateChanged: profile " + profile + ", device=" + mDevice
+                    + ", newProfileState " + newProfileState);
         }
         if (mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_TURNING_OFF)
         {
@@ -224,6 +224,10 @@
         connectWithoutResettingTimer(connectAllProfiles);
     }
 
+    public boolean isHearingAidDevice() {
+        return mHiSyncId != BluetoothHearingAid.HI_SYNC_ID_INVALID;
+    }
+
     void onBondingDockConnect() {
         // Attempt to connect if UUIDs are available. Otherwise,
         // we will connect when the ACTION_UUID intent arrives.
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index e9d96ae..1bfcf9a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -162,14 +162,14 @@
      */
     public synchronized String getHearingAidPairDeviceSummary(CachedBluetoothDevice device) {
         String pairDeviceSummary = null;
-        if (device.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
-            for (CachedBluetoothDevice hearingAidDevice : mHearingAidDevicesNotAddedInCache) {
-                if (hearingAidDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID
-                    && hearingAidDevice.getHiSyncId() == device.getHiSyncId()) {
-                    pairDeviceSummary = hearingAidDevice.getConnectionSummary();
-                }
-            }
+        CachedBluetoothDevice otherHearingAidDevice =
+            getHearingAidOtherDevice(device, device.getHiSyncId());
+        if (otherHearingAidDevice != null) {
+            pairDeviceSummary = otherHearingAidDevice.getConnectionSummary();
         }
+        log("getHearingAidPairDeviceSummary: pairDeviceSummary=" + pairDeviceSummary
+            + ", otherHearingAidDevice=" + otherHearingAidDevice);
+ 
         return pairDeviceSummary;
     }
 
@@ -358,7 +358,7 @@
         }
     }
 
-    private CachedBluetoothDevice getHearingAidOtherDevice(CachedBluetoothDevice thisDevice,
+    public CachedBluetoothDevice getHearingAidOtherDevice(CachedBluetoothDevice thisDevice,
                                                            long hiSyncId) {
         if (hiSyncId == BluetoothHearingAid.HI_SYNC_ID_INVALID) {
             return null;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 29f2190..7ff5448 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -361,9 +361,10 @@
                 Log.i(TAG, "Failed to connect " + mProfile + " device");
             }
 
-            if (getHearingAidProfile() != null &&
-                mProfile instanceof HearingAidProfile &&
-                (newState == BluetoothProfile.STATE_CONNECTED)) {
+            boolean isHearingAidProfile = (getHearingAidProfile() != null) &&
+                (mProfile instanceof HearingAidProfile);
+
+            if (isHearingAidProfile && (newState == BluetoothProfile.STATE_CONNECTED)) {
                 // Check if the HiSyncID has being initialized
                 if (cachedDevice.getHiSyncId() == BluetoothHearingAid.HI_SYNC_ID_INVALID) {
 
@@ -376,10 +377,22 @@
                 }
             }
 
-            mEventManager.dispatchProfileConnectionStateChanged(cachedDevice, newState,
-                    mProfile.getProfileId());
             cachedDevice.onProfileStateChanged(mProfile, newState);
             cachedDevice.refresh();
+
+            if (isHearingAidProfile) {
+                CachedBluetoothDevice otherDevice =
+                    mDeviceManager.getHearingAidOtherDevice(cachedDevice, cachedDevice.getHiSyncId());
+                if (otherDevice != null) {
+                    if (DEBUG) {
+                        Log.d(TAG, "Refreshing other hearing aid=" + otherDevice
+                               + ", newState=" + newState);
+                    }
+                    otherDevice.refresh();
+                }
+            }
+            mEventManager.dispatchProfileConnectionStateChanged(cachedDevice, newState,
+                    mProfile.getProfileId());
         }
     }
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
index 16ed85c..db9b44f 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -835,4 +835,20 @@
         assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
         assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEARING_AID)).isFalse();
     }
+
+    /**
+     * Test to verify getHearingAidOtherDevice() for hearing aid devices with same HiSyncId.
+     */
+    @Test
+    public void testGetHearingAidOtherDevice_bothHearingAidsPaired_returnsOtherDevice() {
+        mCachedDevice1.setHiSyncId(HISYNCID1);
+        mCachedDevice2.setHiSyncId(HISYNCID1);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+        mCachedDeviceManager.mHearingAidDevicesNotAddedInCache.add(mCachedDevice2);
+        doAnswer((invocation) -> DEVICE_SUMMARY_1).when(mCachedDevice1).getConnectionSummary();
+        doAnswer((invocation) -> DEVICE_SUMMARY_2).when(mCachedDevice2).getConnectionSummary();
+
+        assertThat(mCachedDeviceManager.getHearingAidOtherDevice(mCachedDevice1, HISYNCID1))
+            .isEqualTo(mCachedDevice2);
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index c39fb85..30da882 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -28,6 +28,7 @@
 
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHearingAid;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 import android.media.AudioManager;
@@ -611,4 +612,16 @@
 
         assertThat(mCachedDevice.isConnectedHearingAidDevice()).isFalse();
     }
+
+    @Test
+    public void testIsHearingAidDevice_isHearingAidDevice() {
+        mCachedDevice.setHiSyncId(0x1234);
+        assertThat(mCachedDevice.isHearingAidDevice()).isTrue();
+    }
+
+    @Test
+    public void testIsHearingAidDevice_isNotHearingAidDevice() {
+        mCachedDevice.setHiSyncId(BluetoothHearingAid.HI_SYNC_ID_INVALID);
+        assertThat(mCachedDevice.isHearingAidDevice()).isFalse();
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
index d342bc8..d7b651b 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
@@ -21,6 +21,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.anyLong;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -52,6 +53,7 @@
 @RunWith(RobolectricTestRunner.class)
 @Config(resourceDir = "../../res")
 public class LocalBluetoothProfileManagerTest {
+    private final static long HI_SYNC_ID = 0x1234;
     @Mock
     private CachedBluetoothDeviceManager mDeviceManager;
     @Mock
@@ -62,6 +64,8 @@
     private BluetoothDevice mDevice;
     @Mock
     private CachedBluetoothDevice mCachedBluetoothDevice;
+    @Mock
+    private CachedBluetoothDevice mHearingAidOtherDevice;
 
     private Context mContext;
     private LocalBluetoothProfileManager mProfileManager;
@@ -200,6 +204,32 @@
     }
 
     /**
+     * Verify BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED with uuid intent will dispatch to
+     * refresh both sides devices.
+     */
+    @Test
+    public void stateChangedHandler_receiveHAPConnectionStateChanged_shouldRefreshBothSides() {
+        ArrayList<Integer> supportProfiles = new ArrayList<>();
+        supportProfiles.add(BluetoothProfile.HEARING_AID);
+        when(mAdapter.getSupportedProfiles()).thenReturn(supportProfiles);
+        when(mCachedBluetoothDevice.getHiSyncId()).thenReturn(HI_SYNC_ID);
+        when(mDeviceManager.getHearingAidOtherDevice(mCachedBluetoothDevice, HI_SYNC_ID))
+            .thenReturn(mHearingAidOtherDevice);
+
+        mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager,
+                mEventManager);
+        mIntent = new Intent(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
+        mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
+        mIntent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTING);
+        mIntent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED);
+
+        mContext.sendBroadcast(mIntent);
+
+        verify(mCachedBluetoothDevice).refresh();
+        verify(mHearingAidOtherDevice).refresh();
+    }
+
+    /**
      * Verify BluetoothPan.ACTION_CONNECTION_STATE_CHANGED intent with uuid will dispatch to
      * profile connection state changed callback
      */