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.google.common.truth.Truth.assertThat; 19 20 import static org.mockito.Mockito.doReturn; 21 import static org.mockito.Mockito.never; 22 import static org.mockito.Mockito.spy; 23 import static org.mockito.Mockito.verify; 24 import static org.mockito.Mockito.when; 25 26 import android.bluetooth.BluetoothAdapter; 27 import android.content.BroadcastReceiver; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.content.pm.PackageManager; 31 import android.text.BidiFormatter; 32 import android.text.TextUtils; 33 34 import com.android.settings.R; 35 import com.android.settings.bluetooth.AlwaysDiscoverable; 36 import com.android.settings.core.BasePreferenceController; 37 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; 38 import com.android.settingslib.widget.FooterPreference; 39 40 import org.junit.Before; 41 import org.junit.Test; 42 import org.junit.runner.RunWith; 43 import org.mockito.Mock; 44 import org.mockito.MockitoAnnotations; 45 import org.robolectric.RobolectricTestRunner; 46 import org.robolectric.RuntimeEnvironment; 47 import org.robolectric.Shadows; 48 import org.robolectric.annotation.Config; 49 import org.robolectric.shadows.ShadowApplication; 50 import org.robolectric.util.ReflectionHelpers; 51 52 import java.util.ArrayList; 53 import java.util.List; 54 55 @RunWith(RobolectricTestRunner.class) 56 @Config(shadows = ShadowBluetoothAdapter.class) 57 public class DiscoverableFooterPreferenceControllerTest { 58 59 private static final String DEVICE_NAME = "device name"; 60 61 @Mock 62 private PackageManager mPackageManager; 63 @Mock 64 private AlwaysDiscoverable mAlwaysDiscoverable; 65 66 private Context mContext; 67 private FooterPreference mPreference; 68 private DiscoverableFooterPreferenceController mDiscoverableFooterPreferenceController; 69 private BroadcastReceiver mBluetoothChangedReceiver; 70 private ShadowApplication mShadowApplication; 71 72 @Before setUp()73 public void setUp() { 74 MockitoAnnotations.initMocks(this); 75 mShadowApplication = Shadows.shadowOf(RuntimeEnvironment.application); 76 mContext = spy(RuntimeEnvironment.application); 77 78 doReturn(mPackageManager).when(mContext).getPackageManager(); 79 mDiscoverableFooterPreferenceController = 80 new DiscoverableFooterPreferenceController(mContext, "key"); 81 mPreference = new FooterPreference(mContext); 82 ReflectionHelpers 83 .setField(mDiscoverableFooterPreferenceController, "mPreference", mPreference); 84 ReflectionHelpers 85 .setField(mDiscoverableFooterPreferenceController, 86 "mAlwaysDiscoverable", mAlwaysDiscoverable); 87 mBluetoothChangedReceiver = mDiscoverableFooterPreferenceController 88 .mBluetoothChangedReceiver; 89 } 90 91 @Test getAvailabilityStatus_noBluetoothFeature_returnUnSupported()92 public void getAvailabilityStatus_noBluetoothFeature_returnUnSupported() { 93 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)).thenReturn(false); 94 95 assertThat(mDiscoverableFooterPreferenceController.getAvailabilityStatus()).isEqualTo( 96 BasePreferenceController.UNSUPPORTED_ON_DEVICE); 97 } 98 99 @Test getAvailabilityStatus_BluetoothFeature_returnAvailableUnsearchable()100 public void getAvailabilityStatus_BluetoothFeature_returnAvailableUnsearchable() { 101 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)).thenReturn(true); 102 103 assertThat(mDiscoverableFooterPreferenceController.getAvailabilityStatus()).isEqualTo( 104 BasePreferenceController.AVAILABLE_UNSEARCHABLE); 105 } 106 107 @Test onStart_setAlwaysDiscoverableAsTrue_shouldRegisterBluetoothChanged()108 public void onStart_setAlwaysDiscoverableAsTrue_shouldRegisterBluetoothChanged() { 109 mDiscoverableFooterPreferenceController.setAlwaysDiscoverable(true); 110 mDiscoverableFooterPreferenceController.onStart(); 111 112 assertThat(getRegisteredBroadcastReceivers()).contains(mBluetoothChangedReceiver); 113 verify(mAlwaysDiscoverable).start(); 114 } 115 116 @Test onStop_setAlwaysDiscoverableAsTrue_shouldUnregisterBluetoothChanged()117 public void onStop_setAlwaysDiscoverableAsTrue_shouldUnregisterBluetoothChanged() { 118 mDiscoverableFooterPreferenceController.setAlwaysDiscoverable(true); 119 mDiscoverableFooterPreferenceController.onStart(); 120 mDiscoverableFooterPreferenceController.onStop(); 121 122 assertThat(getRegisteredBroadcastReceivers()).doesNotContain(mBluetoothChangedReceiver); 123 verify(mAlwaysDiscoverable).stop(); 124 } 125 126 @Test onStart_setAlwaysDiscoverableAsFalse_shouldNotRegisterBluetoothChanged()127 public void onStart_setAlwaysDiscoverableAsFalse_shouldNotRegisterBluetoothChanged() { 128 mDiscoverableFooterPreferenceController.setAlwaysDiscoverable(false); 129 mDiscoverableFooterPreferenceController.onStart(); 130 131 assertThat(getRegisteredBroadcastReceivers()).contains(mBluetoothChangedReceiver); 132 verify(mAlwaysDiscoverable, never()).start(); 133 } 134 135 @Test onStop_setAlwaysDiscoverableAsFalse_shouldNotUnregisterBluetoothChanged()136 public void onStop_setAlwaysDiscoverableAsFalse_shouldNotUnregisterBluetoothChanged() { 137 mDiscoverableFooterPreferenceController.setAlwaysDiscoverable(false); 138 mDiscoverableFooterPreferenceController.onStart(); 139 mDiscoverableFooterPreferenceController.onStop(); 140 141 assertThat(getRegisteredBroadcastReceivers()).doesNotContain(mBluetoothChangedReceiver); 142 verify(mAlwaysDiscoverable, never()).stop(); 143 } 144 145 @Test onBluetoothStateChanged_bluetoothOn_updateTitle()146 public void onBluetoothStateChanged_bluetoothOn_updateTitle() { 147 BluetoothAdapter.getDefaultAdapter().setName(DEVICE_NAME); 148 sendBluetoothStateChangedIntent(BluetoothAdapter.STATE_ON); 149 150 assertThat(mPreference.getTitle()).isEqualTo(generateTitle(DEVICE_NAME)); 151 } 152 153 @Test onBluetoothStateChanged_bluetoothOff_updateTitle()154 public void onBluetoothStateChanged_bluetoothOff_updateTitle() { 155 BluetoothAdapter.getDefaultAdapter().setName(DEVICE_NAME); 156 sendBluetoothStateChangedIntent(BluetoothAdapter.STATE_OFF); 157 158 assertThat(mPreference.getTitle()).isEqualTo(generateTitle(null)); 159 } 160 161 @Test onStart_localBluetoothManagerNull_shouldNotCrash()162 public void onStart_localBluetoothManagerNull_shouldNotCrash() { 163 mDiscoverableFooterPreferenceController.mLocalManager = null; 164 165 // Shouldn't crash 166 mDiscoverableFooterPreferenceController.onStart(); 167 } 168 169 @Test onStop_localBluetoothManagerNull_shouldNotCrash()170 public void onStop_localBluetoothManagerNull_shouldNotCrash() { 171 mDiscoverableFooterPreferenceController.mLocalManager = null; 172 173 // Shouldn't crash 174 mDiscoverableFooterPreferenceController.onStop(); 175 } 176 generateTitle(String deviceName)177 private CharSequence generateTitle(String deviceName) { 178 if (deviceName == null) { 179 return mContext.getString(R.string.bluetooth_off_footer); 180 181 } else { 182 return TextUtils.expandTemplate( 183 mContext.getText(R.string.bluetooth_device_name_summary), 184 BidiFormatter.getInstance().unicodeWrap(deviceName)); 185 } 186 } 187 sendBluetoothStateChangedIntent(int state)188 private void sendBluetoothStateChangedIntent(int state) { 189 Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); 190 intent.putExtra(BluetoothAdapter.EXTRA_STATE, state); 191 mBluetoothChangedReceiver.onReceive(mContext, intent); 192 } 193 194 /** 195 * Return a list of all the registered broadcast receivers 196 */ getRegisteredBroadcastReceivers()197 private List<BroadcastReceiver> getRegisteredBroadcastReceivers() { 198 List<BroadcastReceiver> registeredBroadcastReceivers = new ArrayList<>(); 199 List<ShadowApplication.Wrapper> registeredReceivers = 200 mShadowApplication.getRegisteredReceivers(); 201 for (ShadowApplication.Wrapper wrapper : registeredReceivers) { 202 registeredBroadcastReceivers.add(wrapper.getBroadcastReceiver()); 203 } 204 return registeredBroadcastReceivers; 205 } 206 }