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 static com.google.common.truth.Truth.assertThat; 19 20 import static org.mockito.Matchers.any; 21 import static org.mockito.Matchers.anyBoolean; 22 import static org.mockito.Mockito.mock; 23 import static org.mockito.Mockito.never; 24 import static org.mockito.Mockito.spy; 25 import static org.mockito.Mockito.verify; 26 import static org.mockito.Mockito.when; 27 28 import android.bluetooth.BluetoothAdapter; 29 import android.content.BroadcastReceiver; 30 import android.content.ComponentName; 31 import android.content.Context; 32 import android.content.Intent; 33 import android.content.IntentFilter; 34 import android.os.UserManager; 35 import android.support.v7.preference.PreferenceViewHolder; 36 import android.view.View; 37 import android.widget.Switch; 38 39 import com.android.settings.R; 40 import com.android.settings.testutils.SettingsRobolectricTestRunner; 41 import com.android.settings.testutils.shadow.SettingsShadowResources; 42 import com.android.settings.widget.SwitchBar; 43 import com.android.settings.widget.SwitchBarController; 44 import com.android.settings.widget.SwitchWidgetController; 45 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; 46 import com.android.settingslib.RestrictedSwitchPreference; 47 import com.android.settingslib.bluetooth.LocalBluetoothAdapter; 48 import com.android.settingslib.bluetooth.LocalBluetoothManager; 49 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; 50 51 import org.junit.Before; 52 import org.junit.BeforeClass; 53 import org.junit.Test; 54 import org.junit.runner.RunWith; 55 import org.mockito.ArgumentCaptor; 56 import org.mockito.Mock; 57 import org.mockito.MockitoAnnotations; 58 import org.robolectric.RuntimeEnvironment; 59 import org.robolectric.annotation.Config; 60 61 @RunWith(SettingsRobolectricTestRunner.class) 62 @Config(shadows = SettingsShadowResources.SettingsShadowTheme.class) 63 public class BluetoothEnablerTest { 64 65 private static EnforcedAdmin sFakeEnforcedAdmin; 66 private PreferenceViewHolder mHolder; 67 private RestrictedSwitchPreference mRestrictedSwitchPreference; 68 69 @BeforeClass beforeClass()70 public static void beforeClass() { 71 sFakeEnforcedAdmin = new EnforcedAdmin(new ComponentName("test.package", "test.Class"), 10); 72 } 73 74 @Mock 75 private MetricsFeatureProvider mMetricsFeatureProvider; 76 @Mock 77 private RestrictionUtils mRestrictionUtils; 78 @Mock 79 private LocalBluetoothManager mBluetoothManager; 80 @Mock 81 private LocalBluetoothAdapter mBluetoothAdapter; 82 @Mock 83 private SwitchWidgetController.OnSwitchChangeListener mCallback; 84 85 private Context mContext; 86 private SwitchWidgetController mSwitchController; 87 private BluetoothEnabler mBluetoothEnabler; 88 89 @Before setUp()90 public void setUp() { 91 MockitoAnnotations.initMocks(this); 92 mContext = spy(RuntimeEnvironment.application); 93 when(mBluetoothManager.getBluetoothAdapter()).thenReturn(mBluetoothAdapter); 94 95 mRestrictedSwitchPreference = new RestrictedSwitchPreference(mContext); 96 mSwitchController = spy(new SwitchBarController(new SwitchBar(mContext))); 97 mBluetoothEnabler = new BluetoothEnabler( 98 mContext, 99 mSwitchController, 100 mMetricsFeatureProvider, 101 mBluetoothManager, 102 123, 103 mRestrictionUtils); 104 mHolder = PreferenceViewHolder.createInstanceForTests(mock(View.class)); 105 mRestrictedSwitchPreference.onBindViewHolder(mHolder); 106 mBluetoothEnabler.setToggleCallback(mCallback); 107 } 108 109 @Test onSwitchToggled_shouldLogActionWithSuppliedEvent()110 public void onSwitchToggled_shouldLogActionWithSuppliedEvent() { 111 // WHEN the switch is toggled... 112 mBluetoothEnabler.onSwitchToggled(false); 113 114 // THEN the corresponding metrics action is logged. 115 verify(mMetricsFeatureProvider).action(mContext, 123, false); 116 } 117 118 @Test onSwitchToggled_shouldTriggerCallback()119 public void onSwitchToggled_shouldTriggerCallback() { 120 // WHEN the switch is toggled... 121 mBluetoothEnabler.onSwitchToggled(false); 122 123 // THEN the callback is triggered 124 verify(mCallback).onSwitchToggled(false); 125 } 126 127 @Test maybeEnforceRestrictions_noRestrictions()128 public void maybeEnforceRestrictions_noRestrictions() { 129 // GIVEN there are no restrictions set... 130 when(mRestrictionUtils.checkIfRestrictionEnforced(any(Context.class), any(String.class))) 131 .thenReturn(null); 132 133 // WHEN the maybeEnforceRestrictions is called... 134 // THEN false is returned to indicate there was no restriction to enforce 135 assertThat(mBluetoothEnabler.maybeEnforceRestrictions()).isFalse(); 136 137 // THEN a null EnfoceAdmin is set. 138 verify(mSwitchController).setDisabledByAdmin(null); 139 // THEN the state of the switch isn't changed. 140 verify(mSwitchController, never()).setChecked(anyBoolean()); 141 } 142 143 @Test maybeEnforceRestrictions_disallowBluetoothRestrictionSet()144 public void maybeEnforceRestrictions_disallowBluetoothRestrictionSet() { 145 // GIVEN Bluetooth has been disallowed... 146 when(mRestrictionUtils.checkIfRestrictionEnforced( 147 mContext, UserManager.DISALLOW_BLUETOOTH)).thenReturn(sFakeEnforcedAdmin); 148 when(mRestrictionUtils.checkIfRestrictionEnforced( 149 mContext, UserManager.DISALLOW_CONFIG_BLUETOOTH)).thenReturn(null); 150 151 // WHEN the maybeEnforceRestrictions is called... 152 // THEN true is returned to indicate there was a restriction to enforce. 153 assertThat(mBluetoothEnabler.maybeEnforceRestrictions()).isTrue(); 154 155 // THEN the expected EnfoceAdmin is set. 156 verify(mSwitchController).setDisabledByAdmin(sFakeEnforcedAdmin); 157 158 // THEN the switch is unchecked. 159 verify(mSwitchController).setChecked(false); 160 } 161 162 @Test maybeEnforceRestrictions_disallowConfigBluetoothRestrictionSet()163 public void maybeEnforceRestrictions_disallowConfigBluetoothRestrictionSet() { 164 // GIVEN configuring Bluetooth has been disallowed... 165 when(mRestrictionUtils.checkIfRestrictionEnforced( 166 mContext, UserManager.DISALLOW_BLUETOOTH)).thenReturn(null); 167 when(mRestrictionUtils.checkIfRestrictionEnforced( 168 mContext, UserManager.DISALLOW_CONFIG_BLUETOOTH)).thenReturn(sFakeEnforcedAdmin); 169 170 // WHEN the maybeEnforceRestrictions is called... 171 // THEN true is returned to indicate there was a restriction to enforce. 172 assertThat(mBluetoothEnabler.maybeEnforceRestrictions()).isTrue(); 173 174 // THEN the expected EnfoceAdmin is set. 175 verify(mSwitchController).setDisabledByAdmin(sFakeEnforcedAdmin); 176 177 // THEN the switch is unchecked. 178 verify(mSwitchController).setChecked(false); 179 } 180 181 @Test maybeEnforceRestrictions_disallowBluetoothNotOverriden()182 public void maybeEnforceRestrictions_disallowBluetoothNotOverriden() { 183 // GIVEN Bluetooth has been disallowed... 184 when(mRestrictionUtils.checkIfRestrictionEnforced( 185 mContext, UserManager.DISALLOW_BLUETOOTH)).thenReturn(sFakeEnforcedAdmin); 186 when(mRestrictionUtils.checkIfRestrictionEnforced( 187 mContext, UserManager.DISALLOW_CONFIG_BLUETOOTH)).thenReturn(null); 188 189 mBluetoothEnabler.resume(mContext); 190 191 verify(mSwitchController, never()).setEnabled(true); 192 } 193 194 @Test startWithBluetoothOff_switchIsOff()195 public void startWithBluetoothOff_switchIsOff() { 196 when(mBluetoothAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_OFF); 197 verify(mSwitchController, never()).setChecked(anyBoolean()); 198 mBluetoothEnabler.resume(mContext); 199 verify(mSwitchController, never()).setChecked(true); 200 } 201 202 @Test startWithBluetoothOn_switchIsOn()203 public void startWithBluetoothOn_switchIsOn() { 204 when(mBluetoothAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON); 205 verify(mSwitchController, never()).setChecked(anyBoolean()); 206 mBluetoothEnabler.resume(mContext); 207 verify(mSwitchController, never()).setChecked(false); 208 verify(mSwitchController).setChecked(true); 209 } 210 211 @Test bluetoothTurnsOff_switchTurnsOff()212 public void bluetoothTurnsOff_switchTurnsOff() { 213 // Start up with bluetooth turned on. The switch should get turned on. 214 ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class); 215 when(mContext.registerReceiver(captor.capture(), any(IntentFilter.class))).thenReturn(null); 216 when(mBluetoothAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON); 217 verify(mSwitchController, never()).setChecked(anyBoolean()); 218 mBluetoothEnabler.resume(mContext); 219 verify(mSwitchController, never()).setChecked(false); 220 verify(mSwitchController).setChecked(true); 221 222 // Now simulate bluetooth being turned off via an event. 223 BroadcastReceiver receiver = captor.getValue(); 224 Intent turningOff = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); 225 turningOff.putExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_TURNING_OFF); 226 receiver.onReceive(mContext, turningOff); 227 Intent off = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); 228 off.putExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF); 229 receiver.onReceive(mContext, off); 230 231 // Make sure the switch was turned off. 232 verify(mSwitchController).setChecked(false); 233 } 234 235 @Test bluetoothTurnsOn_switchTurnsOn()236 public void bluetoothTurnsOn_switchTurnsOn() { 237 // Start up with bluetooth turned on. The switch should be left off. 238 ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class); 239 when(mContext.registerReceiver(captor.capture(), any(IntentFilter.class))).thenReturn(null); 240 when(mBluetoothAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_OFF); 241 verify(mSwitchController, never()).setChecked(anyBoolean()); 242 mBluetoothEnabler.resume(mContext); 243 verify(mSwitchController, never()).setChecked(anyBoolean()); 244 245 // Now simulate bluetooth being turned on via an event. 246 BroadcastReceiver receiver = captor.getValue(); 247 Intent turningOn = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); 248 turningOn.putExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_TURNING_ON); 249 receiver.onReceive(mContext, turningOn); 250 Intent on = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); 251 on.putExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_ON); 252 receiver.onReceive(mContext, on); 253 254 // Make sure the switch was turned on. 255 verify(mSwitchController).setChecked(true); 256 } 257 } 258