1 /*
2  * Copyright (C) 2016 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.dashboard;
17 
18 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.DASHBOARD_CONTAINER;
19 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_GROUP_KEY;
20 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT;
21 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_PENDING_INTENT;
22 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SWITCH_URI;
23 
24 import static com.google.common.truth.Truth.assertThat;
25 
26 import static org.mockito.ArgumentMatchers.any;
27 import static org.mockito.ArgumentMatchers.nullable;
28 import static org.mockito.Mockito.mock;
29 import static org.mockito.Mockito.never;
30 import static org.mockito.Mockito.spy;
31 import static org.mockito.Mockito.times;
32 import static org.mockito.Mockito.verify;
33 import static org.mockito.Mockito.when;
34 
35 import android.app.PendingIntent;
36 import android.app.settings.SettingsEnums;
37 import android.content.ContentResolver;
38 import android.content.Context;
39 import android.content.Intent;
40 import android.content.pm.ActivityInfo;
41 import android.content.pm.ProviderInfo;
42 import android.net.Uri;
43 import android.os.Bundle;
44 import android.os.UserHandle;
45 import android.preference.PreferenceManager.OnActivityResultListener;
46 
47 import androidx.preference.Preference;
48 import androidx.preference.PreferenceCategory;
49 import androidx.preference.PreferenceFragmentCompat;
50 import androidx.preference.PreferenceManager;
51 import androidx.preference.PreferenceScreen;
52 import androidx.preference.SwitchPreferenceCompat;
53 import androidx.test.core.app.ApplicationProvider;
54 
55 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
56 import com.android.settings.R;
57 import com.android.settings.core.PreferenceControllerMixin;
58 import com.android.settings.slices.BlockingSlicePrefController;
59 import com.android.settings.testutils.FakeFeatureFactory;
60 import com.android.settingslib.PrimarySwitchPreference;
61 import com.android.settingslib.core.AbstractPreferenceController;
62 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
63 import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
64 import com.android.settingslib.drawer.ActivityTile;
65 import com.android.settingslib.drawer.DashboardCategory;
66 import com.android.settingslib.drawer.ProviderTile;
67 import com.android.settingslib.drawer.Tile;
68 
69 import org.junit.Before;
70 import org.junit.Rule;
71 import org.junit.Test;
72 import org.junit.runner.RunWith;
73 import org.mockito.Mock;
74 import org.mockito.junit.MockitoJUnit;
75 import org.mockito.junit.MockitoRule;
76 import org.robolectric.RobolectricTestRunner;
77 import org.robolectric.annotation.Config;
78 import org.robolectric.annotation.Implementation;
79 import org.robolectric.annotation.Implements;
80 import org.robolectric.util.ReflectionHelpers;
81 
82 import java.util.ArrayList;
83 import java.util.Arrays;
84 import java.util.HashMap;
85 import java.util.List;
86 import java.util.Map;
87 
88 @RunWith(RobolectricTestRunner.class)
89 public class DashboardFragmentTest {
90     @Rule
91     public final MockitoRule mMockitoRule = MockitoJUnit.rule();
92 
93     private final Context mAppContext = ApplicationProvider.getApplicationContext();
94 
95     @Mock
96     private FakeFeatureFactory mFakeFeatureFactory;
97     private DashboardCategory mDashboardCategory;
98     private Context mContext;
99     private TestFragment mTestFragment;
100     private List<AbstractPreferenceController> mControllers;
101     private ActivityTile mActivityTile;
102     private ProviderTile mProviderTile;
103 
104     @Before
setUp()105     public void setUp() {
106         mContext = spy(mAppContext);
107         final ActivityInfo activityInfo = new ActivityInfo();
108         activityInfo.packageName = "pkg";
109         activityInfo.name = "class";
110         activityInfo.metaData = new Bundle();
111         activityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "injected_tile_key");
112         mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
113         mDashboardCategory = new DashboardCategory("key");
114         mActivityTile = new ActivityTile(activityInfo, mDashboardCategory.key);
115         mDashboardCategory.addTile(mActivityTile);
116 
117         final ProviderInfo providerInfo = new ProviderInfo();
118         providerInfo.packageName = "pkg";
119         providerInfo.name = "provider";
120         providerInfo.authority = "authority";
121         final Bundle metaData = new Bundle();
122         metaData.putString(META_DATA_PREFERENCE_KEYHINT, "injected_tile_key2");
123         metaData.putString(META_DATA_PREFERENCE_SWITCH_URI, "uri");
124         mProviderTile = new ProviderTile(providerInfo, mDashboardCategory.key, metaData);
125         mDashboardCategory.addTile(mProviderTile);
126 
127         mTestFragment = new TestFragment(mAppContext);
128         when(mFakeFeatureFactory.dashboardFeatureProvider
129                 .getTilesForCategory(nullable(String.class)))
130                 .thenReturn(mDashboardCategory);
131         mTestFragment.onAttach(mAppContext);
132         when(mContext.getPackageName()).thenReturn("TestPackage");
133         mControllers = new ArrayList<>();
134     }
135 
136     @Test
testPreferenceControllerGetterSetter_shouldAddAndGetProperly()137     public void testPreferenceControllerGetterSetter_shouldAddAndGetProperly() {
138         final TestPreferenceController controller = new TestPreferenceController(mContext);
139         mTestFragment.addPreferenceController(controller);
140 
141         final TestPreferenceController retrievedController = mTestFragment.use
142                 (TestPreferenceController.class);
143 
144         assertThat(controller).isSameInstanceAs(retrievedController);
145     }
146 
147     @Test
testPreferenceControllerSetter_shouldAddAndNotReplace()148     public void testPreferenceControllerSetter_shouldAddAndNotReplace() {
149         final TestPreferenceController controller1 = new TestPreferenceController(mContext);
150         mTestFragment.addPreferenceController(controller1);
151         final TestPreferenceController controller2 = new TestPreferenceController(mContext);
152         mTestFragment.addPreferenceController(controller2);
153 
154         final TestPreferenceController retrievedController = mTestFragment.use
155                 (TestPreferenceController.class);
156 
157         assertThat(controller1).isSameInstanceAs(retrievedController);
158     }
159 
160     @Test
useAll_returnsAllControllersOfType()161     public void useAll_returnsAllControllersOfType() {
162         final TestPreferenceController controller1 = new TestPreferenceController(mContext);
163         final TestPreferenceController controller2 = new TestPreferenceController(mContext);
164         final SubTestPreferenceController controller3 = new SubTestPreferenceController(mContext);
165         mTestFragment.addPreferenceController(controller1);
166         mTestFragment.addPreferenceController(controller2);
167         mTestFragment.addPreferenceController(controller3);
168 
169         final List<TestPreferenceController> retrievedControllers = mTestFragment.useAll(
170                 TestPreferenceController.class);
171 
172         assertThat(retrievedControllers).containsExactly(controller1, controller2);
173     }
174 
175     @Test
displayTilesAsPreference_shouldAddTilesWithIntent()176     public void displayTilesAsPreference_shouldAddTilesWithIntent() {
177         when(mFakeFeatureFactory.dashboardFeatureProvider
178                 .getTilesForCategory(nullable(String.class)))
179                 .thenReturn(mDashboardCategory);
180         when(mFakeFeatureFactory.dashboardFeatureProvider
181                 .getDashboardKeyForTile(any(ActivityTile.class)))
182                 .thenReturn("test_key");
183         when(mFakeFeatureFactory.dashboardFeatureProvider
184                 .getDashboardKeyForTile(any(ProviderTile.class)))
185                 .thenReturn("test_key2");
186         mTestFragment.onCreatePreferences(new Bundle(), "rootKey");
187 
188         verify(mTestFragment.mScreen, times(2)).addPreference(nullable(Preference.class));
189     }
190 
191     @Test
displayTilesAsPreference_withGroup_shouldAddTilesIntoGroup()192     public void displayTilesAsPreference_withGroup_shouldAddTilesIntoGroup() {
193         final ProviderInfo providerInfo = new ProviderInfo();
194         providerInfo.packageName = "pkg";
195         providerInfo.name = "provider";
196         providerInfo.authority = "authority";
197         final Bundle groupTileMetaData = new Bundle();
198         groupTileMetaData.putString(META_DATA_PREFERENCE_KEYHINT, "injected_tile_group_key");
199         ProviderTile groupTile = new ProviderTile(providerInfo, mDashboardCategory.key,
200                 groupTileMetaData);
201         mDashboardCategory.addTile(groupTile);
202 
203         final Bundle subTileMetaData = new Bundle();
204         subTileMetaData.putString(META_DATA_PREFERENCE_KEYHINT, "injected_tile_key3");
205         subTileMetaData.putString(META_DATA_PREFERENCE_GROUP_KEY, "injected_tile_group_key");
206         subTileMetaData.putParcelable(
207                 META_DATA_PREFERENCE_PENDING_INTENT,
208                 PendingIntent.getActivity(mContext, 0, new Intent(), 0));
209         ProviderTile subTile = new ProviderTile(providerInfo, mDashboardCategory.key,
210                 subTileMetaData);
211         mDashboardCategory.addTile(subTile);
212 
213         PreferenceCategory groupPreference = mock(PreferenceCategory.class);
214         when(mFakeFeatureFactory.dashboardFeatureProvider
215                 .getTilesForCategory(nullable(String.class)))
216                 .thenReturn(mDashboardCategory);
217         when(mFakeFeatureFactory.dashboardFeatureProvider
218                 .getDashboardKeyForTile(any(Tile.class)))
219                 .then(invocation -> ((Tile) invocation.getArgument(0)).getKey(mContext));
220         when(mTestFragment.mScreen.findPreference("injected_tile_group_key"))
221                 .thenReturn(groupPreference);
222         mTestFragment.onCreatePreferences(new Bundle(), "rootKey");
223 
224         verify(mTestFragment.mScreen, times(3)).addPreference(nullable(Preference.class));
225         verify(groupPreference).addPreference(nullable(Preference.class));
226     }
227 
228     @Test
displayTilesAsPreference_shouldNotAddTilesWithoutIntent()229     public void displayTilesAsPreference_shouldNotAddTilesWithoutIntent() {
230         mTestFragment.onCreatePreferences(new Bundle(), "rootKey");
231 
232         verify(mTestFragment.mScreen, never()).addPreference(nullable(Preference.class));
233     }
234 
235     @Test
displayTilesAsPreference_withEmptyCategory_shouldNotAddTiles()236     public void displayTilesAsPreference_withEmptyCategory_shouldNotAddTiles() {
237         mDashboardCategory.removeTile(0);
238         mTestFragment.onCreatePreferences(new Bundle(), "rootKey");
239 
240         verify(mTestFragment.mScreen, never()).addPreference(nullable(Preference.class));
241     }
242 
243     @Test
244     @Config(qualifiers = "mcc999")
displayTilesAsPreference_shouldNotAddSuppressedTiles()245     public void displayTilesAsPreference_shouldNotAddSuppressedTiles() {
246         when(mFakeFeatureFactory.dashboardFeatureProvider
247                 .getTilesForCategory(nullable(String.class)))
248                 .thenReturn(mDashboardCategory);
249         when(mFakeFeatureFactory.dashboardFeatureProvider
250                 .getDashboardKeyForTile(any(ActivityTile.class)))
251                 .thenReturn("test_key");
252         when(mFakeFeatureFactory.dashboardFeatureProvider
253                 .getDashboardKeyForTile(any(ProviderTile.class)))
254                 .thenReturn("test_key2");
255         mTestFragment.onCreatePreferences(new Bundle(), "rootKey");
256 
257         verify(mTestFragment.mScreen, never()).addPreference(nullable(Preference.class));
258     }
259 
260     @Test
onAttach_shouldCreatePlaceholderPreferenceController()261     public void onAttach_shouldCreatePlaceholderPreferenceController() {
262         final AbstractPreferenceController controller = mTestFragment.use(
263                 DashboardTilePlaceholderPreferenceController.class);
264 
265         assertThat(controller).isNotNull();
266     }
267 
268     @Test
269     @Config(shadows = ShadowPreferenceFragmentCompat.class)
onStart_shouldRegisterDynamicDataObservers()270     public void onStart_shouldRegisterDynamicDataObservers() {
271         final DynamicDataObserver observer = new TestDynamicDataObserver();
272         mTestFragment.mDashboardTilePrefKeys.put("key", Arrays.asList(observer));
273 
274         mTestFragment.onStart();
275 
276         verify(mTestFragment.getContentResolver()).registerContentObserver(observer.getUri(), false,
277                 observer);
278     }
279 
280     @Test
281     @Config(shadows = ShadowPreferenceFragmentCompat.class)
onStop_shouldUnregisterDynamicDataObservers()282     public void onStop_shouldUnregisterDynamicDataObservers() {
283         final DynamicDataObserver observer = new TestDynamicDataObserver();
284         mTestFragment.registerDynamicDataObservers(Arrays.asList(observer));
285 
286         mTestFragment.onStop();
287 
288         verify(mTestFragment.getContentResolver()).unregisterContentObserver(observer);
289     }
290 
291     @Test
updateState_skipUnavailablePrefs()292     public void updateState_skipUnavailablePrefs() {
293         final List<AbstractPreferenceController> preferenceControllers = mTestFragment.mControllers;
294         final AbstractPreferenceController mockController1 =
295                 mock(AbstractPreferenceController.class);
296         final AbstractPreferenceController mockController2 =
297                 mock(AbstractPreferenceController.class);
298         when(mockController1.getPreferenceKey()).thenReturn("key1");
299         when(mockController2.getPreferenceKey()).thenReturn("key2");
300         preferenceControllers.add(mockController1);
301         preferenceControllers.add(mockController2);
302         when(mockController1.isAvailable()).thenReturn(false);
303         when(mockController2.isAvailable()).thenReturn(true);
304         mTestFragment.onAttach(mAppContext);
305         mTestFragment.onResume();
306 
307         verify(mockController1).getPreferenceKey();
308         verify(mockController2, times(2)).getPreferenceKey();
309     }
310 
311     @Test
updateState_doesNotSkipControllersOfSameClass()312     public void updateState_doesNotSkipControllersOfSameClass() {
313         final AbstractPreferenceController mockController1 =
314                 mock(AbstractPreferenceController.class);
315         final AbstractPreferenceController mockController2 =
316                 mock(AbstractPreferenceController.class);
317         mTestFragment.addPreferenceController(mockController1);
318         mTestFragment.addPreferenceController(mockController2);
319         when(mockController1.isAvailable()).thenReturn(true);
320         when(mockController2.isAvailable()).thenReturn(true);
321 
322         mTestFragment.updatePreferenceStates();
323 
324         verify(mockController1).getPreferenceKey();
325         verify(mockController2).getPreferenceKey();
326     }
327 
328     @Test
onExpandButtonClick_shouldLogAdvancedButtonExpand()329     public void onExpandButtonClick_shouldLogAdvancedButtonExpand() {
330         final MetricsFeatureProvider metricsFeatureProvider
331                 = mFakeFeatureFactory.getMetricsFeatureProvider();
332         mTestFragment.onExpandButtonClick();
333 
334         verify(metricsFeatureProvider).action(SettingsEnums.PAGE_UNKNOWN,
335                 MetricsEvent.ACTION_SETTINGS_ADVANCED_BUTTON_EXPAND,
336                 DASHBOARD_CONTAINER, null, 0);
337     }
338 
339     @Test
updatePreferenceVisibility_prefKeyNull_shouldNotCrash()340     public void updatePreferenceVisibility_prefKeyNull_shouldNotCrash() {
341         final Map<Class, List<AbstractPreferenceController>> prefControllers = new HashMap<>();
342         final List<AbstractPreferenceController> controllerList = new ArrayList<>();
343         controllerList.add(new TestPreferenceController(mContext));
344         prefControllers.put(TestPreferenceController.class, controllerList);
345         mTestFragment.mBlockerController = new UiBlockerController(Arrays.asList("pref_key"));
346 
347         // Should not crash
348         mTestFragment.updatePreferenceVisibility(prefControllers);
349     }
350 
351     @Test
forceUpdatePreferences_prefKeyNull_shouldNotCrash()352     public void forceUpdatePreferences_prefKeyNull_shouldNotCrash() {
353         mTestFragment.addPreferenceController(new TestPreferenceController(mContext));
354 
355         // Should not crash
356         mTestFragment.forceUpdatePreferences();
357     }
358 
359     @Test
checkUiBlocker_noUiBlocker_controllerIsNull()360     public void checkUiBlocker_noUiBlocker_controllerIsNull() {
361         mTestFragment.mBlockerController = null;
362         mControllers.add(new TestPreferenceController(mContext));
363 
364         mTestFragment.checkUiBlocker(mControllers);
365 
366         assertThat(mTestFragment.mBlockerController).isNull();
367     }
368 
369     @Test
checkUiBlocker_hasUiBlockerAndControllerIsAvailable_controllerNotNull()370     public void checkUiBlocker_hasUiBlockerAndControllerIsAvailable_controllerNotNull() {
371         final BlockingSlicePrefController controller =
372                 new BlockingSlicePrefController(mContext, "pref_key");
373         controller.setSliceUri(Uri.parse("testUri"));
374         mTestFragment.mBlockerController = null;
375         mControllers.add(new TestPreferenceController(mContext));
376         mControllers.add(controller);
377 
378         mTestFragment.checkUiBlocker(mControllers);
379 
380         assertThat(mTestFragment.mBlockerController).isNotNull();
381     }
382 
383     @Test
checkUiBlocker_hasUiBlockerAndControllerIsNotAvailable_controllerIsNull()384     public void checkUiBlocker_hasUiBlockerAndControllerIsNotAvailable_controllerIsNull() {
385         mTestFragment.mBlockerController = null;
386         mControllers.add(new TestPreferenceController(mContext));
387         mControllers.add(new BlockingSlicePrefController(mContext, "pref_key"));
388 
389         mTestFragment.checkUiBlocker(mControllers);
390 
391         assertThat(mTestFragment.mBlockerController).isNull();
392     }
393 
394     @Test
createPreference_isProviderTile_returnSwitchPreference()395     public void createPreference_isProviderTile_returnSwitchPreference() {
396         final Preference pref = mTestFragment.createPreference(mProviderTile);
397 
398         assertThat(pref).isInstanceOf(SwitchPreferenceCompat.class);
399     }
400 
401     @Test
createPreference_isActivityTile_returnPreference()402     public void createPreference_isActivityTile_returnPreference() {
403         final Preference pref = mTestFragment.createPreference(mActivityTile);
404 
405         assertThat(pref).isInstanceOf(Preference.class);
406         assertThat(pref).isNotInstanceOf(PrimarySwitchPreference.class);
407         assertThat(pref).isNotInstanceOf(SwitchPreferenceCompat.class);
408         assertThat(pref.getWidgetLayoutResource()).isEqualTo(0);
409     }
410 
411     @Test
createPreference_isActivityTileAndHasSwitch_returnPrimarySwitchPreference()412     public void createPreference_isActivityTileAndHasSwitch_returnPrimarySwitchPreference() {
413         mActivityTile.getMetaData().putString(META_DATA_PREFERENCE_SWITCH_URI, "uri");
414 
415         final Preference pref = mTestFragment.createPreference(mActivityTile);
416 
417         assertThat(pref).isInstanceOf(PrimarySwitchPreference.class);
418     }
419 
420     @Test
createPreference_isProviderTileWithPendingIntent_returnPreferenceWithIcon()421     public void createPreference_isProviderTileWithPendingIntent_returnPreferenceWithIcon() {
422         final ProviderInfo providerInfo = new ProviderInfo();
423         providerInfo.packageName = "pkg";
424         providerInfo.name = "provider";
425         providerInfo.authority = "authority";
426         final Bundle metaData = new Bundle();
427         metaData.putString(META_DATA_PREFERENCE_KEYHINT, "injected_tile_key2");
428         ProviderTile providerTile = new ProviderTile(providerInfo, mDashboardCategory.key,
429                 metaData);
430         providerTile.pendingIntentMap.put(
431                 UserHandle.CURRENT, PendingIntent.getActivity(mContext, 0, new Intent(), 0));
432 
433         final Preference pref = mTestFragment.createPreference(providerTile);
434 
435         assertThat(pref).isInstanceOf(Preference.class);
436         assertThat(pref).isNotInstanceOf(PrimarySwitchPreference.class);
437         assertThat(pref).isNotInstanceOf(SwitchPreferenceCompat.class);
438         assertThat(pref.getWidgetLayoutResource())
439                 .isEqualTo(R.layout.preference_external_action_icon);
440     }
441 
442     @Test
createPreference_isProviderTileWithPendingIntentAndSwitch_returnPrimarySwitch()443     public void createPreference_isProviderTileWithPendingIntentAndSwitch_returnPrimarySwitch() {
444         mProviderTile.pendingIntentMap.put(
445                 UserHandle.CURRENT, PendingIntent.getActivity(mContext, 0, new Intent(), 0));
446 
447         final Preference pref = mTestFragment.createPreference(mProviderTile);
448 
449         assertThat(pref).isInstanceOf(PrimarySwitchPreference.class);
450     }
451 
452     @Test
createPreference_isGroupTile_returnPreferenceCategory_logTileAdded()453     public void createPreference_isGroupTile_returnPreferenceCategory_logTileAdded() {
454         final ProviderInfo providerInfo = new ProviderInfo();
455         providerInfo.packageName = "pkg";
456         providerInfo.name = "provider";
457         providerInfo.authority = "authority";
458         final Bundle metaData = new Bundle();
459         metaData.putString(META_DATA_PREFERENCE_KEYHINT, "injected_tile_key2");
460         ProviderTile providerTile =
461                 new ProviderTile(providerInfo, mDashboardCategory.key, metaData);
462         MetricsFeatureProvider metricsFeatureProvider =
463                 mFakeFeatureFactory.getMetricsFeatureProvider();
464         when(metricsFeatureProvider.getAttribution(any())).thenReturn(123);
465 
466         final Preference pref = mTestFragment.createPreference(providerTile);
467 
468         assertThat(pref).isInstanceOf(PreferenceCategory.class);
469         verify(metricsFeatureProvider)
470                 .action(
471                         123,
472                         SettingsEnums.ACTION_SETTINGS_GROUP_TILE_ADDED_TO_SCREEN,
473                         mTestFragment.getMetricsCategory(),
474                         "injected_tile_key2",
475                         0);
476     }
477 
478     @Test
onActivityResult_test()479     public void onActivityResult_test() {
480         final int requestCode = 10;
481         final int resultCode = 1;
482         final TestOnActivityResultPreferenceController activityResultPref = spy(
483                 new TestOnActivityResultPreferenceController(mContext));
484         mTestFragment.addPreferenceController(activityResultPref);
485 
486         mTestFragment.onActivityResult(requestCode, resultCode, null);
487 
488         verify(activityResultPref).onActivityResult(requestCode, resultCode, null);
489     }
490 
491     public static class TestPreferenceController extends AbstractPreferenceController
492             implements PreferenceControllerMixin {
493 
TestPreferenceController(Context context)494         private TestPreferenceController(Context context) {
495             super(context);
496         }
497 
498         @Override
handlePreferenceTreeClick(Preference preference)499         public boolean handlePreferenceTreeClick(Preference preference) {
500             return false;
501         }
502 
503         @Override
isAvailable()504         public boolean isAvailable() {
505             return false;
506         }
507 
508         @Override
getPreferenceKey()509         public String getPreferenceKey() {
510             return null;
511         }
512 
513         @Override
updateNonIndexableKeys(List<String> keys)514         public void updateNonIndexableKeys(List<String> keys) {
515         }
516     }
517 
518     public static class SubTestPreferenceController extends TestPreferenceController {
519 
SubTestPreferenceController(Context context)520         private SubTestPreferenceController(Context context) {
521             super(context);
522         }
523     }
524 
525     public static class TestOnActivityResultPreferenceController extends
526             TestPreferenceController implements OnActivityResultListener {
527 
TestOnActivityResultPreferenceController(Context context)528         private TestOnActivityResultPreferenceController(Context context) {
529             super(context);
530         }
531 
532         @Override
onActivityResult(int requestCode, int resultCode, Intent data)533         public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
534             return true;
535         }
536     }
537 
538     private static class TestFragment extends DashboardFragment {
539 
540         private final PreferenceManager mPreferenceManager;
541         private final Context mContext;
542         private final List<AbstractPreferenceController> mControllers;
543         private final ContentResolver mContentResolver;
544 
545         public final PreferenceScreen mScreen;
546 
TestFragment(Context context)547         public TestFragment(Context context) {
548             mContext = context;
549             mPreferenceManager = mock(PreferenceManager.class);
550             mScreen = mock(PreferenceScreen.class);
551             mContentResolver = mock(ContentResolver.class);
552             mControllers = new ArrayList<>();
553 
554             when(mPreferenceManager.getContext()).thenReturn(mContext);
555             ReflectionHelpers.setField(
556                     this, "mVisibilityLoggerMixin", mock(VisibilityLoggerMixin.class));
557         }
558 
559         @Override
getContext()560         public Context getContext() {
561             return mContext;
562         }
563 
564         @Override
getMetricsCategory()565         public int getMetricsCategory() {
566             return DASHBOARD_CONTAINER;
567         }
568 
569         @Override
getPreferenceScreen()570         public PreferenceScreen getPreferenceScreen() {
571             return mScreen;
572         }
573 
574         @Override
getLogTag()575         protected String getLogTag() {
576             return "TEST_FRAG";
577         }
578 
579         @Override
getPreferenceScreenResId()580         protected int getPreferenceScreenResId() {
581             return 0;
582         }
583 
584         @Override
createPreferenceControllers(Context context)585         protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
586             return mControllers;
587         }
588 
589         @Override
getPreferenceManager()590         public PreferenceManager getPreferenceManager() {
591             return mPreferenceManager;
592         }
593 
594         @Override
getContentResolver()595         protected ContentResolver getContentResolver() {
596             return mContentResolver;
597         }
598 
599     }
600 
601     private static class TestDynamicDataObserver extends DynamicDataObserver {
602 
603         @Override
getUri()604         public Uri getUri() {
605             return Uri.parse("content://abc");
606         }
607 
608         @Override
onDataChanged()609         public void onDataChanged() {
610         }
611     }
612 
613     @Implements(PreferenceFragmentCompat.class)
614     public static class ShadowPreferenceFragmentCompat {
615 
616         @Implementation
onStart()617         public void onStart() {
618             // do nothing
619         }
620 
621         @Implementation
onStop()622         public void onStop() {
623             // do nothing
624         }
625     }
626 }
627