diff --git a/AndroidManifest.xml b/AndroidManifest.xml index fd6ac4b1558..2c62ebd684c 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -5307,6 +5307,23 @@ android:value="true" /> + + + + + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 9930c3685c0..6c4afd1e60d 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -5489,11 +5489,11 @@ High contrast text has been replaced - Try Maximize text contrast instead. Find it in Settings. + Try Text outlines instead. Find it in Settings. Open Settings - - Maximize text contrast + + Text outlines Add a black or white background around text to increase contrast @@ -5978,6 +5978,8 @@ screen size, large screen High contrast, low vision, bold font, bold face + + high contrast text @@ -11367,7 +11369,7 @@ Go back, Home, and switch apps with buttons at the bottom of your screen. - Start gesture navigation tutorial, button. Double tap to activate. + Start gesture navigation tutorial. system navigation, 2 button navigation, 3 button navigation, gesture navigation, swipe @@ -13125,10 +13127,6 @@ Show media on lock screen To quickly resume playback, media player stays open on lock screen - - Show Assistant media recommendations - - Based on your activity Hide player diff --git a/res/xml/accessibility_text_reading_options.xml b/res/xml/accessibility_text_reading_options.xml index 40201f0318d..30594fc4730 100644 --- a/res/xml/accessibility_text_reading_options.xml +++ b/res/xml/accessibility_text_reading_options.xml @@ -57,7 +57,8 @@ android:key="toggle_high_text_contrast_preference" android:persistent="false" android:title="@string/accessibility_toggle_maximize_text_contrast_preference_title" - android:summary="@string/accessibility_toggle_maximize_text_contrast_preference_summary" /> + android:summary="@string/accessibility_toggle_maximize_text_contrast_preference_summary" + settings:keywords="@string/keywords_maximize_text_contrast"/> + android:title="@string/lockscreen_notification_what_to_show_title" + settings:controller="com.android.settings.notification.LockScreenWhatToShowController"> - - diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index 91494af29c6..ee866babffc 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -518,6 +518,11 @@ public class Settings extends SettingsActivity { */ public static class OneHandedSettingsActivity extends SettingsActivity { /* empty */ } + /** + * Activity for Double Tap Power Settings + */ + public static class DoubleTapPowerSettingsActivity extends SettingsActivity { /* empty */ } + public static class PreviouslyConnectedDeviceActivity extends SettingsActivity { /* empty */ } public static class ScreenTimeoutActivity extends SettingsActivity { /* empty */ } diff --git a/src/com/android/settings/accessibility/ItemInfoArrayAdapter.java b/src/com/android/settings/accessibility/ItemInfoArrayAdapter.java index a7c41771cea..285a52b1b9c 100644 --- a/src/com/android/settings/accessibility/ItemInfoArrayAdapter.java +++ b/src/com/android/settings/accessibility/ItemInfoArrayAdapter.java @@ -60,12 +60,17 @@ public class ItemInfoArrayAdapter exten summary.setVisibility(View.GONE); } final ImageView image = root.findViewById(R.id.image); - image.setImageResource(item.mDrawableId); - if (getContext().getResources().getConfiguration().getLayoutDirection() - == View.LAYOUT_DIRECTION_LTR) { - image.setScaleType(ImageView.ScaleType.FIT_START); + if (item.mDrawableId == null) { + image.setVisibility(View.GONE); } else { - image.setScaleType(ImageView.ScaleType.FIT_END); + image.setVisibility(View.VISIBLE); + image.setImageResource(item.mDrawableId); + if (getContext().getResources().getConfiguration().getLayoutDirection() + == View.LAYOUT_DIRECTION_LTR) { + image.setScaleType(ImageView.ScaleType.FIT_START); + } else { + image.setScaleType(ImageView.ScaleType.FIT_END); + } } return root; } @@ -78,11 +83,12 @@ public class ItemInfoArrayAdapter exten public final CharSequence mTitle; @Nullable public final CharSequence mSummary; + @Nullable @DrawableRes - public final int mDrawableId; + public final Integer mDrawableId; public ItemInfo(@NonNull CharSequence title, @Nullable CharSequence summary, - @DrawableRes int drawableId) { + @Nullable @DrawableRes Integer drawableId) { mTitle = title; mSummary = summary; mDrawableId = drawableId; diff --git a/src/com/android/settings/accessibility/ToggleAutoclickIgnoreMinorCursorMovementController.java b/src/com/android/settings/accessibility/ToggleAutoclickIgnoreMinorCursorMovementController.java index 302e42a2b2f..d5d4fddeaff 100644 --- a/src/com/android/settings/accessibility/ToggleAutoclickIgnoreMinorCursorMovementController.java +++ b/src/com/android/settings/accessibility/ToggleAutoclickIgnoreMinorCursorMovementController.java @@ -16,7 +16,14 @@ package com.android.settings.accessibility; +import static android.view.accessibility.AccessibilityManager.AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT_DEFAULT; + +import static com.android.settings.accessibility.AccessibilityUtil.State.OFF; +import static com.android.settings.accessibility.AccessibilityUtil.State.ON; + +import android.content.ContentResolver; import android.content.Context; +import android.provider.Settings; import androidx.annotation.NonNull; @@ -29,9 +36,13 @@ public class ToggleAutoclickIgnoreMinorCursorMovementController extends TogglePr private static final String TAG = ToggleAutoclickIgnoreMinorCursorMovementController.class.getSimpleName(); + private final ContentResolver mContentResolver; + public ToggleAutoclickIgnoreMinorCursorMovementController( @NonNull Context context, @NonNull String key) { super(context, key); + + mContentResolver = context.getContentResolver(); } @Override @@ -41,13 +52,19 @@ public class ToggleAutoclickIgnoreMinorCursorMovementController extends TogglePr @Override public boolean isChecked() { - // TODO(b/388845718): retrieve check status from settings. - return false; + return Settings.Secure.getInt( + mContentResolver, + Settings.Secure.ACCESSIBILITY_AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT, + AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT_DEFAULT ? ON : OFF) + == ON; } @Override public boolean setChecked(boolean isChecked) { - // TODO(b/388845718): Update settings. + Settings.Secure.putInt( + mContentResolver, + Settings.Secure.ACCESSIBILITY_AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT, + isChecked ? ON : OFF); return true; } diff --git a/src/com/android/settings/connecteddevice/audiosharing/TemporaryBondDeviceGroupUpdater.java b/src/com/android/settings/connecteddevice/audiosharing/TemporaryBondDeviceGroupUpdater.java new file mode 100644 index 00000000000..59e37c51c08 --- /dev/null +++ b/src/com/android/settings/connecteddevice/audiosharing/TemporaryBondDeviceGroupUpdater.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2025 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.connecteddevice.audiosharing; + +import android.content.Context; +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.android.settings.bluetooth.BluetoothDeviceUpdater; +import com.android.settings.connecteddevice.DevicePreferenceCallback; +import com.android.settingslib.bluetooth.BluetoothUtils; +import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.flags.Flags; + +/** Maintain and update connected temporary bond bluetooth devices */ +public class TemporaryBondDeviceGroupUpdater extends BluetoothDeviceUpdater { + private static final String TAG = "TemporaryBondDeviceGroupUpdater"; + private static final String PREF_KEY_PREFIX = "temp_bond_bt_"; + + public TemporaryBondDeviceGroupUpdater( + @NonNull Context context, + @NonNull DevicePreferenceCallback devicePreferenceCallback, + int metricsCategory) { + super(context, devicePreferenceCallback, metricsCategory); + } + + @Override + public boolean isFilterMatched(@NonNull CachedBluetoothDevice cachedDevice) { + // Only connected temporary bond device should be shown in this section when Audio + // sharing UI is available. + boolean isFilterMatched = Flags.enableTemporaryBondDevicesUi() + && BluetoothUtils.isTemporaryBondDevice(cachedDevice.getDevice()) + && isDeviceConnected(cachedDevice) && isDeviceInCachedDevicesList(cachedDevice) + && BluetoothUtils.isAudioSharingUIAvailable(mContext); + Log.d( + TAG, + "isFilterMatched() device : " + + cachedDevice.getName() + + ", isFilterMatched : " + + isFilterMatched); + return isFilterMatched; + } + + @Override + protected String getPreferenceKeyPrefix() { + return PREF_KEY_PREFIX; + } + + @Override + protected String getLogTag() { + return TAG; + } + + @Override + protected void update(CachedBluetoothDevice cachedBluetoothDevice) { + super.update(cachedBluetoothDevice); + Log.d(TAG, "Map : " + mPreferenceMap); + } +} diff --git a/src/com/android/settings/display/AdaptiveSleepPreference.kt b/src/com/android/settings/display/AdaptiveSleepPreference.kt index 0fe2a098734..45b05ec3471 100644 --- a/src/com/android/settings/display/AdaptiveSleepPreference.kt +++ b/src/com/android/settings/display/AdaptiveSleepPreference.kt @@ -33,18 +33,18 @@ import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.KeyedObservableDelegate import com.android.settingslib.datastore.SettingsSecureStore import com.android.settingslib.datastore.SettingsStore +import com.android.settingslib.metadata.BooleanValuePreference import com.android.settingslib.metadata.PreferenceAvailabilityProvider import com.android.settingslib.metadata.PreferenceLifecycleContext import com.android.settingslib.metadata.PreferenceLifecycleProvider import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.SensitivityLevel -import com.android.settingslib.metadata.TwoStatePreference import com.android.settingslib.preference.PreferenceBindingPlaceholder import com.android.settingslib.preference.SwitchPreferenceBinding // LINT.IfChange class AdaptiveSleepPreference : - TwoStatePreference, + BooleanValuePreference, SwitchPreferenceBinding, PreferenceLifecycleProvider, PreferenceBindingPlaceholder, // not needed once controller class is cleaned up diff --git a/src/com/android/settings/display/AmbientDisplayAlwaysOnPreference.kt b/src/com/android/settings/display/AmbientDisplayAlwaysOnPreference.kt index 2d2fe2b2d70..3cc608bec91 100644 --- a/src/com/android/settings/display/AmbientDisplayAlwaysOnPreference.kt +++ b/src/com/android/settings/display/AmbientDisplayAlwaysOnPreference.kt @@ -25,15 +25,13 @@ import android.provider.Settings.Secure.DOZE_ALWAYS_ON import com.android.settings.PreferenceRestrictionMixin import com.android.settings.R import com.android.settings.display.AmbientDisplayAlwaysOnPreferenceController.isAodSuppressedByBedtime +import com.android.settingslib.datastore.AbstractKeyedDataObservable import com.android.settingslib.datastore.HandlerExecutor import com.android.settingslib.datastore.KeyValueStore -import com.android.settingslib.datastore.KeyedObservableDelegate import com.android.settingslib.datastore.KeyedObserver import com.android.settingslib.datastore.SettingsSecureStore import com.android.settingslib.datastore.SettingsStore import com.android.settingslib.metadata.PreferenceAvailabilityProvider -import com.android.settingslib.metadata.PreferenceLifecycleContext -import com.android.settingslib.metadata.PreferenceLifecycleProvider import com.android.settingslib.metadata.PreferenceSummaryProvider import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.SensitivityLevel @@ -44,11 +42,8 @@ class AmbientDisplayAlwaysOnPreference : SwitchPreference(KEY, R.string.doze_always_on_title, R.string.doze_always_on_summary), PreferenceAvailabilityProvider, PreferenceSummaryProvider, - PreferenceLifecycleProvider, PreferenceRestrictionMixin { - private var keyMappingObserver: KeyedObserver? = null - override val keywords: Int get() = R.string.keywords_always_show_time_info @@ -88,24 +83,17 @@ class AmbientDisplayAlwaysOnPreference : override val sensitivityLevel get() = SensitivityLevel.NO_SENSITIVITY - override fun onCreate(context: PreferenceLifecycleContext) { - val storage = SettingsSecureStore.get(context) - keyMappingObserver = - KeyedObserver { _, reason -> storage.notifyChange(KEY, reason) } - .also { storage.addObserver(DOZE_ALWAYS_ON, it, HandlerExecutor.main) } - } - - override fun onDestroy(context: PreferenceLifecycleContext) { - keyMappingObserver?.let { - SettingsSecureStore.get(context).removeObserver(DOZE_ALWAYS_ON, it) - } - } - + /** + * Datastore of the preference. + * + * The preference key and underlying storage key are the different, leverage + * [AbstractKeyedDataObservable] to redirect data change event. + */ @Suppress("UNCHECKED_CAST") class Storage( private val context: Context, private val settingsStore: SettingsStore = SettingsSecureStore.get(context), - ) : KeyedObservableDelegate(settingsStore), KeyValueStore { + ) : AbstractKeyedDataObservable(), KeyedObserver, KeyValueStore { override fun contains(key: String) = settingsStore.contains(DOZE_ALWAYS_ON) @@ -118,6 +106,20 @@ class AmbientDisplayAlwaysOnPreference : override fun setValue(key: String, valueType: Class, value: T?) = settingsStore.setValue(DOZE_ALWAYS_ON, valueType, value) + + override fun onFirstObserverAdded() { + // observe the underlying storage key + settingsStore.addObserver(DOZE_ALWAYS_ON, this, HandlerExecutor.main) + } + + override fun onKeyChanged(key: String, reason: Int) { + // forward data change to preference hierarchy key + notifyChange(KEY, reason) + } + + override fun onLastObserverRemoved() { + settingsStore.removeObserver(DOZE_ALWAYS_ON, this) + } } companion object { diff --git a/src/com/android/settings/display/AutoBrightnessScreen.kt b/src/com/android/settings/display/AutoBrightnessScreen.kt index c42588853c6..b594b558192 100644 --- a/src/com/android/settings/display/AutoBrightnessScreen.kt +++ b/src/com/android/settings/display/AutoBrightnessScreen.kt @@ -17,7 +17,7 @@ package com.android.settings.display import android.content.Context import android.os.UserManager -import android.provider.Settings +import android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE import android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC import android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL import androidx.preference.Preference @@ -26,8 +26,10 @@ import com.android.settings.PreferenceRestrictionMixin import com.android.settings.R import com.android.settings.flags.Flags import com.android.settingslib.PrimarySwitchPreferenceBinding +import com.android.settingslib.datastore.AbstractKeyedDataObservable +import com.android.settingslib.datastore.HandlerExecutor import com.android.settingslib.datastore.KeyValueStore -import com.android.settingslib.datastore.KeyedObservableDelegate +import com.android.settingslib.datastore.KeyedObserver import com.android.settingslib.datastore.SettingsStore import com.android.settingslib.datastore.SettingsSystemStore import com.android.settingslib.metadata.BooleanValuePreference @@ -106,18 +108,32 @@ class AutoBrightnessScreen : */ @Suppress("UNCHECKED_CAST") private class AutoBrightnessDataStore(private val settingsStore: SettingsStore) : - KeyedObservableDelegate(settingsStore), KeyValueStore { + AbstractKeyedDataObservable(), KeyedObserver, KeyValueStore { - override fun contains(key: String) = settingsStore.contains(key) + override fun contains(key: String) = settingsStore.contains(SCREEN_BRIGHTNESS_MODE) override fun getDefaultValue(key: String, valueType: Class) = DEFAULT_VALUE.toBoolean() as T override fun getValue(key: String, valueType: Class) = - (settingsStore.getInt(key) ?: DEFAULT_VALUE).toBoolean() as T + (settingsStore.getInt(SCREEN_BRIGHTNESS_MODE) ?: DEFAULT_VALUE).toBoolean() as T override fun setValue(key: String, valueType: Class, value: T?) = - settingsStore.setInt(key, (value as? Boolean)?.toBrightnessMode()) + settingsStore.setInt(SCREEN_BRIGHTNESS_MODE, (value as? Boolean)?.toBrightnessMode()) + + override fun onFirstObserverAdded() { + // observe the underlying storage key + settingsStore.addObserver(SCREEN_BRIGHTNESS_MODE, this, HandlerExecutor.main) + } + + override fun onKeyChanged(key: String, reason: Int) { + // forward data change to preference hierarchy key + notifyChange(KEY, reason) + } + + override fun onLastObserverRemoved() { + settingsStore.removeObserver(SCREEN_BRIGHTNESS_MODE, this) + } /** Converts brightness mode integer to boolean. */ private fun Int.toBoolean() = this == SCREEN_BRIGHTNESS_MODE_AUTOMATIC @@ -128,7 +144,7 @@ class AutoBrightnessScreen : } companion object { - const val KEY = Settings.System.SCREEN_BRIGHTNESS_MODE + const val KEY = "auto_brightness_entry" private const val DEFAULT_VALUE = SCREEN_BRIGHTNESS_MODE_MANUAL } } diff --git a/src/com/android/settings/display/BrightnessLevelPreference.kt b/src/com/android/settings/display/BrightnessLevelPreference.kt index e14db6b59a6..0465d22361e 100644 --- a/src/com/android/settings/display/BrightnessLevelPreference.kt +++ b/src/com/android/settings/display/BrightnessLevelPreference.kt @@ -55,7 +55,6 @@ import java.text.NumberFormat // LINT.IfChange class BrightnessLevelPreference : - PreferenceMetadata, PersistentPreference, RangeValue, PreferenceBinding, diff --git a/src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt b/src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt index f0a3ae67af9..36654691c36 100644 --- a/src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt +++ b/src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt @@ -39,7 +39,6 @@ import com.android.settingslib.widget.UsageProgressBarPreference // LINT.IfChange class BatteryHeaderPreference : PersistentPreference, - PreferenceMetadata, PreferenceBinding, PreferenceLifecycleProvider, RangeValue { diff --git a/src/com/android/settings/notification/CallVolumePreference.kt b/src/com/android/settings/notification/CallVolumePreference.kt index 3caac242316..cc6f45fe270 100644 --- a/src/com/android/settings/notification/CallVolumePreference.kt +++ b/src/com/android/settings/notification/CallVolumePreference.kt @@ -43,7 +43,6 @@ import com.android.settingslib.preference.PreferenceBinding // LINT.IfChange open class CallVolumePreference : - PreferenceMetadata, PreferenceBinding, PersistentPreference, RangeValue, diff --git a/src/com/android/settings/notification/LockScreenWhatToShowController.java b/src/com/android/settings/notification/LockScreenWhatToShowController.java new file mode 100644 index 00000000000..9e5af4fc3be --- /dev/null +++ b/src/com/android/settings/notification/LockScreenWhatToShowController.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2025 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; + +import android.content.ContentResolver; +import android.content.Context; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; +import android.os.Looper; +import android.provider.Settings; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleEventObserver; +import androidx.lifecycle.LifecycleOwner; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.widget.PreferenceCategoryController; + +public class LockScreenWhatToShowController extends PreferenceCategoryController implements + LifecycleEventObserver { + + @Nullable + private Preference mPreference; + private final ContentResolver mContentResolver; + + final ContentObserver mContentObserver = new ContentObserver( + new Handler(Looper.getMainLooper())) { + @Override + public void onChange(boolean selfChange, @Nullable Uri uri) { + if (mPreference == null) return; + updateState(mPreference); + } + }; + + @Override + public void updateState(@Nullable Preference preference) { + super.updateState(preference); + if (preference == null) return; + preference.setVisible(isAvailable()); + } + + public LockScreenWhatToShowController(@NonNull Context context, @NonNull String key) { + super(context, key); + mContentResolver = context.getContentResolver(); + } + + @Override + public void displayPreference(@NonNull PreferenceScreen screen) { + super.displayPreference(screen); + mPreference = screen.findPreference(getPreferenceKey()); + } + + @Override + public int getAvailabilityStatus() { + if (!lockScreenShowNotification()) { + return CONDITIONALLY_UNAVAILABLE; + } + return AVAILABLE; + } + + /** + * @return Whether showing notifications on the lockscreen is enabled. + */ + private boolean lockScreenShowNotification() { + return Settings.Secure.getInt( + mContext.getContentResolver(), + Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, + LockScreenNotificationsGlobalPreferenceController.OFF + ) == LockScreenNotificationsGlobalPreferenceController.ON; + } + + @Override + public void onStateChanged(@NonNull LifecycleOwner lifecycleOwner, + @NonNull Lifecycle.Event event) { + if (event == Lifecycle.Event.ON_RESUME) { + mContentResolver.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS), + /* notifyForDescendants= */ false, mContentObserver); + } else if (event == Lifecycle.Event.ON_PAUSE) { + mContentResolver.unregisterContentObserver(mContentObserver); + } + } +} diff --git a/src/com/android/settings/notification/MediaVolumePreference.kt b/src/com/android/settings/notification/MediaVolumePreference.kt index 02bf82479c0..71f2f91276f 100644 --- a/src/com/android/settings/notification/MediaVolumePreference.kt +++ b/src/com/android/settings/notification/MediaVolumePreference.kt @@ -40,7 +40,6 @@ import com.android.settingslib.preference.PreferenceBinding // LINT.IfChange open class MediaVolumePreference : - PreferenceMetadata, PreferenceBinding, PersistentPreference, RangeValue, diff --git a/src/com/android/settings/notification/SeparateRingVolumePreference.kt b/src/com/android/settings/notification/SeparateRingVolumePreference.kt index 4cdac1434bf..7bc39a82d10 100644 --- a/src/com/android/settings/notification/SeparateRingVolumePreference.kt +++ b/src/com/android/settings/notification/SeparateRingVolumePreference.kt @@ -58,7 +58,6 @@ import com.android.settingslib.preference.PreferenceBinding // LINT.IfChange open class SeparateRingVolumePreference : - PreferenceMetadata, PreferenceBinding, PersistentPreference, RangeValue, diff --git a/src/com/android/settings/password/ChooseLockPattern.java b/src/com/android/settings/password/ChooseLockPattern.java index 9680d5a2748..a30c38b20b8 100644 --- a/src/com/android/settings/password/ChooseLockPattern.java +++ b/src/com/android/settings/password/ChooseLockPattern.java @@ -348,9 +348,9 @@ public class ChooseLockPattern extends SettingsActivity { */ enum RightButtonMode { Continue(R.string.next_label, true), - ContinueDisabled(R.string.next_label, false), + ContinueDisabled(R.string.next_label, true), Confirm(R.string.lockpattern_confirm_button_text, true), - ConfirmDisabled(R.string.lockpattern_confirm_button_text, false), + ConfirmDisabled(R.string.lockpattern_confirm_button_text, true), Ok(android.R.string.ok, true); /** @@ -563,6 +563,7 @@ public class ChooseLockPattern extends SettingsActivity { mLockPatternView = (LockPatternView) view.findViewById(R.id.lockPattern); mLockPatternView.setOnPatternListener(mChooseNewLockPatternListener); mLockPatternView.setFadePattern(false); + mLockPatternView.setClickable(false); mFooterText = (TextView) view.findViewById(R.id.footerText); diff --git a/src/com/android/settings/sound/MediaControlsRecommendationController.java b/src/com/android/settings/sound/MediaControlsRecommendationController.java deleted file mode 100644 index 842a1417a15..00000000000 --- a/src/com/android/settings/sound/MediaControlsRecommendationController.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2021 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.sound; - -import static android.provider.Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION; - -import android.content.Context; -import android.provider.Settings; - -import com.android.settings.R; -import com.android.settings.core.TogglePreferenceController; - -/** - * Toggle for media controls recommendation setting - */ -public class MediaControlsRecommendationController extends TogglePreferenceController { - - public MediaControlsRecommendationController(Context context, String key) { - super(context, key); - } - - @Override - public boolean isChecked() { - int val = Settings.Secure.getInt(mContext.getContentResolver(), - MEDIA_CONTROLS_RECOMMENDATION, 1); - return val == 1; - } - - @Override - public boolean setChecked(boolean isChecked) { - int val = isChecked ? 1 : 0; - return Settings.Secure.putInt(mContext.getContentResolver(), - MEDIA_CONTROLS_RECOMMENDATION, val); - } - - @Override - public int getAvailabilityStatus() { - return AVAILABLE; - } - - @Override - public int getSliceHighlightMenuRes() { - return R.string.menu_key_sound; - } -} diff --git a/src/com/android/settings/widget/MainSwitchBarMetadata.kt b/src/com/android/settings/widget/MainSwitchBarMetadata.kt index 4fc89bc19b6..0f07bba3eaa 100644 --- a/src/com/android/settings/widget/MainSwitchBarMetadata.kt +++ b/src/com/android/settings/widget/MainSwitchBarMetadata.kt @@ -18,14 +18,14 @@ package com.android.settings.widget import android.content.Context import androidx.preference.Preference +import com.android.settingslib.metadata.BooleanValuePreference import com.android.settingslib.metadata.PreferenceMetadata -import com.android.settingslib.metadata.TwoStatePreference import com.android.settingslib.preference.PreferenceBindingPlaceholder -import com.android.settingslib.preference.TwoStatePreferenceBinding +import com.android.settingslib.preference.BooleanValuePreferenceBinding /** Base metadata of `MainSwitchBar`. */ interface MainSwitchBarMetadata : - TwoStatePreference, TwoStatePreferenceBinding, PreferenceBindingPlaceholder { + BooleanValuePreference, BooleanValuePreferenceBinding, PreferenceBindingPlaceholder { /** * Disable main switch bar when user toggles the switch. By this way, user cannot toggle again diff --git a/src/com/android/settings/wifi/calling/WifiCallingMainSwitchPreference.kt b/src/com/android/settings/wifi/calling/WifiCallingMainSwitchPreference.kt index dc6737310d3..8765547a957 100644 --- a/src/com/android/settings/wifi/calling/WifiCallingMainSwitchPreference.kt +++ b/src/com/android/settings/wifi/calling/WifiCallingMainSwitchPreference.kt @@ -33,11 +33,11 @@ import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.NoOpKeyedObservable import com.android.settingslib.datastore.Permissions import com.android.settingslib.datastore.and +import com.android.settingslib.metadata.BooleanValuePreference import com.android.settingslib.metadata.PreferenceAvailabilityProvider import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.SensitivityLevel -import com.android.settingslib.metadata.TwoStatePreference -import com.android.settingslib.preference.TwoStatePreferenceBinding +import com.android.settingslib.preference.BooleanValuePreferenceBinding import kotlinx.coroutines.flow.first import kotlinx.coroutines.runBlocking @@ -47,7 +47,7 @@ import kotlinx.coroutines.runBlocking * TODO(b/372732219): apply metadata to UI */ class WifiCallingMainSwitchPreference(private val subId: Int) : - TwoStatePreference, TwoStatePreferenceBinding, PreferenceAvailabilityProvider { + BooleanValuePreference, BooleanValuePreferenceBinding, PreferenceAvailabilityProvider { override val key: String get() = KEY diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickIgnoreMinorCursorMovementControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickIgnoreMinorCursorMovementControllerTest.java index 889b7322888..552e89742b4 100644 --- a/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickIgnoreMinorCursorMovementControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickIgnoreMinorCursorMovementControllerTest.java @@ -16,12 +16,17 @@ package com.android.settings.accessibility; +import static android.view.accessibility.AccessibilityManager.AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT_DEFAULT; + +import static com.android.settings.accessibility.AccessibilityUtil.State.OFF; +import static com.android.settings.accessibility.AccessibilityUtil.State.ON; import static com.google.common.truth.Truth.assertThat; import android.content.Context; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; +import android.provider.Settings; import androidx.test.core.app.ApplicationProvider; @@ -66,4 +71,27 @@ public class ToggleAutoclickIgnoreMinorCursorMovementControllerTest { assertThat(mController.getAvailabilityStatus()) .isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE); } + + @Test + public void isChecked_matchesSetting() { + assertThat(mController.isChecked()).isEqualTo(readSetting() == ON); + } + + @Test + public void setChecked_true_updatesSetting() { + mController.setChecked(true); + assertThat(readSetting()).isEqualTo(ON); + } + + @Test + public void setChecked_false_updatesSetting() { + mController.setChecked(false); + assertThat(readSetting()).isEqualTo(OFF); + } + + private int readSetting() { + return Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT, + AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT_DEFAULT ? ON : OFF); + } } diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/TemporaryBondDeviceGroupUpdaterTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/TemporaryBondDeviceGroupUpdaterTest.java new file mode 100644 index 00000000000..0b34c101719 --- /dev/null +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/TemporaryBondDeviceGroupUpdaterTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2025 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.connecteddevice.audiosharing; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothStatusCodes; +import android.content.Context; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; + +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.bluetooth.Utils; +import com.android.settings.connecteddevice.DevicePreferenceCallback; +import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; +import com.android.settings.testutils.shadow.ShadowBluetoothUtils; +import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; +import com.android.settingslib.bluetooth.LocalBluetoothManager; +import com.android.settingslib.flags.Flags; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; +import org.robolectric.shadow.api.Shadow; + +import java.util.ArrayList; +import java.util.Collection; + +/** Tests for {@link TemporaryBondDeviceGroupUpdater}. */ +@RunWith(RobolectricTestRunner.class) +@Config( + shadows = { + ShadowBluetoothAdapter.class, + ShadowBluetoothUtils.class + }) +public class TemporaryBondDeviceGroupUpdaterTest { + private static final String TAG = "TemporaryBondDeviceGroupUpdater"; + private static final String PREF_KEY_PREFIX = "temp_bond_bt_"; + private static final String TEMP_BOND_METADATA = + "le_audio_sharing"; + private static final int METADATA_FAST_PAIR_CUSTOMIZED_FIELDS = 25; + + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + + @Mock + private DevicePreferenceCallback mDevicePreferenceCallback; + @Mock + private CachedBluetoothDevice mCachedBluetoothDevice; + @Mock + private BluetoothDevice mBluetoothDevice; + @Mock + private LocalBluetoothManager mLocalBtManager; + @Mock + private CachedBluetoothDeviceManager mCachedDeviceManager; + + private TemporaryBondDeviceGroupUpdater mDeviceUpdater; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract( + BluetoothAdapter.getDefaultAdapter()); + shadowBluetoothAdapter.setEnabled(true); + shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported( + BluetoothStatusCodes.FEATURE_SUPPORTED); + shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( + BluetoothStatusCodes.FEATURE_SUPPORTED); + Context context = ApplicationProvider.getApplicationContext(); + ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager; + mLocalBtManager = Utils.getLocalBtManager(context); + when(mLocalBtManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager); + when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); + Collection cachedDevices = new ArrayList<>(); + cachedDevices.add(mCachedBluetoothDevice); + when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices); + mDeviceUpdater = + spy( + new TemporaryBondDeviceGroupUpdater( + context, mDevicePreferenceCallback, /* metricsCategory= */ 0)); + mDeviceUpdater.setPrefContext(context); + } + + @After + public void tearDown() { + ShadowBluetoothUtils.reset(); + } + + @Test + @RequiresFlagsEnabled({Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI, + Flags.FLAG_ENABLE_LE_AUDIO_SHARING}) + public void isFilterMatched_isTemporaryBondDevice_returnsTrue() { + when(mBluetoothDevice.isConnected()).thenReturn(true); + when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED); + when(mBluetoothDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS)) + .thenReturn(TEMP_BOND_METADATA.getBytes()); + + assertThat(mDeviceUpdater.isFilterMatched(mCachedBluetoothDevice)).isTrue(); + } + + @Test + public void getLogTag_returnsCorrectTag() { + assertThat(mDeviceUpdater.getLogTag()).isEqualTo(TAG); + } + + @Test + public void getPreferenceKey_returnsCorrectKey() { + assertThat(mDeviceUpdater.getPreferenceKeyPrefix()).isEqualTo(PREF_KEY_PREFIX); + } +} diff --git a/tests/robotests/src/com/android/settings/display/AutoBrightnessScreenTest.kt b/tests/robotests/src/com/android/settings/display/AutoBrightnessScreenTest.kt index ab2d9bd29d9..5da5c2a8a37 100644 --- a/tests/robotests/src/com/android/settings/display/AutoBrightnessScreenTest.kt +++ b/tests/robotests/src/com/android/settings/display/AutoBrightnessScreenTest.kt @@ -128,7 +128,11 @@ class AutoBrightnessScreenTest { } private fun setScreenBrightnessMode(value: Int) = - Settings.System.putInt(context.contentResolver, AutoBrightnessScreen.KEY, value) + Settings.System.putInt( + context.contentResolver, + Settings.System.SCREEN_BRIGHTNESS_MODE, + value, + ) private fun getResId() = when { diff --git a/tests/robotests/src/com/android/settings/notification/LockScreenWhatToShowControllerTest.java b/tests/robotests/src/com/android/settings/notification/LockScreenWhatToShowControllerTest.java new file mode 100644 index 00000000000..1e07a43bba3 --- /dev/null +++ b/tests/robotests/src/com/android/settings/notification/LockScreenWhatToShowControllerTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2025 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; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import android.content.Context; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; +import android.provider.Settings; + +import androidx.annotation.Nullable; +import androidx.preference.Preference; +import androidx.test.core.app.ApplicationProvider; + +import com.android.server.notification.Flags; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +@RunWith(RobolectricTestRunner.class) +@EnableFlags(Flags.FLAG_NOTIFICATION_LOCK_SCREEN_SETTINGS) +public class LockScreenWhatToShowControllerTest { + + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + + private static final String PREFERENCE_KEY = "lockscreen_notification_what_to_show"; + + private LockScreenWhatToShowController mController; + private Context mContext; + @Nullable + private Preference mPreference; + + @Before + public void setUp() { + mContext = ApplicationProvider.getApplicationContext(); + MockitoAnnotations.initMocks(this); + mController = new LockScreenWhatToShowController( + RuntimeEnvironment.application, + PREFERENCE_KEY); + mPreference = new Preference(mContext); + mPreference.setKey(PREFERENCE_KEY); + } + + @Test + public void updateState_preferenceVisibleWhenSettingIsOn() { + // Before: the show LOCK_SCREEN_SHOW_NOTIFICATIONS setting is on + Settings.Secure.putInt( + mContext.getContentResolver(), + Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, + LockScreenNotificationsGlobalPreferenceController.ON + ); + + // When: update state + mController.updateState(mPreference); + + // Then: the preference is visible + assertNotNull(mPreference); + assertTrue(mPreference.isVisible()); + } + + @Test + public void updateState_preferenceInvisibleWhenSettingIsOff() { + // Before: the show LOCK_SCREEN_SHOW_NOTIFICATIONS setting is off + Settings.Secure.putInt( + mContext.getContentResolver(), + Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, + LockScreenNotificationsGlobalPreferenceController.OFF + ); + + // When: update state + mController.updateState(mPreference); + + // Then: the preference is not visible + assertNotNull(mPreference); + assertFalse(mPreference.isVisible()); + } +} diff --git a/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java b/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java index be3b63bf805..1d42495d077 100644 --- a/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java +++ b/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java @@ -287,7 +287,6 @@ public class SetupChooseLockPatternTest { final FooterButton nextButton = footerBarMixin.getPrimaryButton(); assertThat(nextButton.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(nextButton.isEnabled()).isFalse(); enterPattern(); @@ -333,7 +332,6 @@ public class SetupChooseLockPatternTest { mContext.getString(R.string.lockpattern_need_to_unlock_wrong)); assertThat(nextButton.getText().toString()).isEqualTo( mContext.getString(R.string.lockpattern_confirm_button_text)); - assertThat(nextButton.isEnabled()).isFalse(); } @Test diff --git a/tests/unit/src/com/android/settings/privatespace/FaceFingerprintUnlockControllerTest.java b/tests/unit/src/com/android/settings/privatespace/FaceFingerprintUnlockControllerTest.java index bdeede874fc..ba82e19a6e6 100644 --- a/tests/unit/src/com/android/settings/privatespace/FaceFingerprintUnlockControllerTest.java +++ b/tests/unit/src/com/android/settings/privatespace/FaceFingerprintUnlockControllerTest.java @@ -34,8 +34,8 @@ import com.android.settings.privatespace.onelock.FaceFingerprintUnlockController import com.android.settings.testutils.FakeFeatureFactory; import com.android.settingslib.core.lifecycle.Lifecycle; +import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -51,6 +51,7 @@ public class FaceFingerprintUnlockControllerTest { @Mock LockPatternUtils mLockPatternUtils; private Preference mPreference; + private PrivateSpaceMaintainer mPrivateSpaceMaintainer; private FaceFingerprintUnlockController mFaceFingerprintUnlockController; /** Required setup before a test. */ @@ -68,12 +69,26 @@ public class FaceFingerprintUnlockControllerTest { .thenReturn(mLockPatternUtils); doReturn(true).when(mLockPatternUtils).isSecure(anyInt()); + + mPrivateSpaceMaintainer = PrivateSpaceMaintainer.getInstance(mContext); + assertThat(mPrivateSpaceMaintainer.createPrivateSpace()).isTrue(); + assertThat(mPrivateSpaceMaintainer.doesPrivateSpaceExist()).isTrue(); + mFaceFingerprintUnlockController = new FaceFingerprintUnlockController(mContext, mLifecycle); } + @After + public void tearDown() { + // Ensure PSMaintainer is able to remove PS. + mSetFlagsRule.enableFlags( + android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE, + android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES); + assertThat(mPrivateSpaceMaintainer.deletePrivateSpace()) + .isEqualTo(PrivateSpaceMaintainer.ErrorDeletingPrivateSpace.DELETE_PS_ERROR_NONE); + } + /** Tests that the controller is always available. */ - @Ignore("b/323652985") @Test public void getAvailabilityStatus_whenFlagsEnabled_returnsAvailable() { mSetFlagsRule.enableFlags( @@ -134,7 +149,6 @@ public class FaceFingerprintUnlockControllerTest { } /** Tests that preference is enabled and summary is not same as device lock. */ - @Ignore("b/323652985") @Test public void getSummary_whenSeparateProfileLock() { doReturn(true).when(mLockPatternUtils).isSeparateProfileChallengeEnabled(anyInt()); diff --git a/tests/unit/src/com/android/settings/sound/MediaControlsRecommendationControllerTest.java b/tests/unit/src/com/android/settings/sound/MediaControlsRecommendationControllerTest.java deleted file mode 100644 index 68170b24af8..00000000000 --- a/tests/unit/src/com/android/settings/sound/MediaControlsRecommendationControllerTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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.sound; - -import static com.android.settings.core.BasePreferenceController.AVAILABLE; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.spy; - -import android.content.ContentResolver; -import android.content.Context; -import android.provider.Settings; - -import androidx.test.core.app.ApplicationProvider; -import androidx.test.ext.junit.runners.AndroidJUnit4; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(AndroidJUnit4.class) -public class MediaControlsRecommendationControllerTest { - - private static final String KEY = "media_controls_recommendations"; - - private Context mContext; - private int mOriginalRecommendation; - private ContentResolver mContentResolver; - private MediaControlsRecommendationController mController; - - @Before - public void setUp() { - mContext = spy(ApplicationProvider.getApplicationContext()); - mContentResolver = mContext.getContentResolver(); - mOriginalRecommendation = Settings.Secure.getInt(mContentResolver, - Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, 1); - mController = new MediaControlsRecommendationController(mContext, KEY); - } - - @After - public void tearDown() { - Settings.Secure.putInt(mContentResolver, Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, - mOriginalRecommendation); - } - - @Test - public void getAvailability_returnAvailable() { - assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); - } - - @Test - public void setChecked_enable_shouldTurnOn() { - Settings.Secure.putInt(mContentResolver, Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, 1); - - assertThat(mController.isChecked()).isTrue(); - - mController.setChecked(false); - - assertThat(Settings.Secure.getInt(mContentResolver, - Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, -1)).isEqualTo(0); - } - - @Test - public void setChecked_disable_shouldTurnOff() { - Settings.Secure.putInt(mContentResolver, Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, 0); - - assertThat(mController.isChecked()).isFalse(); - - mController.setChecked(true); - - assertThat(Settings.Secure.getInt(mContentResolver, - Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, -1)).isEqualTo(1); - } -}