Merge "Align dropdown preference's dropdown with preference text"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index a3365f7..4c8ba07 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1945,11 +1945,11 @@
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="android.intent.category.VOICE_LAUNCH" />
             </intent-filter>
-            <intent-filter android:priority="3">
+            <intent-filter android:priority="2">
                 <action android:name="com.android.settings.action.SETTINGS" />
             </intent-filter>
             <meta-data android:name="com.android.settings.category"
-                android:value="com.android.settings.category.system" />
+                android:value="com.android.settings.category.ia.device" />
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
                 android:value="com.android.settings.print.PrintSettingsFragment" />
         </activity>
@@ -3100,17 +3100,6 @@
                        android:value="com.android.settings.applications.ProcessStatsSummary" />
         </activity-alias>
 
-        <activity-alias android:name="PrintDashboardAlias"
-                        android:targetActivity="Settings$PrintSettingsActivity">
-            <intent-filter android:priority="2">
-                <action android:name="com.android.settings.action.SETTINGS"/>
-            </intent-filter>
-            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
-                       android:value="com.android.settings.print.PrintSettingsFragment" />
-            <meta-data android:name="com.android.settings.category"
-                       android:value="com.android.settings.category.ia.device" />
-        </activity-alias>
-
         <activity-alias android:name="ManageApplicationsDashboardAlias"
                         android:targetActivity="Settings$ManageApplicationsActivity">
             <intent-filter android:priority="200">
diff --git a/src/com/android/settings/CreateShortcut.java b/src/com/android/settings/CreateShortcut.java
index 7d5a6d2..8bc801b 100644
--- a/src/com/android/settings/CreateShortcut.java
+++ b/src/com/android/settings/CreateShortcut.java
@@ -71,7 +71,7 @@
         ShortcutManager sm = getSystemService(ShortcutManager.class);
         ActivityInfo activityInfo = resolveInfo.activityInfo;
 
-        Icon maskableIcon = activityInfo.icon != 0 ? Icon.createWithMaskableBitmap(
+        Icon maskableIcon = activityInfo.icon != 0 ? Icon.createWithAdaptiveBitmap(
                 createIcon(activityInfo.icon,
                         R.layout.shortcut_badge_maskable,
                         getResources().getDimensionPixelSize(R.dimen.shortcut_size_maskable))) :
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index b48174c..1b9b3b3 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -236,7 +236,6 @@
     private DashboardFeatureProvider mDashboardFeatureProvider;
     private Intent mResultIntentData;
     private ComponentName mCurrentSuggestion;
-    private final StringBuffer mDebugData = new StringBuffer();
 
     @VisibleForTesting
     String mSearchQuery;
@@ -433,34 +432,7 @@
             mDisplaySearch = savedState.getBoolean(SAVE_KEY_SHOW_SEARCH);
 
         } else {
-            if (!mIsShowingDashboard) {
-                if (initialFragmentName == null) {
-                    logFragmentData(intent, className, isSubSettings);
-                }
-                mDisplaySearch = false;
-                // UP will be shown only if it is a sub settings
-                if (mIsShortcut) {
-                    mDisplayHomeAsUpEnabled = isSubSettings;
-                } else if (isSubSettings) {
-                    mDisplayHomeAsUpEnabled = true;
-                } else {
-                    mDisplayHomeAsUpEnabled = false;
-                }
-                setTitleFromIntent(intent);
-
-                Bundle initialArguments = intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
-                switchToFragment(initialFragmentName, initialArguments, true, false,
-                        mInitialTitleResId, mInitialTitle, false);
-            } else {
-                // No UP affordance if we are displaying the main Dashboard
-                mDisplayHomeAsUpEnabled = false;
-                // Show Search affordance
-                mDisplaySearch = true;
-                mInitialTitleResId = R.string.dashboard_title;
-
-                switchToFragment(DashboardSummary.class.getName(), null /* args */, false, false,
-                            mInitialTitleResId, mInitialTitle, false);
-            }
+            launchSettingFragment(initialFragmentName, isSubSettings, intent);
         }
 
         mActionBar = getActionBar();
@@ -532,6 +504,35 @@
         }
     }
 
+    @VisibleForTesting
+    void launchSettingFragment(String initialFragmentName, boolean isSubSettings, Intent intent) {
+        if (!mIsShowingDashboard && initialFragmentName != null) {
+            mDisplaySearch = false;
+            // UP will be shown only if it is a sub settings
+            if (mIsShortcut) {
+                mDisplayHomeAsUpEnabled = isSubSettings;
+            } else if (isSubSettings) {
+                mDisplayHomeAsUpEnabled = true;
+            } else {
+                mDisplayHomeAsUpEnabled = false;
+            }
+            setTitleFromIntent(intent);
+
+            Bundle initialArguments = intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
+            switchToFragment(initialFragmentName, initialArguments, true, false,
+                mInitialTitleResId, mInitialTitle, false);
+        } else {
+            // No UP affordance if we are displaying the main Dashboard
+            mDisplayHomeAsUpEnabled = false;
+            // Show Search affordance
+            mDisplaySearch = true;
+            mInitialTitleResId = R.string.dashboard_title;
+
+            switchToFragment(DashboardSummary.class.getName(), null /* args */, false, false,
+                mInitialTitleResId, mInitialTitle, false);
+        }
+    }
+
     public void setDisplaySearchMenu(boolean displaySearch) {
         if (displaySearch != mDisplaySearch) {
             mDisplaySearch = displaySearch;
@@ -693,7 +694,6 @@
         String startingFragment = getStartingFragmentClass(superIntent);
         // This is called from super.onCreate, isMultiPane() is not yet reliable
         // Do not use onIsHidingHeaders either, which relies itself on this method
-        log("getIntent() startingFragment", startingFragment);
         if (startingFragment != null) {
             Intent modIntent = new Intent(superIntent);
             modIntent.putExtra(EXTRA_SHOW_FRAGMENT, startingFragment);
@@ -715,11 +715,9 @@
      * returns the class name to load as a fragment.
      */
     private String getStartingFragmentClass(Intent intent) {
-        log("getStartingFragmentClass() mFragmentClass", mFragmentClass);
         if (mFragmentClass != null) return mFragmentClass;
 
         String intentClass = intent.getComponent().getClassName();
-        log("getStartingFragmentClass() intentClass", intentClass);
         if (intentClass.equals(getClass().getName())) return null;
 
         if ("com.android.settings.ManageApplications".equals(intentClass)
@@ -1116,37 +1114,4 @@
         }
         super.onActivityResult(requestCode, resultCode, data);
     }
-
-    private void logFragmentData(Intent intent, String className, boolean isSubSettings) {
-        if (intent != null) {
-            logBundleData(intent.getExtras(), "Intent extra");
-            logBundleData(intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS), "Fragment args");
-        } else {
-            log("Intent data", "NULL");
-        }
-        log("Fragment", mFragmentClass);
-        log("Shortcut", mIsShortcut);
-        log("Class Name", className);
-        log("Show dashboard", mIsShowingDashboard);
-        log("Sub setting", isSubSettings);
-        log("Title", mInitialTitle);
-        Log.d(LOG_TAG, mDebugData.toString());
-        mDebugData.delete(0, mDebugData.length());
-    }
-
-    private void logBundleData(Bundle data, String name) {
-        if (data != null) {
-            final Set<String> keys = data.keySet();
-            mDebugData.append(name).append(": ");
-            for (String key : keys) {
-                log(key, data.get(key));
-            }
-        } else {
-            log(name, "NULL");
-        }
-    }
-
-    private void log(String key, Object data) {
-        mDebugData.append(key).append("=").append(data).append(", ");
-    }
 }
diff --git a/src/com/android/settings/applications/MusicViewHolderController.java b/src/com/android/settings/applications/MusicViewHolderController.java
index d7c142f..4599fcc 100644
--- a/src/com/android/settings/applications/MusicViewHolderController.java
+++ b/src/com/android/settings/applications/MusicViewHolderController.java
@@ -68,8 +68,10 @@
 
     @Override
     public void onClick(Fragment fragment) {
-        Intent intent = new Intent(DocumentsContract.ACTION_BROWSE);
-        intent.setData(DocumentsContract.buildRootUri(AUTHORITY_MEDIA, "audio_root"));
+        Intent intent = new Intent(Intent.ACTION_VIEW);
+        intent.setDataAndType(
+                DocumentsContract.buildRootUri(AUTHORITY_MEDIA, "audio_root"),
+                DocumentsContract.Root.MIME_TYPE_ITEM);
         intent.addCategory(Intent.CATEGORY_DEFAULT);
         intent.putExtra(Intent.EXTRA_USER_ID, mUser);
         Utils.launchIntent(fragment, intent);
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index d6564fe..e0ed1eb 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -53,7 +53,6 @@
 import com.android.settings.applications.DrawOverlayDetails;
 import com.android.settings.applications.InstalledAppDetails;
 import com.android.settings.applications.ManageApplications;
-import com.android.settings.applications.assist.ManageAssist;
 import com.android.settings.applications.ManageDomainUrls;
 import com.android.settings.applications.NotificationApps;
 import com.android.settings.applications.PictureInPictureSettings;
@@ -62,6 +61,7 @@
 import com.android.settings.applications.UsageAccessDetails;
 import com.android.settings.applications.VrListenerSettings;
 import com.android.settings.applications.WriteSettingsDetails;
+import com.android.settings.applications.assist.ManageAssist;
 import com.android.settings.bluetooth.BluetoothSettings;
 import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
 import com.android.settings.dashboard.SupportFragment;
@@ -273,7 +273,9 @@
             // Home page
             Settings.NetworkDashboardActivity.class.getName(),
             Settings.ConnectedDeviceDashboardActivity.class.getName(),
+            Settings.WifiDisplaySettingsActivity.class.getName(),
             Settings.AppAndNotificationDashboardActivity.class.getName(),
+            Settings.StorageDashboardActivity.class.getName(),
             "com.android.settings.SoundDashboardAlias",
             "com.android.settings.SecurityDashboardAlias",
             "com.android.settings.UsersDashboardAlias",
diff --git a/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java b/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
index 6c492cc..d6fe1aa 100644
--- a/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
@@ -67,7 +67,7 @@
         super(context);
         mActivity = activity;
         mFragment = fragment;
-        mUm = UserManager.get(context);
+        mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
         mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
         if (lifecycle != null) {
             lifecycle.addObserver(this);
diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java b/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
index eb07a7f..076ec05 100644
--- a/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
+++ b/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
@@ -483,20 +483,26 @@
 
             } break;
             case R.string.storage_detail_images: {
-                intent = new Intent(DocumentsContract.ACTION_BROWSE);
-                intent.setData(DocumentsContract.buildRootUri(AUTHORITY_MEDIA, "images_root"));
+                intent = new Intent(Intent.ACTION_VIEW);
+                intent.setDataAndType(
+                        DocumentsContract.buildRootUri(AUTHORITY_MEDIA, "images_root"),
+                        DocumentsContract.Root.MIME_TYPE_ITEM);
                 intent.addCategory(Intent.CATEGORY_DEFAULT);
 
             } break;
             case R.string.storage_detail_videos: {
-                intent = new Intent(DocumentsContract.ACTION_BROWSE);
-                intent.setData(DocumentsContract.buildRootUri(AUTHORITY_MEDIA, "videos_root"));
+                intent = new Intent(Intent.ACTION_VIEW);
+                intent.setDataAndType(
+                        DocumentsContract.buildRootUri(AUTHORITY_MEDIA, "videos_root"),
+                        DocumentsContract.Root.MIME_TYPE_ITEM);
                 intent.addCategory(Intent.CATEGORY_DEFAULT);
 
             } break;
             case R.string.storage_detail_audio: {
-                intent = new Intent(DocumentsContract.ACTION_BROWSE);
-                intent.setData(DocumentsContract.buildRootUri(AUTHORITY_MEDIA, "audio_root"));
+                intent = new Intent(DocumentsContract.Root.MIME_TYPE_ITEM);
+                intent.setDataAndType(
+                        DocumentsContract.buildRootUri(AUTHORITY_MEDIA, "audio_root"),
+                        DocumentsContract.Root.MIME_TYPE_ITEM);
                 intent.addCategory(Intent.CATEGORY_DEFAULT);
 
             } break;
diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java
index 4c310e6..eecc77c 100644
--- a/src/com/android/settings/notification/AppNotificationSettings.java
+++ b/src/com/android/settings/notification/AppNotificationSettings.java
@@ -182,13 +182,13 @@
                             getPrefContext());
                     channelPref.setDisabledByAdmin(mSuspendedAppsAdmin);
                     channelPref.setKey(channel.getId());
-                    channelPref.setTitle(channel.getName());
+                    channelPref.setTitle(getNotificationChannelLabel(channel));
                     channelPref.setChecked(channel.getImportance() != IMPORTANCE_NONE);
                     channelPref.setMultiLine(true);
 
                     if (channel.isDeleted()) {
-                        channelPref.setTitle(
-                                getString(R.string.deleted_channel_name, channel.getName()));
+                        channelPref.setTitle(getString(R.string.deleted_channel_name,
+                                getNotificationChannelLabel(channel)));
                         channelPref.setEnabled(false);
                     } else {
                         channelPref.setSummary(getImportanceSummary(channel.getImportance()));
@@ -275,8 +275,10 @@
             if (left.isDeleted() != right.isDeleted()) {
                 return Boolean.compare(left.isDeleted(), right.isDeleted());
             }
-            if (!Objects.equals(left.getName(), right.getName())) {
-                return sCollator.compare(left.getName().toString(), right.getName().toString());
+            if (!Objects.equals(getNotificationChannelLabel(left),
+                    getNotificationChannelLabel(right))) {
+                return sCollator.compare(getNotificationChannelLabel(left).toString(),
+                        getNotificationChannelLabel(right).toString());
             }
             return left.getId().compareTo(right.getId());
         }
diff --git a/src/com/android/settings/notification/ChannelNotificationSettings.java b/src/com/android/settings/notification/ChannelNotificationSettings.java
index ea450f4..7be98c1 100644
--- a/src/com/android/settings/notification/ChannelNotificationSettings.java
+++ b/src/com/android/settings/notification/ChannelNotificationSettings.java
@@ -130,7 +130,7 @@
                     .getApplicationFeatureProvider(activity)
                     .newAppHeaderController(this /* fragment */, null /* appHeader */)
                     .setIcon(mAppRow.icon)
-                    .setLabel(mChannel.getName())
+                    .setLabel(getNotificationChannelLabel(mChannel))
                     .setSummary(mAppRow.label)
                     .setPackageName(mAppRow.pkg)
                     .setUid(mAppRow.uid)
diff --git a/src/com/android/settings/notification/EmergencyBroadcastPreferenceController.java b/src/com/android/settings/notification/EmergencyBroadcastPreferenceController.java
index 1154493..8f26ed8 100644
--- a/src/com/android/settings/notification/EmergencyBroadcastPreferenceController.java
+++ b/src/com/android/settings/notification/EmergencyBroadcastPreferenceController.java
@@ -48,7 +48,7 @@
     EmergencyBroadcastPreferenceController(Context context, AccountRestrictionHelper helper) {
         super(context);
         mHelper = helper;
-        mUserManager = UserManager.get(context);
+        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
         mPm = mContext.getPackageManager();
         // Enable link to CMAS app settings depending on the value in config.xml.
         mCellBroadcastAppLinkEnabled = isCellBroadcastAppLinkEnabled();
diff --git a/src/com/android/settings/notification/NotificationBackend.java b/src/com/android/settings/notification/NotificationBackend.java
index 2a2185d..d201d60 100644
--- a/src/com/android/settings/notification/NotificationBackend.java
+++ b/src/com/android/settings/notification/NotificationBackend.java
@@ -155,8 +155,4 @@
         public boolean showBadge;
         public int userId;
     }
-
-    public static class ChannelRow extends AppRow {
-        public NotificationChannel channel;
-    }
 }
diff --git a/src/com/android/settings/notification/NotificationSettingsBase.java b/src/com/android/settings/notification/NotificationSettingsBase.java
index 80d249f..099b4f4 100644
--- a/src/com/android/settings/notification/NotificationSettingsBase.java
+++ b/src/com/android/settings/notification/NotificationSettingsBase.java
@@ -248,4 +248,17 @@
                 return getContext().getString(R.string.notification_importance_high);
         }
     }
+
+    protected CharSequence getNotificationChannelLabel(NotificationChannel channel) {
+        if (channel.getName() != null) {
+            return channel.getName();
+        }
+        try {
+            ApplicationInfo info = mPm.getApplicationInfoAsUser(mAppRow.pkg, 0, mAppRow.userId);
+            return mPm.getText(mAppRow.pkg, channel.getNameResId(), info);
+        } catch (NameNotFoundException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
 }
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index d97b461..d652efa 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -954,6 +954,8 @@
                 Log.e(TAG, "Failed to forget invalid network " + mSelectedAccessPoint.getConfig());
                 return;
             }
+        } else if (mSelectedAccessPoint.getConfig().isPasspoint()) {
+            mWifiManager.removePasspointConfiguration(mSelectedAccessPoint.getConfig().FQDN);
         } else {
             mWifiManager.forget(mSelectedAccessPoint.getConfig().networkId, mForgetListener);
         }
diff --git a/tests/robotests/assets/grandfather_not_sharing_pref_controllers_with_search_provider b/tests/robotests/assets/grandfather_not_sharing_pref_controllers_with_search_provider
new file mode 100644
index 0000000..cb04679
--- /dev/null
+++ b/tests/robotests/assets/grandfather_not_sharing_pref_controllers_with_search_provider
@@ -0,0 +1,11 @@
+com.android.settings.gestures.PickupGestureSettings
+com.android.settings.language.LanguageAndInputSettings
+com.android.settings.enterprise.EnterprisePrivacySettings
+com.android.settings.gestures.DoubleTapScreenSettings
+com.android.settings.applications.AdvancedAppSettings
+com.android.settings.gestures.AssistGestureSettings
+com.android.settings.fuelgauge.PowerUsageSummary
+com.android.settings.gestures.SwipeToNotificationSettings
+com.android.settings.inputmethod.InputMethodAndLanguageSettings
+com.android.settings.gestures.DoubleTapPowerSettings
+com.android.settings.gestures.DoubleTwistGestureSettings
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/SettingsActivityTest.java b/tests/robotests/src/com/android/settings/SettingsActivityTest.java
index 1661947..df7a454 100644
--- a/tests/robotests/src/com/android/settings/SettingsActivityTest.java
+++ b/tests/robotests/src/com/android/settings/SettingsActivityTest.java
@@ -16,18 +16,47 @@
 
 package com.android.settings;
 
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.content.Context;
+import android.content.Intent;
+import com.android.settings.testutils.FakeFeatureFactory;
+
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
 import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class SettingsActivityTest {
 
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private Context mContext;
+    @Mock
+    private FragmentManager mFragmentManager;
+
     private SettingsActivity mActivity;
 
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        FakeFeatureFactory.setupForTest(mContext);
+        final FakeFeatureFactory factory =
+            (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
+        when(factory.dashboardFeatureProvider.isEnabled()).thenReturn(true);
+    }
+
     @Test
     public void testQueryTextChange_shouldUpdate() {
         final String testQuery = "abc";
@@ -42,4 +71,16 @@
 
         assertThat(mActivity.mSearchQuery).isEqualTo(testQuery);
     }
+
+    @Test
+    public void launchSettingFragment_nullExtraShowFragment_shouldNotCrash()
+            throws ClassNotFoundException {
+        mActivity = spy(new SettingsActivity());
+        when(mActivity.getFragmentManager()).thenReturn(mFragmentManager);
+        when(mFragmentManager.beginTransaction()).thenReturn(mock(FragmentTransaction.class));
+
+        doReturn(RuntimeEnvironment.application.getClassLoader()).when(mActivity).getClassLoader();
+
+        mActivity.launchSettingFragment(null, true, mock(Intent.class));
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/applications/MusicViewHolderControllerTest.java b/tests/robotests/src/com/android/settings/applications/MusicViewHolderControllerTest.java
index 592293d..9bc7482 100644
--- a/tests/robotests/src/com/android/settings/applications/MusicViewHolderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/MusicViewHolderControllerTest.java
@@ -99,9 +99,10 @@
         verify(mFragment).startActivity(argumentCaptor.capture());
         Intent intent = argumentCaptor.getValue();
 
-        assertThat(intent.getAction()).isEqualTo(DocumentsContract.ACTION_BROWSE);
+        assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW);
         assertThat(intent.getData()).isEqualTo(DocumentsContract.buildRootUri(
                 "com.android.providers.media.documents",
                 "audio_root"));
+        assertThat(intent.getType()).isEqualTo(DocumentsContract.Root.MIME_TYPE_ITEM);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java
index 8e46343..5902ec0 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java
@@ -32,6 +32,7 @@
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
 import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.ShadowUserManager;
 import com.android.settingslib.drawer.CategoryKey;
 import com.android.settingslib.drawer.CategoryManager;
 import com.android.settingslib.drawer.DashboardCategory;
@@ -62,7 +63,9 @@
 import static org.robolectric.Shadows.shadowOf;
 
 @RunWith(SettingsRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+@Config(manifest = TestConfig.MANIFEST_PATH,
+        sdk = TestConfig.SDK_VERSION,
+        shadows = ShadowUserManager.class)
 public class DashboardFeatureProviderImplTest {
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentSearchIndexProviderInspector.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentSearchIndexProviderInspector.java
new file mode 100644
index 0000000..6b22f7b
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentSearchIndexProviderInspector.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.dashboard;
+
+import android.app.Fragment;
+import android.content.Context;
+
+import com.android.settings.core.PreferenceController;
+import com.android.settings.search.Indexable;
+import com.android.settings.search2.DatabaseIndexingUtils;
+
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.List;
+
+public class DashboardFragmentSearchIndexProviderInspector {
+
+    public static boolean isSharingPreferenceControllers(Class clazz) {
+        final Context context = RuntimeEnvironment.application;
+        final Fragment fragment;
+        try {
+            fragment = Fragment.instantiate(context, clazz.getName());
+        } catch (Throwable e) {
+            // Can't do much with exception, assume the test passed.
+            return true;
+        }
+        if (!(fragment instanceof DashboardFragment)) {
+            return true;
+        }
+
+        final Indexable.SearchIndexProvider provider =
+                DatabaseIndexingUtils.getSearchIndexProvider(clazz);
+        if (provider == null) {
+            return true;
+        }
+        final List<PreferenceController> controllersFromSearchIndexProvider;
+        final List<PreferenceController> controllersFromFragment;
+        try {
+            controllersFromSearchIndexProvider = provider.getPreferenceControllers(context);
+        } catch (Throwable e) {
+            // Can't do much with exception, assume the test passed.
+            return true;
+        }
+        try {
+            controllersFromFragment =
+                    ((DashboardFragment) fragment).getPreferenceControllers(context);
+        } catch (Throwable e) {
+            // Can't do much with exception, assume the test passed.
+            return true;
+        }
+
+        if (controllersFromFragment == controllersFromSearchIndexProvider) {
+            return true;
+        } else if (controllersFromFragment != null && controllersFromSearchIndexProvider != null) {
+            return controllersFromFragment.size() == controllersFromSearchIndexProvider.size();
+        } else {
+            return false;
+        }
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
index 0a74cc4..5455b13 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
@@ -47,6 +47,7 @@
 import static org.mockito.Answers.RETURNS_DEEP_STUBS;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
@@ -117,6 +118,7 @@
         mController = new BuildNumberPreferenceController(
                 context, mActivity, mFragment, mLifecycle);
         ReflectionHelpers.setField(mController, "mContext", context);
+        ReflectionHelpers.setField(mController, "mUm", mUserManager);
 
         assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
         verify(mFactory.metricsFeatureProvider).action(
diff --git a/tests/robotests/src/com/android/settings/search/SearchIndexProviderCodeInspector.java b/tests/robotests/src/com/android/settings/search/SearchIndexProviderCodeInspector.java
index 3c820ec..801b509 100644
--- a/tests/robotests/src/com/android/settings/search/SearchIndexProviderCodeInspector.java
+++ b/tests/robotests/src/com/android/settings/search/SearchIndexProviderCodeInspector.java
@@ -21,6 +21,7 @@
 
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.core.codeinspection.CodeInspector;
+import com.android.settings.dashboard.DashboardFragmentSearchIndexProviderInspector;
 
 import java.lang.reflect.Field;
 import java.util.ArrayList;
@@ -40,6 +41,9 @@
     private static final String NOT_CONTAINING_PROVIDER_OBJECT_ERROR =
             "Indexable should have public field " + Index.FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER
                     + " but these are not:\n";
+    private static final String NOT_SHARING_PREF_CONTROLLERS_BETWEEN_FRAG_AND_PROVIDER =
+            "DashboardFragment should share pref controllers with its SearchIndexProvider, but "
+                    + " these are not: \n";
     private static final String NOT_IN_INDEXABLE_PROVIDER_REGISTRY =
             "Class containing " + Index.FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + " must be added to "
                     + SearchIndexableResources.class.getName() + " but these are not: \n";
@@ -47,18 +51,22 @@
     private final List<String> notImplementingIndexableGrandfatherList;
     private final List<String> notImplementingIndexProviderGrandfatherList;
     private final List<String> notInSearchIndexableRegistryGrandfatherList;
+    private final List<String> notSharingPrefControllersGrandfatherList;
 
     public SearchIndexProviderCodeInspector(List<Class<?>> classes) {
         super(classes);
         notImplementingIndexableGrandfatherList = new ArrayList<>();
         notImplementingIndexProviderGrandfatherList = new ArrayList<>();
         notInSearchIndexableRegistryGrandfatherList = new ArrayList<>();
+        notSharingPrefControllersGrandfatherList = new ArrayList<>();
         initializeGrandfatherList(notImplementingIndexableGrandfatherList,
                 "grandfather_not_implementing_indexable");
         initializeGrandfatherList(notImplementingIndexProviderGrandfatherList,
                 "grandfather_not_implementing_index_provider");
         initializeGrandfatherList(notInSearchIndexableRegistryGrandfatherList,
                 "grandfather_not_in_search_index_provider_registry");
+        initializeGrandfatherList(notSharingPrefControllersGrandfatherList,
+                "grandfather_not_sharing_pref_controllers_with_search_provider");
     }
 
     @Override
@@ -66,6 +74,7 @@
         final Set<String> notImplementingIndexable = new ArraySet<>();
         final Set<String> notImplementingIndexProvider = new ArraySet<>();
         final Set<String> notInSearchProviderRegistry = new ArraySet<>();
+        final Set<String> notSharingPreferenceControllers = new ArraySet<>();
 
         for (Class clazz : mClasses) {
             if (!isConcreteSettingsClass(clazz)) {
@@ -78,20 +87,36 @@
             }
             // If it's a SettingsPreferenceFragment, it must also be Indexable.
             final boolean implementsIndexable = Indexable.class.isAssignableFrom(clazz);
-            if (!implementsIndexable
-                    && !notImplementingIndexableGrandfatherList.contains(className)) {
-                notImplementingIndexable.add(className);
+            if (!implementsIndexable) {
+                if (!notImplementingIndexableGrandfatherList.contains(className)) {
+                    notImplementingIndexable.add(className);
+                }
+                continue;
             }
             final boolean hasSearchIndexProvider = hasSearchIndexProvider(clazz);
             // If it implements Indexable, it must also implement the index provider field.
-            if (implementsIndexable && !hasSearchIndexProvider
-                    && !notImplementingIndexProviderGrandfatherList.contains(className)) {
-                notImplementingIndexProvider.add(className);
+            if (!hasSearchIndexProvider) {
+                if (!notImplementingIndexProviderGrandfatherList.contains(className)) {
+                    notImplementingIndexProvider.add(className);
+                }
+                continue;
             }
-            if (hasSearchIndexProvider
-                    && SearchIndexableResources.getResourceByName(className) == null
-                    && !notInSearchIndexableRegistryGrandfatherList.contains(className)) {
-                notInSearchProviderRegistry.add(className);
+            // If it implements index provider field AND it's a DashboardFragment, its fragment and
+            // search provider must share the same set of PreferenceControllers.
+            final boolean isSharingPrefControllers = DashboardFragmentSearchIndexProviderInspector
+                    .isSharingPreferenceControllers(clazz);
+            if (!isSharingPrefControllers) {
+                if (!notSharingPrefControllersGrandfatherList.contains(className)) {
+                    notSharingPreferenceControllers.add(className);
+                }
+                continue;
+            }
+            // Must be in SearchProviderRegistry
+            if (SearchIndexableResources.getResourceByName(className) == null) {
+                if (!notInSearchIndexableRegistryGrandfatherList.contains(className)) {
+                    notInSearchProviderRegistry.add(className);
+                }
+                continue;
             }
         }
 
@@ -100,15 +125,21 @@
                 notImplementingIndexable);
         final String indexProviderError = buildErrorMessage(NOT_CONTAINING_PROVIDER_OBJECT_ERROR,
                 notImplementingIndexProvider);
+        final String notSharingPrefControllerError = buildErrorMessage(
+                NOT_SHARING_PREF_CONTROLLERS_BETWEEN_FRAG_AND_PROVIDER,
+                notSharingPreferenceControllers);
         final String notInProviderRegistryError =
                 buildErrorMessage(NOT_IN_INDEXABLE_PROVIDER_REGISTRY, notInSearchProviderRegistry);
         assertWithMessage(indexableError)
                 .that(notImplementingIndexable)
                 .isEmpty();
-        assertWithMessage(indexProviderError.toString())
+        assertWithMessage(indexProviderError)
                 .that(notImplementingIndexProvider)
                 .isEmpty();
-        assertWithMessage(notInProviderRegistryError.toString())
+        assertWithMessage(notSharingPrefControllerError)
+                .that(notSharingPreferenceControllers)
+                .isEmpty();
+        assertWithMessage(notInProviderRegistryError)
                 .that(notInSearchProviderRegistry)
                 .isEmpty();
     }