Loading packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java +1 −0 Original line number Diff line number Diff line Loading @@ -444,6 +444,7 @@ public class BluetoothEventManager { private void dispatchActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) { mDeviceManager.onActiveDeviceChanged(activeDevice, bluetoothProfile); synchronized (mCallbacks) { for (BluetoothCallback callback : mCallbacks) { callback.onActiveDeviceChanged(activeDevice, bluetoothProfile); Loading packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +24 −3 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.os.SystemClock; import android.text.TextUtils; import android.util.Log; import android.bluetooth.BluetoothAdapter; import android.support.annotation.VisibleForTesting; import com.android.settingslib.R; Loading Loading @@ -461,12 +462,12 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> } /** * Set the device status as active or non-active per Bluetooth profile. * Update the device status as active or non-active per Bluetooth profile. * * @param isActive true if the device is active * @param bluetoothProfile the Bluetooth profile */ public void setActiveDevice(boolean isActive, int bluetoothProfile) { public void onActiveDeviceChanged(boolean isActive, int bluetoothProfile) { boolean changed = false; switch (bluetoothProfile) { case BluetoothProfile.A2DP: Loading @@ -478,7 +479,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> mIsActiveDeviceHeadset = isActive; break; default: Log.w(TAG, "setActiveDevice: unknown profile " + bluetoothProfile + Log.w(TAG, "onActiveDeviceChanged: unknown profile " + bluetoothProfile + " isActive " + isActive); break; } Loading @@ -487,6 +488,26 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> } } /** * Get the device status as active or non-active per Bluetooth profile. * * @param bluetoothProfile the Bluetooth profile * @return true if the device is active */ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) public boolean isActiveDevice(int bluetoothProfile) { switch (bluetoothProfile) { case BluetoothProfile.A2DP: return mIsActiveDeviceA2dp; case BluetoothProfile.HEADSET: return mIsActiveDeviceHeadset; default: Log.w(TAG, "getActiveDevice: unknown profile " + bluetoothProfile); break; } return false; } void setRssi(short rssi) { if (mRssi != rssi) { mRssi = rssi; Loading packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java +10 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.util.Log; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Objects; /** * CachedBluetoothDeviceManager manages the set of remote Bluetooth devices. Loading Loading @@ -167,6 +168,15 @@ public class CachedBluetoothDeviceManager { } } } public synchronized void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) { for (CachedBluetoothDevice cachedDevice : mCachedDevices) { boolean isActive = Objects.equals(cachedDevice, activeDevice); cachedDevice.onActiveDeviceChanged(isActive, bluetoothProfile); } } private void log(String msg) { if (DEBUG) { Log.d(TAG, msg); Loading packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java 0 → 100644 +283 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settingslib.bluetooth; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.Context; import com.android.settingslib.R; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import java.util.Collection; @RunWith(RobolectricTestRunner.class) public class CachedBluetoothDeviceManagerTest { private final static String DEVICE_NAME_1 = "TestName_1"; private final static String DEVICE_NAME_2 = "TestName_2"; private final static String DEVICE_ALIAS_1 = "TestAlias_1"; private final static String DEVICE_ALIAS_2 = "TestAlias_2"; private final static String DEVICE_ADDRESS_1 = "AA:BB:CC:DD:EE:11"; private final static String DEVICE_ADDRESS_2 = "AA:BB:CC:DD:EE:22"; private final BluetoothClass DEVICE_CLASS_1 = new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES); private final BluetoothClass DEVICE_CLASS_2 = new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE); @Mock private LocalBluetoothAdapter mLocalAdapter; @Mock private LocalBluetoothProfileManager mLocalProfileManager; @Mock private LocalBluetoothManager mLocalBluetoothManager; @Mock private BluetoothEventManager mBluetoothEventManager; @Mock private HeadsetProfile mHfpProfile; @Mock private A2dpProfile mA2dpProfile; @Mock private PanProfile mPanProfile; @Mock private BluetoothDevice mDevice1; @Mock private BluetoothDevice mDevice2; private CachedBluetoothDeviceManager mCachedDeviceManager; private Context mContext; private String[] mActiveDeviceStringsArray; private String mActiveDeviceStringNone; private String mActiveDeviceStringAll; private String mActiveDeviceStringMedia; private String mActiveDeviceStringPhone; @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; when(mDevice1.getAddress()).thenReturn(DEVICE_ADDRESS_1); when(mDevice2.getAddress()).thenReturn(DEVICE_ADDRESS_2); when(mDevice1.getName()).thenReturn(DEVICE_NAME_1); when(mDevice2.getName()).thenReturn(DEVICE_NAME_2); when(mDevice1.getAliasName()).thenReturn(DEVICE_ALIAS_1); when(mDevice2.getAliasName()).thenReturn(DEVICE_ALIAS_2); when(mDevice1.getBluetoothClass()).thenReturn(DEVICE_CLASS_1); when(mDevice2.getBluetoothClass()).thenReturn(DEVICE_CLASS_2); when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager); when(mLocalAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON); when(mHfpProfile.isProfileReady()).thenReturn(true); when(mA2dpProfile.isProfileReady()).thenReturn(true); when(mPanProfile.isProfileReady()).thenReturn(true); mCachedDeviceManager = new CachedBluetoothDeviceManager(mContext, mLocalBluetoothManager); } /** * Test to verify addDevice(). */ @Test public void testAddDevice_validCachedDevices_devicesAdded() { CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter, mLocalProfileManager, mDevice1); assertThat(cachedDevice1).isNotNull(); CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter, mLocalProfileManager, mDevice2); assertThat(cachedDevice2).isNotNull(); Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy(); assertThat(devices).contains(cachedDevice1); assertThat(devices).contains(cachedDevice2); assertThat(mCachedDeviceManager.findDevice(mDevice1)).isEqualTo(cachedDevice1); assertThat(mCachedDeviceManager.findDevice(mDevice2)).isEqualTo(cachedDevice2); } /** * Test to verify getName(). */ @Test public void testGetName_validCachedDevice_nameFound() { CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter, mLocalProfileManager, mDevice1); assertThat(cachedDevice1).isNotNull(); assertThat(mCachedDeviceManager.getName(mDevice1)).isEqualTo(DEVICE_ALIAS_1); } /** * Test to verify onDeviceNameUpdated(). */ @Test public void testOnDeviceNameUpdated_validName_nameUpdated() { CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter, mLocalProfileManager, mDevice1); assertThat(cachedDevice1).isNotNull(); assertThat(cachedDevice1.getName()).isEqualTo(DEVICE_ALIAS_1); final String newAliasName = "NewAliasName"; when(mDevice1.getAliasName()).thenReturn(newAliasName); mCachedDeviceManager.onDeviceNameUpdated(mDevice1); assertThat(cachedDevice1.getName()).isEqualTo(newAliasName); } /** * Test to verify clearNonBondedDevices(). */ @Test public void testClearNonBondedDevices_bondedAndNonBondedDevices_nonBondedDevicesCleared() { CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter, mLocalProfileManager, mDevice1); assertThat(cachedDevice1).isNotNull(); CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter, mLocalProfileManager, mDevice2); assertThat(cachedDevice2).isNotNull(); when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDING); mCachedDeviceManager.clearNonBondedDevices(); Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy(); assertThat(devices).contains(cachedDevice1); assertThat(devices).contains(cachedDevice2); when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_NONE); mCachedDeviceManager.clearNonBondedDevices(); devices = mCachedDeviceManager.getCachedDevicesCopy(); assertThat(devices).contains(cachedDevice1); assertThat(devices).doesNotContain(cachedDevice2); when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_NONE); when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_NONE); mCachedDeviceManager.clearNonBondedDevices(); devices = mCachedDeviceManager.getCachedDevicesCopy(); assertThat(devices).doesNotContain(cachedDevice1); assertThat(devices).doesNotContain(cachedDevice2); } /** * Test to verify onBtClassChanged(). */ @Test public void testOnBtClassChanged_validBtClass_classChanged() { CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter, mLocalProfileManager, mDevice1); assertThat(cachedDevice1).isNotNull(); assertThat(cachedDevice1.getBtClass()).isEqualTo(DEVICE_CLASS_1); final BluetoothClass newBluetoothClass = DEVICE_CLASS_2; when(mDevice1.getBluetoothClass()).thenReturn(newBluetoothClass); mCachedDeviceManager.onBtClassChanged(mDevice1); assertThat(cachedDevice1.getBtClass()).isEqualTo(newBluetoothClass); } /** * Test to verify onDeviceDisappeared(). */ @Test public void testOnDeviceDisappeared_deviceBondedUnbonded_unbondedDeviceDisappeared() { CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter, mLocalProfileManager, mDevice1); assertThat(cachedDevice1).isNotNull(); when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); assertThat(mCachedDeviceManager.onDeviceDisappeared(cachedDevice1)).isFalse(); when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_NONE); assertThat(mCachedDeviceManager.onDeviceDisappeared(cachedDevice1)).isTrue(); } /** * Test to verify onActiveDeviceChanged(). */ @Test public void testOnActiveDeviceChanged_connectedDevices_activeDeviceChanged() { CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter, mLocalProfileManager, mDevice1); assertThat(cachedDevice1).isNotNull(); CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter, mLocalProfileManager, mDevice2); assertThat(cachedDevice2).isNotNull(); when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); // Connect both devices for A2DP and HFP cachedDevice1.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED); cachedDevice2.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED); cachedDevice1.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED); cachedDevice2.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED); // Verify that both devices are connected and none is Active assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isFalse(); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isFalse(); // The first device is active for A2DP, the second device is active for HFP mCachedDeviceManager.onActiveDeviceChanged(cachedDevice1, BluetoothProfile.A2DP); mCachedDeviceManager.onActiveDeviceChanged(cachedDevice2, BluetoothProfile.HEADSET); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isTrue(); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isTrue(); // The first device is active for A2DP and HFP mCachedDeviceManager.onActiveDeviceChanged(cachedDevice1, BluetoothProfile.HEADSET); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isTrue(); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isTrue(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isFalse(); // The second device is active for A2DP and HFP mCachedDeviceManager.onActiveDeviceChanged(cachedDevice2, BluetoothProfile.A2DP); mCachedDeviceManager.onActiveDeviceChanged(cachedDevice2, BluetoothProfile.HEADSET); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isFalse(); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isTrue(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isTrue(); // No active device for A2DP mCachedDeviceManager.onActiveDeviceChanged(null, BluetoothProfile.A2DP); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isFalse(); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isTrue(); // No active device for HFP mCachedDeviceManager.onActiveDeviceChanged(null, BluetoothProfile.HEADSET); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isFalse(); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isFalse(); } } packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java +11 −11 Original line number Diff line number Diff line Loading @@ -152,7 +152,7 @@ public class CachedBluetoothDeviceTest { assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected"); // Set device as Active for A2DP and test connection state summary mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP); mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP); assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(media)"); // Test with battery level Loading @@ -168,7 +168,7 @@ public class CachedBluetoothDeviceTest { mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN; // Set A2DP profile to be connected, Active and test connection state summary mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED); mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP); mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP); assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(media)"); // Set A2DP profile to be disconnected and test connection state summary Loading @@ -184,7 +184,7 @@ public class CachedBluetoothDeviceTest { assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected"); // Set device as Active for HFP and test connection state summary mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET); mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET); assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(phone)"); // Test with battery level Loading @@ -200,7 +200,7 @@ public class CachedBluetoothDeviceTest { mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN; // Set HFP profile to be connected, Active and test connection state summary mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED); mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET); mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET); assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(phone)"); // Set HFP profile to be disconnected and test connection state summary Loading @@ -217,8 +217,8 @@ public class CachedBluetoothDeviceTest { assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected"); // Set device as Active for A2DP and HFP and test connection state summary mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP); mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET); mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP); mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET); assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active"); // Test with battery level Loading @@ -227,16 +227,16 @@ public class CachedBluetoothDeviceTest { "Connected, battery 10%, active"); // Disconnect A2DP only and test connection state summary mCachedDevice.setActiveDevice(false, BluetoothProfile.A2DP); mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.A2DP); mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED); assertThat(mCachedDevice.getConnectionSummary()).isEqualTo( "Connected (no media), battery 10%, active(phone)"); // Disconnect HFP only and test connection state summary mCachedDevice.setActiveDevice(false, BluetoothProfile.HEADSET); mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.HEADSET); mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED); mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED); mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP); mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP); assertThat(mCachedDevice.getConnectionSummary()).isEqualTo( "Connected (no phone), battery 10%, active(media)"); Loading @@ -245,8 +245,8 @@ public class CachedBluetoothDeviceTest { // Set A2DP and HFP profiles to be connected, Active and test connection state summary mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED); mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED); mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP); mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET); mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP); mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET); assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active"); // Set A2DP and HFP profiles to be disconnected and test connection state summary Loading Loading
packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java +1 −0 Original line number Diff line number Diff line Loading @@ -444,6 +444,7 @@ public class BluetoothEventManager { private void dispatchActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) { mDeviceManager.onActiveDeviceChanged(activeDevice, bluetoothProfile); synchronized (mCallbacks) { for (BluetoothCallback callback : mCallbacks) { callback.onActiveDeviceChanged(activeDevice, bluetoothProfile); Loading
packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +24 −3 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.os.SystemClock; import android.text.TextUtils; import android.util.Log; import android.bluetooth.BluetoothAdapter; import android.support.annotation.VisibleForTesting; import com.android.settingslib.R; Loading Loading @@ -461,12 +462,12 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> } /** * Set the device status as active or non-active per Bluetooth profile. * Update the device status as active or non-active per Bluetooth profile. * * @param isActive true if the device is active * @param bluetoothProfile the Bluetooth profile */ public void setActiveDevice(boolean isActive, int bluetoothProfile) { public void onActiveDeviceChanged(boolean isActive, int bluetoothProfile) { boolean changed = false; switch (bluetoothProfile) { case BluetoothProfile.A2DP: Loading @@ -478,7 +479,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> mIsActiveDeviceHeadset = isActive; break; default: Log.w(TAG, "setActiveDevice: unknown profile " + bluetoothProfile + Log.w(TAG, "onActiveDeviceChanged: unknown profile " + bluetoothProfile + " isActive " + isActive); break; } Loading @@ -487,6 +488,26 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> } } /** * Get the device status as active or non-active per Bluetooth profile. * * @param bluetoothProfile the Bluetooth profile * @return true if the device is active */ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) public boolean isActiveDevice(int bluetoothProfile) { switch (bluetoothProfile) { case BluetoothProfile.A2DP: return mIsActiveDeviceA2dp; case BluetoothProfile.HEADSET: return mIsActiveDeviceHeadset; default: Log.w(TAG, "getActiveDevice: unknown profile " + bluetoothProfile); break; } return false; } void setRssi(short rssi) { if (mRssi != rssi) { mRssi = rssi; Loading
packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java +10 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.util.Log; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Objects; /** * CachedBluetoothDeviceManager manages the set of remote Bluetooth devices. Loading Loading @@ -167,6 +168,15 @@ public class CachedBluetoothDeviceManager { } } } public synchronized void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) { for (CachedBluetoothDevice cachedDevice : mCachedDevices) { boolean isActive = Objects.equals(cachedDevice, activeDevice); cachedDevice.onActiveDeviceChanged(isActive, bluetoothProfile); } } private void log(String msg) { if (DEBUG) { Log.d(TAG, msg); Loading
packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java 0 → 100644 +283 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settingslib.bluetooth; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.Context; import com.android.settingslib.R; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import java.util.Collection; @RunWith(RobolectricTestRunner.class) public class CachedBluetoothDeviceManagerTest { private final static String DEVICE_NAME_1 = "TestName_1"; private final static String DEVICE_NAME_2 = "TestName_2"; private final static String DEVICE_ALIAS_1 = "TestAlias_1"; private final static String DEVICE_ALIAS_2 = "TestAlias_2"; private final static String DEVICE_ADDRESS_1 = "AA:BB:CC:DD:EE:11"; private final static String DEVICE_ADDRESS_2 = "AA:BB:CC:DD:EE:22"; private final BluetoothClass DEVICE_CLASS_1 = new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES); private final BluetoothClass DEVICE_CLASS_2 = new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE); @Mock private LocalBluetoothAdapter mLocalAdapter; @Mock private LocalBluetoothProfileManager mLocalProfileManager; @Mock private LocalBluetoothManager mLocalBluetoothManager; @Mock private BluetoothEventManager mBluetoothEventManager; @Mock private HeadsetProfile mHfpProfile; @Mock private A2dpProfile mA2dpProfile; @Mock private PanProfile mPanProfile; @Mock private BluetoothDevice mDevice1; @Mock private BluetoothDevice mDevice2; private CachedBluetoothDeviceManager mCachedDeviceManager; private Context mContext; private String[] mActiveDeviceStringsArray; private String mActiveDeviceStringNone; private String mActiveDeviceStringAll; private String mActiveDeviceStringMedia; private String mActiveDeviceStringPhone; @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; when(mDevice1.getAddress()).thenReturn(DEVICE_ADDRESS_1); when(mDevice2.getAddress()).thenReturn(DEVICE_ADDRESS_2); when(mDevice1.getName()).thenReturn(DEVICE_NAME_1); when(mDevice2.getName()).thenReturn(DEVICE_NAME_2); when(mDevice1.getAliasName()).thenReturn(DEVICE_ALIAS_1); when(mDevice2.getAliasName()).thenReturn(DEVICE_ALIAS_2); when(mDevice1.getBluetoothClass()).thenReturn(DEVICE_CLASS_1); when(mDevice2.getBluetoothClass()).thenReturn(DEVICE_CLASS_2); when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager); when(mLocalAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON); when(mHfpProfile.isProfileReady()).thenReturn(true); when(mA2dpProfile.isProfileReady()).thenReturn(true); when(mPanProfile.isProfileReady()).thenReturn(true); mCachedDeviceManager = new CachedBluetoothDeviceManager(mContext, mLocalBluetoothManager); } /** * Test to verify addDevice(). */ @Test public void testAddDevice_validCachedDevices_devicesAdded() { CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter, mLocalProfileManager, mDevice1); assertThat(cachedDevice1).isNotNull(); CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter, mLocalProfileManager, mDevice2); assertThat(cachedDevice2).isNotNull(); Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy(); assertThat(devices).contains(cachedDevice1); assertThat(devices).contains(cachedDevice2); assertThat(mCachedDeviceManager.findDevice(mDevice1)).isEqualTo(cachedDevice1); assertThat(mCachedDeviceManager.findDevice(mDevice2)).isEqualTo(cachedDevice2); } /** * Test to verify getName(). */ @Test public void testGetName_validCachedDevice_nameFound() { CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter, mLocalProfileManager, mDevice1); assertThat(cachedDevice1).isNotNull(); assertThat(mCachedDeviceManager.getName(mDevice1)).isEqualTo(DEVICE_ALIAS_1); } /** * Test to verify onDeviceNameUpdated(). */ @Test public void testOnDeviceNameUpdated_validName_nameUpdated() { CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter, mLocalProfileManager, mDevice1); assertThat(cachedDevice1).isNotNull(); assertThat(cachedDevice1.getName()).isEqualTo(DEVICE_ALIAS_1); final String newAliasName = "NewAliasName"; when(mDevice1.getAliasName()).thenReturn(newAliasName); mCachedDeviceManager.onDeviceNameUpdated(mDevice1); assertThat(cachedDevice1.getName()).isEqualTo(newAliasName); } /** * Test to verify clearNonBondedDevices(). */ @Test public void testClearNonBondedDevices_bondedAndNonBondedDevices_nonBondedDevicesCleared() { CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter, mLocalProfileManager, mDevice1); assertThat(cachedDevice1).isNotNull(); CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter, mLocalProfileManager, mDevice2); assertThat(cachedDevice2).isNotNull(); when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDING); mCachedDeviceManager.clearNonBondedDevices(); Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy(); assertThat(devices).contains(cachedDevice1); assertThat(devices).contains(cachedDevice2); when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_NONE); mCachedDeviceManager.clearNonBondedDevices(); devices = mCachedDeviceManager.getCachedDevicesCopy(); assertThat(devices).contains(cachedDevice1); assertThat(devices).doesNotContain(cachedDevice2); when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_NONE); when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_NONE); mCachedDeviceManager.clearNonBondedDevices(); devices = mCachedDeviceManager.getCachedDevicesCopy(); assertThat(devices).doesNotContain(cachedDevice1); assertThat(devices).doesNotContain(cachedDevice2); } /** * Test to verify onBtClassChanged(). */ @Test public void testOnBtClassChanged_validBtClass_classChanged() { CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter, mLocalProfileManager, mDevice1); assertThat(cachedDevice1).isNotNull(); assertThat(cachedDevice1.getBtClass()).isEqualTo(DEVICE_CLASS_1); final BluetoothClass newBluetoothClass = DEVICE_CLASS_2; when(mDevice1.getBluetoothClass()).thenReturn(newBluetoothClass); mCachedDeviceManager.onBtClassChanged(mDevice1); assertThat(cachedDevice1.getBtClass()).isEqualTo(newBluetoothClass); } /** * Test to verify onDeviceDisappeared(). */ @Test public void testOnDeviceDisappeared_deviceBondedUnbonded_unbondedDeviceDisappeared() { CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter, mLocalProfileManager, mDevice1); assertThat(cachedDevice1).isNotNull(); when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); assertThat(mCachedDeviceManager.onDeviceDisappeared(cachedDevice1)).isFalse(); when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_NONE); assertThat(mCachedDeviceManager.onDeviceDisappeared(cachedDevice1)).isTrue(); } /** * Test to verify onActiveDeviceChanged(). */ @Test public void testOnActiveDeviceChanged_connectedDevices_activeDeviceChanged() { CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter, mLocalProfileManager, mDevice1); assertThat(cachedDevice1).isNotNull(); CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter, mLocalProfileManager, mDevice2); assertThat(cachedDevice2).isNotNull(); when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); // Connect both devices for A2DP and HFP cachedDevice1.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED); cachedDevice2.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED); cachedDevice1.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED); cachedDevice2.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED); // Verify that both devices are connected and none is Active assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isFalse(); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isFalse(); // The first device is active for A2DP, the second device is active for HFP mCachedDeviceManager.onActiveDeviceChanged(cachedDevice1, BluetoothProfile.A2DP); mCachedDeviceManager.onActiveDeviceChanged(cachedDevice2, BluetoothProfile.HEADSET); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isTrue(); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isTrue(); // The first device is active for A2DP and HFP mCachedDeviceManager.onActiveDeviceChanged(cachedDevice1, BluetoothProfile.HEADSET); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isTrue(); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isTrue(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isFalse(); // The second device is active for A2DP and HFP mCachedDeviceManager.onActiveDeviceChanged(cachedDevice2, BluetoothProfile.A2DP); mCachedDeviceManager.onActiveDeviceChanged(cachedDevice2, BluetoothProfile.HEADSET); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isFalse(); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isTrue(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isTrue(); // No active device for A2DP mCachedDeviceManager.onActiveDeviceChanged(null, BluetoothProfile.A2DP); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isFalse(); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isTrue(); // No active device for HFP mCachedDeviceManager.onActiveDeviceChanged(null, BluetoothProfile.HEADSET); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isFalse(); assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isFalse(); } }
packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java +11 −11 Original line number Diff line number Diff line Loading @@ -152,7 +152,7 @@ public class CachedBluetoothDeviceTest { assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected"); // Set device as Active for A2DP and test connection state summary mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP); mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP); assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(media)"); // Test with battery level Loading @@ -168,7 +168,7 @@ public class CachedBluetoothDeviceTest { mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN; // Set A2DP profile to be connected, Active and test connection state summary mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED); mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP); mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP); assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(media)"); // Set A2DP profile to be disconnected and test connection state summary Loading @@ -184,7 +184,7 @@ public class CachedBluetoothDeviceTest { assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected"); // Set device as Active for HFP and test connection state summary mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET); mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET); assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(phone)"); // Test with battery level Loading @@ -200,7 +200,7 @@ public class CachedBluetoothDeviceTest { mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN; // Set HFP profile to be connected, Active and test connection state summary mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED); mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET); mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET); assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(phone)"); // Set HFP profile to be disconnected and test connection state summary Loading @@ -217,8 +217,8 @@ public class CachedBluetoothDeviceTest { assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected"); // Set device as Active for A2DP and HFP and test connection state summary mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP); mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET); mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP); mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET); assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active"); // Test with battery level Loading @@ -227,16 +227,16 @@ public class CachedBluetoothDeviceTest { "Connected, battery 10%, active"); // Disconnect A2DP only and test connection state summary mCachedDevice.setActiveDevice(false, BluetoothProfile.A2DP); mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.A2DP); mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED); assertThat(mCachedDevice.getConnectionSummary()).isEqualTo( "Connected (no media), battery 10%, active(phone)"); // Disconnect HFP only and test connection state summary mCachedDevice.setActiveDevice(false, BluetoothProfile.HEADSET); mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.HEADSET); mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED); mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED); mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP); mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP); assertThat(mCachedDevice.getConnectionSummary()).isEqualTo( "Connected (no phone), battery 10%, active(media)"); Loading @@ -245,8 +245,8 @@ public class CachedBluetoothDeviceTest { // Set A2DP and HFP profiles to be connected, Active and test connection state summary mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED); mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED); mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP); mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET); mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP); mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET); assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active"); // Set A2DP and HFP profiles to be disconnected and test connection state summary Loading