Audio output switcher: show low battery in color
Bug: 292067610
Test: atest CachedBluetoothDeviceTest
Change-Id: I820d4529a80e8e1dcfcb0ddc1348edb43a7bab51
diff --git a/packages/SettingsLib/tests/robotests/Android.bp b/packages/SettingsLib/tests/robotests/Android.bp
index 2d875cf..732c336 100644
--- a/packages/SettingsLib/tests/robotests/Android.bp
+++ b/packages/SettingsLib/tests/robotests/Android.bp
@@ -49,6 +49,8 @@
"androidx.fragment_fragment",
"androidx.test.core",
"androidx.core_core",
+ "flag-junit",
+ "settingslib_flags_lib",
"testng", // TODO: remove once JUnit on Android provides assertThrows
],
java_resource_dirs: ["config"],
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 85efe69..ed545ab 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
@@ -35,13 +35,18 @@
import android.content.Context;
import android.graphics.drawable.BitmapDrawable;
import android.media.AudioManager;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.text.Spannable;
+import android.text.style.ForegroundColorSpan;
import android.util.LruCache;
import com.android.settingslib.R;
+import com.android.settingslib.media.flags.Flags;
import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settingslib.widget.AdaptiveOutlineDrawable;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -60,10 +65,13 @@
private static final String DEVICE_ALIAS_NEW = "TestAliasNew";
private static final String TWS_BATTERY_LEFT = "15";
private static final String TWS_BATTERY_RIGHT = "25";
+ private static final String TWS_LOW_BATTERY_THRESHOLD_LOW = "10";
+ private static final String TWS_LOW_BATTERY_THRESHOLD_HIGH = "25";
private static final short RSSI_1 = 10;
private static final short RSSI_2 = 11;
private static final boolean JUSTDISCOVERED_1 = true;
private static final boolean JUSTDISCOVERED_2 = false;
+ private static final int LOW_BATTERY_COLOR = android.R.color.holo_red_dark;
@Mock
private LocalBluetoothProfileManager mProfileManager;
@Mock
@@ -89,9 +97,13 @@
private int mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TV_MEDIA_OUTPUT_DIALOG);
mContext = RuntimeEnvironment.application;
mAudioManager = mContext.getSystemService(AudioManager.class);
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
@@ -179,6 +191,17 @@
}
@Test
+ public void getTvConnectionSummary_testProfilesInactive_returnPairing() {
+ // Arrange:
+ // Bond State: Bonding
+ when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDING);
+
+ // Act & Assert:
+ // Get "Pairing…" result without Battery Level.
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo("Pairing…");
+ }
+
+ @Test
public void getConnectionSummary_testSingleProfileConnectDisconnect() {
// Test without battery level
// Set PAN profile to be connected and test connection state summary
@@ -212,6 +235,39 @@
}
@Test
+ public void getTvConnectionSummary_testSingleProfileConnectDisconnect() {
+ // Test without battery level
+ // Set PAN profile to be connected and test connection state summary
+ updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary()).isNull();
+
+ // Set PAN profile to be disconnected and test connection state summary
+ updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary()).isNull();
+
+ // Test with battery level
+ mBatteryLevel = 10;
+ // Set PAN profile to be connected and test connection state summary
+ updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo("Battery 10%");
+
+ // Set PAN profile to be disconnected and test connection state summary
+ updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary()).isNull();
+
+ // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
+ mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
+
+ // Set PAN profile to be connected and test connection state summary
+ updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary()).isNull();
+
+ // Set PAN profile to be disconnected and test connection state summary
+ updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary()).isNull();
+ }
+
+ @Test
public void getConnectionSummary_testMultipleProfileConnectDisconnect() {
mBatteryLevel = 10;
@@ -243,6 +299,37 @@
}
@Test
+ public void getTvConnectionSummary_testMultipleProfileConnectDisconnect() {
+ mBatteryLevel = 10;
+
+ // Set HFP, A2DP and PAN profile to be connected and test connection state summary
+ updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo("Battery 10%");
+
+ // Disconnect HFP only and test connection state summary
+ updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo(
+ "Battery 10%");
+
+ // Disconnect A2DP only and test connection state summary
+ updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo(
+ "Battery 10%");
+
+ // Disconnect both HFP and A2DP and test connection state summary
+ updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo(
+ "Battery 10%");
+
+ // Disconnect all profiles and test connection state summary
+ updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary()).isNull();
+ }
+
+ @Test
public void getConnectionSummary_testSingleProfileActiveDeviceA2dp() {
// Test without battery level
// Set A2DP profile to be connected and test connection state summary
@@ -275,6 +362,37 @@
}
@Test
+ public void getTvConnectionSummary_testSingleProfileActiveDeviceA2dp() {
+ // Test without battery level
+ // Set A2DP profile to be connected and test connection state summary
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary()).isNull();
+
+ // Set device as Active for A2DP and test connection state summary
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
+ assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
+
+ // Test with battery level
+ mBatteryLevel = 10;
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo("Battery 10%");
+
+ // Set A2DP profile to be disconnected and test connection state summary
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary()).isNull();
+
+ // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
+ mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
+ // Set A2DP profile to be connected, Active and test connection state summary
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo("Active");
+
+ // Set A2DP profile to be disconnected and test connection state summary
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary()).isNull();
+ }
+
+ @Test
public void getConnectionSummary_shortSummary_returnShortSummary() {
// Test without battery level
// Set A2DP profile to be connected and test connection state summary
@@ -309,6 +427,18 @@
}
@Test
+ public void getTvConnectionSummary_testA2dpBatteryInactive_returnBattery() {
+ // Arrange:
+ // 1. Profile: {A2DP, CONNECTED, Inactive}
+ // 2. Battery Level: 10
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ mBatteryLevel = 10;
+
+ // Act & Assert:
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo("Battery 10%");
+ }
+
+ @Test
public void getConnectionSummary_testA2dpInCall_returnNull() {
// Arrange:
// 1. Profile: {A2DP, Connected, Active}
@@ -323,6 +453,20 @@
}
@Test
+ public void getTvConnectionSummary_testA2dpInCall_returnNull() {
+ // Arrange:
+ // 1. Profile: {A2DP, Connected, Active}
+ // 2. Audio Manager: In Call
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
+ mAudioManager.setMode(AudioManager.MODE_IN_CALL);
+
+ // Act & Assert:
+ // Get null result without Battery Level.
+ assertThat(mCachedDevice.getTvConnectionSummary()).isNull();
+ }
+
+ @Test
public void getConnectionSummary_testA2dpBatteryInCall_returnBattery() {
// Arrange:
// 1. Profile: {A2DP, Connected, Active}
@@ -339,6 +483,22 @@
}
@Test
+ public void getTvConnectionSummary_testA2dpBatteryInCall_returnBattery() {
+ // Arrange:
+ // 1. Profile: {A2DP, Connected, Active}
+ // 3. Battery Level: 10
+ // 2. Audio Manager: In Call
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
+ mBatteryLevel = 10;
+ mAudioManager.setMode(AudioManager.MODE_IN_CALL);
+
+ // Act & Assert:
+ // Get "10% battery" result with Battery Level 10.
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo("Battery 10%");
+ }
+
+ @Test
public void getConnectionSummary_testSingleProfileActiveDeviceHfp() {
// Test without battery level
// Set HFP profile to be connected and test connection state summary
@@ -372,6 +532,39 @@
}
@Test
+ public void getTvConnectionSummary_testSingleProfileActiveDeviceHfp() {
+ // Test without battery level
+ // Set HFP profile to be connected and test connection state summary
+ updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary()).isNull();
+
+ // Set device as Active for HFP and test connection state summary
+ mCachedDevice.onAudioModeChanged();
+ mAudioManager.setMode(AudioManager.MODE_IN_CALL);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo("Active");
+
+ // Test with battery level
+ mBatteryLevel = 10;
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo("Battery 10%");
+
+ // Set HFP profile to be disconnected and test connection state summary
+ updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary()).isNull();
+
+ // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
+ mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
+ // Set HFP profile to be connected, Active and test connection state summary
+ updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo("Active");
+
+ // Set HFP profile to be disconnected and test connection state summary
+ updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary()).isNull();
+ }
+
+ @Test
public void getConnectionSummary_testHeadsetBatteryInactive_returnBattery() {
// Arrange:
// 1. Profile: {HEADSET, CONNECTED, Inactive}
@@ -385,6 +578,19 @@
}
@Test
+ public void getTvConnectionSummary_testHeadsetBatteryInactive_returnBattery() {
+ // Arrange:
+ // 1. Profile: {HEADSET, CONNECTED, Inactive}
+ // 2. Battery Level: 10
+ updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+ mBatteryLevel = 10;
+
+ // Act & Assert:
+ // Get "10% battery" result without Battery Level.
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo("Battery 10%");
+ }
+
+ @Test
public void getConnectionSummary_testHeadsetWithoutInCall_returnNull() {
// Arrange:
// 1. Profile: {HEADSET, Connected, Active}
@@ -398,6 +604,19 @@
}
@Test
+ public void getTvConnectionSummary_testHeadsetWithoutInCall_returnNull() {
+ // Arrange:
+ // 1. Profile: {HEADSET, Connected, Active}
+ // 2. Audio Manager: Normal (Without In Call)
+ updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
+
+ // Act & Assert:
+ // Get null result without Battery Level.
+ assertThat(mCachedDevice.getTvConnectionSummary()).isNull();
+ }
+
+ @Test
public void getConnectionSummary_testHeadsetBatteryWithoutInCall_returnBattery() {
// Arrange:
// 1. Profile: {HEADSET, Connected, Active}
@@ -413,6 +632,22 @@
}
@Test
+ public void getTvConnectionSummary_testHeadsetBatteryWithoutInCall_returnBattery() {
+ // Arrange:
+ // 1. Profile: {HEADSET, Connected, Active}
+ // 2. Battery Level: 10
+ // 3. Audio Manager: Normal (Without In Call)
+ updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
+ mBatteryLevel = 10;
+
+ // Act & Assert:
+ // Get "10% battery" result with Battery Level 10.
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo("Battery 10%");
+ }
+
+
+ @Test
public void getConnectionSummary_testSingleProfileActiveDeviceHearingAid() {
// Test without battery level
// Set Hearing Aid profile to be connected and test connection state summary
@@ -432,6 +667,26 @@
}
@Test
+ public void getTvConnectionSummary_testSingleProfileActiveDeviceHearingAid() {
+ // Test without battery level
+ // Set Hearing Aid profile to be connected and test connection state summary
+ updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary()).isNull();
+
+ // Set device as Active for Hearing Aid and test connection state summary
+ mCachedDevice.setHearingAidInfo(getLeftAshaHearingAidInfo());
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEARING_AID);
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo(
+ "Active, left only");
+
+ // Set Hearing Aid profile to be disconnected and test connection state summary
+ mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.HEARING_AID);
+ mCachedDevice.onProfileStateChanged(mHearingAidProfile,
+ BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary()).isNull();
+ }
+
+ @Test
public void getConnectionSummary_testHearingAidBatteryInactive_returnBattery() {
// Arrange:
// 1. Profile: {HEARING_AID, CONNECTED, Inactive}
@@ -445,6 +700,19 @@
}
@Test
+ public void getTvConnectionSummary_testHearingAidBatteryInactive_returnBattery() {
+ // Arrange:
+ // 1. Profile: {HEARING_AID, CONNECTED, Inactive}
+ // 2. Battery Level: 10
+ updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+ mBatteryLevel = 10;
+
+ // Act & Assert:
+ // Get "10% battery" result without Battery Level.
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo("Battery 10%");
+ }
+
+ @Test
public void getConnectionSummary_testHearingAidBatteryWithoutInCall_returnActiveBattery() {
// Arrange:
// 1. Profile: {HEARING_AID, Connected, Active}
@@ -460,6 +728,21 @@
}
@Test
+ public void getTvConnectionSummary_testHearingAidBatteryWithoutInCall_returnBattery() {
+ // Arrange:
+ // 1. Profile: {HEARING_AID, Connected, Active}
+ // 2. Battery Level: 10
+ // 3. Audio Manager: Normal (Without In Call)
+ updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEARING_AID);
+ mBatteryLevel = 10;
+
+ // Act & Assert:
+ // Get "Active, 10% battery" result with Battery Level 10.
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo("Battery 10%");
+ }
+
+ @Test
public void getConnectionSummary_testHearingAidRightEarInCall_returnActiveRightEar() {
// Arrange:
// 1. Profile: {HEARING_AID, Connected, Active, Right ear}
@@ -475,6 +758,22 @@
}
@Test
+ public void getTvConnectionSummary_testHearingAidRightEarInCall_returnActiveRightEar() {
+ // Arrange:
+ // 1. Profile: {HEARING_AID, Connected, Active, Right ear}
+ // 2. Audio Manager: In Call
+ updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.setHearingAidInfo(getRightAshaHearingAidInfo());
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEARING_AID);
+ mAudioManager.setMode(AudioManager.MODE_IN_CALL);
+
+ // Act & Assert:
+ // Get "Active" result without Battery Level.
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo(
+ "Active, right only");
+ }
+
+ @Test
public void getConnectionSummary_testHearingAidBothEarInCall_returnActiveBothEar() {
// Arrange:
// 1. Profile: {HEARING_AID, Connected, Active, Both ear}
@@ -493,6 +792,25 @@
}
@Test
+ public void getTvConnectionSummary_testHearingAidBothEarInCall_returnActiveBothEar() {
+ // Arrange:
+ // 1. Profile: {HEARING_AID, Connected, Active, Both ear}
+ // 2. Audio Manager: In Call
+ mCachedDevice.setHearingAidInfo(getRightAshaHearingAidInfo());
+ updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+ mSubCachedDevice.setHearingAidInfo(getLeftAshaHearingAidInfo());
+ updateSubDeviceProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.setSubDevice(mSubCachedDevice);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEARING_AID);
+ mAudioManager.setMode(AudioManager.MODE_IN_CALL);
+
+ // Act & Assert:
+ // Get "Active" result without Battery Level.
+ assertThat(mCachedDevice.getTvConnectionSummary().toString())
+ .isEqualTo("Active, left and right");
+ }
+
+ @Test
public void getConnectionSummary_testHearingAidBatteryInCall_returnActiveBattery() {
// Arrange:
// 1. Profile: {HEARING_AID, Connected, Active}
@@ -509,6 +827,22 @@
}
@Test
+ public void getTvConnectionSummary_testHearingAidBatteryInCall_returnBattery() {
+ // Arrange:
+ // 1. Profile: {HEARING_AID, Connected, Active}
+ // 2. Battery Level: 10
+ // 3. Audio Manager: In Call
+ updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEARING_AID);
+ mAudioManager.setMode(AudioManager.MODE_IN_CALL);
+ mBatteryLevel = 10;
+
+ // Act & Assert:
+ // Get "Active, 10% battery" result with Battery Level 10.
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo("Battery 10%");
+ }
+
+ @Test
public void getConnectionSummary_testActiveDeviceLeAudioHearingAid() {
// Test without battery level
// Set HAP Client and LE Audio profile to be connected and test connection state summary
@@ -529,6 +863,27 @@
}
@Test
+ public void getTvConnectionSummary_testActiveDeviceLeAudioHearingAid() {
+ // Test without battery level
+ // Set HAP Client and LE Audio profile to be connected and test connection state summary
+ when(mProfileManager.getHapClientProfile()).thenReturn(mHapClientProfile);
+ updateProfileStatus(mHapClientProfile, BluetoothProfile.STATE_CONNECTED);
+ updateProfileStatus(mLeAudioProfile, BluetoothProfile.STATE_CONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary()).isNull();
+
+ // Set device as Active for LE Audio and test connection state summary
+ mCachedDevice.setHearingAidInfo(getLeftLeAudioHearingAidInfo());
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.LE_AUDIO);
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo(
+ "Active, left only");
+
+ // Set LE Audio profile to be disconnected and test connection state summary
+ mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.LE_AUDIO);
+ mCachedDevice.onProfileStateChanged(mLeAudioProfile, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary()).isNull();
+ }
+
+ @Test
public void getConnectionSummary_testMemberDevicesExist_returnMinBattery() {
// One device is active with battery level 70.
mBatteryLevel = 70;
@@ -545,6 +900,22 @@
}
@Test
+ public void getTvConnectionSummary_testMemberDevicesExist_returnMinBattery() {
+ // One device is active with battery level 70.
+ mBatteryLevel = 70;
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
+
+
+ // Add a member device with battery level 30.
+ int lowerBatteryLevel = 30;
+ mCachedDevice.addMemberDevice(mSubCachedDevice);
+ doAnswer((invocation) -> lowerBatteryLevel).when(mSubCachedDevice).getBatteryLevel();
+
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo("Battery 30%");
+ }
+
+ @Test
public void getConnectionSummary_testMemberDevicesBatteryUnknown_returnMinBattery() {
// One device is active with battery level 70.
mBatteryLevel = 70;
@@ -560,6 +931,21 @@
}
@Test
+ public void getTvConnectionSummary_testMemberDevicesBatteryUnknown_returnMinBattery() {
+ // One device is active with battery level 70.
+ mBatteryLevel = 70;
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
+
+ // Add a member device with battery level unknown.
+ mCachedDevice.addMemberDevice(mSubCachedDevice);
+ doAnswer((invocation) -> BluetoothDevice.BATTERY_LEVEL_UNKNOWN).when(
+ mSubCachedDevice).getBatteryLevel();
+
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo("Battery 70%");
+ }
+
+ @Test
public void getConnectionSummary_testAllDevicesBatteryUnknown_returnNoBattery() {
// One device is active with battery level unknown.
updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
@@ -574,6 +960,20 @@
}
@Test
+ public void getTvConnectionSummary_testAllDevicesBatteryUnknown_returnNoBattery() {
+ // One device is active with battery level unknown.
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
+
+ // Add a member device with battery level unknown.
+ mCachedDevice.addMemberDevice(mSubCachedDevice);
+ doAnswer((invocation) -> BluetoothDevice.BATTERY_LEVEL_UNKNOWN).when(
+ mSubCachedDevice).getBatteryLevel();
+
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo("Active");
+ }
+
+ @Test
public void getConnectionSummary_testMultipleProfilesActiveDevice() {
// Test without battery level
// Set A2DP and HFP profiles to be connected and test connection state summary
@@ -621,6 +1021,53 @@
}
@Test
+ public void getTvConnectionSummary_testMultipleProfilesActiveDevice() {
+ // Test without battery level
+ // Set A2DP and HFP profiles to be connected and test connection state summary
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary()).isNull();
+
+ // Set device as Active for A2DP and HFP and test connection state summary
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo("Active");
+
+ // Test with battery level
+ mBatteryLevel = 10;
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo(
+ "Battery 10%");
+
+ // Disconnect A2DP only and test connection state summary
+ mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.A2DP);
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo(
+ "Battery 10%");
+
+ // Disconnect HFP only and test connection state summary
+ mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.HEADSET);
+ updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo(
+ "Battery 10%");
+
+ // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
+ mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
+ // Set A2DP and HFP profiles to be connected, Active and test connection state summary
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo("Active");
+
+ // Set A2DP and HFP profiles to be disconnected and test connection state summary
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+ updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getTvConnectionSummary()).isNull();
+ }
+
+ @Test
public void getConnectionSummary_testMultipleProfilesInactive_returnPairing() {
// Arrange:
// 1. Profile 1: {A2DP, CONNECTED, Inactive}
@@ -638,6 +1085,23 @@
}
@Test
+ public void getTvConnectionSummary_testMultipleProfilesInactive_returnPairing() {
+ // Arrange:
+ // 1. Profile 1: {A2DP, CONNECTED, Inactive}
+ // 2. Profile 2: {HEADSET, CONNECTED, Inactive}
+ // 3. Profile 3: {HEARING_AID, CONNECTED, Inactive}
+ // 4. Bond State: Bonding
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+ updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+ when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDING);
+
+ // Act & Assert:
+ // Get "Pairing…" result without Battery Level.
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo("Pairing…");
+ }
+
+ @Test
public void getConnectionSummary_trueWirelessActiveDeviceWithBattery_returnActiveWithBattery() {
updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
@@ -656,6 +1120,24 @@
}
@Test
+ public void getTvConnectionSummary_trueWirelessActiveDeviceWithBattery_returnBattery() {
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+ updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+ when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEARING_AID);
+ when(mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET)).thenReturn(
+ "true".getBytes());
+ when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY)).thenReturn(
+ TWS_BATTERY_LEFT.getBytes());
+ when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY)).thenReturn(
+ TWS_BATTERY_RIGHT.getBytes());
+
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo(
+ "Left 15% Right 25%");
+ }
+
+ @Test
public void getConnectionSummary_trueWirelessDeviceWithBattery_returnActiveWithBattery() {
updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
@@ -673,6 +1155,84 @@
}
@Test
+ public void getTvConnectionSummary_trueWirelessDeviceWithBattery_returnBattery() {
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+ updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+ when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET)).thenReturn(
+ "true".getBytes());
+ when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY)).thenReturn(
+ TWS_BATTERY_LEFT.getBytes());
+ when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY)).thenReturn(
+ TWS_BATTERY_RIGHT.getBytes());
+
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo(
+ "Left 15% Right 25%");
+ }
+
+ @Test
+ public void getTvConnectionSummary_trueWirelessDeviceWithLowBattery() {
+ updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+ updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+ when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET)).thenReturn(
+ "true".getBytes());
+ when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY)).thenReturn(
+ TWS_BATTERY_LEFT.getBytes());
+ when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY)).thenReturn(
+ TWS_BATTERY_RIGHT.getBytes());
+
+ int lowBatteryColor = mContext.getColor(LOW_BATTERY_COLOR);
+
+ // Default low battery threshold, only left battery is low
+ CharSequence summary = mCachedDevice.getTvConnectionSummary(LOW_BATTERY_COLOR);
+ assertForegroundColorSpan(summary, 0, 0, 8, lowBatteryColor);
+ assertThat(summary.toString()).isEqualTo("Left 15% Right 25%");
+
+ // Lower threshold, neither battery should be low
+ when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD))
+ .thenReturn(TWS_LOW_BATTERY_THRESHOLD_LOW.getBytes());
+ when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD))
+ .thenReturn(TWS_LOW_BATTERY_THRESHOLD_LOW.getBytes());
+ summary = mCachedDevice.getTvConnectionSummary(LOW_BATTERY_COLOR);
+ assertNoForegroundColorSpans(summary);
+ assertThat(summary.toString()).isEqualTo("Left 15% Right 25%");
+
+
+ // Higher Threshold, both batteries are low
+ when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD))
+ .thenReturn(TWS_LOW_BATTERY_THRESHOLD_HIGH.getBytes());
+ when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD))
+ .thenReturn(TWS_LOW_BATTERY_THRESHOLD_HIGH.getBytes());
+ summary = mCachedDevice.getTvConnectionSummary(LOW_BATTERY_COLOR);
+ assertForegroundColorSpan(summary, 0, 0, 8, lowBatteryColor);
+ assertForegroundColorSpan(summary, 1, 9, 18, lowBatteryColor);
+ assertThat(summary.toString()).isEqualTo("Left 15% Right 25%");
+ }
+
+ private void assertNoForegroundColorSpans(CharSequence charSequence) {
+ if (charSequence instanceof Spannable) {
+ Spannable summarySpan = (Spannable) charSequence;
+ ForegroundColorSpan[] spans = summarySpan.getSpans(0, summarySpan.length(),
+ ForegroundColorSpan.class);
+ assertThat(spans).isEmpty();
+ }
+ }
+
+ private void assertForegroundColorSpan(CharSequence charSequence, int indexInSpannable,
+ int start, int end, int color) {
+ assertThat(charSequence).isInstanceOf(Spannable.class);
+ Spannable summarySpan = (Spannable) charSequence;
+ ForegroundColorSpan[] spans = summarySpan.getSpans(0, summarySpan.length(),
+ ForegroundColorSpan.class);
+ assertThat(spans[indexInSpannable].getForegroundColor()).isEqualTo(color);
+ assertThat(summarySpan.getSpanStart(spans[indexInSpannable])).isEqualTo(start);
+ assertThat(summarySpan.getSpanEnd(spans[indexInSpannable])).isEqualTo(end);
+ }
+
+ @Test
public void getCarConnectionSummary_singleProfileConnectDisconnect() {
// Test without battery level
// Set PAN profile to be connected and test connection state summary
@@ -1136,6 +1696,18 @@
}
@Test
+ public void getTvConnectionSummary_profileConnectedFail_showErrorMessage() {
+ final A2dpProfile profile = mock(A2dpProfile.class);
+ mCachedDevice.onProfileStateChanged(profile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.setProfileConnectedStatus(BluetoothProfile.A2DP, true);
+
+ when(profile.getConnectionStatus(mDevice)).thenReturn(BluetoothProfile.STATE_CONNECTED);
+
+ assertThat(mCachedDevice.getTvConnectionSummary().toString()).isEqualTo(
+ mContext.getString(R.string.profile_connect_timeout_subtext));
+ }
+
+ @Test
public void onUuidChanged_bluetoothClassIsNull_shouldNotCrash() {
mShadowBluetoothAdapter.setUuids(PbapServerProfile.PBAB_CLIENT_UUIDS);
when(mDevice.getUuids()).thenReturn(PbapServerProfile.PBAB_CLIENT_UUIDS);