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