From 3932b073658789cd20b35b204b58001025a08cca Mon Sep 17 00:00:00 2001 From: Yanting Yang Date: Fri, 20 Nov 2020 04:08:10 +0800 Subject: [PATCH] Move Styles & wallpapers to the homepage group - Add Styles & wallpapers to the homepage group. - Create a new display settings xml for the silky home. - Remove Styles & wallpapers from new display settings xml. - Apply the RestrictedTopLevelPreference to remove the restricted icon. Bug: 168166015 Bug: 174964139 Test: robotest & visual with turning on/off silky home Change-Id: Ib495b39bc62413242247f7e767c0e44bacc6e937 --- res/xml/display_settings_v2.xml | 143 ++++++++++++ res/xml/top_level_settings_grouped.xml | 29 ++- src/com/android/settings/DisplaySettings.java | 18 +- ...TopLevelWallpaperPreferenceController.java | 136 ++++++++++++ ...evelWallpaperPreferenceControllerTest.java | 205 ++++++++++++++++++ 5 files changed, 519 insertions(+), 12 deletions(-) create mode 100644 res/xml/display_settings_v2.xml create mode 100644 src/com/android/settings/display/TopLevelWallpaperPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/display/TopLevelWallpaperPreferenceControllerTest.java 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(); + } +}