• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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.settings.connecteddevice;
17 
18 import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
19 import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
20 
21 import static com.google.common.truth.Truth.assertThat;
22 
23 import static org.mockito.ArgumentMatchers.any;
24 import static org.mockito.ArgumentMatchers.anyString;
25 import static org.mockito.Mockito.doReturn;
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.BluetoothProfile;
31 import android.content.Context;
32 import android.content.pm.PackageManager;
33 import android.media.AudioManager;
34 
35 import androidx.appcompat.app.AlertDialog;
36 import androidx.fragment.app.FragmentActivity;
37 import androidx.preference.Preference;
38 import androidx.preference.PreferenceGroup;
39 import androidx.preference.PreferenceManager;
40 import androidx.preference.PreferenceScreen;
41 
42 import com.android.settings.R;
43 import com.android.settings.bluetooth.AvailableMediaBluetoothDeviceUpdater;
44 import com.android.settings.bluetooth.Utils;
45 import com.android.settings.dashboard.DashboardFragment;
46 import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
47 import com.android.settings.testutils.shadow.ShadowAudioManager;
48 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
49 import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
50 import com.android.settingslib.bluetooth.BluetoothCallback;
51 import com.android.settingslib.bluetooth.BluetoothEventManager;
52 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
53 import com.android.settingslib.bluetooth.HearingAidProfile;
54 import com.android.settingslib.bluetooth.LocalBluetoothManager;
55 
56 import org.junit.Before;
57 import org.junit.Test;
58 import org.junit.runner.RunWith;
59 import org.mockito.Answers;
60 import org.mockito.Mock;
61 import org.mockito.MockitoAnnotations;
62 import org.robolectric.Robolectric;
63 import org.robolectric.RobolectricTestRunner;
64 import org.robolectric.RuntimeEnvironment;
65 import org.robolectric.annotation.Config;
66 
67 /** Tests for {@link AvailableMediaDeviceGroupController}. */
68 @RunWith(RobolectricTestRunner.class)
69 @Config(shadows = {ShadowAudioManager.class, ShadowBluetoothAdapter.class,
70         ShadowBluetoothUtils.class})
71 public class AvailableMediaDeviceGroupControllerTest {
72 
73     private static final String PREFERENCE_KEY_1 = "pref_key_1";
74 
75     @Mock
76     private DashboardFragment mDashboardFragment;
77     @Mock
78     private AvailableMediaBluetoothDeviceUpdater mAvailableMediaBluetoothDeviceUpdater;
79     @Mock
80     private PreferenceScreen mPreferenceScreen;
81     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
82     private PreferenceManager mPreferenceManager;
83     @Mock
84     private PackageManager mPackageManager;
85     @Mock
86     private BluetoothEventManager mEventManager;
87     @Mock
88     private LocalBluetoothManager mLocalManager;
89     @Mock
90     private CachedBluetoothDevice mCachedBluetoothDevice;
91 
92     private PreferenceGroup mPreferenceGroup;
93     private Context mContext;
94     private Preference mPreference;
95     private AvailableMediaDeviceGroupController mAvailableMediaDeviceGroupController;
96     private LocalBluetoothManager mLocalBluetoothManager;
97     private AudioManager mAudioManager;
98 
99     @Before
setUp()100     public void setUp() {
101         MockitoAnnotations.initMocks(this);
102 
103         mContext = spy(RuntimeEnvironment.application);
104         mPreference = new Preference(mContext);
105         mPreference.setKey(PREFERENCE_KEY_1);
106         mPreferenceGroup = spy(new PreferenceScreen(mContext, null));
107         final FragmentActivity mActivity = Robolectric.setupActivity(FragmentActivity.class);
108         when(mPreferenceGroup.getPreferenceManager()).thenReturn(mPreferenceManager);
109         doReturn(mContext).when(mDashboardFragment).getContext();
110         doReturn(mPackageManager).when(mContext).getPackageManager();
111         doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
112         when(mDashboardFragment.getParentFragmentManager()).thenReturn(
113                 mActivity.getSupportFragmentManager());
114 
115         ShadowBluetoothUtils.sLocalBluetoothManager = mLocalManager;
116         mLocalBluetoothManager = Utils.getLocalBtManager(mContext);
117         mAudioManager = mContext.getSystemService(AudioManager.class);
118         doReturn(mEventManager).when(mLocalBluetoothManager).getEventManager();
119 
120         mAvailableMediaDeviceGroupController = spy(
121                 new AvailableMediaDeviceGroupController(mContext));
122         mAvailableMediaDeviceGroupController.
123                 setBluetoothDeviceUpdater(mAvailableMediaBluetoothDeviceUpdater);
124         mAvailableMediaDeviceGroupController.mPreferenceGroup = mPreferenceGroup;
125     }
126 
127     @Test
onDeviceAdded_firstAdd_becomeVisibleAndPreferenceAdded()128     public void onDeviceAdded_firstAdd_becomeVisibleAndPreferenceAdded() {
129         mAvailableMediaDeviceGroupController.onDeviceAdded(mPreference);
130 
131         assertThat(mPreferenceGroup.isVisible()).isTrue();
132         assertThat((Preference) mPreferenceGroup.findPreference(PREFERENCE_KEY_1))
133                 .isEqualTo(mPreference);
134     }
135 
136     @Test
onDeviceRemoved_lastRemove_becomeInvisibleAndPreferenceRemoved()137     public void onDeviceRemoved_lastRemove_becomeInvisibleAndPreferenceRemoved() {
138         mPreferenceGroup.addPreference(mPreference);
139 
140         mAvailableMediaDeviceGroupController.onDeviceRemoved(mPreference);
141 
142         assertThat(mPreferenceGroup.isVisible()).isFalse();
143         assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0);
144     }
145 
146     @Test
onDeviceRemoved_notLastRemove_stillVisible()147     public void onDeviceRemoved_notLastRemove_stillVisible() {
148         mPreferenceGroup.setVisible(true);
149         mPreferenceGroup.addPreference(mPreference);
150         mPreferenceGroup.addPreference(new Preference(mContext));
151 
152         mAvailableMediaDeviceGroupController.onDeviceRemoved(mPreference);
153 
154         assertThat(mPreferenceGroup.isVisible()).isTrue();
155     }
156 
157     @Test
displayPreference_becomeInvisible()158     public void displayPreference_becomeInvisible() {
159         doReturn(mPreferenceGroup).when(mPreferenceScreen).findPreference(anyString());
160 
161         mAvailableMediaDeviceGroupController.displayPreference(mPreferenceScreen);
162 
163         assertThat(mPreferenceGroup.isVisible()).isFalse();
164     }
165 
166     @Test
testRegister()167     public void testRegister() {
168         // register the callback in onStart()
169         mAvailableMediaDeviceGroupController.onStart();
170 
171         verify(mAvailableMediaBluetoothDeviceUpdater).registerCallback();
172         verify(mLocalBluetoothManager.getEventManager()).registerCallback(
173                 any(BluetoothCallback.class));
174         verify(mAvailableMediaBluetoothDeviceUpdater).refreshPreference();
175     }
176 
177     @Test
testUnregister()178     public void testUnregister() {
179         // unregister the callback in onStop()
180         mAvailableMediaDeviceGroupController.onStop();
181         verify(mAvailableMediaBluetoothDeviceUpdater).unregisterCallback();
182         verify(mLocalBluetoothManager.getEventManager()).unregisterCallback(
183                 any(BluetoothCallback.class));
184     }
185 
186     @Test
testGetAvailabilityStatus_noBluetoothFeature_returnUnSupported()187     public void testGetAvailabilityStatus_noBluetoothFeature_returnUnSupported() {
188         doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
189 
190         assertThat(mAvailableMediaDeviceGroupController.getAvailabilityStatus()).isEqualTo(
191                 UNSUPPORTED_ON_DEVICE);
192     }
193 
194     @Test
testGetAvailabilityStatus_BluetoothFeature_returnSupported()195     public void testGetAvailabilityStatus_BluetoothFeature_returnSupported() {
196         doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
197 
198         assertThat(mAvailableMediaDeviceGroupController.getAvailabilityStatus()).isEqualTo(
199                 AVAILABLE_UNSEARCHABLE);
200     }
201 
202     @Test
setTitle_inCallState_showCallStateTitle()203     public void setTitle_inCallState_showCallStateTitle() {
204         mAudioManager.setMode(AudioManager.MODE_IN_CALL);
205         mAvailableMediaDeviceGroupController.onAudioModeChanged();
206 
207         assertThat(mPreferenceGroup.getTitle()).isEqualTo(
208                 mContext.getText(R.string.connected_device_call_device_title));
209     }
210 
211     @Test
setTitle_notInCallState_showMediaStateTitle()212     public void setTitle_notInCallState_showMediaStateTitle() {
213         mAudioManager.setMode(AudioManager.MODE_NORMAL);
214         mAvailableMediaDeviceGroupController.onAudioModeChanged();
215 
216         assertThat(mPreferenceGroup.getTitle()).isEqualTo(
217                 mContext.getText(R.string.connected_device_media_device_title));
218     }
219 
220     @Test
onStart_localBluetoothManagerNull_shouldNotCrash()221     public void onStart_localBluetoothManagerNull_shouldNotCrash() {
222         mAvailableMediaDeviceGroupController.mLocalBluetoothManager = null;
223 
224         // Shouldn't crash
225         mAvailableMediaDeviceGroupController.onStart();
226     }
227 
228     @Test
onStop_localBluetoothManagerNull_shouldNotCrash()229     public void onStop_localBluetoothManagerNull_shouldNotCrash() {
230         mAvailableMediaDeviceGroupController.mLocalBluetoothManager = null;
231 
232         // Shouldn't crash
233         mAvailableMediaDeviceGroupController.onStop();
234     }
235 
236     @Test
237     @Config(shadows = ShadowAlertDialogCompat.class)
onActiveDeviceChanged_hearingAidProfile_launchHearingAidPairingDialog()238     public void onActiveDeviceChanged_hearingAidProfile_launchHearingAidPairingDialog() {
239         when(mCachedBluetoothDevice.isConnectedHearingAidDevice()).thenReturn(true);
240         when(mCachedBluetoothDevice.getDeviceMode()).thenReturn(
241                 HearingAidProfile.DeviceMode.MODE_BINAURAL);
242         when(mCachedBluetoothDevice.getDeviceSide()).thenReturn(
243                 HearingAidProfile.DeviceSide.SIDE_LEFT);
244         mAvailableMediaDeviceGroupController.init(mDashboardFragment);
245 
246         mAvailableMediaDeviceGroupController.onActiveDeviceChanged(mCachedBluetoothDevice,
247                 BluetoothProfile.HEARING_AID);
248 
249         final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
250         assertThat(dialog.isShowing()).isTrue();
251     }
252 }
253