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;
27import static org.robolectric.Shadows.shadowOf;
28
29import android.bluetooth.BluetoothAdapter;
30import android.bluetooth.BluetoothDevice;
31import android.bluetooth.BluetoothProfile;
32import android.content.Context;
33import android.media.AudioManager;
34
35import com.android.settingslib.SettingsLibRobolectricTestRunner;
36
37import org.junit.Before;
38import org.junit.Test;
39import org.junit.runner.RunWith;
40import org.mockito.Mock;
41import org.mockito.MockitoAnnotations;
42import org.robolectric.RuntimeEnvironment;
43import org.robolectric.shadows.ShadowAudioManager;
44
45@RunWith(SettingsLibRobolectricTestRunner.class)
46public class CachedBluetoothDeviceTest {
47    private final static String DEVICE_NAME = "TestName";
48    private final static String DEVICE_ALIAS = "TestAlias";
49    private final static String DEVICE_ADDRESS = "AA:BB:CC:DD:EE:FF";
50    private final static String DEVICE_ALIAS_NEW = "TestAliasNew";
51    @Mock
52    private LocalBluetoothAdapter mAdapter;
53    @Mock
54    private LocalBluetoothProfileManager mProfileManager;
55    @Mock
56    private HeadsetProfile mHfpProfile;
57    @Mock
58    private A2dpProfile mA2dpProfile;
59    @Mock
60    private PanProfile mPanProfile;
61    @Mock
62    private HearingAidProfile mHearingAidProfile;
63    @Mock
64    private BluetoothDevice mDevice;
65    private CachedBluetoothDevice mCachedDevice;
66    private ShadowAudioManager mShadowAudioManager;
67    private Context mContext;
68    private int mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
69
70    @Before
71    public void setUp() {
72        MockitoAnnotations.initMocks(this);
73        mContext = RuntimeEnvironment.application;
74        mShadowAudioManager = shadowOf(mContext.getSystemService(AudioManager.class));
75        when(mDevice.getAddress()).thenReturn(DEVICE_ADDRESS);
76        when(mAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON);
77        when(mHfpProfile.isProfileReady()).thenReturn(true);
78        when(mA2dpProfile.isProfileReady()).thenReturn(true);
79        when(mPanProfile.isProfileReady()).thenReturn(true);
80        when(mHearingAidProfile.isProfileReady()).thenReturn(true);
81        mCachedDevice = spy(
82                new CachedBluetoothDevice(mContext, mAdapter, mProfileManager, mDevice));
83        doAnswer((invocation) -> mBatteryLevel).when(mCachedDevice).getBatteryLevel();
84    }
85
86    @Test
87    public void testGetConnectionSummary_testSingleProfileConnectDisconnect() {
88        // Test without battery level
89        // Set PAN profile to be connected and test connection state summary
90        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED);
91        assertThat(mCachedDevice.getConnectionSummary()).isNull();
92
93        // Set PAN profile to be disconnected and test connection state summary
94        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
95        assertThat(mCachedDevice.getConnectionSummary()).isNull();
96
97        // Test with battery level
98        mBatteryLevel = 10;
99        // Set PAN profile to be connected and test connection state summary
100        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED);
101        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("10% battery");
102
103        // Set PAN profile to be disconnected and test connection state summary
104        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
105        assertThat(mCachedDevice.getConnectionSummary()).isNull();
106
107        // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
108        mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
109
110        // Set PAN profile to be connected and test connection state summary
111        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED);
112        assertThat(mCachedDevice.getConnectionSummary()).isNull();
113
114        // Set PAN profile to be disconnected and test connection state summary
115        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
116        assertThat(mCachedDevice.getConnectionSummary()).isNull();
117    }
118
119    @Test
120    public void testGetConnectionSummary_testMultipleProfileConnectDisconnect() {
121        mBatteryLevel = 10;
122
123        // Set HFP, A2DP and PAN profile to be connected and test connection state summary
124        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
125        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
126        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED);
127        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("10% battery");
128
129        // Disconnect HFP only and test connection state summary
130        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
131        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
132                "10% battery");
133
134        // Disconnect A2DP only and test connection state summary
135        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
136        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
137        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
138                "10% battery");
139
140        // Disconnect both HFP and A2DP and test connection state summary
141        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
142        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
143                "10% battery");
144
145        // Disconnect all profiles and test connection state summary
146        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
147        assertThat(mCachedDevice.getConnectionSummary()).isNull();
148    }
149
150    @Test
151    public void testGetConnectionSummary_testSingleProfileActiveDeviceA2dp() {
152        // Test without battery level
153        // Set A2DP profile to be connected and test connection state summary
154        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
155        assertThat(mCachedDevice.getConnectionSummary()).isNull();
156
157        // Set device as Active for A2DP and test connection state summary
158        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
159        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
160
161        // Test with battery level
162        mBatteryLevel = 10;
163        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
164                "Active, 10% battery");
165
166        // Set A2DP profile to be disconnected and test connection state summary
167        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
168        assertThat(mCachedDevice.getConnectionSummary()).isNull();
169
170        // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
171        mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
172        // Set A2DP profile to be connected, Active and test connection state summary
173        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
174        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
175        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
176
177        // Set A2DP profile to be disconnected and test connection state summary
178        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
179        assertThat(mCachedDevice.getConnectionSummary()).isNull();
180    }
181
182    @Test
183    public void testGetConnectionSummary_testSingleProfileActiveDeviceHfp() {
184        // Test without battery level
185        // Set HFP profile to be connected and test connection state summary
186        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
187        assertThat(mCachedDevice.getConnectionSummary()).isNull();
188
189        // Set device as Active for HFP and test connection state summary
190        mCachedDevice.onAudioModeChanged();
191        mShadowAudioManager.setMode(AudioManager.MODE_IN_CALL);
192        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
193        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
194
195        // Test with battery level
196        mBatteryLevel = 10;
197        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
198                "Active, 10% battery");
199
200        // Set HFP profile to be disconnected and test connection state summary
201        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
202        assertThat(mCachedDevice.getConnectionSummary()).isNull();
203
204        // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
205        mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
206        // Set HFP profile to be connected, Active and test connection state summary
207        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
208        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
209        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
210
211        // Set HFP profile to be disconnected and test connection state summary
212        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
213        assertThat(mCachedDevice.getConnectionSummary()).isNull();
214    }
215
216    @Test
217    public void testGetConnectionSummary_testSingleProfileActiveDeviceHearingAid() {
218        // Test without battery level
219        // Set Hearing Aid profile to be connected and test connection state summary
220        mCachedDevice.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
221        assertThat(mCachedDevice.getConnectionSummary()).isNull();
222
223        // Set device as Active for Hearing Aid and test connection state summary
224        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEARING_AID);
225        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
226
227        // Set Hearing Aid profile to be disconnected and test connection state summary
228        mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.HEARING_AID);
229        mCachedDevice.
230                onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_DISCONNECTED);
231        assertThat(mCachedDevice.getConnectionSummary()).isNull();
232    }
233
234    @Test
235    public void testGetConnectionSummary_testMultipleProfilesActiveDevice() {
236        // Test without battery level
237        // Set A2DP and HFP profiles to be connected and test connection state summary
238        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
239        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
240        assertThat(mCachedDevice.getConnectionSummary()).isNull();
241
242        // Set device as Active for A2DP and HFP and test connection state summary
243        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
244        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
245        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
246
247        // Test with battery level
248        mBatteryLevel = 10;
249        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
250                "Active, 10% battery");
251
252        // Disconnect A2DP only and test connection state summary
253        mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.A2DP);
254        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
255        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
256                "10% battery");
257
258        // Disconnect HFP only and test connection state summary
259        mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.HEADSET);
260        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
261        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
262        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
263        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
264                "Active, 10% battery");
265
266        // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
267        mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
268        // Set A2DP and HFP profiles to be connected, Active and test connection state summary
269        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
270        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
271        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
272        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
273        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
274
275        // Set A2DP and HFP profiles to be disconnected and test connection state summary
276        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
277        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
278        assertThat(mCachedDevice.getConnectionSummary()).isNull();
279    }
280
281    @Test
282    public void getCarConnectionSummary_singleProfileConnectDisconnect() {
283        // Test without battery level
284        // Set PAN profile to be connected and test connection state summary
285        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED);
286        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected");
287
288        // Set PAN profile to be disconnected and test connection state summary
289        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
290        assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
291
292        // Test with battery level
293        mBatteryLevel = 10;
294        // Set PAN profile to be connected and test connection state summary
295        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED);
296        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, battery 10%");
297
298        // Set PAN profile to be disconnected and test connection state summary
299        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
300        assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
301
302        // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
303        mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
304
305        // Set PAN profile to be connected and test connection state summary
306        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED);
307        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected");
308
309        // Set PAN profile to be disconnected and test connection state summary
310        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
311        assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
312    }
313
314    @Test
315    public void getCarConnectionSummary_multipleProfileConnectDisconnect() {
316        mBatteryLevel = 10;
317
318        // Set HFP, A2DP and PAN profile to be connected and test connection state summary
319        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
320        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
321        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_CONNECTED);
322        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, battery 10%");
323
324        // Disconnect HFP only and test connection state summary
325        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
326        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
327                "Connected (no phone), battery 10%");
328
329        // Disconnect A2DP only and test connection state summary
330        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
331        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
332        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
333                "Connected (no media), battery 10%");
334
335        // Disconnect both HFP and A2DP and test connection state summary
336        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
337        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
338                "Connected (no phone or media), battery 10%");
339
340        // Disconnect all profiles and test connection state summary
341        mCachedDevice.onProfileStateChanged(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
342        assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
343    }
344
345    @Test
346    public void getCarConnectionSummary_singleProfileActiveDeviceA2dp() {
347        // Test without battery level
348        // Set A2DP profile to be connected and test connection state summary
349        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
350        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected");
351
352        // Set device as Active for A2DP and test connection state summary
353        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
354        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, active (media)");
355
356        // Test with battery level
357        mBatteryLevel = 10;
358        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
359                "Connected, battery 10%, active (media)");
360
361        // Set A2DP profile to be disconnected and test connection state summary
362        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
363        assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
364
365        // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
366        mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
367        // Set A2DP profile to be connected, Active and test connection state summary
368        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
369        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
370        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, active (media)");
371
372        // Set A2DP profile to be disconnected and test connection state summary
373        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
374        assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
375    }
376
377    @Test
378    public void getCarConnectionSummary_singleProfileActiveDeviceHfp() {
379        // Test without battery level
380        // Set HFP profile to be connected and test connection state summary
381        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
382        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected");
383
384        // Set device as Active for HFP and test connection state summary
385        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
386        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, active (phone)");
387
388        // Test with battery level
389        mBatteryLevel = 10;
390        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
391                "Connected, battery 10%, active (phone)");
392
393        // Set HFP profile to be disconnected and test connection state summary
394        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
395        assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
396
397        // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
398        mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
399        // Set HFP profile to be connected, Active and test connection state summary
400        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
401        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
402        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, active (phone)");
403
404        // Set HFP profile to be disconnected and test connection state summary
405        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
406        assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
407    }
408
409    @Test
410    public void getCarConnectionSummary_singleProfileActiveDeviceHearingAid() {
411        // Test without battery level
412        // Set Hearing Aid profile to be connected and test connection state summary
413        mCachedDevice.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
414        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected");
415
416        // Set device as Active for Hearing Aid and test connection state summary
417        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEARING_AID);
418        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, active");
419
420        // Set Hearing Aid profile to be disconnected and test connection state summary
421        mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.HEARING_AID);
422        mCachedDevice.onProfileStateChanged(mHearingAidProfile,
423                BluetoothProfile.STATE_DISCONNECTED);
424        assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
425    }
426
427    @Test
428    public void getCarConnectionSummary_multipleProfilesActiveDevice() {
429        // Test without battery level
430        // Set A2DP and HFP profiles to be connected and test connection state summary
431        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
432        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
433        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected");
434
435        // Set device as Active for A2DP and HFP and test connection state summary
436        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
437        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
438        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, active");
439
440        // Test with battery level
441        mBatteryLevel = 10;
442        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
443                "Connected, battery 10%, active");
444
445        // Disconnect A2DP only and test connection state summary
446        mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.A2DP);
447        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
448        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
449                "Connected (no media), battery 10%, active (phone)");
450
451        // Disconnect HFP only and test connection state summary
452        mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.HEADSET);
453        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
454        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
455        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
456        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo(
457                "Connected (no phone), battery 10%, active (media)");
458
459        // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
460        mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
461        // Set A2DP and HFP profiles to be connected, Active and test connection state summary
462        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
463        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
464        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
465        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
466        assertThat(mCachedDevice.getCarConnectionSummary()).isEqualTo("Connected, active");
467
468        // Set A2DP and HFP profiles to be disconnected and test connection state summary
469        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
470        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
471        assertThat(mCachedDevice.getCarConnectionSummary()).isNull();
472    }
473
474
475    @Test
476    public void testDeviceName_testAliasNameAvailable() {
477        when(mDevice.getAliasName()).thenReturn(DEVICE_ALIAS);
478        when(mDevice.getName()).thenReturn(DEVICE_NAME);
479        CachedBluetoothDevice cachedBluetoothDevice =
480                new CachedBluetoothDevice(mContext, mAdapter, mProfileManager, mDevice);
481        // Verify alias is returned on getName
482        assertThat(cachedBluetoothDevice.getName()).isEqualTo(DEVICE_ALIAS);
483        // Verify device is visible
484        assertThat(cachedBluetoothDevice.hasHumanReadableName()).isTrue();
485    }
486
487    @Test
488    public void testDeviceName_testNameNotAvailable() {
489        CachedBluetoothDevice cachedBluetoothDevice =
490                new CachedBluetoothDevice(mContext, mAdapter, mProfileManager, mDevice);
491        // Verify device address is returned on getName
492        assertThat(cachedBluetoothDevice.getName()).isEqualTo(DEVICE_ADDRESS);
493        // Verify device is not visible
494        assertThat(cachedBluetoothDevice.hasHumanReadableName()).isFalse();
495    }
496
497    @Test
498    public void testDeviceName_testRenameDevice() {
499        final String[] alias = {DEVICE_ALIAS};
500        doAnswer(invocation -> alias[0]).when(mDevice).getAliasName();
501        doAnswer(invocation -> {
502            alias[0] = (String) invocation.getArguments()[0];
503            return true;
504        }).when(mDevice).setAlias(anyString());
505        when(mDevice.getName()).thenReturn(DEVICE_NAME);
506        CachedBluetoothDevice cachedBluetoothDevice =
507                new CachedBluetoothDevice(mContext, mAdapter, mProfileManager, mDevice);
508        // Verify alias is returned on getName
509        assertThat(cachedBluetoothDevice.getName()).isEqualTo(DEVICE_ALIAS);
510        // Verify null name does not get set
511        cachedBluetoothDevice.setName(null);
512        verify(mDevice, never()).setAlias(any());
513        // Verify new name is set properly
514        cachedBluetoothDevice.setName(DEVICE_ALIAS_NEW);
515        verify(mDevice).setAlias(DEVICE_ALIAS_NEW);
516        // Verify new alias is returned on getName
517        assertThat(cachedBluetoothDevice.getName()).isEqualTo(DEVICE_ALIAS_NEW);
518    }
519
520    @Test
521    public void testSetActive() {
522        when(mProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
523        when(mProfileManager.getHeadsetProfile()).thenReturn(mHfpProfile);
524        when(mA2dpProfile.setActiveDevice(any(BluetoothDevice.class))).thenReturn(true);
525        when(mHfpProfile.setActiveDevice(any(BluetoothDevice.class))).thenReturn(true);
526
527        assertThat(mCachedDevice.setActive()).isFalse();
528
529        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
530        assertThat(mCachedDevice.setActive()).isTrue();
531
532        mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
533        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
534        assertThat(mCachedDevice.setActive()).isTrue();
535
536        mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
537        assertThat(mCachedDevice.setActive()).isFalse();
538    }
539
540    @Test
541    public void testIsA2dpDevice_isA2dpDevice() {
542        when(mProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
543        when(mA2dpProfile.getConnectionStatus(mDevice)).
544                thenReturn(BluetoothProfile.STATE_CONNECTED);
545
546        assertThat(mCachedDevice.isA2dpDevice()).isTrue();
547    }
548
549    @Test
550    public void testIsA2dpDevice_isNotA2dpDevice() {
551        when(mProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
552        when(mA2dpProfile.getConnectionStatus(mDevice)).
553                thenReturn(BluetoothProfile.STATE_DISCONNECTING);
554
555        assertThat(mCachedDevice.isA2dpDevice()).isFalse();
556    }
557
558    @Test
559    public void testIsHfpDevice_isHfpDevice() {
560        when(mProfileManager.getHeadsetProfile()).thenReturn(mHfpProfile);
561        when(mHfpProfile.getConnectionStatus(mDevice)).
562                thenReturn(BluetoothProfile.STATE_CONNECTED);
563
564        assertThat(mCachedDevice.isHfpDevice()).isTrue();
565    }
566
567    @Test
568    public void testIsHfpDevice_isNotHfpDevice() {
569        when(mProfileManager.getHeadsetProfile()).thenReturn(mHfpProfile);
570        when(mHfpProfile.getConnectionStatus(mDevice)).
571                thenReturn(BluetoothProfile.STATE_DISCONNECTING);
572
573        assertThat(mCachedDevice.isHfpDevice()).isFalse();
574    }
575}
576