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