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