diff --git a/res/xml/display_settings_v2.xml b/res/xml/display_settings_v2.xml
new file mode 100644
index 00000000000..ff08c9a36d0
--- /dev/null
+++ b/res/xml/display_settings_v2.xml
@@ -0,0 +1,143 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/xml/top_level_settings_grouped.xml b/res/xml/top_level_settings_grouped.xml
index cdfab91411b..adfdfa3b0c2 100644
--- a/res/xml/top_level_settings_grouped.xml
+++ b/res/xml/top_level_settings_grouped.xml
@@ -22,13 +22,13 @@
@@ -36,27 +36,27 @@
android:fragment="com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment"
android:icon="@drawable/ic_homepage_connected_device"
android:key="top_level_connected_devices"
- android:order="-120"
+ android:order="-130"
android:title="@string/connected_devices_dashboard_title"
settings:controller="com.android.settings.connecteddevice.TopLevelConnectedDevicesPreferenceController"/>
@@ -64,13 +64,13 @@
@@ -78,7 +78,7 @@
android:fragment="com.android.settings.deviceinfo.StorageSettings"
android:icon="@drawable/ic_homepage_storage"
android:key="top_level_storage"
- android:order="-80"
+ android:order="-90"
android:title="@string/storage_settings"
settings:controller="com.android.settings.deviceinfo.TopLevelStoragePreferenceController"/>
@@ -86,17 +86,24 @@
android:fragment="com.android.settings.notification.SoundSettings"
android:icon="@drawable/ic_homepage_sound"
android:key="top_level_sound"
- android:order="-70"
+ android:order="-80"
android:title="@string/sound_settings"/>
+
+
getXmlResourcesToIndex(
+ Context context, boolean enabled) {
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = FeatureFlagUtils.isEnabled(context, FeatureFlags.SILKY_HOME)
+ ? R.xml.display_settings_v2 : R.xml.display_settings;
+ return Arrays.asList(sir);
+ }
@Override
public List createPreferenceControllers(
diff --git a/src/com/android/settings/display/TopLevelWallpaperPreferenceController.java b/src/com/android/settings/display/TopLevelWallpaperPreferenceController.java
new file mode 100644
index 00000000000..beef4f30073
--- /dev/null
+++ b/src/com/android/settings/display/TopLevelWallpaperPreferenceController.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2020 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.display;
+
+import static android.os.UserManager.DISALLOW_SET_WALLPAPER;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.RestrictedLockUtilsInternal;
+import com.android.settingslib.RestrictedTopLevelPreference;
+
+import java.util.List;
+
+/** This controller manages the wallpaper preference of the top level page. */
+public class TopLevelWallpaperPreferenceController extends BasePreferenceController {
+ private static final String TAG = "TopLevelWallpaperPreferenceController";
+ private static final String LAUNCHED_SETTINGS = "app_launched_settings";
+
+ private final String mWallpaperPackage;
+ private final String mWallpaperClass;
+ private final String mStylesAndWallpaperClass;
+ private final String mWallpaperLaunchExtra;
+
+ public TopLevelWallpaperPreferenceController(Context context, String key) {
+ super(context, key);
+ mWallpaperPackage = mContext.getString(R.string.config_wallpaper_picker_package);
+ mWallpaperClass = mContext.getString(R.string.config_wallpaper_picker_class);
+ mStylesAndWallpaperClass =
+ mContext.getString(R.string.config_styles_and_wallpaper_picker_class);
+ mWallpaperLaunchExtra = mContext.getString(R.string.config_wallpaper_picker_launch_extra);
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ Preference preference = screen.findPreference(getPreferenceKey());
+ preference.setTitle(getTitle());
+ }
+
+ public String getTitle() {
+ return mContext.getString(areStylesAvailable()
+ ? R.string.style_and_wallpaper_settings_title : R.string.wallpaper_settings_title);
+ }
+
+ public ComponentName getComponentName() {
+ return new ComponentName(mWallpaperPackage, getComponentClassString());
+ }
+
+ public String getComponentClassString() {
+ return areStylesAvailable() ? mStylesAndWallpaperClass : mWallpaperClass;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if ((TextUtils.isEmpty(mWallpaperClass) && TextUtils.isEmpty(mStylesAndWallpaperClass))
+ || TextUtils.isEmpty(mWallpaperPackage)) {
+ Log.e(TAG, "No Wallpaper picker specified!");
+ return UNSUPPORTED_ON_DEVICE;
+ }
+ return canResolveWallpaperComponent(getComponentClassString())
+ ? AVAILABLE_UNSEARCHABLE : CONDITIONALLY_UNAVAILABLE;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ disablePreferenceIfManaged((RestrictedTopLevelPreference) preference);
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (getPreferenceKey().equals(preference.getKey())) {
+ final Intent intent = new Intent().setComponent(
+ getComponentName()).putExtra(mWallpaperLaunchExtra, LAUNCHED_SETTINGS);
+ if (areStylesAvailable()) {
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ }
+ preference.getContext().startActivity(intent);
+ return true;
+ }
+ return super.handlePreferenceTreeClick(preference);
+ }
+
+ /** Returns whether Styles & Wallpaper is enabled and available. */
+ public boolean areStylesAvailable() {
+ return !TextUtils.isEmpty(mStylesAndWallpaperClass)
+ && canResolveWallpaperComponent(mStylesAndWallpaperClass);
+ }
+
+ private boolean canResolveWallpaperComponent(String className) {
+ final ComponentName componentName = new ComponentName(mWallpaperPackage, className);
+ final PackageManager pm = mContext.getPackageManager();
+ final Intent intent = new Intent().setComponent(componentName);
+ final List resolveInfos = pm.queryIntentActivities(intent, 0 /* flags */);
+ return resolveInfos != null && !resolveInfos.isEmpty();
+ }
+
+ private void disablePreferenceIfManaged(RestrictedTopLevelPreference pref) {
+ final String restriction = DISALLOW_SET_WALLPAPER;
+ if (pref != null) {
+ pref.setDisabledByAdmin(null);
+ if (RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext,
+ restriction, UserHandle.myUserId())) {
+ // Do not show the admin dialog for system restriction.
+ pref.setEnabled(false);
+ } else {
+ pref.checkRestrictionAndSetDisabled(restriction);
+ }
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/display/TopLevelWallpaperPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/TopLevelWallpaperPreferenceControllerTest.java
new file mode 100644
index 00000000000..7b3ae659c33
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/display/TopLevelWallpaperPreferenceControllerTest.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2020 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.display;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+
+import androidx.fragment.app.FragmentActivity;
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+
+import com.google.common.collect.Lists;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.Shadows;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowPackageManager;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {SettingsShadowResources.class})
+public class TopLevelWallpaperPreferenceControllerTest {
+ private static final String TEST_KEY = "test_key";
+
+ private Intent mWallpaperIntent;
+ private Intent mStylesAndWallpaperIntent;
+ private FragmentActivity mContext;
+ private ShadowPackageManager mShadowPackageManager;
+
+ private TopLevelWallpaperPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = Robolectric.buildActivity(FragmentActivity.class).get();
+ SettingsShadowResources.overrideResource(
+ R.string.config_wallpaper_picker_package, "bogus.package.for.testing");
+ SettingsShadowResources.overrideResource(
+ R.string.config_styles_and_wallpaper_picker_class, "bogus.package.class");
+ mWallpaperIntent = new Intent().setComponent(new ComponentName(
+ mContext.getString(R.string.config_wallpaper_picker_package),
+ mContext.getString(R.string.config_wallpaper_picker_class)));
+ mStylesAndWallpaperIntent = new Intent().setComponent(new ComponentName(
+ mContext.getString(R.string.config_wallpaper_picker_package),
+ mContext.getString(R.string.config_styles_and_wallpaper_picker_class)));
+ mShadowPackageManager = Shadows.shadowOf(mContext.getPackageManager());
+ mController = new TopLevelWallpaperPreferenceController(mContext, TEST_KEY);
+ }
+
+ @Test
+ public void isAvailable_wallpaperPickerEnabledAndStylePickerEnabled_returnsTrue() {
+ mShadowPackageManager.setResolveInfosForIntent(
+ mWallpaperIntent, Lists.newArrayList(mock(ResolveInfo.class)));
+ mShadowPackageManager.setResolveInfosForIntent(
+ mStylesAndWallpaperIntent, Lists.newArrayList(mock(ResolveInfo.class)));
+
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isAvailable_wallpaperPickerEnabledAndStylePickerDisabled_returnsTrue() {
+ mShadowPackageManager.setResolveInfosForIntent(
+ mWallpaperIntent, Lists.newArrayList(mock(ResolveInfo.class)));
+ mShadowPackageManager.setResolveInfosForIntent(
+ mStylesAndWallpaperIntent, Lists.newArrayList());
+
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isAvailable_wallpaperPickerDisabledAndStylePickerEnabled_returnsTrue() {
+ mShadowPackageManager.setResolveInfosForIntent(
+ mWallpaperIntent, Lists.newArrayList());
+ mShadowPackageManager.setResolveInfosForIntent(
+ mStylesAndWallpaperIntent, Lists.newArrayList(mock(ResolveInfo.class)));
+
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isAvailable_wallpaperPickerDisabledAndStylePickerDisabled_returnsFalse() {
+ mShadowPackageManager.setResolveInfosForIntent(
+ mWallpaperIntent, Lists.newArrayList());
+ mShadowPackageManager.setResolveInfosForIntent(
+ mStylesAndWallpaperIntent, Lists.newArrayList());
+
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void getComponentClassString_stylesAvailable_returnsStylePickerClassString() {
+ mShadowPackageManager.setResolveInfosForIntent(
+ mStylesAndWallpaperIntent,
+ Lists.newArrayList(mock(ResolveInfo.class)));
+ assertThat(mController.getComponentClassString())
+ .isEqualTo(mContext.getString(R.string.config_styles_and_wallpaper_picker_class));
+ }
+
+ @Test
+ public void getComponentClassString_stylesUnavailable_returnsWallpaperPickerClassString() {
+ mShadowPackageManager.setResolveInfosForIntent(
+ mStylesAndWallpaperIntent, Lists.newArrayList());
+ assertThat(mController.getComponentClassString())
+ .isEqualTo(mContext.getString(R.string.config_wallpaper_picker_class));
+ }
+
+ @Test
+ public void areStylesAvailable_noComponentSpecified() {
+ SettingsShadowResources.overrideResource(
+ R.string.config_styles_and_wallpaper_picker_class, "");
+ mShadowPackageManager.setResolveInfosForIntent(
+ mStylesAndWallpaperIntent, Lists.newArrayList());
+
+ assertThat(mController.areStylesAvailable()).isFalse();
+ }
+
+ @Test
+ public void areStylesAvailable_componentUnresolveable() {
+ mShadowPackageManager.setResolveInfosForIntent(
+ mStylesAndWallpaperIntent, Lists.newArrayList());
+
+ assertThat(mController.areStylesAvailable()).isFalse();
+ }
+
+ @Test
+ public void areStylesAvailable_componentResolved() {
+ mShadowPackageManager.setResolveInfosForIntent(
+ mStylesAndWallpaperIntent,
+ Lists.newArrayList(mock(ResolveInfo.class)));
+
+ assertThat(mController.areStylesAvailable()).isTrue();
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_wallpaperOnly() {
+ mShadowPackageManager.setResolveInfosForIntent(
+ mWallpaperIntent, Lists.newArrayList(mock(ResolveInfo.class)));
+ mShadowPackageManager.setResolveInfosForIntent(
+ mStylesAndWallpaperIntent, Lists.newArrayList());
+ Preference preference = new Preference(mContext);
+ preference.setKey(TEST_KEY);
+
+ mController.handlePreferenceTreeClick(preference);
+
+ assertThat(Shadows.shadowOf(mContext)
+ .getNextStartedActivityForResult().intent.getComponent().getClassName())
+ .isEqualTo(mContext.getString(R.string.config_wallpaper_picker_class));
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_stylesAndWallpaper() {
+ mShadowPackageManager.setResolveInfosForIntent(
+ mWallpaperIntent, Lists.newArrayList());
+ mShadowPackageManager.setResolveInfosForIntent(
+ mStylesAndWallpaperIntent, Lists.newArrayList(mock(ResolveInfo.class)));
+ Preference preference = new Preference(mContext);
+ preference.setKey(TEST_KEY);
+
+ mController.handlePreferenceTreeClick(preference);
+
+ assertThat(Shadows.shadowOf(mContext)
+ .getNextStartedActivityForResult().intent.getComponent().getClassName())
+ .isEqualTo(mContext.getString(R.string.config_styles_and_wallpaper_picker_class));
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_launchSourceExtra() {
+ mShadowPackageManager.setResolveInfosForIntent(
+ mWallpaperIntent, Lists.newArrayList());
+ mShadowPackageManager.setResolveInfosForIntent(
+ mStylesAndWallpaperIntent, Lists.newArrayList());
+ Preference preference = new Preference(mContext);
+ preference.setKey(TEST_KEY);
+
+ mController.handlePreferenceTreeClick(preference);
+
+ assertThat(Shadows.shadowOf(mContext).getNextStartedActivityForResult()
+ .intent.hasExtra("com.android.wallpaper.LAUNCH_SOURCE")).isTrue();
+ }
+}