From fa5ec443d94922424112fe8a7c7f9d3b36dca67d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Hern=C3=A1ndez?= Date: Thu, 15 Jun 2023 18:37:52 +0200 Subject: [PATCH] Settings: don't try to allow NLSes with too-long component names * NotificationAccessConfirmationActivity (triggered through CompanionDeviceManager) -> Don't show the dialog, bail out early similarly to other invalid inputs. * NotificationAccessSettings (from Special App Access) -> No changes, but use the canonical constant now. * ApprovalPreferenceController (used in NotificationAccessDetails) -> Disable the toggle, unless the NLS was previously approved (in which case it can still be removed). Fixes: 260570119 Fixes: 286043036 Test: atest + manually (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:b88fbf932a1631792a422f8ac34e83e1d6ae74d7) Merged-In: Ifc048311746c027e3683cdcf65f1079d04cf7c56 Change-Id: Ifc048311746c027e3683cdcf65f1079d04cf7c56 --- .../ApprovalPreferenceController.java | 5 +++- ...otificationAccessConfirmationActivity.java | 4 ++- .../NotificationAccessSettings.java | 4 +-- .../ApprovalPreferenceControllerTest.java | 30 +++++++++++++++++++ 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java b/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java index 0767e65bbcb..6bee62cc688 100644 --- a/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java +++ b/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java @@ -81,6 +81,8 @@ public void updateState(Preference pref) { final RestrictedSwitchPreference preference = (RestrictedSwitchPreference) pref; final CharSequence label = mPkgInfo.applicationInfo.loadLabel(mPm); + final boolean isAllowedCn = mCn.flattenToShortString().length() + <= NotificationManager.MAX_SERVICE_COMPONENT_NAME_LENGTH; final boolean isEnabled = isServiceEnabled(mCn); preference.setChecked(isEnabled); preference.setOnPreferenceChangeListener((p, newValue) -> { @@ -105,7 +107,8 @@ public void updateState(Preference pref) { return false; } }); - preference.updateState(mCn.getPackageName(), mPkgInfo.applicationInfo.uid, isEnabled); + preference.updateState( + mCn.getPackageName(), mPkgInfo.applicationInfo.uid, isAllowedCn, isEnabled); } public void disable(final ComponentName cn) { diff --git a/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java b/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java index dfe6df2a5ca..a6b565ae6ba 100644 --- a/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java +++ b/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java @@ -67,7 +67,9 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { mUserId = getIntent().getIntExtra(EXTRA_USER_ID, UserHandle.USER_NULL); CharSequence mAppLabel; - if (mComponentName == null || mComponentName.getPackageName() == null) { + if (mComponentName == null || mComponentName.getPackageName() == null + || mComponentName.flattenToString().length() + > NotificationManager.MAX_SERVICE_COMPONENT_NAME_LENGTH) { finish(); return; } diff --git a/src/com/android/settings/notification/NotificationAccessSettings.java b/src/com/android/settings/notification/NotificationAccessSettings.java index 369c4f6dfaf..e2ef0ddccb4 100644 --- a/src/com/android/settings/notification/NotificationAccessSettings.java +++ b/src/com/android/settings/notification/NotificationAccessSettings.java @@ -66,7 +66,6 @@ public class NotificationAccessSettings extends EmptyTextSettings { private static final String TAG = "NotifAccessSettings"; static final String ALLOWED_KEY = "allowed"; static final String NOT_ALLOWED_KEY = "not_allowed"; - private static final int MAX_CN_LENGTH = 500; private static final ManagedServiceSettings.Config CONFIG = new ManagedServiceSettings.Config.Builder() @@ -150,7 +149,8 @@ void updateList(List services) { for (ServiceInfo service : services) { final ComponentName cn = new ComponentName(service.packageName, service.name); boolean isAllowed = mNm.isNotificationListenerAccessGranted(cn); - if (!isAllowed && cn.flattenToString().length() > MAX_CN_LENGTH) { + if (!isAllowed && cn.flattenToString().length() + > NotificationManager.MAX_SERVICE_COMPONENT_NAME_LENGTH) { continue; } diff --git a/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java index 249b713987c..4601a1cfbaa 100644 --- a/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java @@ -83,6 +83,36 @@ public void setUp() { } + @Test + public void updateState_enabled() { + when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn( + AppOpsManager.MODE_ALLOWED); + when(mNm.isNotificationListenerAccessGranted(mCn)).thenReturn(true); + RestrictedSwitchPreference pref = new RestrictedSwitchPreference( + mContext); + pref.setAppOps(mAppOpsManager); + + mController.updateState(pref); + + assertThat(pref.isEnabled()).isTrue(); + } + + @Test + public void updateState_invalidCn_disabled() { + ComponentName longCn = new ComponentName("com.example.package", + com.google.common.base.Strings.repeat("Blah", 150)); + mController.setCn(longCn); + when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn( + AppOpsManager.MODE_ALLOWED); + RestrictedSwitchPreference pref = new RestrictedSwitchPreference( + mContext); + pref.setAppOps(mAppOpsManager); + + mController.updateState(pref); + + assertThat(pref.isEnabled()).isFalse(); + } + @Test public void updateState_checked() { when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn(