• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
16 package com.android.settingslib.bluetooth;
17 
18 import static com.google.common.truth.Truth.assertThat;
19 
20 import static org.mockito.ArgumentMatchers.any;
21 import static org.mockito.ArgumentMatchers.anyString;
22 import static org.mockito.Mockito.doAnswer;
23 import static org.mockito.Mockito.doReturn;
24 import static org.mockito.Mockito.mock;
25 import static org.mockito.Mockito.never;
26 import static org.mockito.Mockito.spy;
27 import static org.mockito.Mockito.verify;
28 import static org.mockito.Mockito.when;
29 
30 import android.bluetooth.BluetoothAdapter;
31 import android.bluetooth.BluetoothDevice;
32 import android.bluetooth.BluetoothProfile;
33 import android.bluetooth.BluetoothStatusCodes;
34 import android.content.Context;
35 import android.graphics.drawable.BitmapDrawable;
36 import android.media.AudioManager;
37 import android.util.LruCache;
38 
39 import com.android.settingslib.R;
40 import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
41 import com.android.settingslib.widget.AdaptiveOutlineDrawable;
42 
43 import org.junit.Before;
44 import org.junit.Test;
45 import org.junit.runner.RunWith;
46 import org.mockito.Mock;
47 import org.mockito.MockitoAnnotations;
48 import org.robolectric.RobolectricTestRunner;
49 import org.robolectric.RuntimeEnvironment;
50 import org.robolectric.annotation.Config;
51 import org.robolectric.shadow.api.Shadow;
52 
53 @RunWith(RobolectricTestRunner.class)
54 @Config(shadows = {ShadowBluetoothAdapter.class})
55 public class CachedBluetoothDeviceTest {
56     private static final String DEVICE_NAME = "TestName";
57     private static final String DEVICE_ALIAS = "TestAlias";
58     private static final String DEVICE_ADDRESS = "AA:BB:CC:DD:EE:FF";
59     private static final String DEVICE_ALIAS_NEW = "TestAliasNew";
60     private static final String TWS_BATTERY_LEFT = "15";
61     private static final String TWS_BATTERY_RIGHT = "25";
62     private static final short RSSI_1 = 10;
63     private static final short RSSI_2 = 11;
64     private static final boolean JUSTDISCOVERED_1 = true;
65     private static final boolean JUSTDISCOVERED_2 = false;
66     @Mock
67     private LocalBluetoothProfileManager mProfileManager;
68     @Mock
69     private HeadsetProfile mHfpProfile;
70     @Mock
71     private A2dpProfile mA2dpProfile;
72     @Mock
73     private PanProfile mPanProfile;
74     @Mock
75     private HearingAidProfile mHearingAidProfile;
76     @Mock
77     private BluetoothDevice mDevice;
78     @Mock
79     private BluetoothDevice mSubDevice;
80     private CachedBluetoothDevice mCachedDevice;
81     private AudioManager mAudioManager;
82     private Context mContext;
83     private int mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
84     private ShadowBluetoothAdapter mShadowBluetoothAdapter;
85 
86     @Before
setUp()87     public void setUp() {
88         MockitoAnnotations.initMocks(this);
89         mContext = RuntimeEnvironment.application;
90         mAudioManager = mContext.getSystemService(AudioManager.class);
91         mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
92         when(mDevice.getAddress()).thenReturn(DEVICE_ADDRESS);
93         when(mHfpProfile.isProfileReady()).thenReturn(true);
94         when(mA2dpProfile.isProfileReady()).thenReturn(true);
95         when(mPanProfile.isProfileReady()).thenReturn(true);
96         when(mHearingAidProfile.isProfileReady()).thenReturn(true);
97         mCachedDevice = spy(new CachedBluetoothDevice(mContext, mProfileManager, mDevice));
98         doAnswer((invocation) -> mBatteryLevel).when(mCachedDevice).getBatteryLevel();
99     }
100 
101     @Test
getConnectionSummary_testProfilesInactive_returnPairing()102     public void getConnectionSummary_testProfilesInactive_returnPairing() {
103         // Arrange:
104         //   Bond State: Bonding
105         when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDING);
106 
107         // Act & Assert:
108         //   Get "Pairing…" result without Battery Level.
109         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Pairing…");
110     }
111 
112     @Test
getConnectionSummary_testSingleProfileConnectDisconnect()113     public void getConnectionSummary_testSingleProfileConnectDisconnect() {
114         // Test without battery level
115         // Set PAN profile to be connected and test connection state summary
116         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
117         assertThat(mCachedDevice.getConnectionSummary()).isNull();
118 
119         // Set PAN profile to be disconnected and test connection state summary
120         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
121         assertThat(mCachedDevice.getConnectionSummary()).isNull();
122 
123         // Test with battery level
124         mBatteryLevel = 10;
125         // Set PAN profile to be connected and test connection state summary
126         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
127         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("10% battery");
128 
129         // Set PAN profile to be disconnected and test connection state summary
130         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
131         assertThat(mCachedDevice.getConnectionSummary()).isNull();
132 
133         // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
134         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
135 
136         // Set PAN profile to be connected and test connection state summary
137         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
138         assertThat(mCachedDevice.getConnectionSummary()).isNull();
139 
140         // Set PAN profile to be disconnected and test connection state summary
141         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
142         assertThat(mCachedDevice.getConnectionSummary()).isNull();
143     }
144 
145     @Test
getConnectionSummary_testMultipleProfileConnectDisconnect()146     public void getConnectionSummary_testMultipleProfileConnectDisconnect() {
147         mBatteryLevel = 10;
148 
149         // Set HFP, A2DP and PAN profile to be connected and test connection state summary
150         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
151         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
152         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
153         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("10% battery");
154 
155         // Disconnect HFP only and test connection state summary
156         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
157         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
158                 "10% battery");
159 
160         // Disconnect A2DP only and test connection state summary
161         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
162         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
163         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
164                 "10% battery");
165 
166         // Disconnect both HFP and A2DP and test connection state summary
167         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
168         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
169                 "10% battery");
170 
171         // Disconnect all profiles and test connection state summary
172         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
173         assertThat(mCachedDevice.getConnectionSummary()).isNull();
174     }
175 
176     @Test
getConnectionSummary_testSingleProfileActiveDeviceA2dp()177     public void getConnectionSummary_testSingleProfileActiveDeviceA2dp() {
178         // Test without battery level
179         // Set A2DP profile to be connected and test connection state summary
180         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
181         assertThat(mCachedDevice.getConnectionSummary()).isNull();
182 
183         // Set device as Active for A2DP and test connection state summary
184         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
185         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
186 
187         // Test with battery level
188         mBatteryLevel = 10;
189         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
190                 "Active, 10% battery");
191 
192         // Set A2DP profile to be disconnected and test connection state summary
193         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
194         assertThat(mCachedDevice.getConnectionSummary()).isNull();
195 
196         // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
197         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
198         // Set A2DP profile to be connected, Active and test connection state summary
199         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
200         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
201         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
202 
203         // Set A2DP profile to be disconnected and test connection state summary
204         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
205         assertThat(mCachedDevice.getConnectionSummary()).isNull();
206     }
207 
208     @Test
getConnectionSummary_shortSummary_returnShortSummary()209     public void getConnectionSummary_shortSummary_returnShortSummary() {
210         // Test without battery level
211         // Set A2DP profile to be connected and test connection state summary
212         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
213         assertThat(mCachedDevice.getConnectionSummary(true /* shortSummary */)).isNull();
214 
215         // Set device as Active for A2DP and test connection state summary
216         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
217         assertThat(mCachedDevice.getConnectionSummary(true /* shortSummary */)).isEqualTo("Active");
218 
219         // Test with battery level
220         mBatteryLevel = 10;
221         assertThat(mCachedDevice.getConnectionSummary(true /* shortSummary */)).isEqualTo(
222                 "Active");
223 
224         // Set A2DP profile to be disconnected and test connection state summary
225         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
226         assertThat(mCachedDevice.getConnectionSummary()).isNull();
227     }
228 
229     @Test
getConnectionSummary_testA2dpBatteryInactive_returnBattery()230     public void getConnectionSummary_testA2dpBatteryInactive_returnBattery() {
231         // Arrange:
232         //   1. Profile:       {A2DP, CONNECTED, Inactive}
233         //   2. Battery Level: 10
234         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
235         mBatteryLevel = 10;
236 
237         // Act & Assert:
238         //   Get "10% battery" result without Battery Level.
239         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("10% battery");
240     }
241 
242     @Test
getConnectionSummary_testA2dpInCall_returnNull()243     public void getConnectionSummary_testA2dpInCall_returnNull() {
244         // Arrange:
245         //   1. Profile:       {A2DP, Connected, Active}
246         //   2. Audio Manager: In Call
247         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
248         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
249         mAudioManager.setMode(AudioManager.MODE_IN_CALL);
250 
251         // Act & Assert:
252         //   Get null result without Battery Level.
253         assertThat(mCachedDevice.getConnectionSummary()).isNull();
254     }
255 
256     @Test
getConnectionSummary_testA2dpBatteryInCall_returnBattery()257     public void getConnectionSummary_testA2dpBatteryInCall_returnBattery() {
258         // Arrange:
259         //   1. Profile:       {A2DP, Connected, Active}
260         //   3. Battery Level: 10
261         //   2. Audio Manager: In Call
262         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
263         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
264         mBatteryLevel = 10;
265         mAudioManager.setMode(AudioManager.MODE_IN_CALL);
266 
267         // Act & Assert:
268         //   Get "10% battery" result with Battery Level 10.
269         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("10% battery");
270     }
271 
272     @Test
getConnectionSummary_testSingleProfileActiveDeviceHfp()273     public void getConnectionSummary_testSingleProfileActiveDeviceHfp() {
274         // Test without battery level
275         // Set HFP profile to be connected and test connection state summary
276         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
277         assertThat(mCachedDevice.getConnectionSummary()).isNull();
278 
279         // Set device as Active for HFP and test connection state summary
280         mCachedDevice.onAudioModeChanged();
281         mAudioManager.setMode(AudioManager.MODE_IN_CALL);
282         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
283         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
284 
285         // Test with battery level
286         mBatteryLevel = 10;
287         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active, 10% battery");
288 
289         // Set HFP profile to be disconnected and test connection state summary
290         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
291         assertThat(mCachedDevice.getConnectionSummary()).isNull();
292 
293         // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
294         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
295         // Set HFP profile to be connected, Active and test connection state summary
296         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
297         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
298         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
299 
300         // Set HFP profile to be disconnected and test connection state summary
301         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
302         assertThat(mCachedDevice.getConnectionSummary()).isNull();
303     }
304 
305     @Test
getConnectionSummary_testHeadsetBatteryInactive_returnBattery()306     public void getConnectionSummary_testHeadsetBatteryInactive_returnBattery() {
307         // Arrange:
308         //   1. Profile:       {HEADSET, CONNECTED, Inactive}
309         //   2. Battery Level: 10
310         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
311         mBatteryLevel = 10;
312 
313         // Act & Assert:
314         //   Get "10% battery" result without Battery Level.
315         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("10% battery");
316     }
317 
318     @Test
getConnectionSummary_testHeadsetWithoutInCall_returnNull()319     public void getConnectionSummary_testHeadsetWithoutInCall_returnNull() {
320         // Arrange:
321         //   1. Profile:       {HEADSET, Connected, Active}
322         //   2. Audio Manager: Normal (Without In Call)
323         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
324         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
325 
326         // Act & Assert:
327         //   Get null result without Battery Level.
328         assertThat(mCachedDevice.getConnectionSummary()).isNull();
329     }
330 
331     @Test
getConnectionSummary_testHeadsetBatteryWithoutInCall_returnBattery()332     public void getConnectionSummary_testHeadsetBatteryWithoutInCall_returnBattery() {
333         // Arrange:
334         //   1. Profile:       {HEADSET, Connected, Active}
335         //   2. Battery Level: 10
336         //   3. Audio Manager: Normal (Without In Call)
337         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
338         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
339         mBatteryLevel = 10;
340 
341         // Act & Assert:
342         //   Get "10% battery" result with Battery Level 10.
343         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("10% battery");
344     }
345 
346     @Test
getConnectionSummary_testSingleProfileActiveDeviceHearingAid()347     public void getConnectionSummary_testSingleProfileActiveDeviceHearingAid() {
348         // Test without battery level
349         // Set Hearing Aid profile to be connected and test connection state summary
350         updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
351         assertThat(mCachedDevice.getConnectionSummary()).isNull();
352 
353         // Set device as Active for Hearing Aid and test connection state summary
354         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEARING_AID);
355         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
356 
357         // Set Hearing Aid profile to be disconnected and test connection state summary
358         mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.HEARING_AID);
359         mCachedDevice.
360                 onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_DISCONNECTED);
361         assertThat(mCachedDevice.getConnectionSummary()).isNull();
362     }
363 
364     @Test
getConnectionSummary_testHearingAidBatteryInactive_returnBattery()365     public void getConnectionSummary_testHearingAidBatteryInactive_returnBattery() {
366         // Arrange:
367         //   1. Profile:       {HEARING_AID, CONNECTED, Inactive}
368         //   2. Battery Level: 10
369         updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
370         mBatteryLevel = 10;
371 
372         // Act & Assert:
373         //   Get "10% battery" result without Battery Level.
374         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("10% battery");
375     }
376 
377     @Test
getConnectionSummary_testHearingAidBatteryWithoutInCall_returnActiveBattery()378     public void getConnectionSummary_testHearingAidBatteryWithoutInCall_returnActiveBattery() {
379         // Arrange:
380         //   1. Profile:       {HEARING_AID, Connected, Active}
381         //   2. Battery Level: 10
382         //   3. Audio Manager: Normal (Without In Call)
383         updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
384         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEARING_AID);
385         mBatteryLevel = 10;
386 
387         // Act & Assert:
388         //   Get "Active, 10% battery" result with Battery Level 10.
389         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active, 10% battery");
390     }
391 
392     @Test
getConnectionSummary_testHearingAidInCall_returnActive()393     public void getConnectionSummary_testHearingAidInCall_returnActive() {
394         // Arrange:
395         //   1. Profile:       {HEARING_AID, Connected, Active}
396         //   2. Audio Manager: In Call
397         updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
398         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEARING_AID);
399         mAudioManager.setMode(AudioManager.MODE_IN_CALL);
400 
401         // Act & Assert:
402         //   Get "Active" result without Battery Level.
403         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
404     }
405 
406     @Test
getConnectionSummary_testHearingAidBatteryInCall_returnActiveBattery()407     public void getConnectionSummary_testHearingAidBatteryInCall_returnActiveBattery() {
408         // Arrange:
409         //   1. Profile:       {HEARING_AID, Connected, Active}
410         //   2. Battery Level: 10
411         //   3. Audio Manager: In Call
412         updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
413         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEARING_AID);
414         mAudioManager.setMode(AudioManager.MODE_IN_CALL);
415         mBatteryLevel = 10;
416 
417         // Act & Assert:
418         //   Get "Active, 10% battery" result with Battery Level 10.
419         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active, 10% battery");
420     }
421 
422     @Test
getConnectionSummary_testMultipleProfilesActiveDevice()423     public void getConnectionSummary_testMultipleProfilesActiveDevice() {
424         // Test without battery level
425         // Set A2DP and HFP profiles to be connected and test connection state summary
426         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
427         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
428         assertThat(mCachedDevice.getConnectionSummary()).isNull();
429 
430         // Set device as Active for A2DP and HFP and test connection state summary
431         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
432         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
433         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
434 
435         // Test with battery level
436         mBatteryLevel = 10;
437         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
438                 "Active, 10% battery");
439 
440         // Disconnect A2DP only and test connection state summary
441         mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.A2DP);
442         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
443         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
444                 "10% battery");
445 
446         // Disconnect HFP only and test connection state summary
447         mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.HEADSET);
448         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
449         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
450         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
451         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
452                 "Active, 10% battery");
453 
454         // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
455         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
456         // Set A2DP and HFP profiles to be connected, Active and test connection state summary
457         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
458         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
459         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
460         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
461         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
462 
463         // Set A2DP and HFP profiles to be disconnected and test connection state summary
464         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
465         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
466         assertThat(mCachedDevice.getConnectionSummary()).isNull();
467     }
468 
469     @Test
getConnectionSummary_testMultipleProfilesInactive_returnPairing()470     public void getConnectionSummary_testMultipleProfilesInactive_returnPairing() {
471         // Arrange:
472         //   1. Profile 1:  {A2DP, CONNECTED, Inactive}
473         //   2. Profile 2:  {HEADSET, CONNECTED, Inactive}
474         //   3. Profile 3:  {HEARING_AID, CONNECTED, Inactive}
475         //   4. Bond State: Bonding
476         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
477         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
478         updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
479         when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDING);
480 
481         // Act & Assert:
482         //    Get "Pairing…" result without Battery Level.
483         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Pairing…");
484     }
485 
486     @Test
getConnectionSummary_trueWirelessActiveDeviceWithBattery_returnActiveWithBattery()487     public void getConnectionSummary_trueWirelessActiveDeviceWithBattery_returnActiveWithBattery() {
488         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
489         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
490         updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
491         when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
492         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEARING_AID);
493         when(mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET)).thenReturn(
494                 "true".getBytes());
495         when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY)).thenReturn(
496                 TWS_BATTERY_LEFT.getBytes());
497         when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY)).thenReturn(
498                 TWS_BATTERY_RIGHT.getBytes());
499 
500         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
501                 "Active, L: 15% battery, R: 25% battery");
502     }
503 
504     @Test
getConnectionSummary_trueWirelessDeviceWithBattery_returnActiveWithBattery()505     public void getConnectionSummary_trueWirelessDeviceWithBattery_returnActiveWithBattery() {
506         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
507         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
508         updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
509         when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
510         when(mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET)).thenReturn(
511                 "true".getBytes());
512         when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY)).thenReturn(
513                 TWS_BATTERY_LEFT.getBytes());
514         when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY)).thenReturn(
515                 TWS_BATTERY_RIGHT.getBytes());
516 
517         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
518                 "L: 15% battery, R: 25% battery");
519     }
520 
521     @Test
getCarConnectionSummary_singleProfileConnectDisconnect()522     public void getCarConnectionSummary_singleProfileConnectDisconnect() {
523         // Test without battery level
524         // Set PAN profile to be connected and test connection state summary
525         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
526         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected");
527 
528         // Set PAN profile to be disconnected and test connection state summary
529         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
530         assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
531 
532         // Test with battery level
533         mBatteryLevel = 10;
534         // Set PAN profile to be connected and test connection state summary
535         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
536         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, battery 10%");
537 
538         // Set PAN profile to be disconnected and test connection state summary
539         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
540         assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
541 
542         // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
543         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
544 
545         // Set PAN profile to be connected and test connection state summary
546         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
547         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected");
548 
549         // Set PAN profile to be disconnected and test connection state summary
550         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
551         assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
552     }
553 
554     @Test
getCarConnectionSummary_multipleProfileConnectDisconnect()555     public void getCarConnectionSummary_multipleProfileConnectDisconnect() {
556         mBatteryLevel = 10;
557 
558         // Set HFP, A2DP and PAN profile to be connected and test connection state summary
559         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
560         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
561         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_CONNECTED);
562         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, battery 10%");
563 
564         // Disconnect HFP only and test connection state summary
565         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
566         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
567                 "Connected (no phone), battery 10%");
568 
569         // Disconnect A2DP only and test connection state summary
570         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
571         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
572         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
573                 "Connected (no media), battery 10%");
574 
575         // Disconnect both HFP and A2DP and test connection state summary
576         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
577         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
578                 "Connected (no phone or media), battery 10%");
579 
580         // Disconnect all profiles and test connection state summary
581         updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
582         assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
583     }
584 
585     @Test
getCarConnectionSummary_singleProfileActiveDeviceA2dp()586     public void getCarConnectionSummary_singleProfileActiveDeviceA2dp() {
587         // Test without battery level
588         // Set A2DP profile to be connected and test connection state summary
589         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
590         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected");
591 
592         // Set device as Active for A2DP and test connection state summary
593         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
594         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, active (media)");
595 
596         // Test with battery level
597         mBatteryLevel = 10;
598         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
599                 "Connected, battery 10%, active (media)");
600 
601         // Set A2DP profile to be disconnected and test connection state summary
602         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
603         assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
604 
605         // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
606         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
607         // Set A2DP profile to be connected, Active and test connection state summary
608         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
609         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
610         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, active (media)");
611 
612         // Set A2DP profile to be disconnected and test connection state summary
613         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
614         assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
615     }
616 
617     @Test
getCarConnectionSummary_singleProfileActiveDeviceHfp()618     public void getCarConnectionSummary_singleProfileActiveDeviceHfp() {
619         // Test without battery level
620         // Set HFP profile to be connected and test connection state summary
621         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
622         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected");
623 
624         // Set device as Active for HFP and test connection state summary
625         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
626         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, active (phone)");
627 
628         // Test with battery level
629         mBatteryLevel = 10;
630         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
631                 "Connected, battery 10%, active (phone)");
632 
633         // Set HFP profile to be disconnected and test connection state summary
634         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
635         assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
636 
637         // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
638         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
639         // Set HFP profile to be connected, Active and test connection state summary
640         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
641         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
642         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, active (phone)");
643 
644         // Set HFP profile to be disconnected and test connection state summary
645         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
646         assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
647     }
648 
649     @Test
getCarConnectionSummary_singleProfileActiveDeviceHearingAid()650     public void getCarConnectionSummary_singleProfileActiveDeviceHearingAid() {
651         // Test without battery level
652         // Set Hearing Aid profile to be connected and test connection state summary
653         updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
654         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected");
655 
656         // Set device as Active for Hearing Aid and test connection state summary
657         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEARING_AID);
658         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, active");
659 
660         // Set Hearing Aid profile to be disconnected and test connection state summary
661         mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.HEARING_AID);
662         updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_DISCONNECTED);
663         assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
664     }
665 
666     @Test
getCarConnectionSummary_multipleProfilesActiveDevice()667     public void getCarConnectionSummary_multipleProfilesActiveDevice() {
668         // Test without battery level
669         // Set A2DP and HFP profiles to be connected and test connection state summary
670         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
671         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
672         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected");
673 
674         // Set device as Active for A2DP and HFP and test connection state summary
675         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
676         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
677         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, active");
678 
679         // Test with battery level
680         mBatteryLevel = 10;
681         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
682                 "Connected, battery 10%, active");
683 
684         // Disconnect A2DP only and test connection state summary
685         mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.A2DP);
686         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
687         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
688                 "Connected (no media), battery 10%, active (phone)");
689 
690         // Disconnect HFP only and test connection state summary
691         mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.HEADSET);
692         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
693         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
694         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
695         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
696                 "Connected (no phone), battery 10%, active (media)");
697 
698         // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
699         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
700         // Set A2DP and HFP profiles to be connected, Active and test connection state summary
701         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
702         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
703         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
704         mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
705         assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, active");
706 
707         // Set A2DP and HFP profiles to be disconnected and test connection state summary
708         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
709         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
710         assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
711     }
712 
713 
714     @Test
deviceName_testAliasNameAvailable()715     public void deviceName_testAliasNameAvailable() {
716         when(mDevice.getAlias()).thenReturn(DEVICE_ALIAS);
717         when(mDevice.getName()).thenReturn(DEVICE_NAME);
718         CachedBluetoothDevice cachedBluetoothDevice =
719                 new CachedBluetoothDevice(mContext, mProfileManager, mDevice);
720         // Verify alias is returned on getName
721         assertThat(cachedBluetoothDevice.getName()).isEqualTo(DEVICE_ALIAS);
722         // Verify device is visible
723         assertThat(cachedBluetoothDevice.hasHumanReadableName()).isTrue();
724     }
725 
726     @Test
deviceName_testNameNotAvailable()727     public void deviceName_testNameNotAvailable() {
728         CachedBluetoothDevice cachedBluetoothDevice =
729                 new CachedBluetoothDevice(mContext, mProfileManager, mDevice);
730         // Verify device address is returned on getName
731         assertThat(cachedBluetoothDevice.getName()).isEqualTo(DEVICE_ADDRESS);
732         // Verify device is not visible
733         assertThat(cachedBluetoothDevice.hasHumanReadableName()).isFalse();
734     }
735 
736     @Test
deviceName_testRenameDevice()737     public void deviceName_testRenameDevice() {
738         final String[] alias = {DEVICE_ALIAS};
739         doAnswer(invocation -> alias[0]).when(mDevice).getAlias();
740         doAnswer(invocation -> {
741             alias[0] = (String) invocation.getArguments()[0];
742             return BluetoothStatusCodes.SUCCESS;
743         }).when(mDevice).setAlias(anyString());
744         when(mDevice.getName()).thenReturn(DEVICE_NAME);
745         CachedBluetoothDevice cachedBluetoothDevice =
746                 new CachedBluetoothDevice(mContext, mProfileManager, mDevice);
747         // Verify alias is returned on getName
748         assertThat(cachedBluetoothDevice.getName()).isEqualTo(DEVICE_ALIAS);
749         // Verify null name does not get set
750         cachedBluetoothDevice.setName(null);
751         verify(mDevice, never()).setAlias(any());
752         // Verify new name is set properly
753         cachedBluetoothDevice.setName(DEVICE_ALIAS_NEW);
754         verify(mDevice).setAlias(DEVICE_ALIAS_NEW);
755         // Verify new alias is returned on getName
756         assertThat(cachedBluetoothDevice.getName()).isEqualTo(DEVICE_ALIAS_NEW);
757     }
758 
759     @Test
setActive()760     public void setActive() {
761         when(mProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
762         when(mProfileManager.getHeadsetProfile()).thenReturn(mHfpProfile);
763         when(mA2dpProfile.setActiveDevice(any(BluetoothDevice.class))).thenReturn(true);
764         when(mHfpProfile.setActiveDevice(any(BluetoothDevice.class))).thenReturn(true);
765 
766         assertThat(mCachedDevice.setActive()).isFalse();
767 
768         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
769         assertThat(mCachedDevice.setActive()).isTrue();
770 
771         updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
772         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
773         assertThat(mCachedDevice.setActive()).isTrue();
774 
775         updateProfileStatus(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
776         assertThat(mCachedDevice.setActive()).isFalse();
777     }
778 
779     @Test
isA2dpDevice_isA2dpDevice()780     public void isA2dpDevice_isA2dpDevice() {
781         when(mProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
782         when(mA2dpProfile.getConnectionStatus(mDevice)).
783                 thenReturn(BluetoothProfile.STATE_CONNECTED);
784 
785         assertThat(mCachedDevice.isConnectedA2dpDevice()).isTrue();
786     }
787 
788     @Test
isA2dpDevice_isNotA2dpDevice()789     public void isA2dpDevice_isNotA2dpDevice() {
790         when(mProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
791         when(mA2dpProfile.getConnectionStatus(mDevice)).
792                 thenReturn(BluetoothProfile.STATE_DISCONNECTING);
793 
794         assertThat(mCachedDevice.isConnectedA2dpDevice()).isFalse();
795     }
796 
797     @Test
isHfpDevice_isHfpDevice()798     public void isHfpDevice_isHfpDevice() {
799         when(mProfileManager.getHeadsetProfile()).thenReturn(mHfpProfile);
800         when(mHfpProfile.getConnectionStatus(mDevice)).
801                 thenReturn(BluetoothProfile.STATE_CONNECTED);
802 
803         assertThat(mCachedDevice.isConnectedHfpDevice()).isTrue();
804     }
805 
806     @Test
testIsHfpDevice_isNotHfpDevice()807     public void testIsHfpDevice_isNotHfpDevice() {
808         when(mProfileManager.getHeadsetProfile()).thenReturn(mHfpProfile);
809         when(mHfpProfile.getConnectionStatus(mDevice)).
810                 thenReturn(BluetoothProfile.STATE_DISCONNECTING);
811 
812         assertThat(mCachedDevice.isConnectedHfpDevice()).isFalse();
813     }
814 
815     @Test
isConnectedHearingAidDevice_connected_returnTrue()816     public void isConnectedHearingAidDevice_connected_returnTrue() {
817         when(mProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile);
818         when(mHearingAidProfile.getConnectionStatus(mDevice)).
819                 thenReturn(BluetoothProfile.STATE_CONNECTED);
820 
821         assertThat(mCachedDevice.isConnectedHearingAidDevice()).isTrue();
822     }
823 
824     @Test
isConnectedHearingAidDevice_disconnected_returnFalse()825     public void isConnectedHearingAidDevice_disconnected_returnFalse() {
826         when(mProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile);
827         when(mHearingAidProfile.getConnectionStatus(mDevice)).
828                 thenReturn(BluetoothProfile.STATE_DISCONNECTED);
829 
830         assertThat(mCachedDevice.isConnectedHearingAidDevice()).isFalse();
831     }
832 
833     @Test
isConnectedHfpDevice_profileIsNull_returnFalse()834     public void isConnectedHfpDevice_profileIsNull_returnFalse() {
835         when(mProfileManager.getHeadsetProfile()).thenReturn(null);
836 
837         assertThat(mCachedDevice.isConnectedHfpDevice()).isFalse();
838     }
839 
840     @Test
isConnectedA2dpDevice_profileIsNull_returnFalse()841     public void isConnectedA2dpDevice_profileIsNull_returnFalse() {
842         when(mProfileManager.getA2dpProfile()).thenReturn(null);
843 
844         assertThat(mCachedDevice.isConnectedA2dpDevice()).isFalse();
845     }
846 
847     @Test
isConnectedHearingAidDevice_profileIsNull_returnFalse()848     public void isConnectedHearingAidDevice_profileIsNull_returnFalse() {
849         when(mProfileManager.getHearingAidProfile()).thenReturn(null);
850 
851         assertThat(mCachedDevice.isConnectedHearingAidDevice()).isFalse();
852     }
853 
854     @Test
getName_aliasNameNotNull_returnAliasName()855     public void getName_aliasNameNotNull_returnAliasName() {
856         when(mDevice.getAlias()).thenReturn(DEVICE_NAME);
857 
858         assertThat(mCachedDevice.getName()).isEqualTo(DEVICE_NAME);
859     }
860 
861     @Test
getName_aliasNameIsNull_returnAddress()862     public void getName_aliasNameIsNull_returnAddress() {
863         when(mDevice.getAlias()).thenReturn(null);
864 
865         assertThat(mCachedDevice.getName()).isEqualTo(DEVICE_ADDRESS);
866     }
867 
868     @Test
setName_setDeviceNameIsNotNull()869     public void setName_setDeviceNameIsNotNull() {
870         final String name = "test name";
871         when(mDevice.getAlias()).thenReturn(DEVICE_NAME);
872 
873         mCachedDevice.setName(name);
874 
875         verify(mDevice).setAlias(name);
876     }
877 
878     @Test
setName_setDeviceNameIsNull()879     public void setName_setDeviceNameIsNull() {
880         mCachedDevice.setName(null);
881 
882         verify(mDevice, never()).setAlias(any());
883     }
884 
885     @Test
getProfileConnectionState_nullProfile_returnDisconnected()886     public void getProfileConnectionState_nullProfile_returnDisconnected() {
887         assertThat(mCachedDevice.getProfileConnectionState(null)).isEqualTo(
888                 BluetoothProfile.STATE_DISCONNECTED);
889     }
890 
891     @Test
getProfileConnectionState_profileConnected_returnConnected()892     public void getProfileConnectionState_profileConnected_returnConnected() {
893         doReturn(BluetoothProfile.STATE_CONNECTED).when(mA2dpProfile).getConnectionStatus(
894                 any(BluetoothDevice.class));
895 
896         assertThat(mCachedDevice.getProfileConnectionState(mA2dpProfile)).isEqualTo(
897                 BluetoothProfile.STATE_CONNECTED);
898     }
899 
updateProfileStatus(LocalBluetoothProfile profile, int status)900     private void updateProfileStatus(LocalBluetoothProfile profile, int status) {
901         doReturn(status).when(profile).getConnectionStatus(mDevice);
902         mCachedDevice.onProfileStateChanged(profile, status);
903     }
904 
905     @Test
getSubDevice_setSubDevice()906     public void getSubDevice_setSubDevice() {
907         CachedBluetoothDevice subCachedDevice = new CachedBluetoothDevice(mContext, mProfileManager,
908                 mSubDevice);
909         mCachedDevice.setSubDevice(subCachedDevice);
910 
911         assertThat(mCachedDevice.getSubDevice()).isEqualTo(subCachedDevice);
912     }
913 
914     @Test
switchSubDeviceContent()915     public void switchSubDeviceContent() {
916         CachedBluetoothDevice subCachedDevice = new CachedBluetoothDevice(mContext, mProfileManager,
917                 mSubDevice);
918         mCachedDevice.mRssi = RSSI_1;
919         mCachedDevice.mJustDiscovered = JUSTDISCOVERED_1;
920         subCachedDevice.mRssi = RSSI_2;
921         subCachedDevice.mJustDiscovered = JUSTDISCOVERED_2;
922         mCachedDevice.setSubDevice(subCachedDevice);
923 
924         assertThat(mCachedDevice.mRssi).isEqualTo(RSSI_1);
925         assertThat(mCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_1);
926         assertThat(mCachedDevice.mDevice).isEqualTo(mDevice);
927         assertThat(subCachedDevice.mRssi).isEqualTo(RSSI_2);
928         assertThat(subCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_2);
929         assertThat(subCachedDevice.mDevice).isEqualTo(mSubDevice);
930         mCachedDevice.switchSubDeviceContent();
931 
932         assertThat(mCachedDevice.mRssi).isEqualTo(RSSI_2);
933         assertThat(mCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_2);
934         assertThat(mCachedDevice.mDevice).isEqualTo(mSubDevice);
935         assertThat(subCachedDevice.mRssi).isEqualTo(RSSI_1);
936         assertThat(subCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_1);
937         assertThat(subCachedDevice.mDevice).isEqualTo(mDevice);
938     }
939 
940     @Test
getConnectionSummary_profileConnectedFail_showErrorMessage()941     public void getConnectionSummary_profileConnectedFail_showErrorMessage() {
942         final A2dpProfile profle = mock(A2dpProfile.class);
943         mCachedDevice.onProfileStateChanged(profle, BluetoothProfile.STATE_CONNECTED);
944         mCachedDevice.setProfileConnectedStatus(BluetoothProfile.A2DP, true);
945 
946         when(profle.getConnectionStatus(mDevice)).thenReturn(BluetoothProfile.STATE_CONNECTED);
947 
948         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
949                 mContext.getString(R.string.profile_connect_timeout_subtext));
950     }
951 
952     @Test
onUuidChanged_bluetoothClassIsNull_shouldNotCrash()953     public void onUuidChanged_bluetoothClassIsNull_shouldNotCrash() {
954         mShadowBluetoothAdapter.setUuids(PbapServerProfile.PBAB_CLIENT_UUIDS);
955         when(mDevice.getUuids()).thenReturn(PbapServerProfile.PBAB_CLIENT_UUIDS);
956         when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
957         when(mDevice.getPhonebookAccessPermission()).thenReturn(BluetoothDevice.ACCESS_UNKNOWN);
958         when(mDevice.getBluetoothClass()).thenReturn(null);
959 
960         mCachedDevice.onUuidChanged();
961 
962         // Should not crash
963     }
964 
965     @Test
getDrawableWithDescription_isAdvancedDevice_returnAdvancedIcon()966     public void getDrawableWithDescription_isAdvancedDevice_returnAdvancedIcon() {
967         LruCache lruCache = mock(LruCache.class);
968         mCachedDevice.mDrawableCache = lruCache;
969         BitmapDrawable drawable = mock(BitmapDrawable.class);
970         when(lruCache.get("fake_uri")).thenReturn(drawable);
971         when(mDevice.getMetadata(BluetoothDevice.METADATA_MAIN_ICON))
972                 .thenReturn("fake_uri".getBytes());
973         when(mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
974                 .thenReturn("true".getBytes());
975 
976         mCachedDevice.refresh();
977 
978         assertThat(mCachedDevice.getDrawableWithDescription().first).isInstanceOf(
979                 AdaptiveOutlineDrawable.class);
980     }
981 
982     @Test
getDrawableWithDescription_isNotAdvancedDevice_returnBluetoothIcon()983     public void getDrawableWithDescription_isNotAdvancedDevice_returnBluetoothIcon() {
984         when(mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
985                 .thenReturn("false".getBytes());
986 
987         mCachedDevice.refresh();
988 
989         assertThat(mCachedDevice.getDrawableWithDescription().first).isNotInstanceOf(
990                 AdaptiveOutlineDrawable.class);
991     }
992 
993     @Test
releaseLruCache_lruCacheShouldBeRelease()994     public void releaseLruCache_lruCacheShouldBeRelease() {
995         when(mDevice.getMetadata(BluetoothDevice.METADATA_MAIN_ICON))
996                 .thenReturn("fake_uri".getBytes());
997         when(mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
998                 .thenReturn("true".getBytes());
999 
1000         mCachedDevice.refresh();
1001         mCachedDevice.releaseLruCache();
1002 
1003         assertThat(mCachedDevice.mDrawableCache.size()).isEqualTo(0);
1004     }
1005 }
1006