• 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.shadows.androidx.fragment.FragmentController;
53 import org.robolectric.shadow.api.Shadow;
54 import org.robolectric.shadows.ShadowUserManager;
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     })
searchIndex_pageEnabled_shouldNotAddKeysToNonIndexable()138     public void searchIndex_pageEnabled_shouldNotAddKeysToNonIndexable() {
139         final Context appContext = RuntimeEnvironment.application;
140         DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(appContext, true);
141 
142         final List<String> nonIndexableKeys =
143                 DevelopmentSettingsDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
144                         .getNonIndexableKeys(appContext);
145 
146         assertThat(nonIndexableKeys).doesNotContain("development_prefs_screen");
147     }
148 
149     @Test
150     @Config(shadows = ShadowEnableDevelopmentSettingWarningDialog.class)
onSwitchChanged_sameState_shouldDoNothing()151     public void onSwitchChanged_sameState_shouldDoNothing() {
152         when(mDashboard.getContext()).thenReturn(mContext);
153         Settings.Global.putInt(mContext.getContentResolver(),
154                 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0);
155 
156         mDashboard.onSwitchChanged(mSwitch, false /* isChecked */);
157         assertThat(ShadowEnableDevelopmentSettingWarningDialog.mShown).isFalse();
158     }
159 
160     @Test
161     @Config(shadows = ShadowEnableDevelopmentSettingWarningDialog.class)
onSwitchChanged_turnOn_shouldShowWarningDialog()162     public void onSwitchChanged_turnOn_shouldShowWarningDialog() {
163         when(mDashboard.getContext()).thenReturn(mContext);
164         Settings.Global.putInt(mContext.getContentResolver(),
165                 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0);
166 
167         mDashboard.onSwitchChanged(mSwitch, true /* isChecked */);
168         assertThat(ShadowEnableDevelopmentSettingWarningDialog.mShown).isTrue();
169     }
170 
171     @Test
172     @Config(shadows = ShadowEnableDevelopmentSettingWarningDialog.class)
onSwitchChanged_turnOff_shouldTurnOff()173     public void onSwitchChanged_turnOff_shouldTurnOff() {
174         when(mDashboard.getContext()).thenReturn(mContext);
175         Settings.Global.putInt(mContext.getContentResolver(),
176                 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
177 
178         mDashboard.onSwitchChanged(mSwitch, false /* isChecked */);
179 
180         assertThat(ShadowEnableDevelopmentSettingWarningDialog.mShown).isFalse();
181         assertThat(DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)).isFalse();
182     }
183 
184     @Test
185     @Config(shadows = ShadowDisableDevSettingsDialogFragment.class)
onSwitchChanged_turnOff_andOffloadIsNotDefaultValue_shouldShowWarningDialog()186     public void onSwitchChanged_turnOff_andOffloadIsNotDefaultValue_shouldShowWarningDialog() {
187         final BluetoothA2dpHwOffloadPreferenceController controller =
188                 mock(BluetoothA2dpHwOffloadPreferenceController.class);
189         when(mDashboard.getContext()).thenReturn(mContext);
190         when(mDashboard.getDevelopmentOptionsController(
191                 BluetoothA2dpHwOffloadPreferenceController.class)).thenReturn(controller);
192         when(controller.isDefaultValue()).thenReturn(false);
193         Settings.Global.putInt(mContext.getContentResolver(),
194                 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
195 
196         mDashboard.onSwitchChanged(mSwitch, false /* isChecked */);
197 
198         AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
199         assertThat(dialog).isNotNull();
200         ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
201         assertThat(shadowDialog.getTitle()).isEqualTo(
202                 mContext.getString(R.string.bluetooth_disable_a2dp_hw_offload_dialog_title));
203         assertThat(shadowDialog.getMessage()).isEqualTo(
204                 mContext.getString(R.string.bluetooth_disable_a2dp_hw_offload_dialog_message));
205     }
206 
207     @Test
onOemUnlockDialogConfirmed_shouldCallControllerOemConfirmed()208     public void onOemUnlockDialogConfirmed_shouldCallControllerOemConfirmed() {
209         final OemUnlockPreferenceController controller = mock(OemUnlockPreferenceController.class);
210         doReturn(controller).when(mDashboard)
211                 .getDevelopmentOptionsController(OemUnlockPreferenceController.class);
212         mDashboard.onOemUnlockDialogConfirmed();
213         verify(controller).onOemUnlockConfirmed();
214     }
215 
216     @Test
onOemUnlockDialogConfirmed_shouldCallControllerOemDismissed()217     public void onOemUnlockDialogConfirmed_shouldCallControllerOemDismissed() {
218         final OemUnlockPreferenceController controller = mock(OemUnlockPreferenceController.class);
219         doReturn(controller).when(mDashboard)
220                 .getDevelopmentOptionsController(OemUnlockPreferenceController.class);
221         mDashboard.onOemUnlockDialogDismissed();
222         verify(controller).onOemUnlockDismissed();
223     }
224 
225     @Test
onAdbDialogConfirmed_shouldCallControllerDialogConfirmed()226     public void onAdbDialogConfirmed_shouldCallControllerDialogConfirmed() {
227         final AdbPreferenceController controller = mock(AdbPreferenceController.class);
228         doReturn(controller).when(mDashboard)
229                 .getDevelopmentOptionsController(AdbPreferenceController.class);
230         mDashboard.onEnableAdbDialogConfirmed();
231 
232         verify(controller).onAdbDialogConfirmed();
233     }
234 
235     @Test
onAdbDialogDismissed_shouldCallControllerOemDismissed()236     public void onAdbDialogDismissed_shouldCallControllerOemDismissed() {
237         final AdbPreferenceController controller = mock(AdbPreferenceController.class);
238         doReturn(controller).when(mDashboard)
239                 .getDevelopmentOptionsController(AdbPreferenceController.class);
240         mDashboard.onEnableAdbDialogDismissed();
241 
242         verify(controller).onAdbDialogDismissed();
243     }
244 
245     @Test
onAdbClearKeysDialogConfirmed_shouldCallControllerDialogConfirmed()246     public void onAdbClearKeysDialogConfirmed_shouldCallControllerDialogConfirmed() {
247         final ClearAdbKeysPreferenceController controller =
248                 mock(ClearAdbKeysPreferenceController.class);
249         doReturn(controller).when(mDashboard)
250                 .getDevelopmentOptionsController(ClearAdbKeysPreferenceController.class);
251         mDashboard.onAdbClearKeysDialogConfirmed();
252 
253         verify(controller).onClearAdbKeysConfirmed();
254     }
255 
256     @Test
onDisableLogPersistDialogConfirmed_shouldCallControllerDialogConfirmed()257     public void onDisableLogPersistDialogConfirmed_shouldCallControllerDialogConfirmed() {
258         final LogPersistPreferenceController controller =
259                 mock(LogPersistPreferenceController.class);
260         doReturn(controller).when(mDashboard)
261                 .getDevelopmentOptionsController(LogPersistPreferenceController.class);
262         mDashboard.onDisableLogPersistDialogConfirmed();
263 
264         verify(controller).onDisableLogPersistDialogConfirmed();
265     }
266 
267     @Test
onDisableLogPersistDialogRejected_shouldCallControllerDialogRejected()268     public void onDisableLogPersistDialogRejected_shouldCallControllerDialogRejected() {
269         final LogPersistPreferenceController controller =
270                 mock(LogPersistPreferenceController.class);
271         doReturn(controller).when(mDashboard)
272                 .getDevelopmentOptionsController(LogPersistPreferenceController.class);
273         mDashboard.onDisableLogPersistDialogRejected();
274 
275         verify(controller).onDisableLogPersistDialogRejected();
276     }
277 
278     @Implements(EnableDevelopmentSettingWarningDialog.class)
279     public static class ShadowEnableDevelopmentSettingWarningDialog {
280 
281         static boolean mShown;
282 
reset()283         public static void reset() {
284             mShown = false;
285         }
286 
287         @Implementation
show(DevelopmentSettingsDashboardFragment host)288         protected static void show(DevelopmentSettingsDashboardFragment host) {
289             mShown = true;
290         }
291     }
292 
293     @Implements(DisableDevSettingsDialogFragment.class)
294     public static class ShadowDisableDevSettingsDialogFragment {
295 
296         @Implementation
show(DevelopmentSettingsDashboardFragment host)297         public static void show(DevelopmentSettingsDashboardFragment host) {
298             DisableDevSettingsDialogFragment mFragment =
299                     spy(DisableDevSettingsDialogFragment.newInstance());
300             FragmentController.setupFragment(mFragment, FragmentActivity.class,
301                     0 /* containerViewId */, null /* bundle */);
302         }
303     }
304 
305     @Implements(PictureColorModePreferenceController.class)
306     public static class ShadowPictureColorModePreferenceController {
307         @Implementation
isAvailable()308         protected boolean isAvailable() {
309             return true;
310         }
311     }
312 
313     @Implements(AbstractEnableAdbPreferenceController.class)
314     public static class ShadowAdbPreferenceController {
315         @Implementation
isAvailable()316         protected boolean isAvailable() {
317             return true;
318         }
319     }
320 
321     @Implements(ClearAdbKeysPreferenceController.class)
322     public static class ShadowClearAdbKeysPreferenceController {
323         @Implementation
isAvailable()324         protected boolean isAvailable() {
325             return true;
326         }
327     }
328 }
329