diff --git a/res/drawable/audio_sharing_rounded_bg.xml b/res/drawable/audio_sharing_rounded_bg.xml index db1e1bbe3fb..35517ea0ec1 100644 --- a/res/drawable/audio_sharing_rounded_bg.xml +++ b/res/drawable/audio_sharing_rounded_bg.xml @@ -15,8 +15,10 @@ ~ limitations under the License. --> - - + \ No newline at end of file diff --git a/res/layout-land/bluetooth_audio_streams_qr_code.xml b/res/layout-land/bluetooth_audio_streams_qr_code.xml index b35bc65f84f..17151979074 100644 --- a/res/layout-land/bluetooth_audio_streams_qr_code.xml +++ b/res/layout-land/bluetooth_audio_streams_qr_code.xml @@ -48,7 +48,7 @@ android:id="@+id/qrcode_view" android:layout_width="@dimen/qrcode_size" android:layout_height="@dimen/qrcode_size" - android:contentDescription="@string/audio_streams_qr_code_page_image_label" + android:contentDescription="@string/qr_code_content_description" android:focusable="true" /> @@ -27,6 +28,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="4dp" + android:textColor="?androidprv:attr/textColorOnAccent" android:background="@drawable/audio_sharing_rounded_bg_ripple" android:textAlignment="center" /> diff --git a/res/layout/bluetooth_audio_streams_qr_code.xml b/res/layout/bluetooth_audio_streams_qr_code.xml index fd521febc4a..ae2d4e0764b 100644 --- a/res/layout/bluetooth_audio_streams_qr_code.xml +++ b/res/layout/bluetooth_audio_streams_qr_code.xml @@ -48,7 +48,7 @@ android:id="@+id/qrcode_view" android:layout_width="@dimen/qrcode_size" android:layout_height="@dimen/qrcode_size" - android:contentDescription="@string/audio_streams_qr_code_page_image_label" + android:contentDescription="@string/qr_code_content_description" android:focusable="true"/> - @@ -60,6 +62,7 @@ android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginTop="4dp" + android:textColor="?androidprv:attr/textColorOnAccent" android:background="@drawable/audio_sharing_rounded_bg_ripple" android:visibility="gone" /> @@ -70,6 +73,7 @@ android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginTop="4dp" + android:textColor="?androidprv:attr/textColorOnAccent" android:background="@drawable/audio_sharing_rounded_bg_ripple" android:visibility="gone" /> diff --git a/res/values/strings.xml b/res/values/strings.xml index 154218a47da..5fa003176ed 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -78,6 +78,8 @@ Preview + + QR code Make smaller @@ -1896,8 +1898,6 @@ Restart - - mirror, external display, connected display, usb display, resolution, rotation On @@ -13762,8 +13762,6 @@ Scan an audio stream QR code to listen with %1$s Can\u0027t edit password while sharing. To change the password, first turn off audio sharing. - - QR code QR code scanner diff --git a/res/xml/external_display_settings.xml b/res/xml/external_display_settings.xml index 00472115e0c..e4dc5bbc12b 100644 --- a/res/xml/external_display_settings.xml +++ b/res/xml/external_display_settings.xml @@ -17,6 +17,5 @@ diff --git a/src/com/android/settings/MainClearConfirm.java b/src/com/android/settings/MainClearConfirm.java index 042c5c26c1a..a5fbebf6e8e 100644 --- a/src/com/android/settings/MainClearConfirm.java +++ b/src/com/android/settings/MainClearConfirm.java @@ -89,8 +89,7 @@ public class MainClearConfirm extends InstrumentedFragment { final PersistentDataBlockManager pdbManager; // pre-flight check hardware support PersistentDataBlockManager if (!SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP).equals("")) { - pdbManager = (PersistentDataBlockManager) - getActivity().getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE); + pdbManager = getActivity().getSystemService(PersistentDataBlockManager.class); } else { pdbManager = null; } @@ -152,6 +151,11 @@ public class MainClearConfirm extends InstrumentedFragment { return false; } + // Do not try to erase factory reset protection data if the protection is alive. + if (pdbManager.isFactoryResetProtectionActive()) { + return false; + } + // The persistent data block will persist if the device is still being provisioned. if (isDeviceStillBeingProvisioned()) { return false; diff --git a/src/com/android/settings/backup/SettingsBackupHelper.java b/src/com/android/settings/backup/SettingsBackupHelper.java index 556ab725c28..73760a42a44 100644 --- a/src/com/android/settings/backup/SettingsBackupHelper.java +++ b/src/com/android/settings/backup/SettingsBackupHelper.java @@ -28,19 +28,30 @@ import com.android.settingslib.datastore.BackupRestoreStorageManager; /** Backup agent for Settings APK */ public class SettingsBackupHelper extends BackupAgentHelper { public static final String SOUND_BACKUP_HELPER = "SoundSettingsBackup"; + public static final String ACCESSIBILITY_APPEARANCE_BACKUP_HELPER = + "AccessibilityAppearanceSettingsBackup"; @Override public void onCreate() { super.onCreate(); BackupRestoreStorageManager.getInstance(this).addBackupAgentHelpers(this); + OnboardingFeatureProvider onboardingFeatureProvider = + FeatureFactory.getFeatureFactory().getOnboardingFeatureProvider(); + if (Flags.enableSoundBackup()) { - OnboardingFeatureProvider onboardingFeatureProvider = - FeatureFactory.getFeatureFactory().getOnboardingFeatureProvider(); if (onboardingFeatureProvider != null) { addHelper(SOUND_BACKUP_HELPER, onboardingFeatureProvider. getSoundBackupHelper(this, this.getBackupRestoreEventLogger())); } } + + if (Flags.accessibilityAppearanceSettingsBackupEnabled()) { + if (onboardingFeatureProvider != null) { + addHelper(ACCESSIBILITY_APPEARANCE_BACKUP_HELPER, + onboardingFeatureProvider.getAccessibilityAppearanceBackupHelper( + this, this.getBackupRestoreEventLogger())); + } + } } @Override diff --git a/src/com/android/settings/connecteddevice/display/ExternalDisplayPreferenceFragment.java b/src/com/android/settings/connecteddevice/display/ExternalDisplayPreferenceFragment.java index 09f8e92ea49..7b5bef625f6 100644 --- a/src/com/android/settings/connecteddevice/display/ExternalDisplayPreferenceFragment.java +++ b/src/com/android/settings/connecteddevice/display/ExternalDisplayPreferenceFragment.java @@ -48,9 +48,6 @@ import com.android.settings.SettingsPreferenceFragmentBase; import com.android.settings.connecteddevice.display.ExternalDisplaySettingsConfiguration.DisplayListener; import com.android.settings.connecteddevice.display.ExternalDisplaySettingsConfiguration.Injector; import com.android.settings.core.SubSettingLauncher; -import com.android.settings.search.BaseSearchIndexProvider; -import com.android.settingslib.search.Indexable; -import com.android.settingslib.search.SearchIndexable; import com.android.settingslib.widget.FooterPreference; import com.android.settingslib.widget.IllustrationPreference; import com.android.settingslib.widget.MainSwitchPreference; @@ -63,12 +60,8 @@ import java.util.List; /** * The Settings screen for External Displays configuration and connection management. */ -@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) -public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmentBase - implements Indexable { +public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmentBase { static final int EXTERNAL_DISPLAY_SETTINGS_RESOURCE = R.xml.external_display_settings; - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider(EXTERNAL_DISPLAY_SETTINGS_RESOURCE); static final String DISPLAYS_LIST_PREFERENCE_KEY = "displays_list_preference"; static final String EXTERNAL_DISPLAY_USE_PREFERENCE_KEY = "external_display_use_preference"; static final String EXTERNAL_DISPLAY_ROTATION_KEY = "external_display_rotation"; @@ -77,7 +70,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen R.string.external_display_change_resolution_footer_title; static final int EXTERNAL_DISPLAY_LANDSCAPE_DRAWABLE = R.drawable.external_display_mirror_landscape; - static final int EXTERANAL_DISPLAY_TITLE_RESOURCE = + static final int EXTERNAL_DISPLAY_TITLE_RESOURCE = R.string.external_display_settings_title; static final int EXTERNAL_DISPLAY_USE_TITLE_RESOURCE = R.string.external_display_use_title; @@ -332,7 +325,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen return; } } - activity.setTitle(EXTERANAL_DISPLAY_TITLE_RESOURCE); + activity.setTitle(EXTERNAL_DISPLAY_TITLE_RESOURCE); } private void showTextWhenNoDisplaysToShow(@NonNull final PreferenceScreen screen, diff --git a/src/com/android/settings/connecteddevice/display/ExternalDisplaySettingsConfiguration.java b/src/com/android/settings/connecteddevice/display/ExternalDisplaySettingsConfiguration.java index 89d464c9a4e..c9ea8ae0a04 100644 --- a/src/com/android/settings/connecteddevice/display/ExternalDisplaySettingsConfiguration.java +++ b/src/com/android/settings/connecteddevice/display/ExternalDisplaySettingsConfiguration.java @@ -23,6 +23,8 @@ import static android.hardware.display.DisplayManager.EVENT_FLAG_DISPLAY_CONNECT import static android.hardware.display.DisplayManager.EVENT_FLAG_DISPLAY_REMOVED; import static android.view.Display.INVALID_DISPLAY; +import static com.android.server.display.feature.flags.Flags.enableModeLimitForExternalDisplay; + import android.content.Context; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerGlobal; @@ -271,6 +273,13 @@ public class ExternalDisplaySettingsConfiguration { public void setUserPreferredDisplayMode(int displayId, @NonNull Mode mode) { DisplayManagerGlobal.getInstance().setUserPreferredDisplayMode(displayId, mode); } + + /** + * @return true if the display mode limit flag enabled. + */ + public boolean isModeLimitForExternalDisplayEnabled() { + return enableModeLimitForExternalDisplay(); + } } public abstract static class DisplayListener implements DisplayManager.DisplayListener { diff --git a/src/com/android/settings/connecteddevice/display/ResolutionPreferenceFragment.java b/src/com/android/settings/connecteddevice/display/ResolutionPreferenceFragment.java index 10314cb1e21..db81be89a42 100644 --- a/src/com/android/settings/connecteddevice/display/ResolutionPreferenceFragment.java +++ b/src/com/android/settings/connecteddevice/display/ResolutionPreferenceFragment.java @@ -52,7 +52,7 @@ import java.util.ArrayList; import java.util.HashSet; public class ResolutionPreferenceFragment extends SettingsPreferenceFragmentBase { - private static final String TAG = "ResolutionPreferenceFragment"; + private static final String TAG = "ResolutionPreference"; static final int DEFAULT_LOW_REFRESH_RATE = 60; static final String MORE_OPTIONS_KEY = "more_options"; static final String TOP_OPTIONS_KEY = "top_options"; @@ -60,6 +60,8 @@ public class ResolutionPreferenceFragment extends SettingsPreferenceFragmentBase R.string.external_display_more_options_title; static final int EXTERNAL_DISPLAY_RESOLUTION_SETTINGS_RESOURCE = R.xml.external_display_resolution_settings; + static final String DISPLAY_MODE_LIMIT_OVERRIDE_PROP = "persist.sys.com.android.server.display" + + ".feature.flags.enable_mode_limit_for_external_display-override"; @Nullable private Injector mInjector; @Nullable @@ -323,16 +325,29 @@ public class ResolutionPreferenceFragment extends SettingsPreferenceFragmentBase } } + private boolean isDisplayResolutionLimitEnabled() { + if (mInjector == null) { + return false; + } + var flagOverride = mInjector.getSystemProperty(DISPLAY_MODE_LIMIT_OVERRIDE_PROP); + var isOverrideEnabled = "true".equals(flagOverride); + var isOverrideEnabledOrNotSet = !"false".equals(flagOverride); + return (mInjector.isModeLimitForExternalDisplayEnabled() && isOverrideEnabledOrNotSet) + || isOverrideEnabled; + } + private void updateDisplayModeLimits(@Nullable Context context) { if (context == null) { return; } mExternalDisplayPeakRefreshRate = getResources(context).getInteger( com.android.internal.R.integer.config_externalDisplayPeakRefreshRate); - mExternalDisplayPeakWidth = getResources(context).getInteger( + if (isDisplayResolutionLimitEnabled()) { + mExternalDisplayPeakWidth = getResources(context).getInteger( com.android.internal.R.integer.config_externalDisplayPeakWidth); - mExternalDisplayPeakHeight = getResources(context).getInteger( + mExternalDisplayPeakHeight = getResources(context).getInteger( com.android.internal.R.integer.config_externalDisplayPeakHeight); + } mRefreshRateSynchronizationEnabled = getResources(context).getBoolean( com.android.internal.R.bool.config_refreshRateSynchronizationEnabled); Log.d(TAG, "mExternalDisplayPeakRefreshRate=" + mExternalDisplayPeakRefreshRate); diff --git a/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceController.java b/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceController.java index a1467c80ac5..467a8cac6bd 100644 --- a/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceController.java +++ b/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceController.java @@ -45,9 +45,10 @@ public class BluetoothMaxConnectedAudioDevicesPreferenceController extends super(context); final BluetoothManager bluetoothManager = context.getSystemService(BluetoothManager.class); - - mDefaultMaxConnectedAudioDevices = - bluetoothManager.getAdapter().getMaxConnectedAudioDevices(); + if(bluetoothManager != null && bluetoothManager.getAdapter() != null) { + mDefaultMaxConnectedAudioDevices = + bluetoothManager.getAdapter().getMaxConnectedAudioDevices(); + } } @Override diff --git a/src/com/android/settings/notification/modes/CircularIconsPreference.java b/src/com/android/settings/notification/modes/CircularIconsPreference.java index 1ce34766fdc..e3cd94848b0 100644 --- a/src/com/android/settings/notification/modes/CircularIconsPreference.java +++ b/src/com/android/settings/notification/modes/CircularIconsPreference.java @@ -51,6 +51,8 @@ import java.util.concurrent.Executor; public class CircularIconsPreference extends RestrictedPreference { + private static final float DISABLED_ITEM_ALPHA = 0.3f; + private Executor mUiExecutor; @Nullable private LinearLayout mIconContainer; @@ -98,6 +100,14 @@ public class CircularIconsPreference extends RestrictedPreference { displayIconsIfPending(); } + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + if (mIconContainer != null) { + applyEnabledToIcons(mIconContainer, enabled); + } + } + private void displayIconsIfPending() { CircularIconSet pendingIconSet = mPendingDisplayIconSet; if (pendingIconSet != null) { @@ -211,6 +221,8 @@ public class CircularIconsPreference extends RestrictedPreference { textView.setText(getContext().getString(R.string.zen_mode_plus_n_items, extraItems)); } + applyEnabledToIcons(mIconContainer, isEnabled()); + // Display icons when all are ready (more consistent than randomly loading). mPendingLoadIconsFuture = Futures.allAsList(iconFutures); FutureUtil.whenDone( @@ -224,6 +236,13 @@ public class CircularIconsPreference extends RestrictedPreference { mUiExecutor); } + private void applyEnabledToIcons(ViewGroup container, boolean enabled) { + for (int i = 0; i < container.getChildCount(); i++) { + View child = container.getChildAt(i); + child.setAlpha(enabled ? 1.0f : DISABLED_ITEM_ALPHA); + } + } + private static Drawable getPlaceholderImage(Context context) { ShapeDrawable placeholder = new ShapeDrawable(new OvalShape()); placeholder.setTintList(Utils.getColorAttr(context, @@ -249,6 +268,18 @@ public class CircularIconsPreference extends RestrictedPreference { return parent.getChildAt(parent.getChildCount() - 1); } + @VisibleForTesting(otherwise = VisibleForTesting.NONE) + List getViews() { + if (mIconContainer == null) { + return List.of(); + } + ArrayList views = new ArrayList<>(); + for (int i = 0; i < mIconContainer.getChildCount(); i++) { + views.add(mIconContainer.getChildAt(i)); + } + return views; + } + @VisibleForTesting(otherwise = VisibleForTesting.NONE) List getIcons() { if (mIconContainer == null) { diff --git a/src/com/android/settings/notification/modes/InterruptionFilterPreferenceController.java b/src/com/android/settings/notification/modes/InterruptionFilterPreferenceController.java index 8bdeea40762..9d4a1725bcc 100644 --- a/src/com/android/settings/notification/modes/InterruptionFilterPreferenceController.java +++ b/src/com/android/settings/notification/modes/InterruptionFilterPreferenceController.java @@ -44,6 +44,7 @@ class InterruptionFilterPreferenceController extends AbstractZenModePreferenceCo @Override public void updateState(Preference preference, @NonNull ZenMode zenMode) { + preference.setEnabled(zenMode.isEnabled()); boolean filteringNotifications = zenMode.getRule().getInterruptionFilter() != INTERRUPTION_FILTER_ALL; ((TwoStatePreference) preference).setChecked(filteringNotifications); diff --git a/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceController.java index 962e0162310..1521a8b4f09 100644 --- a/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceController.java +++ b/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceController.java @@ -34,7 +34,6 @@ import androidx.preference.Preference; import com.android.settings.R; import com.android.settings.Utils; -import com.android.settings.core.SubSettingLauncher; import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.applications.ApplicationsState.AppEntry; import com.android.settingslib.notification.modes.ZenMode; @@ -95,11 +94,11 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr Bundle bundle = new Bundle(); bundle.putString(EXTRA_AUTOMATIC_ZEN_RULE_ID, zenMode.getId()); // TODO(b/332937635): Update metrics category - preference.setIntent(new SubSettingLauncher(mContext) - .setDestination(ZenModeAppsFragment.class.getName()) - .setSourceMetricsCategory(0) - .setArguments(bundle) - .toIntent()); + preference.setIntent( + ZenSubSettingLauncher.forModeFragment(mContext, ZenModeAppsFragment.class, + zenMode.getId(), 0).toIntent()); + preference.setEnabled(zenMode.isEnabled()); + mZenMode = zenMode; mPreference = (CircularIconsPreference) preference; diff --git a/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceController.java index d3559f1cf5f..bba5e342732 100644 --- a/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceController.java +++ b/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceController.java @@ -24,7 +24,6 @@ import android.os.Bundle; import androidx.annotation.NonNull; import androidx.preference.Preference; -import com.android.settings.core.SubSettingLauncher; import com.android.settingslib.notification.modes.ZenMode; import com.android.settingslib.notification.modes.ZenModesBackend; @@ -43,11 +42,10 @@ class ZenModeDisplayLinkPreferenceController extends AbstractZenModePreferenceCo Bundle bundle = new Bundle(); bundle.putString(EXTRA_AUTOMATIC_ZEN_RULE_ID, zenMode.getId()); // TODO(b/332937635): Update metrics category - preference.setIntent(new SubSettingLauncher(mContext) - .setDestination(ZenModeDisplayFragment.class.getName()) - .setSourceMetricsCategory(0) - .setArguments(bundle) - .toIntent()); + preference.setIntent( + ZenSubSettingLauncher.forModeFragment(mContext, ZenModeDisplayFragment.class, + zenMode.getId(), 0).toIntent()); + preference.setEnabled(zenMode.isEnabled()); } @Override diff --git a/src/com/android/settings/notification/modes/ZenModeFragment.java b/src/com/android/settings/notification/modes/ZenModeFragment.java index 7d7631bef02..06612844dba 100644 --- a/src/com/android/settings/notification/modes/ZenModeFragment.java +++ b/src/com/android/settings/notification/modes/ZenModeFragment.java @@ -53,12 +53,15 @@ public class ZenModeFragment extends ZenModeFragmentBase { prefControllers.add(new ZenModeHeaderController(context, "header", this)); prefControllers.add( new ZenModeButtonPreferenceController(context, "activate", this, mBackend)); + prefControllers.add(new ZenModePreferenceCategoryController(context, "modes_filters")); prefControllers.add(new ZenModePeopleLinkPreferenceController( context, "zen_mode_people", mHelperBackend)); prefControllers.add(new ZenModeAppsLinkPreferenceController( context, "zen_mode_apps", this, mBackend, mHelperBackend)); prefControllers.add(new ZenModeOtherLinkPreferenceController( context, "zen_other_settings", mHelperBackend)); + prefControllers.add( + new ZenModePreferenceCategoryController(context, "modes_additional_actions")); prefControllers.add(new ZenModeDisplayLinkPreferenceController( context, "mode_display_settings", mBackend, mHelperBackend)); prefControllers.add(new ZenModeSetTriggerLinkPreferenceController(context, diff --git a/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java index d7bd5177aaf..15e0edcf1df 100644 --- a/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java +++ b/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java @@ -70,6 +70,7 @@ class ZenModeOtherLinkPreferenceController extends AbstractZenModePreferenceCont ZenSubSettingLauncher.forModeFragment(mContext, ZenModeOtherFragment.class, zenMode.getId(), 0).toIntent()); + preference.setEnabled(zenMode.isEnabled()); preference.setSummary(mSummaryHelper.getOtherSoundCategoriesSummary(zenMode)); ((CircularIconsPreference) preference).displayIcons(getSoundIcons(zenMode.getPolicy())); } diff --git a/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceController.java b/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceController.java index 762cdd57ca6..b5938c6d3ea 100644 --- a/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceController.java +++ b/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceController.java @@ -92,6 +92,7 @@ class ZenModePeopleLinkPreferenceController extends AbstractZenModePreferenceCon ZenSubSettingLauncher.forModeFragment(mContext, ZenModePeopleFragment.class, zenMode.getId(), 0).toIntent()); + preference.setEnabled(zenMode.isEnabled()); preference.setSummary(mSummaryHelper.getPeopleSummary(zenMode.getPolicy())); ((CircularIconsPreference) preference).displayIcons(getPeopleIcons(zenMode.getPolicy())); } diff --git a/src/com/android/settings/notification/modes/ZenModePreferenceCategoryController.java b/src/com/android/settings/notification/modes/ZenModePreferenceCategoryController.java new file mode 100644 index 00000000000..6ebcb1fd1f2 --- /dev/null +++ b/src/com/android/settings/notification/modes/ZenModePreferenceCategoryController.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 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.notification.modes; + +import android.content.Context; + +import androidx.annotation.NonNull; +import androidx.preference.Preference; + +import com.android.settingslib.notification.modes.ZenMode; + +/** + * Simple {@link AbstractZenModePreferenceController} used for all {@code PreferenceCategory} + * entries in {@link ZenModeFragment} that should be disabled when the mode is disabled. + */ +class ZenModePreferenceCategoryController extends AbstractZenModePreferenceController { + ZenModePreferenceCategoryController(@NonNull Context context, @NonNull String key) { + super(context, key); + } + + @Override + void updateState(Preference preference, @NonNull ZenMode zenMode) { + preference.setEnabled(zenMode.isEnabled()); + } +} diff --git a/src/com/android/settings/onboarding/OnboardingFeatureProvider.kt b/src/com/android/settings/onboarding/OnboardingFeatureProvider.kt index f76e29a8353..58afb25b92d 100644 --- a/src/com/android/settings/onboarding/OnboardingFeatureProvider.kt +++ b/src/com/android/settings/onboarding/OnboardingFeatureProvider.kt @@ -39,4 +39,12 @@ interface OnboardingFeatureProvider { * @param logger To log B&R stats. */ fun getSoundBackupHelper(context: Context, logger: BackupRestoreEventLogger): BackupHelper + + /** + * Return a BackupHelper for backup accessibility appearance related settings. + * + * @param context App context + * @param logger To log B&R stats. + */ + fun getAccessibilityAppearanceBackupHelper(context: Context, logger: BackupRestoreEventLogger): BackupHelper } \ No newline at end of file diff --git a/src/com/android/settings/widget/HighlightableTopLevelPreferenceAdapter.java b/src/com/android/settings/widget/HighlightableTopLevelPreferenceAdapter.java index 9ddec5cb0c5..15e83de9149 100644 --- a/src/com/android/settings/widget/HighlightableTopLevelPreferenceAdapter.java +++ b/src/com/android/settings/widget/HighlightableTopLevelPreferenceAdapter.java @@ -17,6 +17,7 @@ package com.android.settings.widget; import android.content.Context; +import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.text.TextUtils; import android.util.Log; @@ -212,6 +213,14 @@ public class HighlightableTopLevelPreferenceAdapter extends RoundCornerPreferenc // Scroll to the top to reset the position. mRecyclerView.nestedScrollBy(0, -mRecyclerView.getHeight()); + // get the visible area of the recycler view + Rect rvRect = new Rect(); + mRecyclerView.getGlobalVisibleRect(rvRect); + if (Flags.homepageRevamp() && view.getBottom() <= rvRect.height()) { + // the request position already fully visible in the visible area + return; + } + final int scrollY = view.getTop(); if (scrollY > 0) { mRecyclerView.nestedScrollBy(0, scrollY); diff --git a/src/com/android/settings/wifi/WifiConfigController2.java b/src/com/android/settings/wifi/WifiConfigController2.java index 70e08eb9033..1ea0103c28e 100644 --- a/src/com/android/settings/wifi/WifiConfigController2.java +++ b/src/com/android/settings/wifi/WifiConfigController2.java @@ -344,7 +344,7 @@ public class WifiConfigController2 implements TextWatcher, if (mPrivacySettingsSpinner != null) { final int prefMacValue = WifiPrivacyPreferenceController2 - .translateMacRandomizedValueToPrefValue(config.macRandomizationSetting); + .translateWifiEntryPrivacyToPrefValue(mWifiEntry.getPrivacy()); mPrivacySettingsSpinner.setSelection(prefMacValue); } @@ -863,7 +863,7 @@ public class WifiConfigController2 implements TextWatcher, if (mPrivacySettingsSpinner != null) { config.macRandomizationSetting = WifiPrivacyPreferenceController2 - .translatePrefValueToMacRandomizedValue(mPrivacySettingsSpinner + .translatePrefValueToWifiConfigSetting(mPrivacySettingsSpinner .getSelectedItemPosition()); } diff --git a/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java index 5d393e54a21..0c67c04622e 100644 --- a/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java +++ b/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java @@ -17,6 +17,7 @@ package com.android.settings.wifi.details2; import android.content.Context; +import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; import androidx.annotation.NonNull; @@ -98,30 +99,30 @@ public class WifiPrivacyPreferenceController2 extends BasePreferenceController i private static final int PREF_RANDOMIZATION_NONE = 1; /** - * Returns preference index value. + * Translates a WifiEntry.Privacy value to the matching preference index value. * - * @param macRandomized is mac randomized value + * @param privacy WifiEntry.Privacy value * @return index value of preference */ - public static int translateMacRandomizedValueToPrefValue(int macRandomized) { - return (macRandomized == WifiEntry.PRIVACY_RANDOMIZED_MAC) + public static int translateWifiEntryPrivacyToPrefValue(@WifiEntry.Privacy int privacy) { + return (privacy == WifiEntry.PRIVACY_RANDOMIZED_MAC) ? PREF_RANDOMIZATION_PERSISTENT : PREF_RANDOMIZATION_NONE; } /** - * Returns mac randomized value. + * Translates the pref value to WifiConfiguration.MacRandomizationSetting value * * @param prefMacRandomized is preference index value - * @return mac randomized value + * @return WifiConfiguration.MacRandomizationSetting value */ - public static int translatePrefValueToMacRandomizedValue(int prefMacRandomized) { + public static int translatePrefValueToWifiConfigSetting(int prefMacRandomized) { return (prefMacRandomized == PREF_RANDOMIZATION_PERSISTENT) - ? WifiEntry.PRIVACY_RANDOMIZED_MAC : WifiEntry.PRIVACY_DEVICE_MAC; + ? WifiConfiguration.RANDOMIZATION_AUTO : WifiConfiguration.RANDOMIZATION_NONE; } private void updateSummary(ListPreference preference, int macRandomized) { // Translates value here to set RANDOMIZATION_PERSISTENT as first item in UI for better UX. - final int prefMacRandomized = translateMacRandomizedValueToPrefValue(macRandomized); + final int prefMacRandomized = translateWifiEntryPrivacyToPrefValue(macRandomized); preference.setSummary(preference.getEntries()[prefMacRandomized]); } } diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java index 42a74dddc7f..40cf24d52eb 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java +++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java @@ -114,6 +114,7 @@ public class WifiDppQrCodeGeneratorFragment extends WifiDppQrCodeBaseFragment { super.onViewCreated(view, savedInstanceState); mQrCodeView = view.findViewById(R.id.qrcode_view); + mQrCodeView.setContentDescription(getString(R.string.qr_code_content_description)); final WifiNetworkConfig wifiNetworkConfig = getWifiNetworkConfigFromHostActivity(); if (wifiNetworkConfig.isHotspot()) { diff --git a/tests/robotests/src/com/android/settings/MainClearConfirmTest.java b/tests/robotests/src/com/android/settings/MainClearConfirmTest.java index 6d85368d0b8..f7711c81311 100644 --- a/tests/robotests/src/com/android/settings/MainClearConfirmTest.java +++ b/tests/robotests/src/com/android/settings/MainClearConfirmTest.java @@ -77,6 +77,7 @@ public class MainClearConfirmTest { when(mMockActivity.getSystemService(Context.DEVICE_POLICY_SERVICE)) .thenReturn(mDevicePolicyManager); + when(mPersistentDataBlockManager.isFactoryResetProtectionActive()).thenReturn(false); } @Test @@ -112,6 +113,13 @@ public class MainClearConfirmTest { assertThat(mMainClearConfirm.shouldWipePersistentDataBlock(null)).isFalse(); } + @Test + public void shouldWipePersistentDataBlock_frpIsAlive_shouldReturnFalse() { + when(mPersistentDataBlockManager.isFactoryResetProtectionActive()).thenReturn(true); + assertThat(mMainClearConfirm.shouldWipePersistentDataBlock(mPersistentDataBlockManager)) + .isFalse(); + } + @Test public void shouldWipePersistentDataBlock_deviceIsStillBeingProvisioned_shouldReturnFalse() { doReturn(true).when(mMainClearConfirm).isDeviceStillBeingProvisioned(); diff --git a/tests/robotests/src/com/android/settings/notification/modes/CircularIconsPreferenceTest.java b/tests/robotests/src/com/android/settings/notification/modes/CircularIconsPreferenceTest.java index 73754df349b..ce23fc4ba05 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/CircularIconsPreferenceTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/CircularIconsPreferenceTest.java @@ -226,4 +226,32 @@ public class CircularIconsPreferenceTest { mPreference.displayIcons(one); mPreference.displayIcons(same); // if no exception, wasn't called. } + + @Test + public void setEnabled_afterDisplayIcons_showsEnabledOrDisabledImages() { + CircularIconSet iconSet = new CircularIconSet<>(ImmutableList.of(1, 2), + ColorDrawable::new); + bindAndMeasureViewHolder(VIEW_WIDTH); + mPreference.displayIcons(iconSet); + assertThat(mPreference.getViews()).hasSize(2); + + mPreference.setEnabled(false); + assertThat(mPreference.getViews().get(0).getAlpha()).isLessThan(1f); + + mPreference.setEnabled(true); + assertThat(mPreference.getViews().get(0).getAlpha()).isEqualTo(1f); + } + + @Test + public void setEnabled_beforeDisplayIcons_showsEnabledOrDisabledImages() { + CircularIconSet iconSet = new CircularIconSet<>(ImmutableList.of(1, 2), + ColorDrawable::new); + + mPreference.setEnabled(false); + bindAndMeasureViewHolder(VIEW_WIDTH); + mPreference.displayIcons(iconSet); + + assertThat(mPreference.getViews()).hasSize(2); + assertThat(mPreference.getViews().get(0).getAlpha()).isLessThan(1f); + } } diff --git a/tests/robotests/src/com/android/settings/notification/modes/InterruptionFilterPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/InterruptionFilterPreferenceControllerTest.java index 61d31929f4f..0c3f8e1815d 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/InterruptionFilterPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/InterruptionFilterPreferenceControllerTest.java @@ -67,6 +67,18 @@ public final class InterruptionFilterPreferenceControllerTest { mController = new InterruptionFilterPreferenceController(mContext, "something", mBackend); } + @Test + public void testUpdateState_disabled() { + TwoStatePreference preference = mock(TwoStatePreference.class); + ZenMode zenMode = new TestModeBuilder() + .setEnabled(false) + .build(); + + mController.updateZenMode(preference, zenMode); + + verify(preference).setEnabled(false); + } + @Test public void testUpdateState_all() { TwoStatePreference preference = mock(TwoStatePreference.class); diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceControllerTest.java index cc4d30643f7..301ff9092e0 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceControllerTest.java @@ -141,6 +141,17 @@ public final class ZenModeAppsLinkPreferenceControllerTest { assertThat(mController.isAvailable()).isTrue(); } + @Test + public void testUpdateState_disabled() { + ZenMode zenMode = new TestModeBuilder() + .setEnabled(false) + .build(); + + mController.updateState(mPreference, zenMode); + + assertThat(mPreference.isEnabled()).isFalse(); + } + @Test public void testUpdateSetsIntent() { // Create a zen mode that allows priority channels to breakthrough. diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceControllerTest.java index 6c3d74fed8e..29350f6737f 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceControllerTest.java @@ -28,6 +28,7 @@ import android.platform.test.flag.junit.SetFlagsRule; import androidx.preference.Preference; import com.android.settingslib.notification.modes.TestModeBuilder; +import com.android.settingslib.notification.modes.ZenMode; import com.android.settingslib.notification.modes.ZenModesBackend; import org.junit.Before; @@ -61,6 +62,18 @@ public final class ZenModeDisplayLinkPreferenceControllerTest { mContext, "something", mBackend, mHelperBackend); } + @Test + public void testUpdateState_disabled() { + Preference preference = mock(Preference.class); + ZenMode zenMode = new TestModeBuilder() + .setEnabled(false) + .build(); + + mController.updateState(preference, zenMode); + + verify(preference).setEnabled(false); + } + @Test @EnableFlags(Flags.FLAG_MODES_UI) public void testHasSummary() { diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java index 7fa4f9f0e71..8aa87e6c903 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java @@ -61,6 +61,18 @@ public final class ZenModeOtherLinkPreferenceControllerTest { mContext, "something", mHelperBackend); } + @Test + public void updateState_disabled() { + CircularIconsPreference pref = mock(CircularIconsPreference.class); + ZenMode zenMode = new TestModeBuilder() + .setEnabled(false) + .build(); + + mController.updateZenMode(pref, zenMode); + + verify(pref).setEnabled(false); + } + @Test public void updateState_loadsSummary() { CircularIconsPreference pref = mock(CircularIconsPreference.class); diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java index 8ec980d30aa..63068fa201f 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java @@ -111,6 +111,17 @@ public final class ZenModePeopleLinkPreferenceControllerTest { anyBoolean())).thenReturn(new ColorDrawable(Color.BLACK)); } + @Test + public void updateState_disabled() { + ZenMode zenMode = new TestModeBuilder() + .setEnabled(false) + .build(); + + mController.updateState(mPreference, zenMode); + + assertThat(mPreference.isEnabled()).isFalse(); + } + @Test public void updateState_setsSummary() { mController.updateState(mPreference, TestModeBuilder.EXAMPLE); diff --git a/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java b/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java index 7d96496282e..d985ee5b9d3 100644 --- a/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java +++ b/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java @@ -459,46 +459,45 @@ public class WifiConfigController2Test { public void loadMacRandomizedValue_shouldPersistentAsDefault() { final Spinner privacySetting = mView.findViewById(R.id.privacy_settings); final int prefPersist = - WifiPrivacyPreferenceController2.translateMacRandomizedValueToPrefValue( - WifiConfiguration.RANDOMIZATION_PERSISTENT); + WifiPrivacyPreferenceController2.translateWifiEntryPrivacyToPrefValue( + WifiEntry.PRIVACY_RANDOMIZED_MAC); assertThat(privacySetting.getVisibility()).isEqualTo(View.VISIBLE); assertThat(privacySetting.getSelectedItemPosition()).isEqualTo(prefPersist); } @Test - public void loadSavedMacRandomizedPersistentValue_shouldCorrectMacValue() { - checkSavedMacRandomizedValue(WifiConfiguration.RANDOMIZATION_PERSISTENT); + public void loadSavedPrivacyRandomizedMacValue_shouldCorrectMacValue() { + checkSavedMacRandomizedValue(WifiEntry.PRIVACY_RANDOMIZED_MAC); } @Test - public void loadSavedMacRandomizedNoneValue_shouldCorrectMacValue() { - checkSavedMacRandomizedValue(WifiConfiguration.RANDOMIZATION_NONE); + public void loadSavedPrivacyDeviceMacValue_shouldCorrectMacValue() { + checkSavedMacRandomizedValue(WifiEntry.PRIVACY_DEVICE_MAC); } - private void checkSavedMacRandomizedValue(int macRandomizedValue) { + private void checkSavedMacRandomizedValue(@WifiEntry.Privacy int privacy) { when(mWifiEntry.isSaved()).thenReturn(true); final WifiConfiguration mockWifiConfig = spy(new WifiConfiguration()); when(mockWifiConfig.getIpConfiguration()).thenReturn(mock(IpConfiguration.class)); when(mWifiEntry.getWifiConfiguration()).thenReturn(mockWifiConfig); - mockWifiConfig.macRandomizationSetting = macRandomizedValue; + when(mWifiEntry.getPrivacy()).thenReturn(privacy); createController(mWifiEntry, WifiConfigUiBase2.MODE_CONNECT, false); final Spinner privacySetting = mView.findViewById(R.id.privacy_settings); final int expectedPrefValue = - WifiPrivacyPreferenceController2.translateMacRandomizedValueToPrefValue( - macRandomizedValue); + WifiPrivacyPreferenceController2.translateWifiEntryPrivacyToPrefValue(privacy); assertThat(privacySetting.getVisibility()).isEqualTo(View.VISIBLE); assertThat(privacySetting.getSelectedItemPosition()).isEqualTo(expectedPrefValue); } @Test - public void saveMacRandomizedValue_noChanged_shouldPersistentAsDefault() { + public void saveMacRandomizedValue_noChanged_shouldAutoAsDefault() { createController(mWifiEntry, WifiConfigUiBase2.MODE_CONNECT, false); WifiConfiguration config = mController.getConfig(); assertThat(config.macRandomizationSetting).isEqualTo( - WifiConfiguration.RANDOMIZATION_PERSISTENT); + WifiConfiguration.RANDOMIZATION_AUTO); } @Test @@ -506,7 +505,7 @@ public class WifiConfigController2Test { createController(mWifiEntry, WifiConfigUiBase2.MODE_CONNECT, false); final Spinner privacySetting = mView.findViewById(R.id.privacy_settings); final int prefMacNone = - WifiPrivacyPreferenceController2.translateMacRandomizedValueToPrefValue( + WifiPrivacyPreferenceController2.translateWifiEntryPrivacyToPrefValue( WifiConfiguration.RANDOMIZATION_NONE); privacySetting.setSelection(prefMacNone); diff --git a/tests/spa_unit/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.kt b/tests/spa_unit/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.kt index cb1f997f4e5..9260409af37 100644 --- a/tests/spa_unit/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.kt +++ b/tests/spa_unit/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.kt @@ -59,7 +59,7 @@ class WifiPrivacyPreferenceController2Test { controller.updateState(preference) - val prefValue = WifiPrivacyPreferenceController2.translateMacRandomizedValueToPrefValue( + val prefValue = WifiPrivacyPreferenceController2.translateWifiEntryPrivacyToPrefValue( WifiEntry.PRIVACY_DEVICE_MAC ) assertThat(preference.entry).isEqualTo(preferenceStrings[prefValue]) @@ -73,7 +73,7 @@ class WifiPrivacyPreferenceController2Test { controller.updateState(preference) - val prefValue = WifiPrivacyPreferenceController2.translateMacRandomizedValueToPrefValue( + val prefValue = WifiPrivacyPreferenceController2.translateWifiEntryPrivacyToPrefValue( WifiEntry.PRIVACY_RANDOMIZED_MAC ) assertThat(preference.entry).isEqualTo(preferenceStrings[prefValue]) diff --git a/tests/unit/src/com/android/settings/connecteddevice/display/ExternalDisplayTestBase.java b/tests/unit/src/com/android/settings/connecteddevice/display/ExternalDisplayTestBase.java index 60b034288a0..4cba1ef4666 100644 --- a/tests/unit/src/com/android/settings/connecteddevice/display/ExternalDisplayTestBase.java +++ b/tests/unit/src/com/android/settings/connecteddevice/display/ExternalDisplayTestBase.java @@ -87,6 +87,7 @@ public class ExternalDisplayTestBase { doReturn(mHandler).when(mMockedInjector).getHandler(); doReturn("").when(mMockedInjector).getSystemProperty( VIRTUAL_DISPLAY_PACKAGE_NAME_SYSTEM_PROPERTY); + doReturn(true).when(mMockedInjector).isModeLimitForExternalDisplayEnabled(); doAnswer((arg) -> { mListener = arg.getArgument(0); return null; diff --git a/tests/unit/src/com/android/settings/connecteddevice/display/ResolutionPreferenceFragmentTest.java b/tests/unit/src/com/android/settings/connecteddevice/display/ResolutionPreferenceFragmentTest.java index ee38a1cbae2..c8663622e74 100644 --- a/tests/unit/src/com/android/settings/connecteddevice/display/ResolutionPreferenceFragmentTest.java +++ b/tests/unit/src/com/android/settings/connecteddevice/display/ResolutionPreferenceFragmentTest.java @@ -17,6 +17,7 @@ package com.android.settings.connecteddevice.display; import static android.view.Display.INVALID_DISPLAY; +import static com.android.settings.connecteddevice.display.ResolutionPreferenceFragment.DISPLAY_MODE_LIMIT_OVERRIDE_PROP; import static com.android.settings.connecteddevice.display.ResolutionPreferenceFragment.EXTERNAL_DISPLAY_RESOLUTION_SETTINGS_RESOURCE; import static com.android.settings.connecteddevice.display.ResolutionPreferenceFragment.MORE_OPTIONS_KEY; import static com.android.settings.connecteddevice.display.ResolutionPreferenceFragment.TOP_OPTIONS_KEY; @@ -29,6 +30,7 @@ import static org.mockito.Mockito.verify; import android.content.Context; import android.content.res.Resources; +import android.util.Pair; import android.view.View; import android.widget.TextView; @@ -83,18 +85,52 @@ public class ResolutionPreferenceFragmentTest extends ExternalDisplayTestBase { @Test @UiThreadTest - public void testModePreferences() { - mDisplayIdArg = 1; - initFragment(); - mHandler.flush(); - PreferenceCategory topPref = mPreferenceScreen.findPreference(TOP_OPTIONS_KEY); - assertThat(topPref).isNotNull(); - PreferenceCategory morePref = mPreferenceScreen.findPreference(MORE_OPTIONS_KEY); - assertThat(morePref).isNotNull(); + public void testModePreferences_modeLimitFlagIsOn_noOverride() { + doReturn(true).when(mMockedInjector).isModeLimitForExternalDisplayEnabled(); + doReturn(null).when(mMockedInjector).getSystemProperty( + DISPLAY_MODE_LIMIT_OVERRIDE_PROP); + var topAndMorePref = runTestModePreferences(); + PreferenceCategory topPref = topAndMorePref.first, morePref = topAndMorePref.second; assertThat(topPref.getPreferenceCount()).isEqualTo(3); assertThat(morePref.getPreferenceCount()).isEqualTo(1); } + @Test + @UiThreadTest + public void testModePreferences_noModeLimitFlag_overrideIsTrue() { + doReturn(false).when(mMockedInjector).isModeLimitForExternalDisplayEnabled(); + doReturn("true").when(mMockedInjector).getSystemProperty( + DISPLAY_MODE_LIMIT_OVERRIDE_PROP); + var topAndMorePref = runTestModePreferences(); + PreferenceCategory topPref = topAndMorePref.first, morePref = topAndMorePref.second; + assertThat(topPref.getPreferenceCount()).isEqualTo(3); + assertThat(morePref.getPreferenceCount()).isEqualTo(1); + } + + @Test + @UiThreadTest + public void testModePreferences_noModeLimitFlag_noOverride() { + doReturn(false).when(mMockedInjector).isModeLimitForExternalDisplayEnabled(); + doReturn(null).when(mMockedInjector).getSystemProperty( + DISPLAY_MODE_LIMIT_OVERRIDE_PROP); + var topAndMorePref = runTestModePreferences(); + PreferenceCategory topPref = topAndMorePref.first, morePref = topAndMorePref.second; + assertThat(topPref.getPreferenceCount()).isEqualTo(3); + assertThat(morePref.getPreferenceCount()).isEqualTo(2); + } + + @Test + @UiThreadTest + public void testModePreferences_modeLimitFlagIsOn_butOverrideIsFalse() { + doReturn(true).when(mMockedInjector).isModeLimitForExternalDisplayEnabled(); + doReturn("false").when(mMockedInjector).getSystemProperty( + DISPLAY_MODE_LIMIT_OVERRIDE_PROP); + var topAndMorePref = runTestModePreferences(); + PreferenceCategory topPref = topAndMorePref.first, morePref = topAndMorePref.second; + assertThat(topPref.getPreferenceCount()).isEqualTo(3); + assertThat(morePref.getPreferenceCount()).isEqualTo(2); + } + @Test @UiThreadTest public void testModeChange() { @@ -109,6 +145,17 @@ public class ResolutionPreferenceFragmentTest extends ExternalDisplayTestBase { verify(mMockedInjector).setUserPreferredDisplayMode(mDisplayIdArg, mode); } + private Pair runTestModePreferences() { + mDisplayIdArg = 1; + initFragment(); + mHandler.flush(); + PreferenceCategory topPref = mPreferenceScreen.findPreference(TOP_OPTIONS_KEY); + assertThat(topPref).isNotNull(); + PreferenceCategory morePref = mPreferenceScreen.findPreference(MORE_OPTIONS_KEY); + assertThat(morePref).isNotNull(); + return new Pair<>(topPref, morePref); + } + private void initFragment() { if (mFragment != null) { return;