1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package com.android.settingslib.bluetooth; 17 18import static com.google.common.truth.Truth.assertThat; 19 20import static org.mockito.Matchers.any; 21import static org.mockito.Matchers.anyString; 22import static org.mockito.Mockito.doAnswer; 23import static org.mockito.Mockito.never; 24import static org.mockito.Mockito.spy; 25import static org.mockito.Mockito.verify; 26import static org.mockito.Mockito.when; 27 28import android.bluetooth.BluetoothAdapter; 29import android.bluetooth.BluetoothDevice; 30import android.bluetooth.BluetoothProfile; 31import android.content.Context; 32 33import com.android.settingslib.R; 34import com.android.settingslib.TestConfig; 35 36import org.junit.Before; 37import org.junit.Test; 38import org.junit.runner.RunWith; 39import org.mockito.Mock; 40import org.mockito.MockitoAnnotations; 41import org.robolectric.RobolectricTestRunner; 42import org.robolectric.RuntimeEnvironment; 43import org.robolectric.annotation.Config; 44 45@RunWith(RobolectricTestRunner.class) 46@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, resourceDir = 47 "../../res") 48public class CachedBluetoothDeviceTest { 49 private final static String DEVICE_NAME = "TestName"; 50 private final static String DEVICE_ALIAS = "TestAlias"; 51 private final static String DEVICE_ADDRESS = "AA:BB:CC:DD:EE:FF"; 52 private final static String DEVICE_ALIAS_NEW = "TestAliasNew"; 53 @Mock 54 private LocalBluetoothAdapter mAdapter; 55 @Mock 56 private LocalBluetoothProfileManager mProfileManager; 57 @Mock 58 private HeadsetProfile mHfpProfile; 59 @Mock 60 private A2dpProfile mA2dpProfile; 61 @Mock 62 private HidProfile mHidProfile; 63 @Mock 64 private BluetoothDevice mDevice; 65 private CachedBluetoothDevice mCachedDevice; 66 private Context mContext; 67 private int mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN; 68 69 @Before 70 public void setUp() { 71 MockitoAnnotations.initMocks(this); 72 mContext = RuntimeEnvironment.application; 73 when(mDevice.getAddress()).thenReturn(DEVICE_ADDRESS); 74 when(mAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON); 75 when(mHfpProfile.isProfileReady()).thenReturn(true); 76 when(mA2dpProfile.isProfileReady()).thenReturn(true); 77 when(mHidProfile.isProfileReady()).thenReturn(true); 78 mCachedDevice = spy( 79 new CachedBluetoothDevice(mContext, mAdapter, mProfileManager, mDevice)); 80 doAnswer((invocation) -> mBatteryLevel).when(mCachedDevice).getBatteryLevel(); 81 } 82 83 /** 84 * Test to verify the current test context object works so that we are not checking null 85 * against null 86 */ 87 @Test 88 public void testContextMock() { 89 assertThat(mContext.getString(R.string.bluetooth_connected)).isEqualTo("Connected"); 90 } 91 92 @Test 93 public void testGetConnectionSummary_testSingleProfileConnectDisconnect() { 94 // Test without battery level 95 // Set HID profile to be connected and test connection state summary 96 mCachedDevice.onProfileStateChanged(mHidProfile, BluetoothProfile.STATE_CONNECTED); 97 assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString( 98 R.string.bluetooth_connected)); 99 100 // Set HID profile to be disconnected and test connection state summary 101 mCachedDevice.onProfileStateChanged(mHidProfile, BluetoothProfile.STATE_DISCONNECTED); 102 assertThat(mCachedDevice.getConnectionSummary()).isNull(); 103 104 // Test with battery level 105 mBatteryLevel = 10; 106 // Set HID profile to be connected and test connection state summary 107 mCachedDevice.onProfileStateChanged(mHidProfile, BluetoothProfile.STATE_CONNECTED); 108 assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString( 109 R.string.bluetooth_connected_battery_level, 110 com.android.settingslib.Utils.formatPercentage(mBatteryLevel))); 111 112 // Set HID profile to be disconnected and test connection state summary 113 mCachedDevice.onProfileStateChanged(mHidProfile, BluetoothProfile.STATE_DISCONNECTED); 114 assertThat(mCachedDevice.getConnectionSummary()).isNull(); 115 116 // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level 117 mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN; 118 119 // Set HID profile to be connected and test connection state summary 120 mCachedDevice.onProfileStateChanged(mHidProfile, BluetoothProfile.STATE_CONNECTED); 121 assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString( 122 R.string.bluetooth_connected)); 123 124 // Set HID profile to be disconnected and test connection state summary 125 mCachedDevice.onProfileStateChanged(mHidProfile, BluetoothProfile.STATE_DISCONNECTED); 126 assertThat(mCachedDevice.getConnectionSummary()).isNull(); 127 } 128 129 @Test 130 public void testGetConnectionSummary_testMultipleProfileConnectDisconnect() { 131 mBatteryLevel = 10; 132 133 // Set HFP, A2DP and HID profile to be connected and test connection state summary 134 mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED); 135 mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED); 136 mCachedDevice.onProfileStateChanged(mHidProfile, BluetoothProfile.STATE_CONNECTED); 137 assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString( 138 R.string.bluetooth_connected_battery_level, 139 com.android.settingslib.Utils.formatPercentage(mBatteryLevel))); 140 141 // Disconnect HFP only and test connection state summary 142 mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED); 143 assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString( 144 R.string.bluetooth_connected_no_headset_battery_level, 145 com.android.settingslib.Utils.formatPercentage(mBatteryLevel))); 146 147 // Disconnect A2DP only and test connection state summary 148 mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED); 149 mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED); 150 assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString( 151 R.string.bluetooth_connected_no_a2dp_battery_level, 152 com.android.settingslib.Utils.formatPercentage(mBatteryLevel))); 153 154 // Disconnect both HFP and A2DP and test connection state summary 155 mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED); 156 assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString( 157 R.string.bluetooth_connected_no_headset_no_a2dp_battery_level, 158 com.android.settingslib.Utils.formatPercentage(mBatteryLevel))); 159 160 // Disconnect all profiles and test connection state summary 161 mCachedDevice.onProfileStateChanged(mHidProfile, BluetoothProfile.STATE_DISCONNECTED); 162 assertThat(mCachedDevice.getConnectionSummary()).isNull(); 163 } 164 165 @Test 166 public void testDeviceName_testAliasNameAvailable() { 167 when(mDevice.getAliasName()).thenReturn(DEVICE_ALIAS); 168 when(mDevice.getName()).thenReturn(DEVICE_NAME); 169 CachedBluetoothDevice cachedBluetoothDevice = 170 new CachedBluetoothDevice(mContext, mAdapter, mProfileManager, mDevice); 171 // Verify alias is returned on getName 172 assertThat(cachedBluetoothDevice.getName()).isEqualTo(DEVICE_ALIAS); 173 // Verify device is visible 174 assertThat(cachedBluetoothDevice.hasHumanReadableName()).isTrue(); 175 } 176 177 @Test 178 public void testDeviceName_testNameNotAvailable() { 179 CachedBluetoothDevice cachedBluetoothDevice = 180 new CachedBluetoothDevice(mContext, mAdapter, mProfileManager, mDevice); 181 // Verify device address is returned on getName 182 assertThat(cachedBluetoothDevice.getName()).isEqualTo(DEVICE_ADDRESS); 183 // Verify device is not visible 184 assertThat(cachedBluetoothDevice.hasHumanReadableName()).isFalse(); 185 } 186 187 @Test 188 public void testDeviceName_testRenameDevice() { 189 final String[] alias = {DEVICE_ALIAS}; 190 doAnswer(invocation -> alias[0]).when(mDevice).getAliasName(); 191 doAnswer(invocation -> { 192 alias[0] = (String) invocation.getArguments()[0]; 193 return true; 194 }).when(mDevice).setAlias(anyString()); 195 when(mDevice.getName()).thenReturn(DEVICE_NAME); 196 CachedBluetoothDevice cachedBluetoothDevice = 197 new CachedBluetoothDevice(mContext, mAdapter, mProfileManager, mDevice); 198 // Verify alias is returned on getName 199 assertThat(cachedBluetoothDevice.getName()).isEqualTo(DEVICE_ALIAS); 200 // Verify null name does not get set 201 cachedBluetoothDevice.setName(null); 202 verify(mDevice, never()).setAlias(any()); 203 // Verify new name is set properly 204 cachedBluetoothDevice.setName(DEVICE_ALIAS_NEW); 205 verify(mDevice).setAlias(DEVICE_ALIAS_NEW); 206 // Verify new alias is returned on getName 207 assertThat(cachedBluetoothDevice.getName()).isEqualTo(DEVICE_ALIAS_NEW); 208 } 209} 210