• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.settings.development;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.Mockito.doReturn;
22 import static org.mockito.Mockito.mock;
23 import static org.mockito.Mockito.spy;
24 import static org.mockito.Mockito.verify;
25 import static org.mockito.Mockito.when;
26 
27 import android.content.Context;
28 import android.provider.SearchIndexableResource;
29 import android.provider.Settings;
30 
31 import androidx.appcompat.app.AlertDialog;
32 import androidx.fragment.app.FragmentActivity;
33 
34 import com.android.internal.logging.nano.MetricsProto;
35 import com.android.settings.R;
36 import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
37 import com.android.settings.widget.SwitchBar;
38 import com.android.settings.widget.ToggleSwitch;
39 import com.android.settingslib.development.AbstractEnableAdbPreferenceController;
40 import com.android.settingslib.development.DevelopmentSettingsEnabler;
41 
42 import org.junit.After;
43 import org.junit.Before;
44 import org.junit.Test;
45 import org.junit.runner.RunWith;
46 import org.mockito.MockitoAnnotations;
47 import org.robolectric.RobolectricTestRunner;
48 import org.robolectric.RuntimeEnvironment;
49 import org.robolectric.annotation.Config;
50 import org.robolectric.annotation.Implementation;
51 import org.robolectric.annotation.Implements;
52 import org.robolectric.shadow.api.Shadow;
53 import org.robolectric.shadows.ShadowUserManager;
54 import org.robolectric.shadows.androidx.fragment.FragmentController;
55 import org.robolectric.util.ReflectionHelpers;
56 
57 import java.util.List;
58 
59 @RunWith(RobolectricTestRunner.class)
60 @Config(shadows = {ShadowUserManager.class, ShadowAlertDialogCompat.class})
61 public class DevelopmentSettingsDashboardFragmentTest {
62 
63     private ToggleSwitch mSwitch;
64     private Context mContext;
65     private ShadowUserManager mShadowUserManager;
66     private DevelopmentSettingsDashboardFragment mDashboard;
67 
68     @Before
setUp()69     public void setUp() {
70         MockitoAnnotations.initMocks(this);
71         mContext = RuntimeEnvironment.application;
72         SwitchBar switchBar = new SwitchBar(mContext);
73         mSwitch = switchBar.getSwitch();
74         mDashboard = spy(new DevelopmentSettingsDashboardFragment());
75         ReflectionHelpers.setField(mDashboard, "mSwitchBar", switchBar);
76         mShadowUserManager = Shadow.extract(mContext.getSystemService(Context.USER_SERVICE));
77         mShadowUserManager.setIsAdminUser(true);
78     }
79 
80     @After
tearDown()81     public void tearDown() {
82         ShadowEnableDevelopmentSettingWarningDialog.reset();
83     }
84 
85     @Test
shouldNotHaveHelpResource()86     public void shouldNotHaveHelpResource() {
87         assertThat(mDashboard.getHelpResource()).isEqualTo(0);
88     }
89 
90     @Test
shouldLogAsFeatureFlagPage()91     public void shouldLogAsFeatureFlagPage() {
92         assertThat(mDashboard.getMetricsCategory())
93                 .isEqualTo(MetricsProto.MetricsEvent.DEVELOPMENT);
94     }
95 
96     @Test
searchIndex_shouldIndexFromPrefXml()97     public void searchIndex_shouldIndexFromPrefXml() {
98         final List<SearchIndexableResource> index =
99                 DevelopmentSettingsDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
100                         .getXmlResourcesToIndex(RuntimeEnvironment.application, true);
101 
102         assertThat(index.size()).isEqualTo(1);
103         assertThat(index.get(0).xmlResId).isEqualTo(R.xml.development_settings);
104     }
105 
106     @Test
searchIndex_pageDisabledBySetting_shouldAddAllKeysToNonIndexable()107     public void searchIndex_pageDisabledBySetting_shouldAddAllKeysToNonIndexable() {
108         final Context appContext = RuntimeEnvironment.application;
109         DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(appContext, false);
110 
111         final List<String> nonIndexableKeys =
112                 DevelopmentSettingsDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
113                         .getNonIndexableKeys(appContext);
114 
115         assertThat(nonIndexableKeys).contains("enable_adb");
116     }
117 
118     @Test
searchIndex_pageDisabledForNonAdmin_shouldAddAllKeysToNonIndexable()119     public void searchIndex_pageDisabledForNonAdmin_shouldAddAllKeysToNonIndexable() {
120         final Context appContext = RuntimeEnvironment.application;
121         DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(appContext, true);
122         mShadowUserManager.setIsAdminUser(false);
123         mShadowUserManager.setIsDemoUser(false);
124 
125         final List<String> nonIndexableKeys =
126                 DevelopmentSettingsDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
127                         .getNonIndexableKeys(appContext);
128 
129         assertThat(nonIndexableKeys).contains("enable_adb");
130     }
131 
132     @Test
133     @Config(shadows = {
134             ShadowPictureColorModePreferenceController.class,
135             ShadowAdbPreferenceController.class,
136             ShadowClearAdbKeysPreferenceController.class,
137             ShadowWirelessDebuggingPreferenceController.class
138     })
searchIndex_pageEnabled_shouldNotAddKeysToNonIndexable()139     public void searchIndex_pageEnabled_shouldNotAddKeysToNonIndexable() {
140         final Context appContext = RuntimeEnvironment.application;
141         DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(appContext, true);
142 
143         final List<String> nonIndexableKeys =
144                 DevelopmentSettingsDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
145                         .getNonIndexableKeys(appContext);
146 
147         assertThat(nonIndexableKeys).doesNotContain("development_prefs_screen");
148     }
149 
150     @Test
151     @Config(shadows = ShadowEnableDevelopmentSettingWarningDialog.class)
onSwitchChanged_sameState_shouldDoNothing()152     public void onSwitchChanged_sameState_shouldDoNothing() {
153         when(mDashboard.getContext()).thenReturn(mContext);
154         Settings.Global.putInt(mContext.getContentResolver(),
155                 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0);
156 
157         mDashboard.onSwitchChanged(mSwitch, false /* isChecked */);
158         assertThat(ShadowEnableDevelopmentSettingWarningDialog.mShown).isFalse();
159     }
160 
161     @Test
162     @Config(shadows = ShadowEnableDevelopmentSettingWarningDialog.class)
onSwitchChanged_turnOn_shouldShowWarningDialog()163     public void onSwitchChanged_turnOn_shouldShowWarningDialog() {
164         when(mDashboard.getContext()).thenReturn(mContext);
165         Settings.Global.putInt(mContext.getContentResolver(),
166                 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0);
167 
168         mDashboard.onSwitchChanged(mSwitch, true /* isChecked */);
169         assertThat(ShadowEnableDevelopmentSettingWarningDialog.mShown).isTrue();
170     }
171 
172     @Test
173     @Config(shadows = ShadowEnableDevelopmentSettingWarningDialog.class)
onSwitchChanged_turnOff_shouldTurnOff()174     public void onSwitchChanged_turnOff_shouldTurnOff() {
175         when(mDashboard.getContext()).thenReturn(mContext);
176         Settings.Global.putInt(mContext.getContentResolver(),
177                 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
178 
179         mDashboard.onSwitchChanged(mSwitch, false /* isChecked */);
180 
181         assertThat(ShadowEnableDevelopmentSettingWarningDialog.mShown).isFalse();
182         assertThat(DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)).isFalse();
183     }
184 
185     @Test
186     @Config(shadows = ShadowDisableDevSettingsDialogFragment.class)
onSwitchChanged_turnOff_andOffloadIsNotDefaultValue_shouldShowWarningDialog()187     public void onSwitchChanged_turnOff_andOffloadIsNotDefaultValue_shouldShowWarningDialog() {
188         final BluetoothA2dpHwOffloadPreferenceController controller =
189                 mock(BluetoothA2dpHwOffloadPreferenceController.class);
190         when(mDashboard.getContext()).thenReturn(mContext);
191         when(mDashboard.getDevelopmentOptionsController(
192                 BluetoothA2dpHwOffloadPreferenceController.class)).thenReturn(controller);
193         when(controller.isDefaultValue()).thenReturn(false);
194         Settings.Global.putInt(mContext.getContentResolver(),
195                 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
196 
197         mDashboard.onSwitchChanged(mSwitch, false /* isChecked */);
198 
199         AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
200         assertThat(dialog).isNotNull();
201         ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
202         assertThat(shadowDialog.getTitle()).isEqualTo(
203                 mContext.getString(R.string.bluetooth_disable_a2dp_hw_offload_dialog_title));
204         assertThat(shadowDialog.getMessage()).isEqualTo(
205                 mContext.getString(R.string.bluetooth_disable_a2dp_hw_offload_dialog_message));
206     }
207 
208     @Test
onOemUnlockDialogConfirmed_shouldCallControllerOemConfirmed()209     public void onOemUnlockDialogConfirmed_shouldCallControllerOemConfirmed() {
210         final OemUnlockPreferenceController controller = mock(OemUnlockPreferenceController.class);
211         doReturn(controller).when(mDashboard)
212                 .getDevelopmentOptionsController(OemUnlockPreferenceController.class);
213         mDashboard.onOemUnlockDialogConfirmed();
214         verify(controller).onOemUnlockConfirmed();
215     }
216 
217     @Test
onOemUnlockDialogConfirmed_shouldCallControllerOemDismissed()218     public void onOemUnlockDialogConfirmed_shouldCallControllerOemDismissed() {
219         final OemUnlockPreferenceController controller = mock(OemUnlockPreferenceController.class);
220         doReturn(controller).when(mDashboard)
221                 .getDevelopmentOptionsController(OemUnlockPreferenceController.class);
222         mDashboard.onOemUnlockDialogDismissed();
223         verify(controller).onOemUnlockDismissed();
224     }
225 
226     @Test
onAdbDialogConfirmed_shouldCallControllerDialogConfirmed()227     public void onAdbDialogConfirmed_shouldCallControllerDialogConfirmed() {
228         final AdbPreferenceController controller = mock(AdbPreferenceController.class);
229         doReturn(controller).when(mDashboard)
230                 .getDevelopmentOptionsController(AdbPreferenceController.class);
231         mDashboard.onEnableAdbDialogConfirmed();
232 
233         verify(controller).onAdbDialogConfirmed();
234     }
235 
236     @Test
onAdbDialogDismissed_shouldCallControllerOemDismissed()237     public void onAdbDialogDismissed_shouldCallControllerOemDismissed() {
238         final AdbPreferenceController controller = mock(AdbPreferenceController.class);
239         doReturn(controller).when(mDashboard)
240                 .getDevelopmentOptionsController(AdbPreferenceController.class);
241         mDashboard.onEnableAdbDialogDismissed();
242 
243         verify(controller).onAdbDialogDismissed();
244     }
245 
246     @Test
onAdbClearKeysDialogConfirmed_shouldCallControllerDialogConfirmed()247     public void onAdbClearKeysDialogConfirmed_shouldCallControllerDialogConfirmed() {
248         final ClearAdbKeysPreferenceController controller =
249                 mock(ClearAdbKeysPreferenceController.class);
250         doReturn(controller).when(mDashboard)
251                 .getDevelopmentOptionsController(ClearAdbKeysPreferenceController.class);
252         mDashboard.onAdbClearKeysDialogConfirmed();
253 
254         verify(controller).onClearAdbKeysConfirmed();
255     }
256 
257     @Test
onDisableLogPersistDialogConfirmed_shouldCallControllerDialogConfirmed()258     public void onDisableLogPersistDialogConfirmed_shouldCallControllerDialogConfirmed() {
259         final LogPersistPreferenceController controller =
260                 mock(LogPersistPreferenceController.class);
261         doReturn(controller).when(mDashboard)
262                 .getDevelopmentOptionsController(LogPersistPreferenceController.class);
263         mDashboard.onDisableLogPersistDialogConfirmed();
264 
265         verify(controller).onDisableLogPersistDialogConfirmed();
266     }
267 
268     @Test
onDisableLogPersistDialogRejected_shouldCallControllerDialogRejected()269     public void onDisableLogPersistDialogRejected_shouldCallControllerDialogRejected() {
270         final LogPersistPreferenceController controller =
271                 mock(LogPersistPreferenceController.class);
272         doReturn(controller).when(mDashboard)
273                 .getDevelopmentOptionsController(LogPersistPreferenceController.class);
274         mDashboard.onDisableLogPersistDialogRejected();
275 
276         verify(controller).onDisableLogPersistDialogRejected();
277     }
278 
279     @Implements(EnableDevelopmentSettingWarningDialog.class)
280     public static class ShadowEnableDevelopmentSettingWarningDialog {
281 
282         static boolean mShown;
283 
reset()284         public static void reset() {
285             mShown = false;
286         }
287 
288         @Implementation
show(DevelopmentSettingsDashboardFragment host)289         protected static void show(DevelopmentSettingsDashboardFragment host) {
290             mShown = true;
291         }
292     }
293 
294     @Implements(DisableDevSettingsDialogFragment.class)
295     public static class ShadowDisableDevSettingsDialogFragment {
296 
297         @Implementation
show(DevelopmentSettingsDashboardFragment host)298         public static void show(DevelopmentSettingsDashboardFragment host) {
299             DisableDevSettingsDialogFragment mFragment =
300                     spy(DisableDevSettingsDialogFragment.newInstance());
301             FragmentController.setupFragment(mFragment, FragmentActivity.class,
302                     0 /* containerViewId */, null /* bundle */);
303         }
304     }
305 
306     @Implements(PictureColorModePreferenceController.class)
307     public static class ShadowPictureColorModePreferenceController {
308         @Implementation
isAvailable()309         protected boolean isAvailable() {
310             return true;
311         }
312     }
313 
314     @Implements(AbstractEnableAdbPreferenceController.class)
315     public static class ShadowAdbPreferenceController {
316         @Implementation
isAvailable()317         protected boolean isAvailable() {
318             return true;
319         }
320     }
321 
322     @Implements(ClearAdbKeysPreferenceController.class)
323     public static class ShadowClearAdbKeysPreferenceController {
324         @Implementation
isAvailable()325         protected boolean isAvailable() {
326             return true;
327         }
328     }
329 
330     @Implements(WirelessDebuggingPreferenceController.class)
331     public static class ShadowWirelessDebuggingPreferenceController {
332         @Implementation
isAvailable()333         protected boolean isAvailable() {
334             return true;
335         }
336     }
337 }
338