From 16a56909a61ca9290d4e7e83e6f736cc853a6332 Mon Sep 17 00:00:00 2001 From: Stanley Tng Date: Fri, 20 Apr 2018 11:54:36 -0700 Subject: [PATCH] Fixed ConcurrentModificationException with HearingAids profile Prevent ConcurrentModificationException crash when traversing the mCachedDevices list by removing entries outside of the loop. Bug: 78357837 Test: Runs ROBOTEST_FILTER=CachedBluetoothDeviceManagerTest make -j40 RunSettingsLibRoboTests Change-Id: I27db2dc94a7d0108e9b848d187d4e5bc9f5b567c --- .../bluetooth/CachedBluetoothDeviceManager.java | 8 +++++++- .../bluetooth/CachedBluetoothDeviceManagerTest.java | 5 ++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java index 50c6aac57e8f0..3b1e4ce7e97a3 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java @@ -27,8 +27,10 @@ import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.Objects; /** @@ -191,6 +193,7 @@ public class CachedBluetoothDeviceManager { log("updateHearingAidsDevices: getHearingAidProfile() is null"); return; } + final Set syncIdChangedSet = new HashSet(); for (CachedBluetoothDevice cachedDevice : mCachedDevices) { if (cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID) { continue; @@ -200,9 +203,12 @@ public class CachedBluetoothDeviceManager { if (newHiSyncId != BluetoothHearingAid.HI_SYNC_ID_INVALID) { cachedDevice.setHiSyncId(newHiSyncId); - onHiSyncIdChanged(newHiSyncId); + syncIdChangedSet.add(newHiSyncId); } } + for (Long syncId : syncIdChangedSet) { + onHiSyncIdChanged(syncId); + } } /** 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 c3bd161951405..bab3cab3795cc 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 @@ -486,11 +486,14 @@ public class CachedBluetoothDeviceManagerTest { doAnswer((invocation) -> mHearingAidProfile).when(mLocalProfileManager) .getHearingAidProfile(); doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1); + doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice2); mCachedDeviceManager.mCachedDevices.add(mCachedDevice1); + mCachedDeviceManager.mCachedDevices.add(mCachedDevice2); mCachedDeviceManager.updateHearingAidsDevices(mLocalProfileManager); - // Assert that the mCachedDevice1 has an updated HiSyncId. + // Assert that the mCachedDevice1 and mCachedDevice2 have an updated HiSyncId. assertThat(mCachedDevice1.getHiSyncId()).isEqualTo(HISYNCID1); + assertThat(mCachedDevice2.getHiSyncId()).isEqualTo(HISYNCID1); } /**