Snap for 12937884 from 7ce118d601 to 25Q2-release

Change-Id: Ic49de638b37f99bafedeacadc17964a1886c017a
This commit is contained in:
Android Build Coastguard Worker
2025-01-17 18:18:04 -08:00
30 changed files with 586 additions and 224 deletions

View File

@@ -5307,6 +5307,23 @@
android:value="true" />
</activity>
<activity
android:name="Settings$DoubleTapPowerSettingsActivity"
android:label="@string/double_tap_power_title"
android:exported="true"
android:enabled="true">
<intent-filter android:priority="1">
<action android:name="android.settings.action.DOUBLE_TAP_POWER_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.gestures.DoubleTapPowerSettings"/>
<meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
android:value="@string/menu_key_system"/>
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" />
</activity>
<receiver android:name=".safetycenter.SafetySourceBroadcastReceiver"
android:exported="true">
<intent-filter>

View File

@@ -5489,11 +5489,11 @@
<!-- Title for the notification that high contrast text has been replaced. [CHAR LIMIT=NONE] -->
<string name="accessibility_notification_high_contrast_text_title">High contrast text has been replaced</string>
<!-- Text content for the notification that high contrast text has been replaced. [CHAR LIMIT=NONE] -->
<string name="accessibility_notification_high_contrast_text_content">Try Maximize text contrast instead. Find it in Settings.</string>
<string name="accessibility_notification_high_contrast_text_content">Try Text outlines instead. Find it in Settings.</string>
<!-- Action for the notification to high contrast text. [CHAR LIMIT=35] -->
<string name="accessibility_notification_high_contrast_text_action">Open Settings</string>
<!-- Title for the accessibility preference to high contrast text. [CHAR LIMIT=35] -->
<string name="accessibility_toggle_maximize_text_contrast_preference_title">Maximize text contrast</string>
<!-- Title for the accessibility preference that adds an outline behind text to increase contrast and legibility. [CHAR LIMIT=35] -->
<string name="accessibility_toggle_maximize_text_contrast_preference_title">Text outlines</string>
<!-- Summary for the accessibility preference to high contrast text. [CHAR LIMIT=NONE] -->
<string name="accessibility_toggle_maximize_text_contrast_preference_summary">Add a black or white background around text to increase contrast</string>
<!-- Title for the accessibility preference to auto update screen magnification. [CHAR LIMIT=35] -->
@@ -5978,6 +5978,8 @@
<string name="keywords_display_size">screen size, large screen</string>
<!-- List of synonyms used in the settings search bar to find the “Bold text”. [CHAR LIMIT=NONE] -->
<string name="keywords_bold_text">High contrast, low vision, bold font, bold face</string>
<!-- List of synonyms used in the settings search bar to find "Text outlines", previously known as "High contrast text". [CHAR LIMIT=NONE] -->
<string name="keywords_maximize_text_contrast">high contrast text</string>
<!-- List of synonyms used in the settings search bar to find the “Select to Speak”. [CHAR LIMIT=NONE] -->
<string name="keywords_select_to_speak"></string>
<!-- List of synonyms used in the settings search bar to find the “Color correction”. [CHAR LIMIT=NONE] -->
@@ -11367,7 +11369,7 @@
<string name="legacy_navigation_summary">Go back, Home, and switch apps with buttons at the bottom of your screen.</string>
<!-- Accessibility string for gesture nav tutorial button [CHAR_LIMIT=NONE] -->
<string name="nav_tutorial_button_description">Start gesture navigation tutorial, button. Double tap to activate.</string>
<string name="nav_tutorial_button_description">Start gesture navigation tutorial.</string>
<!-- Search keywords for System Navigation settings. [CHAR_LIMIT=NONE]-->
<string name="keywords_system_navigation">system navigation, 2 button navigation, 3 button navigation, gesture navigation, swipe</string>
@@ -13125,10 +13127,6 @@
<string name="media_controls_lockscreen_title">Show media on lock screen</string>
<!-- Description of toggle to enable or disable the media resumption on lockscreen [CHAR LIMIT=NONE]-->
<string name="media_controls_lockscreen_description">To quickly resume playback, media player stays open on lock screen</string>
<!-- Title of toggle to enable or disable media recommendations in quick settings [CHAR LIMIT=NONE] -->
<string name="media_controls_recommendations_title">Show Assistant media recommendations</string>
<!-- Description of toggle to enable or disable media recommendations based on user's activity [CHAR LIMIT=NONE] -->
<string name="media_controls_recommendations_description">Based on your activity</string>
<!-- Subtext for media settings when the player will be hidden [CHAR LIMIT=50] -->
<string name="media_controls_hide_player">Hide player</string>
<!-- Subtext for media settings when the player will be shown [CHAR LIMIT=50] -->

View File

@@ -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"/>
<com.android.settings.accessibility.TextReadingResetPreference
android:key="reset"

View File

@@ -34,7 +34,7 @@
settings:userRestriction="no_config_brightness"/>
<com.android.settingslib.PrimarySwitchPreference
android:key="screen_brightness_mode"
android:key="@string/preference_key_auto_brightness"
android:title="@string/auto_brightness_title"
android:fragment="com.android.settings.display.AutoBrightnessSettings"
settings:useAdminDisabledSummary="true"

View File

@@ -46,7 +46,8 @@
<PreferenceCategory
android:key="lockscreen_notification_what_to_show"
android:title="@string/lockscreen_notification_what_to_show_title">
android:title="@string/lockscreen_notification_what_to_show_title"
settings:controller="com.android.settings.notification.LockScreenWhatToShowController">
<SwitchPreferenceCompat
android:key="lock_screen_notification_show_seen_toggle"

View File

@@ -33,10 +33,4 @@
android:summary="@string/media_controls_lockscreen_description"
app:controller="com.android.settings.sound.MediaControlsLockScreenPreferenceController" />
<SwitchPreferenceCompat
android:key="media_controls_recommendations"
android:title="@string/media_controls_recommendations_title"
android:summary="@string/media_controls_recommendations_description"
app:controller="com.android.settings.sound.MediaControlsRecommendationController" />
</PreferenceScreen>

View File

@@ -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 */ }

View File

@@ -60,6 +60,10 @@ public class ItemInfoArrayAdapter<T extends ItemInfoArrayAdapter.ItemInfo> exten
summary.setVisibility(View.GONE);
}
final ImageView image = root.findViewById(R.id.image);
if (item.mDrawableId == null) {
image.setVisibility(View.GONE);
} else {
image.setVisibility(View.VISIBLE);
image.setImageResource(item.mDrawableId);
if (getContext().getResources().getConfiguration().getLayoutDirection()
== View.LAYOUT_DIRECTION_LTR) {
@@ -67,6 +71,7 @@ public class ItemInfoArrayAdapter<T extends ItemInfoArrayAdapter.ItemInfo> exten
} else {
image.setScaleType(ImageView.ScaleType.FIT_END);
}
}
return root;
}
@@ -78,11 +83,12 @@ public class ItemInfoArrayAdapter<T extends ItemInfoArrayAdapter.ItemInfo> 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;

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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<String>? = 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<String> { _, 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<String>(settingsStore), KeyValueStore {
) : AbstractKeyedDataObservable<String>(), KeyedObserver<String>, KeyValueStore {
override fun contains(key: String) = settingsStore.contains(DOZE_ALWAYS_ON)
@@ -118,6 +106,20 @@ class AmbientDisplayAlwaysOnPreference :
override fun <T : Any> setValue(key: String, valueType: Class<T>, 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 {

View File

@@ -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<String>(settingsStore), KeyValueStore {
AbstractKeyedDataObservable<String>(), KeyedObserver<String>, KeyValueStore {
override fun contains(key: String) = settingsStore.contains(key)
override fun contains(key: String) = settingsStore.contains(SCREEN_BRIGHTNESS_MODE)
override fun <T : Any> getDefaultValue(key: String, valueType: Class<T>) =
DEFAULT_VALUE.toBoolean() as T
override fun <T : Any> getValue(key: String, valueType: Class<T>) =
(settingsStore.getInt(key) ?: DEFAULT_VALUE).toBoolean() as T
(settingsStore.getInt(SCREEN_BRIGHTNESS_MODE) ?: DEFAULT_VALUE).toBoolean() as T
override fun <T : Any> setValue(key: String, valueType: Class<T>, 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
}
}

View File

@@ -55,7 +55,6 @@ import java.text.NumberFormat
// LINT.IfChange
class BrightnessLevelPreference :
PreferenceMetadata,
PersistentPreference<Int>,
RangeValue,
PreferenceBinding,

View File

@@ -39,7 +39,6 @@ import com.android.settingslib.widget.UsageProgressBarPreference
// LINT.IfChange
class BatteryHeaderPreference :
PersistentPreference<Int>,
PreferenceMetadata,
PreferenceBinding,
PreferenceLifecycleProvider,
RangeValue {

View File

@@ -43,7 +43,6 @@ import com.android.settingslib.preference.PreferenceBinding
// LINT.IfChange
open class CallVolumePreference :
PreferenceMetadata,
PreferenceBinding,
PersistentPreference<Int>,
RangeValue,

View File

@@ -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);
}
}
}

View File

@@ -40,7 +40,6 @@ import com.android.settingslib.preference.PreferenceBinding
// LINT.IfChange
open class MediaVolumePreference :
PreferenceMetadata,
PreferenceBinding,
PersistentPreference<Int>,
RangeValue,

View File

@@ -58,7 +58,6 @@ import com.android.settingslib.preference.PreferenceBinding
// LINT.IfChange
open class SeparateRingVolumePreference :
PreferenceMetadata,
PreferenceBinding,
PersistentPreference<Int>,
RangeValue,

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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 =
"<TEMP_BOND_TYPE>le_audio_sharing</TEMP_BOND_TYPE>";
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<CachedBluetoothDevice> 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);
}
}

View File

@@ -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 {

View File

@@ -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());
}
}

View File

@@ -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

View File

@@ -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());

View File

@@ -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);
}
}