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.settings.bluetooth; 17 18 import android.bluetooth.BluetoothClass; 19 import android.bluetooth.BluetoothDevice; 20 import android.content.Context; 21 import android.os.UserManager; 22 23 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 24 import com.android.settings.R; 25 import com.android.settings.testutils.SettingsRobolectricTestRunner; 26 import com.android.settings.TestConfig; 27 import com.android.settings.core.instrumentation.MetricsFeatureProvider; 28 import com.android.settings.testutils.FakeFeatureFactory; 29 import com.android.settings.testutils.shadow.SettingsShadowResources; 30 import com.android.settingslib.bluetooth.CachedBluetoothDevice; 31 32 import org.junit.Before; 33 import org.junit.Test; 34 import org.junit.runner.RunWith; 35 import org.mockito.Mock; 36 import org.mockito.MockitoAnnotations; 37 import org.robolectric.RuntimeEnvironment; 38 import org.robolectric.annotation.Config; 39 import org.robolectric.util.ReflectionHelpers; 40 41 import static com.google.common.truth.Truth.assertThat; 42 43 import static org.mockito.Mockito.doAnswer; 44 import static org.mockito.Mockito.mock; 45 import static org.mockito.Mockito.never; 46 import static org.mockito.Mockito.spy; 47 import static org.mockito.Mockito.verify; 48 import static org.mockito.Mockito.when; 49 50 @RunWith(SettingsRobolectricTestRunner.class) 51 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, 52 shadows = SettingsShadowResources.class) 53 public class BluetoothDevicePreferenceTest { 54 55 private Context mContext; 56 @Mock 57 private CachedBluetoothDevice mCachedBluetoothDevice; 58 @Mock 59 private DeviceListPreferenceFragment mDeviceListPreferenceFragment; 60 61 private FakeFeatureFactory mFakeFeatureFactory; 62 private MetricsFeatureProvider mMetricsFeatureProvider; 63 private BluetoothDevicePreference mPreference; 64 65 @Before setUp()66 public void setUp() { 67 MockitoAnnotations.initMocks(this); 68 mContext = spy(RuntimeEnvironment.application.getApplicationContext()); 69 FakeFeatureFactory.setupForTest(mContext); 70 mFakeFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext); 71 mMetricsFeatureProvider = mFakeFeatureFactory.getMetricsFeatureProvider(); 72 mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, 73 mDeviceListPreferenceFragment); 74 } 75 76 @Test onClicked_deviceConnected_shouldLogBluetoothDisconnectEvent()77 public void onClicked_deviceConnected_shouldLogBluetoothDisconnectEvent() { 78 when(mCachedBluetoothDevice.isConnected()).thenReturn(true); 79 80 mPreference.onClicked(); 81 82 verify(mMetricsFeatureProvider).action( 83 mContext, MetricsEvent.ACTION_SETTINGS_BLUETOOTH_DISCONNECT); 84 } 85 86 @Test onClicked_deviceBonded_shouldLogBluetoothConnectEvent()87 public void onClicked_deviceBonded_shouldLogBluetoothConnectEvent() { 88 when(mCachedBluetoothDevice.isConnected()).thenReturn(false); 89 when(mCachedBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); 90 91 mPreference.onClicked(); 92 93 verify(mMetricsFeatureProvider).action( 94 mContext, MetricsEvent.ACTION_SETTINGS_BLUETOOTH_CONNECT); 95 } 96 97 @Test onClicked_deviceNotBonded_shouldLogBluetoothPairEvent()98 public void onClicked_deviceNotBonded_shouldLogBluetoothPairEvent() { 99 when(mCachedBluetoothDevice.isConnected()).thenReturn(false); 100 when(mCachedBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_NONE); 101 when(mCachedBluetoothDevice.startPairing()).thenReturn(true); 102 when(mCachedBluetoothDevice.hasHumanReadableName()).thenReturn(true); 103 104 mPreference.onClicked(); 105 106 verify(mMetricsFeatureProvider).action( 107 mContext, MetricsEvent.ACTION_SETTINGS_BLUETOOTH_PAIR); 108 verify(mMetricsFeatureProvider, never()).action(mContext, 109 MetricsEvent.ACTION_SETTINGS_BLUETOOTH_PAIR_DEVICES_WITHOUT_NAMES); 110 } 111 112 @Test onClicked_deviceNotBonded_shouldLogBluetoothPairEventAndPairWithoutNameEvent()113 public void onClicked_deviceNotBonded_shouldLogBluetoothPairEventAndPairWithoutNameEvent() { 114 when(mCachedBluetoothDevice.isConnected()).thenReturn(false); 115 when(mCachedBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_NONE); 116 when(mCachedBluetoothDevice.startPairing()).thenReturn(true); 117 when(mCachedBluetoothDevice.hasHumanReadableName()).thenReturn(false); 118 119 mPreference.onClicked(); 120 121 verify(mMetricsFeatureProvider).action( 122 mContext, MetricsEvent.ACTION_SETTINGS_BLUETOOTH_PAIR); 123 verify(mMetricsFeatureProvider).action(mContext, 124 MetricsEvent.ACTION_SETTINGS_BLUETOOTH_PAIR_DEVICES_WITHOUT_NAMES); 125 } 126 127 @Test getSecondTargetResource_shouldBeGearIconLayout()128 public void getSecondTargetResource_shouldBeGearIconLayout() { 129 assertThat(mPreference.getSecondTargetResId()).isEqualTo(R.layout.preference_widget_gear); 130 } 131 132 @Test shouldHideSecondTarget_noDevice_shouldReturnTrue()133 public void shouldHideSecondTarget_noDevice_shouldReturnTrue() { 134 ReflectionHelpers.setField(mPreference, "mCachedDevice", null); 135 136 assertThat(mPreference.shouldHideSecondTarget()).isTrue(); 137 } 138 139 @Test shouldHideSecondTarget_notBond_shouldReturnTrue()140 public void shouldHideSecondTarget_notBond_shouldReturnTrue() { 141 when(mCachedBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_NONE); 142 143 assertThat(mPreference.shouldHideSecondTarget()).isTrue(); 144 } 145 146 @Test shouldHideSecondTarget_hasUserRestriction_shouldReturnTrue()147 public void shouldHideSecondTarget_hasUserRestriction_shouldReturnTrue() { 148 final UserManager um = mock(UserManager.class); 149 ReflectionHelpers.setField(mPreference, "mUserManager", um); 150 when(um.hasUserRestriction(UserManager.DISALLOW_CONFIG_BLUETOOTH)) 151 .thenReturn(true); 152 153 assertThat(mPreference.shouldHideSecondTarget()).isTrue(); 154 } 155 156 @Test shouldHideSecondTarget_hasBoundDeviceAndNoRestriction_shouldReturnFalse()157 public void shouldHideSecondTarget_hasBoundDeviceAndNoRestriction_shouldReturnFalse() { 158 when(mCachedBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); 159 final UserManager um = mock(UserManager.class); 160 ReflectionHelpers.setField(mPreference, "mUserManager", um); 161 when(um.hasUserRestriction(UserManager.DISALLOW_CONFIG_BLUETOOTH)) 162 .thenReturn(false); 163 164 assertThat(mPreference.shouldHideSecondTarget()).isFalse(); 165 } 166 167 @Test imagingDeviceIcon_isICSettingsPrint()168 public void imagingDeviceIcon_isICSettingsPrint() { 169 when(mCachedBluetoothDevice.getBatteryLevel()).thenReturn( 170 BluetoothDevice.BATTERY_LEVEL_UNKNOWN); 171 when(mCachedBluetoothDevice.getBtClass()).thenReturn( 172 new BluetoothClass(BluetoothClass.Device.Major.IMAGING)); 173 174 mPreference.onDeviceAttributesChanged(); 175 assertThat(mPreference.getIcon()).isEqualTo( 176 mContext.getDrawable(R.drawable.ic_settings_print)); 177 } 178 179 @Test testVisible_notVisibleThenVisible()180 public void testVisible_notVisibleThenVisible() { 181 when(mDeviceListPreferenceFragment.shouldShowDevicesWithoutNames()).thenReturn(false); 182 final boolean[] humanReadableName = {false}; 183 doAnswer(invocation -> humanReadableName[0]).when(mCachedBluetoothDevice) 184 .hasHumanReadableName(); 185 BluetoothDevicePreference preference = 186 new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, 187 mDeviceListPreferenceFragment); 188 assertThat(preference.isVisible()).isFalse(); 189 humanReadableName[0] = true; 190 preference.onDeviceAttributesChanged(); 191 assertThat(preference.isVisible()).isTrue(); 192 } 193 194 @Test testVisible_visibleThenNotVisible()195 public void testVisible_visibleThenNotVisible() { 196 when(mDeviceListPreferenceFragment.shouldShowDevicesWithoutNames()).thenReturn(false); 197 final boolean[] humanReadableName = {true}; 198 doAnswer(invocation -> humanReadableName[0]).when(mCachedBluetoothDevice) 199 .hasHumanReadableName(); 200 BluetoothDevicePreference preference = 201 new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, 202 mDeviceListPreferenceFragment); 203 assertThat(preference.isVisible()).isTrue(); 204 humanReadableName[0] = false; 205 preference.onDeviceAttributesChanged(); 206 assertThat(preference.isVisible()).isFalse(); 207 } 208 209 @Test testVisible_alwaysVisibleWhenEnabled()210 public void testVisible_alwaysVisibleWhenEnabled() { 211 when(mDeviceListPreferenceFragment.shouldShowDevicesWithoutNames()).thenReturn(true); 212 final boolean[] humanReadableName = {true}; 213 doAnswer(invocation -> humanReadableName[0]).when(mCachedBluetoothDevice) 214 .hasHumanReadableName(); 215 BluetoothDevicePreference preference = 216 new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, 217 mDeviceListPreferenceFragment); 218 assertThat(preference.isVisible()).isTrue(); 219 humanReadableName[0] = false; 220 preference.onDeviceAttributesChanged(); 221 assertThat(preference.isVisible()).isTrue(); 222 } 223 } 224