From 931b10015951d40de42b852cc09dcae3dd2b6e12 Mon Sep 17 00:00:00 2001 From: Hao Dong Date: Fri, 11 Oct 2024 03:56:57 +0000 Subject: [PATCH 01/17] Set class name when createConfirmDeviceCredentialIntent() API is used. Flag: EXEMPT bugfix Bug: 339532378 Test: manual test Merged-In: I762f280def79d428ed9cf119ace5ccc2b6be2560 Change-Id: I762f280def79d428ed9cf119ace5ccc2b6be2560 --- src/com/android/settings/password/BiometricFragment.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/com/android/settings/password/BiometricFragment.java b/src/com/android/settings/password/BiometricFragment.java index e4c08e73ff8..04c82e559a3 100644 --- a/src/com/android/settings/password/BiometricFragment.java +++ b/src/com/android/settings/password/BiometricFragment.java @@ -140,6 +140,7 @@ public class BiometricFragment extends InstrumentedFragment { .setDisallowBiometricsIfPolicyExists( promptInfo.isDisallowBiometricsIfPolicyExists()) .setReceiveSystemEvents(true) + .setClassNameIfItIsConfirmDeviceCredentialActivity() .build(); } From 354e1faf765484630887392349abda80902873f4 Mon Sep 17 00:00:00 2001 From: Mill Chen Date: Mon, 23 Dec 2024 09:54:36 -0800 Subject: [PATCH 02/17] Add default Sound Picker package name To avoid implicit intents, make intents launch explicitly. Bug: 333344157 Test: Build Change-Id: I905c0f3ddaf0f488ff2fc3bf1747b6df0d802504 Merged-In: Ie19cbceb89842a75a180898abcce81b63c18d46c --- res/values/config.xml | 5 +++++ src/com/android/settings/RingtonePreference.java | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/res/values/config.xml b/res/values/config.xml index 17c33989502..ace50497da8 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -272,6 +272,11 @@ false + + + com.android.soundpicker + + com.android.emergency diff --git a/src/com/android/settings/RingtonePreference.java b/src/com/android/settings/RingtonePreference.java index de5b7c39f76..6b9dad7ffbf 100644 --- a/src/com/android/settings/RingtonePreference.java +++ b/src/com/android/settings/RingtonePreference.java @@ -74,7 +74,8 @@ public class RingtonePreference extends Preference { true); mShowSilent = a.getBoolean(com.android.internal.R.styleable.RingtonePreference_showSilent, true); - setIntent(new Intent(RingtoneManager.ACTION_RINGTONE_PICKER)); + setIntent(new Intent(RingtoneManager.ACTION_RINGTONE_PICKER) + .setPackage(context.getString(R.string.config_sound_picker_package_name))); setUserId(UserHandle.myUserId()); a.recycle(); } From 7a2366b0f1055d4180cc3452df09f53e101d7b4b Mon Sep 17 00:00:00 2001 From: Mill Chen Date: Mon, 23 Dec 2024 09:54:36 -0800 Subject: [PATCH 03/17] Add default Sound Picker package name To avoid implicit intents, make intents launch explicitly. Bug: 333344157 Test: Build Change-Id: I905c0f3ddaf0f488ff2fc3bf1747b6df0d802504 Merged-In: I905c0f3ddaf0f488ff2fc3bf1747b6df0d802504 --- res/values/config.xml | 5 +++++ src/com/android/settings/RingtonePreference.java | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/res/values/config.xml b/res/values/config.xml index 334d4e574c5..6c2f4e3bd6b 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -272,6 +272,11 @@ false + + + com.android.soundpicker + + com.android.emergency diff --git a/src/com/android/settings/RingtonePreference.java b/src/com/android/settings/RingtonePreference.java index de5b7c39f76..6b9dad7ffbf 100644 --- a/src/com/android/settings/RingtonePreference.java +++ b/src/com/android/settings/RingtonePreference.java @@ -74,7 +74,8 @@ public class RingtonePreference extends Preference { true); mShowSilent = a.getBoolean(com.android.internal.R.styleable.RingtonePreference_showSilent, true); - setIntent(new Intent(RingtoneManager.ACTION_RINGTONE_PICKER)); + setIntent(new Intent(RingtoneManager.ACTION_RINGTONE_PICKER) + .setPackage(context.getString(R.string.config_sound_picker_package_name))); setUserId(UserHandle.myUserId()); a.recycle(); } From 89a32bb7d2b16e40d079708cdca66bd011dc7e94 Mon Sep 17 00:00:00 2001 From: Mill Chen Date: Mon, 23 Dec 2024 09:54:36 -0800 Subject: [PATCH 04/17] Add default Sound Picker package name To avoid implicit intents, make intents launch explicitly. Bug: 333344157 Test: Build Change-Id: I905c0f3ddaf0f488ff2fc3bf1747b6df0d802504 Merged-In: I905c0f3ddaf0f488ff2fc3bf1747b6df0d802504 --- res/values/config.xml | 5 +++++ src/com/android/settings/RingtonePreference.java | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/res/values/config.xml b/res/values/config.xml index 4e2c55478c6..804355e8714 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -257,6 +257,11 @@ + + + com.android.soundpicker + + com.android.emergency diff --git a/src/com/android/settings/RingtonePreference.java b/src/com/android/settings/RingtonePreference.java index d283e390fc7..560fdc6df37 100644 --- a/src/com/android/settings/RingtonePreference.java +++ b/src/com/android/settings/RingtonePreference.java @@ -74,7 +74,8 @@ public class RingtonePreference extends Preference { true); mShowSilent = a.getBoolean(com.android.internal.R.styleable.RingtonePreference_showSilent, true); - setIntent(new Intent(RingtoneManager.ACTION_RINGTONE_PICKER)); + setIntent(new Intent(RingtoneManager.ACTION_RINGTONE_PICKER) + .setPackage(context.getString(R.string.config_sound_picker_package_name))); setUserId(UserHandle.myUserId()); a.recycle(); } From be15ba86a76b22348fbdeab79fe5014a0723807c Mon Sep 17 00:00:00 2001 From: Mill Chen Date: Mon, 23 Dec 2024 09:54:36 -0800 Subject: [PATCH 05/17] Add default Sound Picker package name To avoid implicit intents, make intents launch explicitly. Bug: 333344157 Test: Build Change-Id: I905c0f3ddaf0f488ff2fc3bf1747b6df0d802504 Merged-In: I905c0f3ddaf0f488ff2fc3bf1747b6df0d802504 --- res/values/config.xml | 5 +++++ src/com/android/settings/RingtonePreference.java | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/res/values/config.xml b/res/values/config.xml index d7528c63bd0..8570dd717d7 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -253,6 +253,11 @@ + + + com.android.soundpicker + + com.android.emergency diff --git a/src/com/android/settings/RingtonePreference.java b/src/com/android/settings/RingtonePreference.java index d283e390fc7..560fdc6df37 100644 --- a/src/com/android/settings/RingtonePreference.java +++ b/src/com/android/settings/RingtonePreference.java @@ -74,7 +74,8 @@ public class RingtonePreference extends Preference { true); mShowSilent = a.getBoolean(com.android.internal.R.styleable.RingtonePreference_showSilent, true); - setIntent(new Intent(RingtoneManager.ACTION_RINGTONE_PICKER)); + setIntent(new Intent(RingtoneManager.ACTION_RINGTONE_PICKER) + .setPackage(context.getString(R.string.config_sound_picker_package_name))); setUserId(UserHandle.myUserId()); a.recycle(); } From 94681e343679dcfd5af81f11fbd66a70b6a56db1 Mon Sep 17 00:00:00 2001 From: Mill Chen Date: Mon, 23 Dec 2024 09:54:36 -0800 Subject: [PATCH 06/17] Add default Sound Picker package name To avoid implicit intents, make intents launch explicitly. Bug: 333344157 Test: Build Change-Id: I905c0f3ddaf0f488ff2fc3bf1747b6df0d802504 Merged-In: I905c0f3ddaf0f488ff2fc3bf1747b6df0d802504 --- res/values/config.xml | 5 +++++ src/com/android/settings/RingtonePreference.java | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/res/values/config.xml b/res/values/config.xml index 987eaf97254..03020217430 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -243,6 +243,11 @@ + + + com.android.soundpicker + + com.android.emergency diff --git a/src/com/android/settings/RingtonePreference.java b/src/com/android/settings/RingtonePreference.java index d283e390fc7..560fdc6df37 100644 --- a/src/com/android/settings/RingtonePreference.java +++ b/src/com/android/settings/RingtonePreference.java @@ -74,7 +74,8 @@ public class RingtonePreference extends Preference { true); mShowSilent = a.getBoolean(com.android.internal.R.styleable.RingtonePreference_showSilent, true); - setIntent(new Intent(RingtoneManager.ACTION_RINGTONE_PICKER)); + setIntent(new Intent(RingtoneManager.ACTION_RINGTONE_PICKER) + .setPackage(context.getString(R.string.config_sound_picker_package_name))); setUserId(UserHandle.myUserId()); a.recycle(); } From cf52112bcba89ded9e15eea24e025e374844adc8 Mon Sep 17 00:00:00 2001 From: Mill Chen Date: Mon, 23 Dec 2024 09:54:36 -0800 Subject: [PATCH 07/17] Add default Sound Picker package name To avoid implicit intents, make intents launch explicitly. Bug: 333344157 Test: Build Change-Id: I905c0f3ddaf0f488ff2fc3bf1747b6df0d802504 Merged-In: I905c0f3ddaf0f488ff2fc3bf1747b6df0d802504 --- res/values/config.xml | 5 +++++ src/com/android/settings/RingtonePreference.java | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/res/values/config.xml b/res/values/config.xml index 9ed7536e5f7..24053e40241 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -243,6 +243,11 @@ + + + com.android.soundpicker + + com.android.emergency diff --git a/src/com/android/settings/RingtonePreference.java b/src/com/android/settings/RingtonePreference.java index d283e390fc7..560fdc6df37 100644 --- a/src/com/android/settings/RingtonePreference.java +++ b/src/com/android/settings/RingtonePreference.java @@ -74,7 +74,8 @@ public class RingtonePreference extends Preference { true); mShowSilent = a.getBoolean(com.android.internal.R.styleable.RingtonePreference_showSilent, true); - setIntent(new Intent(RingtoneManager.ACTION_RINGTONE_PICKER)); + setIntent(new Intent(RingtoneManager.ACTION_RINGTONE_PICKER) + .setPackage(context.getString(R.string.config_sound_picker_package_name))); setUserId(UserHandle.myUserId()); a.recycle(); } From b1e4cd09ffa36b7ff8cf9c2d9cc4b3f83f0b4c05 Mon Sep 17 00:00:00 2001 From: Mill Chen Date: Mon, 23 Dec 2024 09:54:36 -0800 Subject: [PATCH 08/17] Add default Sound Picker package name To avoid implicit intents, make intents launch explicitly. Bug: 333344157 Test: Build Change-Id: I905c0f3ddaf0f488ff2fc3bf1747b6df0d802504 Merged-In: I905c0f3ddaf0f488ff2fc3bf1747b6df0d802504 --- res/values/config.xml | 5 +++++ src/com/android/settings/RingtonePreference.java | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/res/values/config.xml b/res/values/config.xml index 9ed7536e5f7..24053e40241 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -243,6 +243,11 @@ + + + com.android.soundpicker + + com.android.emergency diff --git a/src/com/android/settings/RingtonePreference.java b/src/com/android/settings/RingtonePreference.java index d283e390fc7..560fdc6df37 100644 --- a/src/com/android/settings/RingtonePreference.java +++ b/src/com/android/settings/RingtonePreference.java @@ -74,7 +74,8 @@ public class RingtonePreference extends Preference { true); mShowSilent = a.getBoolean(com.android.internal.R.styleable.RingtonePreference_showSilent, true); - setIntent(new Intent(RingtoneManager.ACTION_RINGTONE_PICKER)); + setIntent(new Intent(RingtoneManager.ACTION_RINGTONE_PICKER) + .setPackage(context.getString(R.string.config_sound_picker_package_name))); setUserId(UserHandle.myUserId()); a.recycle(); } From 3e1e855094ba6c29f8969faf6bc97b1f30d29b15 Mon Sep 17 00:00:00 2001 From: Jason Chang Date: Tue, 7 Jan 2025 12:56:45 +0000 Subject: [PATCH 09/17] Update Fingerprint adding button with expressive design Flag: EXEMPT flag by System prop (SettingsThemeHelper.isExpressiveTheme) Bug: 388260897 Test: build and manually check the UI and its behaviors. Change-Id: I1c6d859f78305d0f14476e12a5bb4e1b0258d06e --- res/xml/security_settings_fingerprint.xml | 8 +++ .../fingerprint/FingerprintSettings.java | 52 +++++++++++++++++-- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/res/xml/security_settings_fingerprint.xml b/res/xml/security_settings_fingerprint.xml index 32f09244f97..331549c2743 100644 --- a/res/xml/security_settings_fingerprint.xml +++ b/res/xml/security_settings_fingerprint.xml @@ -29,6 +29,14 @@ android:title="@string/fingerprint_add_title" android:icon="@drawable/ic_add_24dp"/> + + items = mFingerprintManager.getEnrolledFingerprints(mUserId); final int fingerprintCount = items.size(); for (int i = 0; i < fingerprintCount; i++) { @@ -715,13 +723,30 @@ public class FingerprintSettings extends SubSettings { mFingerprintsEnrolledCategory.addPreference(pref); pref.setOnPreferenceChangeListener(this); } - mAddFingerprintPreference = findPreference(KEY_FINGERPRINT_ADD); + mAddFingerprintPreference = findPreference(mIsExpressiveThemeStyle + ? KEY_FINGERPRINT_ADD_EXPRESSIVE : KEY_FINGERPRINT_ADD); setupAddFingerprintPreference(); return keyToReturn; } private void setupAddFingerprintPreference() { mAddFingerprintPreference.setOnPreferenceChangeListener(this); + if (mIsExpressiveThemeStyle + && (mAddFingerprintPreference instanceof ButtonPreference)) { + ((ButtonPreference) mAddFingerprintPreference).setOnClickListener(view -> { + mIsEnrolling = true; + Intent intent = new Intent(); + intent.setClassName(SETTINGS_PACKAGE_NAME, + FingerprintEnroll.AddAdditionalFingerprint.class.getName()); + intent.putExtra(Intent.EXTRA_USER_ID, mUserId); + intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken); + if (mCalibrator != null) { + intent.putExtras(mCalibrator.getExtrasForNextIntent()); + } + startActivityForResult(intent, ADD_FINGERPRINT_REQUEST); + }); + } + updateAddPreference(); } @@ -803,12 +828,15 @@ public class FingerprintSettings extends SubSettings { return; // Activity went away } - mAddFingerprintPreference = findPreference(KEY_FINGERPRINT_ADD); + mAddFingerprintPreference = findPreference( + mIsExpressiveThemeStyle ? KEY_FINGERPRINT_ADD_EXPRESSIVE : KEY_FINGERPRINT_ADD); if (mAddFingerprintPreference == null) { return; // b/275519315 Skip if updateAddPreference() invoke before addPreference() } + updateAddingButtonStyle(); + /* Disable preference if too many fingerprints added */ final int max = getContext().getResources().getInteger( com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser); @@ -828,6 +856,20 @@ public class FingerprintSettings extends SubSettings { && !tooMany && !removalInProgress && mToken != null); } + private void updateAddingButtonStyle() { + final Preference nonExpressiveBtnPreference = findPreference(KEY_FINGERPRINT_ADD); + final ButtonPreference expressiveBtnPreference = + findPreference(KEY_FINGERPRINT_ADD_EXPRESSIVE); + + if (nonExpressiveBtnPreference != null) { + nonExpressiveBtnPreference.setVisible(!mIsExpressiveThemeStyle); + } + + if (expressiveBtnPreference != null) { + expressiveBtnPreference.setVisible(mIsExpressiveThemeStyle); + } + } + private void createFooterPreference(PreferenceGroup root) { final Context context = getActivity(); if (context == null) { @@ -925,11 +967,11 @@ public class FingerprintSettings extends SubSettings { @Override public boolean onPreferenceTreeClick(Preference pref) { final String key = pref.getKey(); - if (KEY_FINGERPRINT_ADD.equals(key)) { + if (!mIsExpressiveThemeStyle && KEY_FINGERPRINT_ADD.equals(key)) { mIsEnrolling = true; Intent intent = new Intent(); intent.setClassName(SETTINGS_PACKAGE_NAME, - FingerprintEnroll.AddAdditionalFingerprint.class.getName()); + FingerprintEnroll.AddAdditionalFingerprint.class.getName()); intent.putExtra(Intent.EXTRA_USER_ID, mUserId); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken); if (mCalibrator != null) { From 18279890cc4e1347330c178137dc8c8945d1a8d0 Mon Sep 17 00:00:00 2001 From: Ze Li Date: Wed, 8 Jan 2025 15:34:17 +0800 Subject: [PATCH 10/17] [Temp bonding] Block users to select temp bond device as primary device for call in "Call audio" under "Audio sharing" page Test: com.android.settings.connecteddevice.audiosharing.AudioSharingCallAudioPreferenceControllerTest Bug: 362859132 Flag: com.android.settingslib.flags.enable_temporary_bond_devices_ui Change-Id: Ideafaa1b113a40219830b8ba2b5156b599481eee --- ...oSharingCallAudioPreferenceController.java | 12 +++++++++++ ...ringCallAudioPreferenceControllerTest.java | 21 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java index 719d6cb71e6..3130a0c3600 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java @@ -52,6 +52,7 @@ import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; +import com.android.settingslib.flags.Flags; import com.android.settingslib.utils.ThreadUtils; import com.google.common.collect.ImmutableList; @@ -63,6 +64,7 @@ import java.util.Map; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; /** PreferenceController to control the dialog to choose the active device for calls and alarms */ public class AudioSharingCallAudioPreferenceController extends AudioSharingBasePreferenceController @@ -379,11 +381,21 @@ public class AudioSharingCallAudioPreferenceController extends AudioSharingBaseP private void updateDeviceItemsInSharingSession() { mGroupedConnectedDevices = AudioSharingUtils.fetchConnectedDevicesByGroupId(mBtManager); + if (Flags.enableTemporaryBondDevicesUi()) { + mGroupedConnectedDevices = + mGroupedConnectedDevices.entrySet().stream() + .filter(entry -> !anyTemporaryBondDevice(entry.getValue())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } mDeviceItemsInSharingSession = AudioSharingUtils.buildOrderedConnectedLeadAudioSharingDeviceItem( mBtManager, mGroupedConnectedDevices, /* filterByInSharing= */ true); } + private boolean anyTemporaryBondDevice(List connectedDevices) { + return connectedDevices.stream().anyMatch(BluetoothUtils::isTemporaryBondDevice); + } + @Nullable private Pair getActiveItemWithIndex() { List deviceItems = new ArrayList<>(mDeviceItemsInSharingSession); diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceControllerTest.java index 4dc4dca4ab7..3075573b728 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceControllerTest.java @@ -42,6 +42,7 @@ import android.content.ContentResolver; import android.content.Context; import android.database.ContentObserver; import android.os.Looper; +import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; import android.view.View; @@ -107,8 +108,11 @@ public class AudioSharingCallAudioPreferenceControllerTest { private static final String PREF_KEY = "calls_and_alarms"; private static final String TEST_DEVICE_NAME1 = "test1"; private static final String TEST_DEVICE_NAME2 = "test2"; + private static final String TEMP_BOND_METADATA = + "le_audio_sharing"; private static final int TEST_DEVICE_GROUP_ID1 = 1; private static final int TEST_DEVICE_GROUP_ID2 = 2; + private static final int METADATA_FAST_PAIR_CUSTOMIZED_FIELDS = 25; private static final String TEST_SETTINGS_KEY = "bluetooth_le_broadcast_fallback_active_group_id"; @@ -440,6 +444,23 @@ public class AudioSharingCallAudioPreferenceControllerTest { assertThat(mPreference.getSummary().toString()).isEmpty(); } + @Test + @EnableFlags(Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI) + public void displayPreference_hasTemporaryBondDevice_doNotShow() { + Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID1); + when(mCachedDevice1.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(true); + when(mBroadcast.isEnabled(any())).thenReturn(true); + when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1, mDevice2)); + when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState)); + when(mDevice2.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS)).thenReturn( + TEMP_BOND_METADATA.getBytes()); + + mController.displayPreference(mScreen); + shadowOf(Looper.getMainLooper()).idle(); + + assertThat(mController.mGroupedConnectedDevices).hasSize(0); + } + @Test public void displayPreference_clickToShowCorrectDialog() { AlertDialog latestAlertDialog = ShadowAlertDialogCompat.getLatestAlertDialog(); From 4da20d24c4986b71a24d453df07298dc6daa2c03 Mon Sep 17 00:00:00 2001 From: arunvoddu Date: Wed, 8 Jan 2025 12:51:50 +0000 Subject: [PATCH 11/17] [Satellite] Satellite UX changes in SIM settings as per new UX design. Bug: 382707562 Flag: EXEMPT UX bug fix Test: Verified UX on device Change-Id: I9e600d8f1fd6c273329e05a74079f1e03c209c65 --- res/values/strings.xml | 6 +- ...eSettingsPreferenceCategoryController.java | 73 +------------------ ...tingsPreferenceCategoryControllerTest.java | 31 +------- 3 files changed, 7 insertions(+), 103 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index c3fb2f94ead..0144996f754 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -12431,9 +12431,9 @@ About %1$s - You can send and receive text messages by satellite as part of an eligible %1$s account + You can send and receive text messages by satellite with an eligible %1$s account - Your %1$s plan + Your %1$s account Messaging is included with your account @@ -12451,7 +12451,7 @@ You can text anyone, including emergency services. Your phone will reconnect to a mobile network when available. - %1$s may take longer and is available only in some areas. Weather and certain structures may affect your satellite connection. Calling by satellite isn\u2019t available. Emergency calls may still connect.\n\nIt may take some time for account changes to show in Settings. Contact %1$s for details. + %1$s may take longer and is available only in some areas. Weather and certain structures may affect your satellite connection. Calling by satellite isn\u2019t available. Emergency calls may still connect.\n\nIt may take some time for account changes to show in Settings. Contact %2$s for details. More about %1$s diff --git a/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryController.java b/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryController.java index f0d1da42c88..6218e055038 100644 --- a/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryController.java +++ b/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryController.java @@ -18,21 +18,13 @@ package com.android.settings.network.telephony; import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL; import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ESOS_SUPPORTED_BOOL; -import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_DATA; -import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_SMS; import android.content.Context; import android.os.PersistableBundle; -import android.telephony.TelephonyCallback; -import android.telephony.TelephonyManager; -import android.telephony.satellite.NtnSignalStrength; import android.telephony.satellite.SatelliteManager; import android.util.Log; -import androidx.annotation.NonNull; -import androidx.annotation.VisibleForTesting; import androidx.lifecycle.DefaultLifecycleObserver; -import androidx.lifecycle.LifecycleOwner; import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceScreen; @@ -40,9 +32,6 @@ import com.android.settings.R; import com.android.settings.flags.Flags; import com.android.settings.network.CarrierConfigCache; -import java.util.Arrays; -import java.util.List; - /** Preference controller for Satellite functions in mobile network settings. */ public class SatelliteSettingsPreferenceCategoryController extends TelephonyBasePreferenceController implements DefaultLifecycleObserver { @@ -51,17 +40,11 @@ public class SatelliteSettingsPreferenceCategoryController private CarrierConfigCache mCarrierConfigCache; private SatelliteManager mSatelliteManager; private PreferenceCategory mPreferenceCategory; - private TelephonyManager mTelephonyManager; - - @VisibleForTesting - final CarrierRoamingNtnModeCallback mCarrierRoamingNtnModeCallback = - new CarrierRoamingNtnModeCallback(); public SatelliteSettingsPreferenceCategoryController(Context context, String key) { super(context, key); mCarrierConfigCache = CarrierConfigCache.getInstance(context); mSatelliteManager = context.getSystemService(SatelliteManager.class); - mTelephonyManager = context.getSystemService(TelephonyManager.class); } /** @@ -72,13 +55,13 @@ public class SatelliteSettingsPreferenceCategoryController public void init(int subId) { Log.d(TAG, "init(), subId=" + subId); mSubId = subId; - mTelephonyManager = mTelephonyManager.createForSubscriptionId(subId); } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); mPreferenceCategory = screen.findPreference(getPreferenceKey()); + mPreferenceCategory.setTitle(R.string.category_title_satellite_connectivity); } @Override @@ -103,58 +86,4 @@ public class SatelliteSettingsPreferenceCategoryController return (isSatelliteAttachSupported || isSatelliteSosSupported) ? AVAILABLE_UNSEARCHABLE : UNSUPPORTED_ON_DEVICE; } - - @Override - public void onResume(@NonNull LifecycleOwner owner) { - if (Flags.satelliteOemSettingsUxMigration()) { - mTelephonyManager.registerTelephonyCallback(mContext.getMainExecutor(), - mCarrierRoamingNtnModeCallback); - } - } - - @Override - public void onPause(@NonNull LifecycleOwner owner) { - if (Flags.satelliteOemSettingsUxMigration()) { - mTelephonyManager.unregisterTelephonyCallback(mCarrierRoamingNtnModeCallback); - } - } - - @VisibleForTesting - class CarrierRoamingNtnModeCallback extends TelephonyCallback implements - TelephonyCallback.CarrierRoamingNtnListener { - @Override - public void onCarrierRoamingNtnAvailableServicesChanged(int[] availableServices) { - CarrierRoamingNtnListener.super.onCarrierRoamingNtnAvailableServicesChanged( - availableServices); - List availableServicesList = Arrays.stream(availableServices).boxed().toList(); - boolean isSmsAvailable = availableServicesList.contains(SERVICE_TYPE_SMS); - boolean isDataAvailable = availableServicesList.contains(SERVICE_TYPE_DATA); - Log.i(TAG, "isSmsAvailable : " + isSmsAvailable - + " / isDataAvailable " + isDataAvailable); - if (mPreferenceCategory == null) { - Log.d(TAG, "Satellite preference category is not initialized yet"); - return; - } - if (isDataAvailable) { - mPreferenceCategory.setTitle(R.string.category_title_satellite_connectivity); - } else if (isSmsAvailable) { - mPreferenceCategory.setTitle(R.string.satellite_setting_title); - } - } - - @Override - public void onCarrierRoamingNtnEligibleStateChanged(boolean eligible) { - // Do nothing - } - - @Override - public void onCarrierRoamingNtnModeChanged(boolean active) { - // Do nothing - } - - @Override - public void onCarrierRoamingNtnSignalStrengthChanged(NtnSignalStrength ntnSignalStrength) { - // Do nothing - } - } } diff --git a/tests/unit/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryControllerTest.java index 82119f17bd3..085a68d8173 100644 --- a/tests/unit/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryControllerTest.java +++ b/tests/unit/src/com/android/settings/network/telephony/SatelliteSettingsPreferenceCategoryControllerTest.java @@ -16,13 +16,12 @@ package com.android.settings.network.telephony; -import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_DATA; -import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_SMS; - import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE; import static com.google.common.truth.Truth.assertThat; +import static junit.framework.Assert.assertEquals; + import static org.mockito.Mockito.spy; import android.content.Context; @@ -35,8 +34,6 @@ import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; -import com.android.settings.R; - import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; @@ -72,24 +69,6 @@ public class SatelliteSettingsPreferenceCategoryControllerTest { assertThat(result).isEqualTo(UNSUPPORTED_ON_DEVICE); } - @Test - @Ignore("b/382664790") - public void setPreferenceTitle_hasDataService_showConnectivity() { - PreferenceManager preferenceManager = new PreferenceManager(mContext); - PreferenceScreen preferenceScreen = preferenceManager.createPreferenceScreen(mContext); - PreferenceCategory preferenceCategory = new PreferenceCategory(mContext); - preferenceCategory.setKey(KEY); - preferenceCategory.addPreference(new Preference(mContext)); - preferenceScreen.addPreference(preferenceCategory); - mController.displayPreference(preferenceScreen); - - mController.mCarrierRoamingNtnModeCallback.onCarrierRoamingNtnAvailableServicesChanged( - new int[]{SERVICE_TYPE_DATA}); - - assertThat(preferenceCategory.getTitle()).isEqualTo( - mContext.getString(R.string.title_satellite_setting_connectivity)); - } - @Test @Ignore("b/382664790") public void setPreferenceTitle_hasSmsService_showMessaging() { @@ -101,10 +80,6 @@ public class SatelliteSettingsPreferenceCategoryControllerTest { preferenceCategory.addPreference(new Preference(mContext)); mController.displayPreference(preferenceScreen); - mController.mCarrierRoamingNtnModeCallback.onCarrierRoamingNtnAvailableServicesChanged( - new int[]{SERVICE_TYPE_SMS}); - - assertThat(preferenceCategory.getTitle()).isEqualTo( - mContext.getString(R.string.satellite_setting_title)); + assertEquals(preferenceCategory.getTitle(), "Satellite connectivity"); } } From 41896428ea89daa32d203b7439d2c75a9fb68af5 Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Wed, 20 Nov 2024 10:32:59 -0500 Subject: [PATCH 12/17] Layout improvements for notification pages Changes for upcoming theming changes in Settings: - replacing some margins with padding - merging some (switch pref + info pref) combos into a single preference. I flagged the one that was already launched, but changed the other directly - added some section headers (unflagged) - moved all app wide notification settings to a single section (unflagged) - changed two plain text prefs into TopIntroPreference, the dedicated pref type for that sort of UI - fixed some UI issues with 'Show more categories' appearing too often - removed a duplicate notifcation channel label (unflagged) - replaced a button layout preference with ButtonPreference (unflagged) Test: manual review with is_expressive_design_enabled on and off Test: atest com.android.settings.notification.app Flag: EXEMPT this feature is not using aconfig for flagging Bug: 349652992 Change-Id: I2acd7b2eb9dbcf6929143bfde99cd67163f1f95d --- res/layout/notif_importance_preference.xml | 4 +- ...notif_priority_conversation_preference.xml | 4 +- res/values/strings.xml | 10 +- res/xml/app_notification_settings.xml | 151 ++++++++---------- res/xml/channel_notification_settings.xml | 20 +-- res/xml/modes_calls_settings.xml | 8 +- .../AllConversationsPreferenceController.java | 5 +- .../app/AllowSoundPreferenceController.java | 3 + .../app/AppLinkPreferenceController.java | 3 + .../app/BadgePreferenceController.java | 3 + .../BubbleSummaryPreferenceController.java | 3 + .../app/ChannelListPreferenceController.java | 48 +++--- .../DeletedChannelsPreferenceController.java | 3 + .../app/DndPreferenceController.java | 3 + ...eenIntentPermissionPreferenceController.kt | 3 +- .../app/HeaderPreferenceController.java | 23 +-- ...dConversationInfoPreferenceController.java | 4 + ...validConversationPreferenceController.java | 11 +- ...rityConversationsPreferenceController.java | 5 +- ...otedNotificationsPreferenceController.java | 13 +- ...centConversationsPreferenceController.java | 26 +-- .../app/ShowMorePreferenceController.java | 3 + .../app/VisibilityPreferenceController.java | 4 + .../AllowSoundPreferenceControllerTest.java | 13 +- ...ntentPermissionPreferenceControllerTest.kt | 5 +- .../app/HeaderPreferenceControllerTest.java | 25 +-- ...versationInfoPreferenceControllerTest.java | 16 ++ ...NotificationsPreferenceControllerTest.java | 13 +- ...ConversationsPreferenceControllerTest.java | 35 ++-- .../ChannelListPreferenceControllerTest.java | 9 ++ 30 files changed, 261 insertions(+), 215 deletions(-) diff --git a/res/layout/notif_importance_preference.xml b/res/layout/notif_importance_preference.xml index b2a02d14240..614856c6d9c 100644 --- a/res/layout/notif_importance_preference.xml +++ b/res/layout/notif_importance_preference.xml @@ -21,8 +21,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" - android:layout_marginStart="24dp" - android:layout_marginEnd="16dp" + android:paddingStart="?android:attr/listPreferredItemPaddingStart" + android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" android:paddingTop="@dimen/notification_importance_toggle_marginTop" android:paddingBottom="@dimen/notification_importance_toggle_marginTop" android:orientation="vertical"> diff --git a/res/layout/notif_priority_conversation_preference.xml b/res/layout/notif_priority_conversation_preference.xml index 4601c008563..326c52a5407 100644 --- a/res/layout/notif_priority_conversation_preference.xml +++ b/res/layout/notif_priority_conversation_preference.xml @@ -21,8 +21,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" - android:layout_marginStart="24dp" - android:layout_marginEnd="16dp" + android:paddingStart="?android:attr/listPreferredItemPaddingStart" + android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" android:paddingTop="@dimen/notification_importance_toggle_marginTop" android:paddingBottom="@dimen/notification_importance_toggle_marginTop" android:orientation="vertical"> diff --git a/res/values/strings.xml b/res/values/strings.xml index 69ff0f10a6a..61bcb6efffb 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -8999,9 +8999,12 @@ Conversation section - + Allow app to use conversation section + + Allow app to use conversation section, although conversation features like prioritization and bubbles are not supported by this app. + "%1$s%2$s" @@ -9394,8 +9397,11 @@ This app does not send notifications + + App settings + - Categories + Notification categories Other diff --git a/res/xml/app_notification_settings.xml b/res/xml/app_notification_settings.xml index 06d74f608fa..b91aea9a618 100644 --- a/res/xml/app_notification_settings.xml +++ b/res/xml/app_notification_settings.xml @@ -30,49 +30,21 @@ - - - - - - - - - + android:visibility="gone" + android:layout="@layout/empty_view" > - - - - - - + android:visibility="gone" + android:layout="@layout/empty_view" /> + - + - - + + - - + + + - - + - - + + - + + - + + + + + + + + + + + + + + diff --git a/res/xml/channel_notification_settings.xml b/res/xml/channel_notification_settings.xml index a3895e38c5e..a8b536b717d 100644 --- a/res/xml/channel_notification_settings.xml +++ b/res/xml/channel_notification_settings.xml @@ -111,16 +111,18 @@ android:title="@string/app_notification_override_dnd_title" android:summary="@string/app_notification_override_dnd_summary" /> - - + android:order="110"/> + + + + diff --git a/res/xml/modes_calls_settings.xml b/res/xml/modes_calls_settings.xml index b564020cf71..e3a6fca643d 100644 --- a/res/xml/modes_calls_settings.xml +++ b/res/xml/modes_calls_settings.xml @@ -32,9 +32,11 @@ android:layout_height="16dp"/> - + + + = IMPORTANCE_DEFAULT || mChannel.getImportance() == IMPORTANCE_UNSPECIFIED); + if (preference.getParent() != null) { + preference.getParent().setVisible(true); + } } else { Log.i(TAG, "tried to updatestate on a null channel?!"); } } diff --git a/src/com/android/settings/notification/app/AppLinkPreferenceController.java b/src/com/android/settings/notification/app/AppLinkPreferenceController.java index 043ae698f54..4b397d02ce9 100644 --- a/src/com/android/settings/notification/app/AppLinkPreferenceController.java +++ b/src/com/android/settings/notification/app/AppLinkPreferenceController.java @@ -54,6 +54,9 @@ public class AppLinkPreferenceController extends NotificationPreferenceControlle } public void updateState(Preference preference) { + if (preference.getParent() != null) { + preference.getParent().setVisible(true); + } if (mAppRow != null) { preference.setIntent(mAppRow.settingsIntent); } diff --git a/src/com/android/settings/notification/app/BadgePreferenceController.java b/src/com/android/settings/notification/app/BadgePreferenceController.java index 9d55fa322b8..b5e65fca401 100644 --- a/src/com/android/settings/notification/app/BadgePreferenceController.java +++ b/src/com/android/settings/notification/app/BadgePreferenceController.java @@ -82,6 +82,9 @@ public class BadgePreferenceController extends NotificationPreferenceController public void updateState(Preference preference) { if (mAppRow != null) { + if (preference.getParent() != null) { + preference.getParent().setVisible(true); + } RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference; pref.setDisabledByAdmin(mAdmin); if (mChannel != null) { diff --git a/src/com/android/settings/notification/app/BubbleSummaryPreferenceController.java b/src/com/android/settings/notification/app/BubbleSummaryPreferenceController.java index 8c22f926e9b..e82fe0b31a4 100644 --- a/src/com/android/settings/notification/app/BubbleSummaryPreferenceController.java +++ b/src/com/android/settings/notification/app/BubbleSummaryPreferenceController.java @@ -82,6 +82,9 @@ public class BubbleSummaryPreferenceController extends NotificationPreferenceCon intent.putExtra(Settings.EXTRA_APP_UID, mAppRow.uid); preference.setIntent(intent); } + if (preference.getParent() != null) { + preference.getParent().setVisible(true); + } } @Override diff --git a/src/com/android/settings/notification/app/ChannelListPreferenceController.java b/src/com/android/settings/notification/app/ChannelListPreferenceController.java index b8dfb6a7069..66094a02f5f 100644 --- a/src/com/android/settings/notification/app/ChannelListPreferenceController.java +++ b/src/com/android/settings/notification/app/ChannelListPreferenceController.java @@ -58,6 +58,7 @@ public class ChannelListPreferenceController extends NotificationPreferenceContr private List mChannelGroupList; private PreferenceCategory mPreference; + int mChannelCount; public ChannelListPreferenceController(Context context, NotificationBackend backend) { super(context, backend); @@ -107,6 +108,7 @@ public class ChannelListPreferenceController extends NotificationPreferenceContr } else { mChannelGroupList = mBackend.getGroups(mAppRow.pkg, mAppRow.uid).getList(); } + mChannelCount = mBackend.getChannelCount(mAppRow.pkg, mAppRow.uid); Collections.sort(mChannelGroupList, CHANNEL_GROUP_COMPARATOR); return null; } @@ -116,6 +118,7 @@ public class ChannelListPreferenceController extends NotificationPreferenceContr if (mContext == null) { return; } + updateFullList(mPreference, mChannelGroupList); } }.execute(); @@ -129,25 +132,30 @@ public class ChannelListPreferenceController extends NotificationPreferenceContr void updateFullList(@NonNull PreferenceCategory groupPrefsList, @NonNull List channelGroups) { if (channelGroups.isEmpty()) { - if (groupPrefsList.getPreferenceCount() == 1 - && KEY_ZERO_CATEGORIES.equals(groupPrefsList.getPreference(0).getKey())) { - // Ensure the titles are correct for the current language, but otherwise leave alone - PreferenceGroup groupCategory = (PreferenceGroup) groupPrefsList.getPreference(0); - groupCategory.setTitle(R.string.notification_channels); - groupCategory.getPreference(0).setTitle(R.string.no_channels); - } else { - // Clear any contents and create the 'zero-categories' group. + if (mChannelCount > 0) { groupPrefsList.removeAll(); + } else { + if (groupPrefsList.getPreferenceCount() == 1 + && KEY_ZERO_CATEGORIES.equals(groupPrefsList.getPreference(0).getKey())) { + // Ensure the titles are correct for the current language, but otherwise leave alone + PreferenceGroup groupCategory = (PreferenceGroup) groupPrefsList.getPreference( + 0); + groupCategory.setTitle(R.string.notification_channels); + groupCategory.getPreference(0).setTitle(R.string.no_channels); + } else { + // Clear any contents and create the 'zero-categories' group. + groupPrefsList.removeAll(); - PreferenceCategory groupCategory = new PreferenceCategory(mContext); - groupCategory.setTitle(R.string.notification_channels); - groupCategory.setKey(KEY_ZERO_CATEGORIES); - groupPrefsList.addPreference(groupCategory); + PreferenceCategory groupCategory = new PreferenceCategory(mContext); + groupCategory.setTitle(R.string.notification_channels); + groupCategory.setKey(KEY_ZERO_CATEGORIES); + groupPrefsList.addPreference(groupCategory); - Preference empty = new Preference(mContext); - empty.setTitle(R.string.no_channels); - empty.setEnabled(false); - groupCategory.addPreference(empty); + Preference empty = new Preference(mContext); + empty.setTitle(R.string.no_channels); + empty.setEnabled(false); + groupCategory.addPreference(empty); + } } } else { updateGroupList(groupPrefsList, channelGroups); @@ -211,6 +219,11 @@ public class ChannelListPreferenceController extends NotificationPreferenceContr groupPrefsList.addPreference(group); } } + Preference otherGroup = groupPrefsList.findPreference(KEY_GENERAL_CATEGORY); + if (otherGroup != null) { + otherGroup.setTitle(numFinalGroups == 1 + ? R.string.notification_channels : R.string.notification_channels_other); + } } /** @@ -248,8 +261,7 @@ public class ChannelListPreferenceController extends NotificationPreferenceContr List finalOrderedPrefs = new ArrayList<>(); Preference appDefinedGroupToggle; if (group.getId() == null) { - // For the 'null' group, set the "Other" title. - groupPrefGroup.setTitle(R.string.notification_channels_other); + groupPrefGroup.setTitle(R.string.notification_channels); appDefinedGroupToggle = null; } else { // For an app-defined group, set their name and create a row to toggle 'isBlocked'. diff --git a/src/com/android/settings/notification/app/DeletedChannelsPreferenceController.java b/src/com/android/settings/notification/app/DeletedChannelsPreferenceController.java index 07b7fdab01d..004afe295b9 100644 --- a/src/com/android/settings/notification/app/DeletedChannelsPreferenceController.java +++ b/src/com/android/settings/notification/app/DeletedChannelsPreferenceController.java @@ -63,6 +63,9 @@ public class DeletedChannelsPreferenceController extends NotificationPreferenceC } public void updateState(Preference preference) { + if (preference.getParent() != null) { + preference.getParent().setVisible(true); + } if (mAppRow != null) { int deletedChannelCount = mBackend.getDeletedChannelCount(mAppRow.pkg, mAppRow.uid); preference.setTitle(StringUtil.getIcuPluralsString(mContext, deletedChannelCount, diff --git a/src/com/android/settings/notification/app/DndPreferenceController.java b/src/com/android/settings/notification/app/DndPreferenceController.java index b65928aa915..25337879253 100644 --- a/src/com/android/settings/notification/app/DndPreferenceController.java +++ b/src/com/android/settings/notification/app/DndPreferenceController.java @@ -54,6 +54,9 @@ public class DndPreferenceController extends NotificationPreferenceController public void updateState(Preference preference) { if (mChannel != null) { + if (preference.getParent() != null) { + preference.getParent().setVisible(true); + } RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference; pref.setDisabledByAdmin(mAdmin); pref.setEnabled(!pref.isDisabledByAdmin()); diff --git a/src/com/android/settings/notification/app/FullScreenIntentPermissionPreferenceController.kt b/src/com/android/settings/notification/app/FullScreenIntentPermissionPreferenceController.kt index 4349b4c9f4e..6977a99a6c1 100644 --- a/src/com/android/settings/notification/app/FullScreenIntentPermissionPreferenceController.kt +++ b/src/com/android/settings/notification/app/FullScreenIntentPermissionPreferenceController.kt @@ -21,9 +21,9 @@ import android.app.AppOpsManager import android.app.AppOpsManager.OP_USE_FULL_SCREEN_INTENT import android.content.AttributionSource import android.content.Context -import android.content.pm.PackageManager.NameNotFoundException import android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET import android.content.pm.PackageManager.GET_PERMISSIONS +import android.content.pm.PackageManager.NameNotFoundException import android.os.UserHandle import android.permission.PermissionManager import android.util.Log @@ -65,6 +65,7 @@ class FullScreenIntentPermissionPreferenceController( preference.setDisabledByAdmin(mAdmin) preference.isEnabled = !preference.isDisabledByAdmin preference.isChecked = isPermissionGranted() + preference.parent?.isVisible = true } override fun onPreferenceChange(preference: Preference, value: Any): Boolean { diff --git a/src/com/android/settings/notification/app/HeaderPreferenceController.java b/src/com/android/settings/notification/app/HeaderPreferenceController.java index 220e7b555f1..91abe815794 100644 --- a/src/com/android/settings/notification/app/HeaderPreferenceController.java +++ b/src/com/android/settings/notification/app/HeaderPreferenceController.java @@ -81,9 +81,8 @@ public class HeaderPreferenceController extends NotificationPreferenceController mHeaderController = EntityHeaderController.newInstance( activity, mFragment, pref.findViewById(R.id.entity_header)); pref = mHeaderController.setIcon(mAppRow.icon) - .setLabel(getLabel()) - .setSummary(getSummary()) - .setSecondSummary(getSecondSummary()) + .setLabel(getSummary()) + .setSummary(getSecondSummary()) .setPackageName(mAppRow.pkg) .setUid(mAppRow.uid) .setButtonActions(EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE, @@ -95,14 +94,6 @@ public class HeaderPreferenceController extends NotificationPreferenceController } } - public CharSequence getLabel() { - if (mChannel != null && !isDefaultChannel()) { - return mChannel.getName(); - } else { - return mAppRow.label; - } - } - @OnLifecycleEvent(Lifecycle.Event.ON_START) public void onStart() { mStarted = true; @@ -113,15 +104,7 @@ public class HeaderPreferenceController extends NotificationPreferenceController if (mChannel != null) { if (mChannelGroup != null && !TextUtils.isEmpty(mChannelGroup.getName())) { - final SpannableStringBuilder summary = new SpannableStringBuilder(); - BidiFormatter bidi = BidiFormatter.getInstance(); - summary.append(bidi.unicodeWrap(mAppRow.label)); - summary.append(bidi.unicodeWrap(mContext.getText( - R.string.notification_header_divider_symbol_with_spaces))); - summary.append(bidi.unicodeWrap(mChannelGroup.getName().toString())); - return summary.toString(); - } else { - return mAppRow.label.toString(); + return mChannelGroup.getName().toString(); } } return ""; diff --git a/src/com/android/settings/notification/app/InvalidConversationInfoPreferenceController.java b/src/com/android/settings/notification/app/InvalidConversationInfoPreferenceController.java index 478607b193e..219457944d1 100644 --- a/src/com/android/settings/notification/app/InvalidConversationInfoPreferenceController.java +++ b/src/com/android/settings/notification/app/InvalidConversationInfoPreferenceController.java @@ -23,6 +23,7 @@ import androidx.preference.Preference; import com.android.settings.R; import com.android.settings.notification.NotificationBackend; +import com.android.settingslib.widget.SettingsThemeHelper; public class InvalidConversationInfoPreferenceController extends NotificationPreferenceController { @@ -49,6 +50,9 @@ public class InvalidConversationInfoPreferenceController extends NotificationPre if (mPreferenceFilter != null && !isIncludedInFilter()) { return false; } + if (SettingsThemeHelper.isExpressiveTheme(mContext)) { + return false; + } return mBackend.isInInvalidMsgState(mAppRow.pkg, mAppRow.uid); } diff --git a/src/com/android/settings/notification/app/InvalidConversationPreferenceController.java b/src/com/android/settings/notification/app/InvalidConversationPreferenceController.java index 5c502dccbe0..57eaad9d01e 100644 --- a/src/com/android/settings/notification/app/InvalidConversationPreferenceController.java +++ b/src/com/android/settings/notification/app/InvalidConversationPreferenceController.java @@ -24,6 +24,7 @@ import androidx.preference.Preference; import com.android.settings.R; import com.android.settings.notification.NotificationBackend; import com.android.settingslib.RestrictedSwitchPreference; +import com.android.settingslib.widget.SettingsThemeHelper; public class InvalidConversationPreferenceController extends NotificationPreferenceController implements Preference.OnPreferenceChangeListener { @@ -67,7 +68,15 @@ public class InvalidConversationPreferenceController extends NotificationPrefere pref.setDisabledByAdmin(mAdmin); pref.setEnabled(!pref.isDisabledByAdmin()); pref.setChecked(!mBackend.hasUserDemotedInvalidMsgApp(mAppRow.pkg, mAppRow.uid)); - preference.setSummary(mContext.getString(R.string.conversation_section_switch_summary)); + if (SettingsThemeHelper.isExpressiveTheme(mContext)) { + if (preference.getParent() != null) { + preference.getParent().setVisible(true); + } + preference.setSummary(mContext.getString( + R.string.conversation_section_switch_complete_summary)); + } else { + preference.setSummary(mContext.getString(R.string.conversation_section_switch_summary)); + } } @Override diff --git a/src/com/android/settings/notification/app/PriorityConversationsPreferenceController.java b/src/com/android/settings/notification/app/PriorityConversationsPreferenceController.java index 18fc9178510..55b50df280a 100644 --- a/src/com/android/settings/notification/app/PriorityConversationsPreferenceController.java +++ b/src/com/android/settings/notification/app/PriorityConversationsPreferenceController.java @@ -23,6 +23,7 @@ import androidx.preference.Preference; import com.android.settings.R; import com.android.settings.notification.NotificationBackend; +import com.android.settingslib.widget.TopIntroPreference; public class PriorityConversationsPreferenceController extends ConversationListPreferenceController { @@ -40,9 +41,9 @@ public class PriorityConversationsPreferenceController extends @Override Preference getSummaryPreference() { - Preference pref = new Preference(mContext); + Preference pref = new TopIntroPreference(mContext); pref.setOrder(1); - pref.setSummary(R.string.important_conversations_summary_bubbles); + pref.setTitle(R.string.important_conversations_summary_bubbles); pref.setSelectable(false); return pref; } diff --git a/src/com/android/settings/notification/app/PromotedNotificationsPreferenceController.java b/src/com/android/settings/notification/app/PromotedNotificationsPreferenceController.java index 13417b2ccf1..bd8229e4d48 100644 --- a/src/com/android/settings/notification/app/PromotedNotificationsPreferenceController.java +++ b/src/com/android/settings/notification/app/PromotedNotificationsPreferenceController.java @@ -20,14 +20,12 @@ import android.content.Context; import androidx.annotation.NonNull; import androidx.preference.Preference; -import androidx.preference.PreferenceCategory; import com.android.settings.notification.NotificationBackend; import com.android.settingslib.RestrictedSwitchPreference; public class PromotedNotificationsPreferenceController extends NotificationPreferenceController implements Preference.OnPreferenceChangeListener { - private static final String KEY_PROMOTED_CATEGORY = "promoted_category"; protected static final String KEY_PROMOTED_SWITCH = "promoted_switch"; public PromotedNotificationsPreferenceController(@NonNull Context context, @@ -38,7 +36,7 @@ public class PromotedNotificationsPreferenceController extends @Override @NonNull public String getPreferenceKey() { - return KEY_PROMOTED_CATEGORY; + return KEY_PROMOTED_SWITCH; } @Override @@ -56,12 +54,13 @@ public class PromotedNotificationsPreferenceController extends } /** - * Updates the state of the promoted notifications switch. Because this controller governs - * the full PreferenceCategory, we must find the switch preference within the category first. + * Updates the state of the promoted notifications switch. */ public void updateState(@NonNull Preference preference) { - PreferenceCategory category = (PreferenceCategory) preference; - RestrictedSwitchPreference pref = category.findPreference(KEY_PROMOTED_SWITCH); + RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference; + if (pref.getParent() != null) { + pref.getParent().setVisible(true); + } if (pref != null && mAppRow != null) { pref.setDisabledByAdmin(mAdmin); diff --git a/src/com/android/settings/notification/app/RecentConversationsPreferenceController.java b/src/com/android/settings/notification/app/RecentConversationsPreferenceController.java index f5f2e97090b..4fe0a875334 100644 --- a/src/com/android/settings/notification/app/RecentConversationsPreferenceController.java +++ b/src/com/android/settings/notification/app/RecentConversationsPreferenceController.java @@ -40,6 +40,7 @@ import com.android.settings.applications.AppInfoBase; import com.android.settings.core.SubSettingLauncher; import com.android.settings.notification.NotificationBackend; import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.widget.ButtonPreference; import com.android.settingslib.widget.LayoutPreference; import java.text.Collator; @@ -75,14 +76,12 @@ public class RecentConversationsPreferenceController extends AbstractPreferenceC return true; } - //TODO(b/233325816): Use ButtonPreference instead. - LayoutPreference getClearAll(PreferenceGroup parent) { - LayoutPreference pref = new LayoutPreference( - mContext, R.layout.conversations_clear_recents); + ButtonPreference getClearAll(PreferenceGroup parent) { + ButtonPreference pref = new ButtonPreference(mContext); + pref.setTitle(R.string.conversation_settings_clear_recents); pref.setKey(getPreferenceKey() + CLEAR_ALL_KEY_SUFFIX); pref.setOrder(1); - Button button = pref.findViewById(R.id.conversation_settings_clear_recents); - button.setOnClickListener(v -> { + pref.setOnClickListener(v -> { try { mPs.removeAllRecentConversations(); // Removing recents is asynchronous, so we can't immediately reload the list from @@ -97,7 +96,8 @@ public class RecentConversationsPreferenceController extends AbstractPreferenceC } } } - button.announceForAccessibility(mContext.getString(R.string.recent_convos_removed)); + pref.getButton().announceForAccessibility( + mContext.getString(R.string.recent_convos_removed)); } catch (RemoteException e) { Slog.w(TAG, "Could not clear recents", e); } @@ -160,25 +160,27 @@ public class RecentConversationsPreferenceController extends AbstractPreferenceC .forEachOrdered(pref -> { pref.setOrder(order.getAndIncrement()); mPreferenceGroup.addPreference(pref); - if (pref.hasClearListener()) { + if (pref instanceof RecentConversationPreference + && ((RecentConversationPreference) pref).hasClearListener()) { hasClearable.set(true); } }); return hasClearable.get(); } - protected RecentConversationPreference createConversationPref( + protected Preference createConversationPref( final ConversationChannel conversation) { final String pkg = conversation.getShortcutInfo().getPackage(); final int uid = conversation.getUid(); final String conversationId = conversation.getShortcutInfo().getId(); - RecentConversationPreference pref = new RecentConversationPreference(mContext); + Preference pref = conversation.hasActiveNotifications() ? new Preference(mContext) + : new RecentConversationPreference(mContext); if (!conversation.hasActiveNotifications()) { - pref.setOnClearClickListener(() -> { + ((RecentConversationPreference) pref).setOnClearClickListener(() -> { try { mPs.removeRecentConversation(pkg, UserHandle.getUserId(uid), conversationId); - pref.getClearView().announceForAccessibility( + ((RecentConversationPreference) pref).getClearView().announceForAccessibility( mContext.getString(R.string.recent_convo_removed)); mPreferenceGroup.removePreference(pref); } catch (RemoteException e) { diff --git a/src/com/android/settings/notification/app/ShowMorePreferenceController.java b/src/com/android/settings/notification/app/ShowMorePreferenceController.java index dbc279a6c8b..f44a0c8518e 100644 --- a/src/com/android/settings/notification/app/ShowMorePreferenceController.java +++ b/src/com/android/settings/notification/app/ShowMorePreferenceController.java @@ -56,6 +56,9 @@ public class ShowMorePreferenceController extends NotificationPreferenceControll if (mAppRow.banned || mAppRow.showAllChannels) { return false; } + if (mBackend.getChannelCount(mAppRow.pkg, mAppRow.uid) == 0) { + return false; + } return true; } diff --git a/src/com/android/settings/notification/app/VisibilityPreferenceController.java b/src/com/android/settings/notification/app/VisibilityPreferenceController.java index a2a1d76b71c..0cec7e2a4d6 100644 --- a/src/com/android/settings/notification/app/VisibilityPreferenceController.java +++ b/src/com/android/settings/notification/app/VisibilityPreferenceController.java @@ -75,6 +75,10 @@ public class VisibilityPreferenceController extends NotificationPreferenceContro public void updateState(Preference preference) { if (mChannel != null && mAppRow != null) { + if (preference.getParent() != null) { + preference.getParent().setVisible(true); + } + RestrictedListPreference pref = (RestrictedListPreference) preference; ArrayList entries = new ArrayList<>(); ArrayList values = new ArrayList<>(); diff --git a/tests/robotests/src/com/android/settings/notification/app/AllowSoundPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/AllowSoundPreferenceControllerTest.java index 5260ff64c1d..86a3fe4a02a 100644 --- a/tests/robotests/src/com/android/settings/notification/app/AllowSoundPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/app/AllowSoundPreferenceControllerTest.java @@ -38,6 +38,8 @@ import android.content.Context; import android.os.UserManager; import androidx.preference.Preference; +import androidx.preference.PreferenceCategory; +import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; import com.android.settings.notification.NotificationBackend; @@ -68,7 +70,6 @@ public class AllowSoundPreferenceControllerTest { private NotificationManager mNm; @Mock private UserManager mUm; - @Mock(answer = Answers.RETURNS_DEEP_STUBS) private PreferenceScreen mScreen; @Mock @@ -83,6 +84,7 @@ public class AllowSoundPreferenceControllerTest { shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNm); shadowApplication.setSystemService(Context.USER_SERVICE, mUm); mContext = RuntimeEnvironment.application; + mScreen = new PreferenceManager(mContext).createPreferenceScreen(mContext); mController = spy(new AllowSoundPreferenceController(mContext, mDependentFieldListener, mBackend)); } @@ -160,6 +162,7 @@ public class AllowSoundPreferenceControllerTest { RestrictedLockUtils.EnforcedAdmin.class), null); Preference pref = new RestrictedSwitchPreference(mContext); + mScreen.addPreference(pref); mController.updateState(pref); assertFalse(pref.isEnabled()); @@ -173,6 +176,7 @@ public class AllowSoundPreferenceControllerTest { mController.onResume(appRow, channel, null, null, null, null, null); Preference pref = new RestrictedSwitchPreference(mContext); + mScreen.addPreference(pref); mController.updateState(pref); assertTrue(pref.isEnabled()); @@ -186,6 +190,7 @@ public class AllowSoundPreferenceControllerTest { null); RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext); + mScreen.addPreference(pref); mController.updateState(pref); assertTrue(pref.isChecked()); } @@ -198,6 +203,7 @@ public class AllowSoundPreferenceControllerTest { null); RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext); + mScreen.addPreference(pref); mController.updateState(pref); assertTrue(pref.isChecked()); } @@ -210,6 +216,7 @@ public class AllowSoundPreferenceControllerTest { null); RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext); + mScreen.addPreference(pref); mController.updateState(pref); assertFalse(pref.isChecked()); } @@ -222,7 +229,7 @@ public class AllowSoundPreferenceControllerTest { null); RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext); - when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref); + mScreen.addPreference(pref); mController.displayPreference(mScreen); mController.updateState(pref); pref.setChecked(true); @@ -240,7 +247,7 @@ public class AllowSoundPreferenceControllerTest { null); RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext); - when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref); + mScreen.addPreference(pref); mController.displayPreference(mScreen); mController.updateState(pref); diff --git a/tests/robotests/src/com/android/settings/notification/app/FullScreenIntentPermissionPreferenceControllerTest.kt b/tests/robotests/src/com/android/settings/notification/app/FullScreenIntentPermissionPreferenceControllerTest.kt index 89e33eef509..a9abf8b582b 100644 --- a/tests/robotests/src/com/android/settings/notification/app/FullScreenIntentPermissionPreferenceControllerTest.kt +++ b/tests/robotests/src/com/android/settings/notification/app/FullScreenIntentPermissionPreferenceControllerTest.kt @@ -37,6 +37,7 @@ import android.permission.PermissionManager.PERMISSION_HARD_DENIED import android.permission.PermissionManager.PERMISSION_SOFT_DENIED import android.permission.PermissionManager.PermissionResult import androidx.preference.Preference +import androidx.preference.PreferenceManager import androidx.preference.PreferenceScreen import androidx.test.core.app.ApplicationProvider import com.android.settings.notification.NotificationBackend @@ -80,7 +81,6 @@ class FullScreenIntentPermissionPreferenceControllerTest { private lateinit var preference: RestrictedSwitchPreference - @Mock(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var screen: PreferenceScreen private lateinit var controller: FullScreenIntentPermissionPreferenceController @@ -94,7 +94,8 @@ class FullScreenIntentPermissionPreferenceControllerTest { preference = RestrictedSwitchPreference(context).apply { key = KEY_FSI_PERMISSION } - whenever(screen.findPreference(KEY_FSI_PERMISSION)).thenReturn(preference) + screen = PreferenceManager(context).createPreferenceScreen(context) + screen.addPreference(preference) controller = FullScreenIntentPermissionPreferenceController( context, diff --git a/tests/robotests/src/com/android/settings/notification/app/HeaderPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/HeaderPreferenceControllerTest.java index 05a41a63a53..b5190dd19a7 100644 --- a/tests/robotests/src/com/android/settings/notification/app/HeaderPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/app/HeaderPreferenceControllerTest.java @@ -113,27 +113,6 @@ public class HeaderPreferenceControllerTest { assertTrue(mController.isAvailable()); } - @Test - public void testGetLabel() { - NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); - appRow.label = "bananas"; - mController.onResume(appRow, null, null, null, null, null, null); - assertEquals(appRow.label, mController.getLabel()); - - NotificationChannelGroup group = new NotificationChannelGroup("id", "name"); - mController.onResume(appRow, null, group, null, null, null, null); - assertEquals(appRow.label, mController.getLabel()); - - NotificationChannel channel = new NotificationChannel("cid", "cname", IMPORTANCE_NONE); - mController.onResume(appRow, channel, group, null, null, null, null); - assertEquals(channel.getName(), mController.getLabel()); - - NotificationChannel defaultChannel = new NotificationChannel( - NotificationChannel.DEFAULT_CHANNEL_ID, "", IMPORTANCE_NONE); - mController.onResume(appRow, defaultChannel, null, null, null, null, null); - assertEquals(appRow.label, mController.getLabel()); - } - @Test public void testGetSummary() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); @@ -146,16 +125,14 @@ public class HeaderPreferenceControllerTest { NotificationChannel channel = new NotificationChannel("cid", "cname", IMPORTANCE_NONE); mController.onResume(appRow, channel, group, null, null, null, null); assertTrue(mController.getSummary().toString().contains(group.getName())); - assertTrue(mController.getSummary().toString().contains(appRow.label)); mController.onResume(appRow, channel, null, null, null, null, null); assertFalse(mController.getSummary().toString().contains(group.getName())); - assertTrue(mController.getSummary().toString().contains(appRow.label)); NotificationChannel defaultChannel = new NotificationChannel( NotificationChannel.DEFAULT_CHANNEL_ID, "", IMPORTANCE_NONE); mController.onResume(appRow, defaultChannel, null, null, null, null, null); - assertEquals(appRow.label, mController.getSummary()); + assertEquals("", mController.getSummary()); } @Test diff --git a/tests/robotests/src/com/android/settings/notification/app/InvalidConversationInfoPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/InvalidConversationInfoPreferenceControllerTest.java index eb8046567b2..dcc9daf552e 100644 --- a/tests/robotests/src/com/android/settings/notification/app/InvalidConversationInfoPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/app/InvalidConversationInfoPreferenceControllerTest.java @@ -34,6 +34,7 @@ import androidx.preference.PreferenceScreen; import com.android.settings.notification.NotificationBackend; import com.android.settings.testutils.shadow.SettingsShadowResources; +import com.android.settingslib.widget.SettingsThemeHelper; import com.google.common.collect.ImmutableList; @@ -88,6 +89,18 @@ public class InvalidConversationInfoPreferenceControllerTest { mController.updateState(mock(Preference.class)); } + @Test + public void testIsAvailable_notIfExpressiveTheme() { + if (SettingsThemeHelper.isExpressiveTheme(mContext)) { + when(mBackend.isInInvalidMsgState(anyString(), anyInt())).thenReturn(true); + NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); + appRow.pkg = "hi"; + appRow.uid = 0; + mController.onResume(appRow, null, null, null, null, null, null); + assertFalse(mController.isAvailable()); + } + } + @Test public void testIsAvailable_notIfAppBlocked() { when(mBackend.isInInvalidMsgState(anyString(), anyInt())).thenReturn(true); @@ -111,6 +124,9 @@ public class InvalidConversationInfoPreferenceControllerTest { @Test public void testIsAvailable() { + if (SettingsThemeHelper.isExpressiveTheme(mContext)) { + return; + } when(mBackend.isInInvalidMsgState(anyString(), anyInt())).thenReturn(true); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); appRow.pkg = "hi"; diff --git a/tests/robotests/src/com/android/settings/notification/app/PromotedNotificationsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/PromotedNotificationsPreferenceControllerTest.java index 917d4694ca3..8e0ab965443 100644 --- a/tests/robotests/src/com/android/settings/notification/app/PromotedNotificationsPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/app/PromotedNotificationsPreferenceControllerTest.java @@ -18,13 +18,12 @@ package com.android.settings.notification.app; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import android.app.Flags; import android.content.Context; @@ -32,7 +31,7 @@ import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; -import androidx.preference.PreferenceCategory; +import androidx.preference.PreferenceManager; import androidx.test.core.app.ApplicationProvider; import com.android.settings.notification.NotificationBackend; @@ -55,8 +54,6 @@ public class PromotedNotificationsPreferenceControllerTest { private NotificationBackend.AppRow mAppRow; @Mock private NotificationBackend mBackend; - @Mock - private PreferenceCategory mPrefCategory; private RestrictedSwitchPreference mSwitch; private PromotedNotificationsPreferenceController mPrefController; @@ -66,7 +63,7 @@ public class PromotedNotificationsPreferenceControllerTest { MockitoAnnotations.initMocks(this); mContext = ApplicationProvider.getApplicationContext(); mSwitch = new RestrictedSwitchPreference(mContext); - when(mPrefCategory.findPreference("promoted_switch")).thenReturn(mSwitch); + new PreferenceManager(mContext).createPreferenceScreen(mContext).addPreference(mSwitch); mPrefController = new PromotedNotificationsPreferenceController(mContext, mBackend); mAppRow = new NotificationBackend.AppRow(); @@ -93,12 +90,12 @@ public class PromotedNotificationsPreferenceControllerTest { mAppRow.canBePromoted = true; mPrefController.onResume(mAppRow, null, null, null, null, null, null); - mPrefController.updateState(mPrefCategory); + mPrefController.updateState(mSwitch); assertThat(mSwitch.isChecked()).isTrue(); mAppRow.canBePromoted = false; mPrefController.onResume(mAppRow, null, null, null, null, null, null); - mPrefController.updateState(mPrefCategory); + mPrefController.updateState(mSwitch); assertThat(mSwitch.isChecked()).isFalse(); } diff --git a/tests/robotests/src/com/android/settings/notification/app/RecentConversationsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/RecentConversationsPreferenceControllerTest.java index 3c0a0f33349..538859105ed 100644 --- a/tests/robotests/src/com/android/settings/notification/app/RecentConversationsPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/app/RecentConversationsPreferenceControllerTest.java @@ -50,6 +50,7 @@ import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; import com.android.settings.applications.AppInfoBase; import com.android.settings.notification.NotificationBackend; +import com.android.settingslib.widget.ButtonPreference; import com.android.settingslib.widget.LayoutPreference; import com.google.common.collect.ImmutableList; @@ -232,14 +233,16 @@ public class RecentConversationsPreferenceControllerTest { new NotificationChannelGroup("hi", "group"), 7, false); - RecentConversationPreference pref = mController.createConversationPref(ccw); + Preference pref = mController.createConversationPref(ccw); final View view = View.inflate(mContext, pref.getLayoutResource(), null); PreferenceViewHolder holder = spy(PreferenceViewHolder.createInstanceForTests(view)); - View delete = View.inflate(mContext, pref.getSecondTargetResId(), null); - when(holder.findViewById(pref.getClearId())).thenReturn(delete); + View delete = View.inflate(mContext, ((RecentConversationPreference) pref) + .getSecondTargetResId(), null); + when(holder.findViewById(((RecentConversationPreference) pref).getClearId())) + .thenReturn(delete); pref.onBindViewHolder(holder); - pref.getClearView().performClick(); + ((RecentConversationPreference) pref).getClearView().performClick(); verify(mPs).removeRecentConversation( si.getPackage(), UserHandle.getUserId(ccw.getUid()), si.getId()); @@ -260,24 +263,24 @@ public class RecentConversationsPreferenceControllerTest { new NotificationChannelGroup("hi", "group"), 7, true); - RecentConversationPreference pref = mController.createConversationPref(ccw); + Preference pref = mController.createConversationPref(ccw); final View view = View.inflate(mContext, pref.getLayoutResource(), null); PreferenceViewHolder holder = spy(PreferenceViewHolder.createInstanceForTests(view)); - View delete = View.inflate(mContext, pref.getSecondTargetResId(), null); - when(holder.findViewById(pref.getClearId())).thenReturn(delete); + View delete = View.inflate(mContext, ((RecentConversationPreference) pref). + getSecondTargetResId(), null); + when(holder.findViewById(((RecentConversationPreference) pref).getClearId())) + .thenReturn(delete); mPreferenceGroup.addPreference(pref); - RecentConversationPreference pref2 = mController.createConversationPref(ccw2); - final View view2 = View.inflate(mContext, pref2.getLayoutResource(), null); - PreferenceViewHolder holder2 = spy(PreferenceViewHolder.createInstanceForTests(view2)); - View delete2 = View.inflate(mContext, pref2.getSecondTargetResId(), null); - when(holder2.findViewById(pref.getClearId())).thenReturn(delete2); + Preference pref2 = mController.createConversationPref(ccw2); mPreferenceGroup.addPreference(pref2); - LayoutPreference clearAll = mController.getClearAll(mPreferenceGroup); + ButtonPreference clearAll = mController.getClearAll(mPreferenceGroup); + final View rootView = View.inflate(mContext, clearAll.getLayoutResource(), null); + clearAll.onBindViewHolder(PreferenceViewHolder.createInstanceForTests(rootView)); mPreferenceGroup.addPreference(clearAll); - clearAll.findViewById(R.id.conversation_settings_clear_recents).performClick(); + clearAll.getButton().performClick(); verify(mPs).removeAllRecentConversations(); assertThat((Preference) mPreferenceGroup.findPreference("hi:person")).isNull(); @@ -294,9 +297,9 @@ public class RecentConversationsPreferenceControllerTest { new NotificationChannelGroup("hi", "group"), 7, true); - RecentConversationPreference pref = mController.createConversationPref(ccw); + Preference pref = mController.createConversationPref(ccw); - assertThat(pref.hasClearListener()).isFalse(); + assertThat(pref instanceof RecentConversationPreference).isFalse(); } @Test diff --git a/tests/unit/src/com/android/settings/notification/app/ChannelListPreferenceControllerTest.java b/tests/unit/src/com/android/settings/notification/app/ChannelListPreferenceControllerTest.java index daa2afb71ab..f68ba05b43b 100644 --- a/tests/unit/src/com/android/settings/notification/app/ChannelListPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/notification/app/ChannelListPreferenceControllerTest.java @@ -91,6 +91,14 @@ public class ChannelListPreferenceControllerTest { assertEquals("zeroCategories", mGroupList.getPreference(0).getKey()); } + // Test the case with no groups but hidden channels + inGroups = new ArrayList<>(); + mController.mChannelCount = 1; + mController.updateFullList(mGroupList, inGroups); + { + assertEquals(0, mGroupList.getPreferenceCount()); + } + // Test that adding a group clears the zero category and adds everything NotificationChannelGroup inGroup1 = new NotificationChannelGroup("group1", "Group 1"); inGroup1.addChannel(new NotificationChannel("ch1a", "Channel 1A", IMPORTANCE_DEFAULT)); @@ -250,6 +258,7 @@ public class ChannelListPreferenceControllerTest { } // Test that we go back to the empty state when clearing all groups and channels. + mController.mChannelCount = 0; inGroups.clear(); mController.updateFullList(mGroupList, inGroups); { From e031b30d1d897b28a3b7d416f5548f2801b60bad Mon Sep 17 00:00:00 2001 From: Wenyu Zhang Date: Thu, 9 Jan 2025 22:31:17 +0000 Subject: [PATCH 13/17] a11y: Initialize slider position with cursor area size setting When the preference loads, initialize the slider position using the cursor area size value from settings. In addition, match slider seekbar range and the cursor area size range. Change-Id: Ib6a8ca8463358a3e2de5ae6be8afd5113a5826be Bug: b/383901288 Test: ToggleAutoclickCursorAreaSizeControllerTest Flag: com.android.server.accessibility.enable_autoclick_indicator --- res/xml/accessibility_autoclick_settings.xml | 1 - ...ggleAutoclickCursorAreaSizeController.java | 26 +++++-- ...AutoclickCursorAreaSizeControllerTest.java | 70 +++++++++++++++++-- 3 files changed, 84 insertions(+), 13 deletions(-) diff --git a/res/xml/accessibility_autoclick_settings.xml b/res/xml/accessibility_autoclick_settings.xml index 72371f3e993..d3a951479ad 100644 --- a/res/xml/accessibility_autoclick_settings.xml +++ b/res/xml/accessibility_autoclick_settings.xml @@ -80,7 +80,6 @@ android:key="accessibility_control_autoclick_cursor_area_size" android:title="@string/autoclick_cursor_area_size_title" android:summary="@string/autoclick_cursor_area_size_summary" - settings:seekBarIncrement="20" android:selectable="false" settings:searchable="false" settings:controller="com.android.settings.accessibility.ToggleAutoclickCursorAreaSizeController"/> diff --git a/src/com/android/settings/accessibility/ToggleAutoclickCursorAreaSizeController.java b/src/com/android/settings/accessibility/ToggleAutoclickCursorAreaSizeController.java index 95016b59bb7..835bd5aea1f 100644 --- a/src/com/android/settings/accessibility/ToggleAutoclickCursorAreaSizeController.java +++ b/src/com/android/settings/accessibility/ToggleAutoclickCursorAreaSizeController.java @@ -17,6 +17,7 @@ package com.android.settings.accessibility; import static android.content.Context.MODE_PRIVATE; +import static android.view.accessibility.AccessibilityManager.AUTOCLICK_CURSOR_AREA_INCREMENT_SIZE; import static android.view.accessibility.AccessibilityManager.AUTOCLICK_CURSOR_AREA_SIZE_MAX; import static android.view.accessibility.AccessibilityManager.AUTOCLICK_CURSOR_AREA_SIZE_MIN; @@ -35,6 +36,7 @@ import androidx.preference.PreferenceScreen; import com.android.server.accessibility.Flags; import com.android.settings.core.SliderPreferenceController; +import com.android.settingslib.widget.SliderPreference; /** Controller class that controls accessibility autoclick cursor area size settings. */ public class ToggleAutoclickCursorAreaSizeController extends SliderPreferenceController @@ -44,6 +46,7 @@ public class ToggleAutoclickCursorAreaSizeController extends SliderPreferenceCon private final ContentResolver mContentResolver; private final SharedPreferences mSharedPreferences; + private SliderPreference mPreference; public ToggleAutoclickCursorAreaSizeController(@NonNull Context context, @NonNull String preferenceKey) { @@ -70,6 +73,13 @@ public class ToggleAutoclickCursorAreaSizeController extends SliderPreferenceCon @Override public void displayPreference(@NonNull PreferenceScreen screen) { super.displayPreference(screen); + mPreference = screen.findPreference(getPreferenceKey()); + if (mPreference != null) { + mPreference.setMin(getMin()); + mPreference.setMax(getMax()); + mPreference.setSliderIncrement(AUTOCLICK_CURSOR_AREA_INCREMENT_SIZE); + mPreference.setValue(getSliderPosition()); + } } @Override @@ -85,8 +95,9 @@ public class ToggleAutoclickCursorAreaSizeController extends SliderPreferenceCon @Override public boolean setSliderPosition(int position) { - Settings.Secure.putInt(mContentResolver, - Settings.Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE, position); + int size = validateSize(position); + Settings.Secure.putInt( + mContentResolver, Settings.Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE, size); return true; } @@ -95,10 +106,7 @@ public class ToggleAutoclickCursorAreaSizeController extends SliderPreferenceCon int size = Settings.Secure.getInt(mContentResolver, Settings.Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE, AccessibilityManager.AUTOCLICK_CURSOR_AREA_SIZE_DEFAULT); - // Make sure the size is between min and max allowed value. - size = Math.min(size, AUTOCLICK_CURSOR_AREA_SIZE_MAX); - size = Math.max(size, AUTOCLICK_CURSOR_AREA_SIZE_MIN); - return size; + return validateSize(size); } @Override @@ -110,4 +118,10 @@ public class ToggleAutoclickCursorAreaSizeController extends SliderPreferenceCon public int getMin() { return AUTOCLICK_CURSOR_AREA_SIZE_MIN; } + + private int validateSize(int size) { + size = Math.min(size, AUTOCLICK_CURSOR_AREA_SIZE_MAX); + size = Math.max(size, AUTOCLICK_CURSOR_AREA_SIZE_MIN); + return size; + } } diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickCursorAreaSizeControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickCursorAreaSizeControllerTest.java index 0a22e4ac026..f67053d1a76 100644 --- a/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickCursorAreaSizeControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickCursorAreaSizeControllerTest.java @@ -16,6 +16,9 @@ package com.android.settings.accessibility; +import static android.view.accessibility.AccessibilityManager.AUTOCLICK_CURSOR_AREA_SIZE_MAX; +import static android.view.accessibility.AccessibilityManager.AUTOCLICK_CURSOR_AREA_SIZE_MIN; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.anyInt; @@ -32,9 +35,11 @@ import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; import android.view.accessibility.AccessibilityManager; +import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.widget.SliderPreference; import com.google.common.collect.ImmutableList; @@ -106,21 +111,74 @@ public class ToggleAutoclickCursorAreaSizeControllerTest { } @Test - public void getProgress_matchesSetting() { - assertThat(mController.getSliderPosition()).isEqualTo(readSetting()); + public void getProgress_matchesSetting_inRangeValue() { + // TODO(388844952): Use parameter testing. + for (int size : ImmutableList.of(20, 40, 60, 80, 100)) { + updateSetting(size); + + assertThat(mController.getSliderPosition()).isEqualTo(size); + } } @Test - public void setProgress_updatesSetting() { - for (int size : ImmutableList.of(20, 40, 60, 80, 100)) { - mController.setSliderPosition(size); - assertThat(readSetting()).isEqualTo(size); + public void getProgress_matchesSetting_aboveMaxValue() { + updateSetting(120); + + assertThat(mController.getSliderPosition()).isEqualTo(AUTOCLICK_CURSOR_AREA_SIZE_MAX); + } + + @Test + public void getProgress_matchesSetting_belowMinValue() { + updateSetting(0); + + assertThat(mController.getSliderPosition()).isEqualTo(AUTOCLICK_CURSOR_AREA_SIZE_MIN); + } + + @Test + public void setProgress_updatesSetting_inRangeValue() { + // TODO(388844952): Use parameter testing. + for (int position : ImmutableList.of(20, 40, 60, 80, 100)) { + mController.setSliderPosition(position); + + assertThat(readSetting()).isEqualTo(position); } } + @Test + public void setProgress_updatesSetting_aboveMaxValue() { + mController.setSliderPosition(120); + + assertThat(readSetting()).isEqualTo(AUTOCLICK_CURSOR_AREA_SIZE_MAX); + } + + @Test + public void setProgress_updatesSetting_belowMinValue() { + mController.setSliderPosition(0); + + assertThat(readSetting()).isEqualTo(AUTOCLICK_CURSOR_AREA_SIZE_MIN); + } + + @Test + public void sliderPreference_setCorrectInitialValue() { + SliderPreference preference = mock(SliderPreference.class); + PreferenceScreen screen = mock(PreferenceScreen.class); + doReturn(preference).when(screen).findPreference(anyString()); + + mController.displayPreference(screen); + + verify(preference).setValue(mController.getSliderPosition()); + } + private int readSetting() { return Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE, AccessibilityManager.AUTOCLICK_CURSOR_AREA_SIZE_DEFAULT); } + + private void updateSetting(int value) { + Settings.Secure.putInt( + mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE, + value); + } } From 2000e9f96c1bba1aa260ce1641eeb892f025f2ca Mon Sep 17 00:00:00 2001 From: Chris Antol Date: Thu, 9 Jan 2025 20:43:42 +0000 Subject: [PATCH 14/17] Fix sensitivity to writability declarations Bug: 388877875 Test: N/A - CTS test to follow Flag: com.android.settingslib.flags.settings_catalyst Change-Id: I32d92b427bafe474f0e082923603781ad561cdd8 NO_IFTTT=sensitivity level not a field in legacy Preference Controller --- .../settings/accessibility/VibrationMainSwitchPreference.kt | 4 ++++ src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/com/android/settings/accessibility/VibrationMainSwitchPreference.kt b/src/com/android/settings/accessibility/VibrationMainSwitchPreference.kt index 4f1eec2fcb4..a9a05160557 100644 --- a/src/com/android/settings/accessibility/VibrationMainSwitchPreference.kt +++ b/src/com/android/settings/accessibility/VibrationMainSwitchPreference.kt @@ -30,6 +30,7 @@ import com.android.settingslib.metadata.MainSwitchPreference import com.android.settingslib.metadata.PreferenceLifecycleContext import com.android.settingslib.metadata.PreferenceLifecycleProvider import com.android.settingslib.metadata.ReadWritePermit +import com.android.settingslib.metadata.SensitivityLevel /** Accessibility settings for vibration. */ // LINT.IfChange @@ -62,6 +63,9 @@ class VibrationMainSwitchPreference : callingUid: Int, ) = ReadWritePermit.ALLOW + override val sensitivityLevel: Int + get() = SensitivityLevel.NO_SENSITIVITY + override fun onResume(context: PreferenceLifecycleContext) { vibrator = context.getSystemService(Vibrator::class.java) context diff --git a/src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt b/src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt index 9029a8511ff..f0a3ae67af9 100644 --- a/src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt +++ b/src/com/android/settings/fuelgauge/BatteryHeaderPreference.kt @@ -32,6 +32,7 @@ import com.android.settingslib.metadata.PreferenceLifecycleProvider import com.android.settingslib.metadata.PreferenceMetadata import com.android.settingslib.metadata.RangeValue import com.android.settingslib.metadata.ReadWritePermit +import com.android.settingslib.metadata.SensitivityLevel import com.android.settingslib.preference.PreferenceBinding import com.android.settingslib.widget.UsageProgressBarPreference @@ -113,6 +114,9 @@ class BatteryHeaderPreference : override fun getWritePermit(context: Context, value: Int?, callingPid: Int, callingUid: Int) = ReadWritePermit.DISALLOW + override val sensitivityLevel: Int + get() = SensitivityLevel.NO_SENSITIVITY + companion object { private const val KEY = "battery_header" private const val BATTERY_MAX_LEVEL: Long = 100L From 4ca85b1e5c74bc3e2deb4f4b1243edac16ffca8d Mon Sep 17 00:00:00 2001 From: Fan Wu Date: Thu, 9 Jan 2025 16:16:25 +0800 Subject: [PATCH 15/17] [Catalyst] Update DataChangeReason usages to PreferenceChangeReason Bug: 388677104 Test: atest and manual Flag: EXEMPT refactor NO_IFTTT=refactor Change-Id: I3c1aae3dc10a1c78e1b2b0ead8ffc83da933e174 --- .../settings/connecteddevice/BluetoothPreference.kt | 11 +++++++++-- .../datausage/DataSaverMainSwitchPreference.kt | 4 ++-- .../settings/display/BrightnessLevelPreference.kt | 6 +++--- .../settings/display/darkmode/DarkModeStorage.kt | 6 +++--- .../fuelgauge/batterysaver/BatterySaverPreference.kt | 6 +++--- .../settings/network/AirplaneModePreference.kt | 4 ++-- .../restriction/UserRestrictionBindingHelper.kt | 4 ++-- .../android/settings/restriction/UserRestrictions.kt | 3 ++- src/com/android/settings/wifi/WifiSwitchPreference.kt | 4 ++-- .../wifi/tether/WifiHotspotSwitchPreference.kt | 10 +++++----- 10 files changed, 33 insertions(+), 25 deletions(-) diff --git a/src/com/android/settings/connecteddevice/BluetoothPreference.kt b/src/com/android/settings/connecteddevice/BluetoothPreference.kt index 4d4853efbc5..8c12024ffc3 100644 --- a/src/com/android/settings/connecteddevice/BluetoothPreference.kt +++ b/src/com/android/settings/connecteddevice/BluetoothPreference.kt @@ -34,9 +34,9 @@ import com.android.settings.network.SatelliteWarningDialogActivity import com.android.settings.widget.MainSwitchBarMetadata import com.android.settingslib.WirelessUtils import com.android.settingslib.datastore.AbstractKeyedDataObservable -import com.android.settingslib.datastore.DataChangeReason import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.Permissions +import com.android.settingslib.metadata.PreferenceChangeReason import com.android.settingslib.metadata.PreferenceMetadata import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.SensitivityLevel @@ -152,7 +152,14 @@ class BluetoothPreference(private val bluetoothDataStore: BluetoothDataStore) : broadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { - notifyChange(KEY, DataChangeReason.UPDATE) + val state = + intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR) + if ( + state == BluetoothAdapter.STATE_ON || + state == BluetoothAdapter.STATE_OFF + ) { + notifyChange(KEY, PreferenceChangeReason.STATE) + } } } context.registerReceiver( diff --git a/src/com/android/settings/datausage/DataSaverMainSwitchPreference.kt b/src/com/android/settings/datausage/DataSaverMainSwitchPreference.kt index a05bd8784cc..9127659b8e6 100644 --- a/src/com/android/settings/datausage/DataSaverMainSwitchPreference.kt +++ b/src/com/android/settings/datausage/DataSaverMainSwitchPreference.kt @@ -21,9 +21,9 @@ import android.content.Context import com.android.settings.R import com.android.settings.widget.MainSwitchBarMetadata import com.android.settingslib.datastore.AbstractKeyedDataObservable -import com.android.settingslib.datastore.DataChangeReason import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.Permissions +import com.android.settingslib.metadata.PreferenceChangeReason import com.android.settingslib.metadata.PreferenceLifecycleProvider import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.SensitivityLevel @@ -75,7 +75,7 @@ class DataSaverMainSwitchPreference : MainSwitchBarMetadata, PreferenceLifecycle override fun onLastObserverRemoved() = dataSaverBackend.remListener(this) override fun onDataSaverChanged(isDataSaving: Boolean) = - notifyChange(KEY, DataChangeReason.UPDATE) + notifyChange(KEY, PreferenceChangeReason.VALUE) } companion object { diff --git a/src/com/android/settings/display/BrightnessLevelPreference.kt b/src/com/android/settings/display/BrightnessLevelPreference.kt index f87edcbe758..e14db6b59a6 100644 --- a/src/com/android/settings/display/BrightnessLevelPreference.kt +++ b/src/com/android/settings/display/BrightnessLevelPreference.kt @@ -33,7 +33,6 @@ import com.android.settings.Utils import com.android.settings.core.SettingsBaseActivity import com.android.settingslib.RestrictedPreference import com.android.settingslib.datastore.AbstractKeyedDataObservable -import com.android.settingslib.datastore.DataChangeReason import com.android.settingslib.datastore.HandlerExecutor import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.KeyedObserver @@ -43,6 +42,7 @@ import com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MAX import com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MIN import com.android.settingslib.display.BrightnessUtils.convertLinearToGammaFloat import com.android.settingslib.metadata.PersistentPreference +import com.android.settingslib.metadata.PreferenceChangeReason import com.android.settingslib.metadata.PreferenceMetadata import com.android.settingslib.metadata.PreferenceSummaryProvider import com.android.settingslib.metadata.RangeValue @@ -155,7 +155,7 @@ class BrightnessLevelPreference : } override fun onKeyChanged(key: String, reason: Int) { - notifyChange(KEY, DataChangeReason.UPDATE) + notifyChange(KEY, reason) } override fun onDisplayAdded(displayId: Int) {} @@ -163,7 +163,7 @@ class BrightnessLevelPreference : override fun onDisplayRemoved(displayId: Int) {} override fun onDisplayChanged(displayId: Int) { - notifyChange(KEY, DataChangeReason.UPDATE) + notifyChange(KEY, PreferenceChangeReason.STATE) } } diff --git a/src/com/android/settings/display/darkmode/DarkModeStorage.kt b/src/com/android/settings/display/darkmode/DarkModeStorage.kt index 9c53379c2d0..768a5529822 100644 --- a/src/com/android/settings/display/darkmode/DarkModeStorage.kt +++ b/src/com/android/settings/display/darkmode/DarkModeStorage.kt @@ -24,8 +24,8 @@ import android.content.IntentFilter import android.content.res.Configuration import android.os.PowerManager import com.android.settingslib.datastore.AbstractKeyedDataObservable -import com.android.settingslib.datastore.DataChangeReason import com.android.settingslib.datastore.KeyValueStore +import com.android.settingslib.metadata.PreferenceChangeReason /** * Abstract storage for dark mode settings. @@ -54,7 +54,7 @@ internal class DarkModeStorage(private val context: Context) : broadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { - notifyChange(DataChangeReason.UPDATE) + notifyChange(PreferenceChangeReason.STATE) } } context.registerReceiver( @@ -63,7 +63,7 @@ internal class DarkModeStorage(private val context: Context) : ) darkModeObserver = DarkModeObserver(context) - darkModeObserver.subscribe { notifyChange(DataChangeReason.UPDATE) } + darkModeObserver.subscribe { notifyChange(PreferenceChangeReason.VALUE) } } override fun onLastObserverRemoved() { diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverPreference.kt b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverPreference.kt index be3a3b891e1..3e5cee9f132 100644 --- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverPreference.kt +++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverPreference.kt @@ -22,7 +22,6 @@ import com.android.settings.R import com.android.settings.fuelgauge.BatterySaverReceiver import com.android.settings.fuelgauge.BatterySaverReceiver.BatterySaverListener import com.android.settingslib.datastore.AbstractKeyedDataObservable -import com.android.settingslib.datastore.DataChangeReason import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.Permissions import com.android.settingslib.fuelgauge.BatterySaverLogging.SAVER_ENABLED_SETTINGS @@ -30,6 +29,7 @@ import com.android.settingslib.fuelgauge.BatterySaverUtils import com.android.settingslib.fuelgauge.BatteryStatus import com.android.settingslib.fuelgauge.BatteryUtils import com.android.settingslib.metadata.MainSwitchPreference +import com.android.settingslib.metadata.PreferenceChangeReason import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.SensitivityLevel import kotlinx.coroutines.CoroutineScope @@ -105,12 +105,12 @@ class BatterySaverPreference : override fun onPowerSaveModeChanged() { scope.launch { delay(SWITCH_ANIMATION_DURATION) - notifyChange(KEY, DataChangeReason.UPDATE) + notifyChange(KEY, PreferenceChangeReason.VALUE) } } override fun onBatteryChanged(pluggedIn: Boolean) = - notifyChange(KEY, DataChangeReason.UPDATE) + notifyChange(KEY, PreferenceChangeReason.STATE) } companion object { diff --git a/src/com/android/settings/network/AirplaneModePreference.kt b/src/com/android/settings/network/AirplaneModePreference.kt index 11790d0be26..b870f30eaf1 100644 --- a/src/com/android/settings/network/AirplaneModePreference.kt +++ b/src/com/android/settings/network/AirplaneModePreference.kt @@ -37,11 +37,11 @@ import com.android.settings.network.SatelliteRepository.Companion.isSatelliteOn import com.android.settings.overlay.FeatureFactory.Companion.featureFactory import com.android.settingslib.RestrictedSwitchPreference import com.android.settingslib.datastore.AbstractKeyedDataObservable -import com.android.settingslib.datastore.DataChangeReason import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.SettingsGlobalStore import com.android.settingslib.datastore.SettingsStore import com.android.settingslib.metadata.PreferenceAvailabilityProvider +import com.android.settingslib.metadata.PreferenceChangeReason import com.android.settingslib.metadata.PreferenceLifecycleContext import com.android.settingslib.metadata.PreferenceLifecycleProvider import com.android.settingslib.metadata.ReadWritePermit @@ -126,7 +126,7 @@ class AirplaneModePreference : phoneStateListener = object : PhoneStateListener(Looper.getMainLooper()) { override fun onRadioPowerStateChanged(state: Int) { - notifyChange(KEY, DataChangeReason.UPDATE) + notifyChange(KEY, PreferenceChangeReason.VALUE) } } it.listen(phoneStateListener, PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED) diff --git a/src/com/android/settings/restriction/UserRestrictionBindingHelper.kt b/src/com/android/settings/restriction/UserRestrictionBindingHelper.kt index a1329c2ecdf..4dca003d704 100644 --- a/src/com/android/settings/restriction/UserRestrictionBindingHelper.kt +++ b/src/com/android/settings/restriction/UserRestrictionBindingHelper.kt @@ -20,8 +20,8 @@ import android.content.Context import com.android.settings.PreferenceRestrictionMixin import com.android.settingslib.datastore.HandlerExecutor import com.android.settingslib.datastore.KeyedObserver +import com.android.settingslib.metadata.PreferenceChangeReason import com.android.settingslib.preference.PreferenceScreenBindingHelper -import com.android.settingslib.preference.PreferenceScreenBindingHelper.Companion.CHANGE_REASON_STATE /** Helper to rebind preference immediately when user restriction is changed. */ class UserRestrictionBindingHelper( @@ -55,7 +55,7 @@ class UserRestrictionBindingHelper( override fun onKeyChanged(restrictionKey: String, reason: Int) { val keys = restrictionKeysToPreferenceKeys[restrictionKey] ?: return - for (key in keys) screenBindingHelper.notifyChange(key, CHANGE_REASON_STATE) + for (key in keys) screenBindingHelper.notifyChange(key, PreferenceChangeReason.STATE) } override fun close() { diff --git a/src/com/android/settings/restriction/UserRestrictions.kt b/src/com/android/settings/restriction/UserRestrictions.kt index 880aa5d9991..3d78e8e397f 100644 --- a/src/com/android/settings/restriction/UserRestrictions.kt +++ b/src/com/android/settings/restriction/UserRestrictions.kt @@ -24,6 +24,7 @@ import android.os.UserManager import com.android.settingslib.datastore.AbstractKeyedDataObservable import com.android.settingslib.datastore.DataChangeReason import com.android.settingslib.datastore.KeyedObserver +import com.android.settingslib.metadata.PreferenceChangeReason import java.util.concurrent.Executor /** Helper class to monitor user restriction changes. */ @@ -46,7 +47,7 @@ class UserRestrictions private constructor(private val applicationContext: Conte object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { // there is no way to get the changed keys, just notify all observers - observable.notifyChange(DataChangeReason.UPDATE) + observable.notifyChange(PreferenceChangeReason.STATE) } } diff --git a/src/com/android/settings/wifi/WifiSwitchPreference.kt b/src/com/android/settings/wifi/WifiSwitchPreference.kt index dbe5759a2e4..2b2b3443f60 100644 --- a/src/com/android/settings/wifi/WifiSwitchPreference.kt +++ b/src/com/android/settings/wifi/WifiSwitchPreference.kt @@ -40,9 +40,9 @@ import com.android.settings.wifi.utils.wifiManager import com.android.settingslib.RestrictedSwitchPreference import com.android.settingslib.WirelessUtils import com.android.settingslib.datastore.AbstractKeyedDataObservable -import com.android.settingslib.datastore.DataChangeReason import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.Permissions +import com.android.settingslib.metadata.PreferenceChangeReason import com.android.settingslib.metadata.PreferenceLifecycleProvider import com.android.settingslib.metadata.PreferenceMetadata import com.android.settingslib.metadata.ReadWritePermit @@ -163,7 +163,7 @@ class WifiSwitchPreference : wifiState == WifiManager.WIFI_STATE_ENABLED || wifiState == WifiManager.WIFI_STATE_DISABLED ) { - notifyChange(KEY, DataChangeReason.UPDATE) + notifyChange(KEY, PreferenceChangeReason.VALUE) } } } diff --git a/src/com/android/settings/wifi/tether/WifiHotspotSwitchPreference.kt b/src/com/android/settings/wifi/tether/WifiHotspotSwitchPreference.kt index c93099eb9da..3877a026480 100644 --- a/src/com/android/settings/wifi/tether/WifiHotspotSwitchPreference.kt +++ b/src/com/android/settings/wifi/tether/WifiHotspotSwitchPreference.kt @@ -32,7 +32,6 @@ import com.android.settings.PreferenceRestrictionMixin import com.android.settings.R import com.android.settings.Utils import com.android.settings.core.SubSettingLauncher -import com.android.settings.datausage.DataSaverMainSwitchPreference.Companion.KEY as DATA_SAVER_KEY import com.android.settings.wifi.WifiUtils.canShowWifiHotspot import com.android.settings.wifi.utils.tetheringManager import com.android.settings.wifi.utils.wifiApState @@ -41,12 +40,12 @@ import com.android.settings.wifi.utils.wifiSoftApSsid import com.android.settingslib.PrimarySwitchPreference import com.android.settingslib.TetherUtil import com.android.settingslib.datastore.AbstractKeyedDataObservable -import com.android.settingslib.datastore.DataChangeReason import com.android.settingslib.datastore.HandlerExecutor import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.KeyedObserver import com.android.settingslib.datastore.Permissions import com.android.settingslib.metadata.PreferenceAvailabilityProvider +import com.android.settingslib.metadata.PreferenceChangeReason import com.android.settingslib.metadata.PreferenceMetadata import com.android.settingslib.metadata.PreferenceSummaryProvider import com.android.settingslib.metadata.ReadWritePermit @@ -54,6 +53,7 @@ import com.android.settingslib.metadata.SensitivityLevel import com.android.settingslib.metadata.SwitchPreference import com.android.settingslib.preference.PreferenceBinding import com.android.settingslib.wifi.WifiUtils.Companion.getWifiTetherSummaryForConnectedDevices +import com.android.settings.datausage.DataSaverMainSwitchPreference.Companion.KEY as DATA_SAVER_KEY // LINT.IfChange class WifiHotspotSwitchPreference(context: Context, dataSaverStore: KeyValueStore) : @@ -186,13 +186,13 @@ class WifiHotspotSwitchPreference(context: Context, dataSaverStore: KeyValueStor Log.d(TAG, "onStateChanged(),state=$state,failureReason=$failureReason") sapFailureReason = failureReason if (state == WifiManager.WIFI_AP_STATE_DISABLED) sapClientsSize = null - notifyChange(KEY, DataChangeReason.UPDATE) + notifyChange(KEY, PreferenceChangeReason.VALUE) } override fun onConnectedClientsChanged(clients: List?) { sapClientsSize = clients?.size ?: 0 Log.d(TAG, "onConnectedClientsChanged(),sapClientsSize=$sapClientsSize") - notifyChange(KEY, DataChangeReason.UPDATE) + notifyChange(KEY, PreferenceChangeReason.STATE) } override fun onTetheringStarted() {} @@ -202,7 +202,7 @@ class WifiHotspotSwitchPreference(context: Context, dataSaverStore: KeyValueStor } override fun onKeyChanged(key: String, reason: Int) = - notifyChange(KEY, DataChangeReason.UPDATE) + notifyChange(KEY, reason) } override fun bind(preference: Preference, metadata: PreferenceMetadata) { From 05b678936af84ec087bdd38e837637847fbf1379 Mon Sep 17 00:00:00 2001 From: Jacky Wang Date: Fri, 10 Jan 2025 16:29:09 +0800 Subject: [PATCH 16/17] [Catalyst] Prevent flicker on "Use Data Saver" Fix: 383632913 Flag: com.android.settings.flags.catalyst Test: manual Change-Id: I9aa9544c4749e543f5a923d166e4268af595a500 --- .../datausage/DataSaverMainSwitchPreference.kt | 3 +++ .../android/settings/widget/MainSwitchBarMetadata.kt | 10 ++++++++++ .../android/settings/widget/MainSwitchBarPreference.kt | 2 +- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/datausage/DataSaverMainSwitchPreference.kt b/src/com/android/settings/datausage/DataSaverMainSwitchPreference.kt index 9127659b8e6..e73fe948c74 100644 --- a/src/com/android/settings/datausage/DataSaverMainSwitchPreference.kt +++ b/src/com/android/settings/datausage/DataSaverMainSwitchPreference.kt @@ -36,6 +36,9 @@ class DataSaverMainSwitchPreference : MainSwitchBarMetadata, PreferenceLifecycle override val title get() = R.string.data_saver_switch_title + override val disableWidgetOnCheckedChanged: Boolean + get() = false + override fun storage(context: Context) = createDataStore(context) override fun getReadPermissions(context: Context) = diff --git a/src/com/android/settings/widget/MainSwitchBarMetadata.kt b/src/com/android/settings/widget/MainSwitchBarMetadata.kt index f55cfd03789..4fc89bc19b6 100644 --- a/src/com/android/settings/widget/MainSwitchBarMetadata.kt +++ b/src/com/android/settings/widget/MainSwitchBarMetadata.kt @@ -27,6 +27,16 @@ import com.android.settingslib.preference.TwoStatePreferenceBinding interface MainSwitchBarMetadata : TwoStatePreference, TwoStatePreferenceBinding, PreferenceBindingPlaceholder { + /** + * Disable main switch bar when user toggles the switch. By this way, user cannot toggle again + * before last operation is done. + * + * Side-effect: If the underlying operation is completed quickly, this will causes UI flicker. + * Override and return `false` to get rid of the flicker. + */ + val disableWidgetOnCheckedChanged: Boolean + get() = true + override fun createWidget(context: Context) = MainSwitchBarPreference(context, this) override fun bind(preference: Preference, metadata: PreferenceMetadata) { diff --git a/src/com/android/settings/widget/MainSwitchBarPreference.kt b/src/com/android/settings/widget/MainSwitchBarPreference.kt index b3b341c75a9..a23409a8cc8 100644 --- a/src/com/android/settings/widget/MainSwitchBarPreference.kt +++ b/src/com/android/settings/widget/MainSwitchBarPreference.kt @@ -80,7 +80,7 @@ class MainSwitchBarPreference(context: Context, private val metadata: MainSwitch override fun onCheckedChanged(buttonView: CompoundButton, isChecked: Boolean) { // prevent user from toggling the switch before data store operation is done - isEnabled = false + if (metadata.disableWidgetOnCheckedChanged) isEnabled = false // once data store is updated, isEnabled will be reset due to rebind persistBoolean(isChecked) } From 551fa0d4d6bae28cafc9458bbcdad1ce110a8a18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Fri, 10 Jan 2025 11:57:33 -0800 Subject: [PATCH 17/17] Align ownership between Connectivity and settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (using core_networking_xts, not core_networking because it's a better match for the allowed set of folks) Test: N/A Signed-off-by: Maciej Żenczykowski Change-Id: Ie8192fd06b0d5507884e083eaf6d6614c40ff2ea --- src/com/android/settings/vpn2/OWNERS | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/com/android/settings/vpn2/OWNERS b/src/com/android/settings/vpn2/OWNERS index 41356451dfa..919c56e59c4 100644 --- a/src/com/android/settings/vpn2/OWNERS +++ b/src/com/android/settings/vpn2/OWNERS @@ -1,13 +1,7 @@ # People who can approve changes for submission. -jchalard@google.com -lorenzo@google.com -maze@google.com -reminv@google.com +file:platform/packages/modules/Connectivity:main:/OWNERS_core_networking_xts xiaom@google.com hughchen@google.com robertluo@google.com timhypeng@google.com vincentwei@google.com - -# Emergency approvers in case the above are not available -satk@google.com