1 /* 2 * Copyright (C) 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 17 package com.android.settings; 18 19 import static android.content.Intent.ACTION_MEDIA_SHARED; 20 import static android.content.Intent.ACTION_MEDIA_UNSHARED; 21 import static android.hardware.usb.UsbManager.ACTION_USB_STATE; 22 23 import static com.google.common.truth.Truth.assertThat; 24 25 import static org.mockito.ArgumentMatchers.any; 26 import static org.mockito.ArgumentMatchers.anyInt; 27 import static org.mockito.Mockito.doNothing; 28 import static org.mockito.Mockito.doReturn; 29 import static org.mockito.Mockito.mock; 30 import static org.mockito.Mockito.never; 31 import static org.mockito.Mockito.spy; 32 import static org.mockito.Mockito.times; 33 import static org.mockito.Mockito.verify; 34 import static org.mockito.Mockito.when; 35 36 import android.bluetooth.BluetoothAdapter; 37 import android.bluetooth.BluetoothPan; 38 import android.content.BroadcastReceiver; 39 import android.content.Context; 40 import android.content.Intent; 41 import android.content.IntentFilter; 42 import android.hardware.usb.UsbManager; 43 import android.net.ConnectivityManager; 44 import android.net.TetheringManager; 45 import android.net.wifi.WifiManager; 46 import android.os.UserHandle; 47 import android.os.UserManager; 48 import android.util.FeatureFlagUtils; 49 50 import androidx.fragment.app.FragmentActivity; 51 import androidx.preference.Preference; 52 import androidx.preference.SwitchPreference; 53 54 import com.android.settings.core.FeatureFlags; 55 import com.android.settingslib.RestrictedSwitchPreference; 56 57 import org.junit.Before; 58 import org.junit.Test; 59 import org.junit.runner.RunWith; 60 import org.mockito.ArgumentCaptor; 61 import org.mockito.Mock; 62 import org.mockito.MockitoAnnotations; 63 import org.robolectric.RobolectricTestRunner; 64 import org.robolectric.RuntimeEnvironment; 65 66 import java.util.ArrayList; 67 import java.util.List; 68 69 @RunWith(RobolectricTestRunner.class) 70 public class TetherSettingsTest { 71 72 private Context mContext; 73 74 @Mock 75 private ConnectivityManager mConnectivityManager; 76 @Mock 77 private UserManager mUserManager; 78 @Mock 79 private TetheringManager mTetheringManager; 80 81 @Before setUp()82 public void setUp() throws Exception { 83 mContext = spy(RuntimeEnvironment.application); 84 85 MockitoAnnotations.initMocks(this); 86 doReturn(mConnectivityManager) 87 .when(mContext).getSystemService(Context.CONNECTIVITY_SERVICE); 88 doReturn(mUserManager) 89 .when(mContext).getSystemService(Context.USER_SERVICE); 90 doReturn(mTetheringManager) 91 .when(mContext).getSystemService(Context.TETHERING_SERVICE); 92 doReturn(mContext).when(mContext).createPackageContextAsUser( 93 any(String.class), anyInt(), any(UserHandle.class)); 94 95 setupIsTetherAvailable(true); 96 97 when(mTetheringManager.getTetherableUsbRegexs()).thenReturn(new String[0]); 98 when(mTetheringManager.getTetherableBluetoothRegexs()).thenReturn(new String[0]); 99 } 100 101 @Test testTetherNonIndexableKeys_tetherAvailable_keysNotReturned()102 public void testTetherNonIndexableKeys_tetherAvailable_keysNotReturned() { 103 FeatureFlagUtils.setEnabled(mContext, FeatureFlags.TETHER_ALL_IN_ONE, false); 104 // To let TetherUtil.isTetherAvailable return true, select one of the combinations 105 setupIsTetherAvailable(true); 106 107 final List<String> niks = 108 TetherSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext); 109 110 assertThat(niks).doesNotContain(TetherSettings.KEY_TETHER_PREFS_SCREEN); 111 assertThat(niks).doesNotContain(TetherSettings.KEY_WIFI_TETHER); 112 } 113 114 @Test testTetherNonIndexableKeys_tetherNotAvailable_keysReturned()115 public void testTetherNonIndexableKeys_tetherNotAvailable_keysReturned() { 116 // To let TetherUtil.isTetherAvailable return false, select one of the combinations 117 setupIsTetherAvailable(false); 118 119 final List<String> niks = 120 TetherSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext); 121 122 assertThat(niks).contains(TetherSettings.KEY_TETHER_PREFS_SCREEN); 123 assertThat(niks).contains(TetherSettings.KEY_WIFI_TETHER); 124 } 125 126 @Test testTetherNonIndexableKeys_usbNotAvailable_usbKeyReturned()127 public void testTetherNonIndexableKeys_usbNotAvailable_usbKeyReturned() { 128 when(mTetheringManager.getTetherableUsbRegexs()).thenReturn(new String[0]); 129 130 final List<String> niks = 131 TetherSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext); 132 133 assertThat(niks).contains(TetherSettings.KEY_USB_TETHER_SETTINGS); 134 } 135 136 @Test testTetherNonIndexableKeys_usbAvailable_usbKeyNotReturned()137 public void testTetherNonIndexableKeys_usbAvailable_usbKeyNotReturned() { 138 FeatureFlagUtils.setEnabled(mContext, FeatureFlags.TETHER_ALL_IN_ONE, false); 139 // We can ignore the condition of Utils.isMonkeyRunning() 140 // In normal case, monkey and robotest should not execute at the same time 141 when(mTetheringManager.getTetherableUsbRegexs()).thenReturn(new String[]{"fakeRegex"}); 142 143 final List<String> niks = 144 TetherSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext); 145 146 assertThat(niks).doesNotContain(TetherSettings.KEY_USB_TETHER_SETTINGS); 147 } 148 149 @Test testTetherNonIndexableKeys_bluetoothNotAvailable_bluetoothKeyReturned()150 public void testTetherNonIndexableKeys_bluetoothNotAvailable_bluetoothKeyReturned() { 151 when(mTetheringManager.getTetherableBluetoothRegexs()).thenReturn(new String[0]); 152 153 final List<String> niks = 154 TetherSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext); 155 156 assertThat(niks).contains(TetherSettings.KEY_ENABLE_BLUETOOTH_TETHERING); 157 } 158 159 @Test testTetherNonIndexableKeys_bluetoothAvailable_bluetoothKeyNotReturned()160 public void testTetherNonIndexableKeys_bluetoothAvailable_bluetoothKeyNotReturned() { 161 FeatureFlagUtils.setEnabled(mContext, FeatureFlags.TETHER_ALL_IN_ONE, false); 162 when(mTetheringManager.getTetherableBluetoothRegexs()) 163 .thenReturn(new String[]{"fakeRegex"}); 164 165 final List<String> niks = 166 TetherSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext); 167 168 assertThat(niks).doesNotContain(TetherSettings.KEY_ENABLE_BLUETOOTH_TETHERING); 169 } 170 171 @Test testSetFooterPreferenceTitle_isStaApConcurrencySupported_showStaApString()172 public void testSetFooterPreferenceTitle_isStaApConcurrencySupported_showStaApString() { 173 final TetherSettings spyTetherSettings = spy(new TetherSettings()); 174 spyTetherSettings.mContext = mContext; 175 final Preference mockPreference = mock(Preference.class); 176 when(spyTetherSettings.findPreference(TetherSettings.KEY_TETHER_PREFS_TOP_INTRO)) 177 .thenReturn(mockPreference); 178 final WifiManager mockWifiManager = mock(WifiManager.class); 179 when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mockWifiManager); 180 when(mockWifiManager.isStaApConcurrencySupported()).thenReturn(true); 181 182 spyTetherSettings.setTopIntroPreferenceTitle(); 183 184 verify(mockPreference, never()).setTitle(R.string.tethering_footer_info); 185 verify(mockPreference).setTitle(R.string.tethering_footer_info_sta_ap_concurrency); 186 } 187 188 @Test testBluetoothState_updateBluetoothState_bluetoothTetheringStateOn()189 public void testBluetoothState_updateBluetoothState_bluetoothTetheringStateOn() { 190 final TetherSettings spyTetherSettings = spy(new TetherSettings()); 191 spyTetherSettings.mContext = mContext; 192 spyTetherSettings.mTm = mTetheringManager; 193 final SwitchPreference mockSwitchPreference = mock(SwitchPreference.class); 194 when(spyTetherSettings.findPreference(TetherSettings.KEY_ENABLE_BLUETOOTH_TETHERING)) 195 .thenReturn(mockSwitchPreference); 196 final FragmentActivity mockActivity = mock(FragmentActivity.class); 197 when(spyTetherSettings.getActivity()).thenReturn(mockActivity); 198 final ArgumentCaptor<BroadcastReceiver> captor = 199 ArgumentCaptor.forClass(BroadcastReceiver.class); 200 when(mockActivity.registerReceiver(captor.capture(), any(IntentFilter.class))) 201 .thenReturn(null); 202 // Bluetooth tethering state is on 203 when(spyTetherSettings.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON); 204 when(spyTetherSettings.isBluetoothTetheringOn()).thenReturn(true); 205 206 spyTetherSettings.setupTetherPreference(); 207 spyTetherSettings.registerReceiver(); 208 updateOnlyBluetoothState(spyTetherSettings); 209 210 // Simulate Bluetooth tethering state changed 211 final BroadcastReceiver receiver = captor.getValue(); 212 final Intent bluetoothTetheringOn = new Intent(BluetoothPan.ACTION_TETHERING_STATE_CHANGED); 213 bluetoothTetheringOn.putExtra(BluetoothPan.EXTRA_TETHERING_STATE, 214 BluetoothPan.TETHERING_STATE_ON); 215 receiver.onReceive(mockActivity, bluetoothTetheringOn); 216 217 verify(mockSwitchPreference).setEnabled(true); 218 verify(mockSwitchPreference).setChecked(true); 219 } 220 221 @Test testBluetoothState_updateBluetoothState_bluetoothTetheringStateOff()222 public void testBluetoothState_updateBluetoothState_bluetoothTetheringStateOff() { 223 final TetherSettings spyTetherSettings = spy(new TetherSettings()); 224 spyTetherSettings.mContext = mContext; 225 spyTetherSettings.mTm = mTetheringManager; 226 final SwitchPreference mockSwitchPreference = mock(SwitchPreference.class); 227 when(spyTetherSettings.findPreference(TetherSettings.KEY_ENABLE_BLUETOOTH_TETHERING)) 228 .thenReturn(mockSwitchPreference); 229 final FragmentActivity mockActivity = mock(FragmentActivity.class); 230 when(spyTetherSettings.getActivity()).thenReturn(mockActivity); 231 final ArgumentCaptor<BroadcastReceiver> captor = 232 ArgumentCaptor.forClass(BroadcastReceiver.class); 233 when(mockActivity.registerReceiver(captor.capture(), any(IntentFilter.class))) 234 .thenReturn(null); 235 // Bluetooth tethering state is off 236 when(spyTetherSettings.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON); 237 when(spyTetherSettings.isBluetoothTetheringOn()).thenReturn(false); 238 239 spyTetherSettings.setupTetherPreference(); 240 spyTetherSettings.registerReceiver(); 241 updateOnlyBluetoothState(spyTetherSettings); 242 243 // Simulate Bluetooth tethering state changed 244 final BroadcastReceiver receiver = captor.getValue(); 245 final Intent bluetoothTetheringOn = new Intent(BluetoothPan.ACTION_TETHERING_STATE_CHANGED); 246 bluetoothTetheringOn.putExtra(BluetoothPan.EXTRA_TETHERING_STATE, 247 BluetoothPan.TETHERING_STATE_ON); 248 receiver.onReceive(mockActivity, bluetoothTetheringOn); 249 250 verify(mockSwitchPreference).setEnabled(true); 251 verify(mockSwitchPreference).setChecked(false); 252 } 253 254 @Test updateState_usbTetheringIsEnabled_checksUsbTethering()255 public void updateState_usbTetheringIsEnabled_checksUsbTethering() { 256 String [] tethered = {"rndis0"}; 257 TetherSettings spyTetherSettings = spy(new TetherSettings()); 258 RestrictedSwitchPreference tetheringPreference = mock(RestrictedSwitchPreference.class); 259 when(spyTetherSettings.findPreference(TetherSettings.KEY_USB_TETHER_SETTINGS)) 260 .thenReturn(tetheringPreference); 261 spyTetherSettings.mContext = mContext; 262 spyTetherSettings.mTm = mTetheringManager; 263 spyTetherSettings.setupTetherPreference(); 264 spyTetherSettings.mUsbRegexs = tethered; 265 266 spyTetherSettings.updateUsbState(tethered); 267 268 verify(tetheringPreference).setEnabled(true); 269 verify(tetheringPreference).setChecked(true); 270 } 271 272 @Test updateState_usbTetheringIsDisabled_unchecksUsbTethering()273 public void updateState_usbTetheringIsDisabled_unchecksUsbTethering() { 274 String [] tethered = {"rndis0"}; 275 TetherSettings spyTetherSettings = spy(new TetherSettings()); 276 RestrictedSwitchPreference tetheringPreference = mock(RestrictedSwitchPreference.class); 277 when(spyTetherSettings.findPreference(TetherSettings.KEY_USB_TETHER_SETTINGS)) 278 .thenReturn(tetheringPreference); 279 spyTetherSettings.mContext = mContext; 280 spyTetherSettings.mTm = mTetheringManager; 281 spyTetherSettings.setupTetherPreference(); 282 spyTetherSettings.mUsbRegexs = tethered; 283 284 spyTetherSettings.updateUsbState(new String[0]); 285 286 verify(tetheringPreference).setEnabled(false); 287 verify(tetheringPreference).setChecked(false); 288 } 289 290 @Test onReceive_usbIsConnected_tetheringPreferenceIsEnabled()291 public void onReceive_usbIsConnected_tetheringPreferenceIsEnabled() { 292 RestrictedSwitchPreference tetheringPreference = mock(RestrictedSwitchPreference.class); 293 FragmentActivity mockActivity = mock(FragmentActivity.class); 294 ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class); 295 setupUsbStateComponents(tetheringPreference, captor, mockActivity); 296 297 BroadcastReceiver receiver = captor.getValue(); 298 Intent usbStateChanged = new Intent(ACTION_USB_STATE); 299 usbStateChanged.putExtra(UsbManager.USB_CONNECTED, true); 300 receiver.onReceive(mockActivity, usbStateChanged); 301 302 verify(tetheringPreference).setEnabled(true); 303 } 304 305 @Test onReceive_usbIsDisconnected_tetheringPreferenceIsDisabled()306 public void onReceive_usbIsDisconnected_tetheringPreferenceIsDisabled() { 307 RestrictedSwitchPreference tetheringPreference = mock(RestrictedSwitchPreference.class); 308 FragmentActivity mockActivity = mock(FragmentActivity.class); 309 ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class); 310 setupUsbStateComponents(tetheringPreference, captor, mockActivity); 311 312 BroadcastReceiver receiver = captor.getValue(); 313 Intent usbStateChanged = new Intent(ACTION_USB_STATE); 314 usbStateChanged.putExtra(UsbManager.USB_CONNECTED, false); 315 receiver.onReceive(mockActivity, usbStateChanged); 316 317 verify(tetheringPreference).setEnabled(false); 318 } 319 320 @Test onReceive_mediaIsShared_tetheringPreferenceIsDisabled()321 public void onReceive_mediaIsShared_tetheringPreferenceIsDisabled() { 322 RestrictedSwitchPreference tetheringPreference = mock(RestrictedSwitchPreference.class); 323 FragmentActivity mockActivity = mock(FragmentActivity.class); 324 ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class); 325 setupUsbStateComponents(tetheringPreference, captor, mockActivity); 326 327 BroadcastReceiver receiver = captor.getValue(); 328 Intent mediaIsShared = new Intent(ACTION_MEDIA_SHARED); 329 receiver.onReceive(mockActivity, mediaIsShared); 330 331 verify(tetheringPreference).setEnabled(false); 332 } 333 334 @Test onReceive_mediaIsUnshared_tetheringPreferenceIsEnabled()335 public void onReceive_mediaIsUnshared_tetheringPreferenceIsEnabled() { 336 RestrictedSwitchPreference tetheringPreference = mock(RestrictedSwitchPreference.class); 337 FragmentActivity mockActivity = mock(FragmentActivity.class); 338 ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class); 339 setupUsbStateComponents(tetheringPreference, captor, mockActivity); 340 341 BroadcastReceiver receiver = captor.getValue(); 342 Intent mediaIsShared = new Intent(ACTION_MEDIA_UNSHARED); 343 Intent usbStateChanged = new Intent(ACTION_USB_STATE); 344 usbStateChanged.putExtra(UsbManager.USB_CONNECTED, true); 345 receiver.onReceive(mockActivity, usbStateChanged); 346 receiver.onReceive(mockActivity, mediaIsShared); 347 348 verify(tetheringPreference, times(2)).setEnabled(true); 349 } 350 updateOnlyBluetoothState(TetherSettings tetherSettings)351 private void updateOnlyBluetoothState(TetherSettings tetherSettings) { 352 doReturn(mTetheringManager).when(tetherSettings) 353 .getSystemService(Context.TETHERING_SERVICE); 354 when(mTetheringManager.getTetherableIfaces()).thenReturn(new String[0]); 355 when(mTetheringManager.getTetheredIfaces()).thenReturn(new String[0]); 356 when(mTetheringManager.getTetheringErroredIfaces()).thenReturn(new String[0]); 357 doNothing().when(tetherSettings).updateUsbState(any(String[].class)); 358 doNothing().when(tetherSettings).updateEthernetState(any(String[].class), 359 any(String[].class)); 360 } 361 setupIsTetherAvailable(boolean returnValue)362 private void setupIsTetherAvailable(boolean returnValue) { 363 when(mConnectivityManager.isTetheringSupported()).thenReturn(true); 364 365 // For RestrictedLockUtils.checkIfRestrictionEnforced 366 final int userId = UserHandle.myUserId(); 367 List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>(); 368 when(mUserManager.getUserRestrictionSources( 369 UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.of(userId))) 370 .thenReturn(enforcingUsers); 371 372 // For RestrictedLockUtils.hasBaseUserRestriction 373 when(mUserManager.hasBaseUserRestriction( 374 UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.of(userId))) 375 .thenReturn(!returnValue); 376 } 377 setupUsbStateComponents(RestrictedSwitchPreference preference, ArgumentCaptor<BroadcastReceiver> captor, FragmentActivity activity)378 private void setupUsbStateComponents(RestrictedSwitchPreference preference, 379 ArgumentCaptor<BroadcastReceiver> captor, FragmentActivity activity) { 380 TetherSettings spyTetherSettings = spy(new TetherSettings()); 381 SwitchPreference mockSwitchPreference = mock(SwitchPreference.class); 382 383 when(spyTetherSettings.findPreference(TetherSettings.KEY_USB_TETHER_SETTINGS)) 384 .thenReturn(preference); 385 when(spyTetherSettings.findPreference(TetherSettings.KEY_ENABLE_BLUETOOTH_TETHERING)) 386 .thenReturn(mockSwitchPreference); 387 spyTetherSettings.mContext = mContext; 388 spyTetherSettings.mTm = mTetheringManager; 389 when(spyTetherSettings.getActivity()).thenReturn(activity); 390 when(activity.registerReceiver(captor.capture(), any(IntentFilter.class))) 391 .thenReturn(null); 392 393 spyTetherSettings.setupTetherPreference(); 394 spyTetherSettings.registerReceiver(); 395 updateOnlyBluetoothState(spyTetherSettings); 396 } 397 } 398