diff --git a/core/api/test-current.txt b/core/api/test-current.txt index a448435926d9e..ffb31c9fe5733 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -272,6 +272,7 @@ package android.app { method public void allowAssistantAdjustment(String); method public void disallowAssistantAdjustment(String); method public android.content.ComponentName getEffectsSuppressor(); + method public boolean isNotificationPolicyAccessGrantedForPackage(@NonNull String); method public boolean matchesCallFilter(android.os.Bundle); method @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public void setNotificationListenerAccessGranted(@NonNull android.content.ComponentName, boolean, boolean); method public void updateNotificationChannel(@NonNull String, int, @NonNull android.app.NotificationChannel); diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 12460ba2bd4bf..da7a29f8ac101 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -1501,7 +1501,8 @@ public class NotificationManager { } /** @hide */ - public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) { + @TestApi + public boolean isNotificationPolicyAccessGrantedForPackage(@NonNull String pkg) { INotificationManager service = getService(); try { return service.isNotificationPolicyAccessGrantedForPackage(pkg); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index a61e3cd5f4abc..271f2a71b5b58 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -4777,6 +4777,15 @@ public class SettingsProvider extends ContentProvider { currentVersion = 195; } + if (currentVersion == 195) { + // Version 195: delete obsolete manged services settings + getSecureSettingsLocked(userId).deleteSettingLocked( + Secure.ENABLED_NOTIFICATION_ASSISTANT); + getSecureSettingsLocked(userId).deleteSettingLocked( + Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES); + currentVersion = 196; + } + // vXXX: Add new settings above this point. if (currentVersion != newVersion) { diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java index 8200ca0523bec..769b781b1ae98 100644 --- a/services/core/java/com/android/server/notification/ConditionProviders.java +++ b/services/core/java/com/android/server/notification/ConditionProviders.java @@ -123,7 +123,7 @@ public class ConditionProviders extends ManagedServices { final Config c = new Config(); c.caption = "condition provider"; c.serviceInterface = ConditionProviderService.SERVICE_INTERFACE; - c.secureSettingName = Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES; + c.secureSettingName = null; c.xmlTag = TAG_ENABLED_DND_APPS; c.secondarySettingName = Settings.Secure.ENABLED_NOTIFICATION_LISTENERS; c.bindPermission = android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE; diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index a7ee27286a245..54e9b37be64a1 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -437,9 +437,15 @@ abstract public class ManagedServices { } } } - Settings.Secure.putStringForUser( - mContext.getContentResolver(), element, value, userId); - loadAllowedComponentsFromSettings(); + if (shouldReflectToSettings()) { + Settings.Secure.putStringForUser( + mContext.getContentResolver(), element, value, userId); + } + + for (UserInfo user : mUm.getUsers()) { + addApprovedList(value, user.id, mConfig.secureSettingName.equals(element)); + } + Slog.d(TAG, "Done loading approved values from settings"); rebindServices(false, userId); } } @@ -498,10 +504,13 @@ abstract public class ManagedServices { out.endTag(null, TAG_MANAGED_SERVICES); if (!forBackup && isPrimary) { - // Also write values to settings, for observers who haven't migrated yet - Settings.Secure.putStringForUser(mContext.getContentResolver(), - getConfig().secureSettingName, allowedItems, - approvedUserId); + if (shouldReflectToSettings()) { + // Also write values to settings, for observers who haven't + // migrated yet + Settings.Secure.putStringForUser(mContext.getContentResolver(), + getConfig().secureSettingName, allowedItems, + approvedUserId); + } } } @@ -515,6 +524,13 @@ abstract public class ManagedServices { out.endTag(null, getConfig().xmlTag); } + /** + * Returns whether the approved list of services should also be written to the Settings db + */ + protected boolean shouldReflectToSettings() { + return false; + } + /** * Writes extra xml attributes to {@link #TAG_MANAGED_SERVICES} tag. */ @@ -530,8 +546,20 @@ abstract public class ManagedServices { */ protected void readExtraTag(String tag, TypedXmlPullParser parser) throws IOException {} - protected void migrateToXml() { - loadAllowedComponentsFromSettings(); + protected final void migrateToXml() { + for (UserInfo user : mUm.getUsers()) { + final ContentResolver cr = mContext.getContentResolver(); + addApprovedList(Settings.Secure.getStringForUser( + cr, + getConfig().secureSettingName, + user.id), user.id, true); + if (!TextUtils.isEmpty(getConfig().secondarySettingName)) { + addApprovedList(Settings.Secure.getStringForUser( + cr, + getConfig().secondarySettingName, + user.id), user.id, false); + } + } } void readDefaults(TypedXmlPullParser parser) { @@ -638,23 +666,6 @@ abstract public class ManagedServices { protected abstract String getRequiredPermission(); - private void loadAllowedComponentsFromSettings() { - for (UserInfo user : mUm.getUsers()) { - final ContentResolver cr = mContext.getContentResolver(); - addApprovedList(Settings.Secure.getStringForUser( - cr, - getConfig().secureSettingName, - user.id), user.id, true); - if (!TextUtils.isEmpty(getConfig().secondarySettingName)) { - addApprovedList(Settings.Secure.getStringForUser( - cr, - getConfig().secondarySettingName, - user.id), user.id, false); - } - } - Slog.d(TAG, "Done loading approved values from settings"); - } - protected void addApprovedList(String approved, int userId, boolean isPrimary) { addApprovedList(approved, userId, isPrimary, approved); } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index eb7ef2bbeaf2f..692e97a4ad16c 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -9527,6 +9527,13 @@ public class NotificationManagerService extends SystemService { return null; } + @Override + protected boolean shouldReflectToSettings() { + // androidx has a public method that reads the approved set of listeners from + // Settings so we have to continue writing this list for this type of service + return true; + } + @GuardedBy("mNotificationLock") public void setOnNotificationPostedTrimLocked(ManagedServiceInfo info, int trim) { if (trim == TRIM_LIGHT) { diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java index 4a4d9bc174fbe..ec28baf53d3ca 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java @@ -249,13 +249,13 @@ public class ManagedServicesTest extends UiServiceTestCase { backupPrimary.get(approvalLevel).get(userId), Build.VERSION_CODES.N_MR1, userId); } - verifyExpectedApprovedEntries(service, true); for (int userId : backupSecondary.get(approvalLevel).keySet()) { service.onSettingRestored(service.getConfig().secondarySettingName, backupSecondary.get(approvalLevel).get(userId), Build.VERSION_CODES.N_MR1, userId); } + // both sets of approved entries should be allowed verifyExpectedApprovedEntries(service); verifyExpectedApprovedEntries(service, backupPrimary.get(approvalLevel)); verifyExpectedApprovedEntries(service, backupSecondary.get(approvalLevel)); @@ -638,8 +638,8 @@ public class ManagedServicesTest extends UiServiceTestCase { @Test public void testWriteXml_writesSetting() throws Exception { for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { - ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, - mIpm, approvalLevel); + ManagedServices service = new TestManagedServicesSettings(getContext(), mLock, + mUserProfiles, mIpm, approvalLevel); loadXml(service); TypedXmlSerializer serializer = Xml.newFastSerializer(); @@ -661,6 +661,36 @@ public class ManagedServicesTest extends UiServiceTestCase { } } + @Test + public void testWriteXml_doesNotWriteSetting() throws Exception { + for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { + ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, + mIpm, approvalLevel); + + for (int userId : mUserProfiles.getCurrentProfileIds().toArray()) { + Settings.Secure.putStringForUser( + getContext().getContentResolver(), + service.getConfig().secureSettingName, null, userId); + } + loadXml(service); + + TypedXmlSerializer serializer = Xml.newFastSerializer(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + serializer.setOutput(new BufferedOutputStream(baos), "utf-8"); + serializer.startDocument(null, true); + service.writeXml(serializer, false, UserHandle.USER_ALL); + serializer.endDocument(); + serializer.flush(); + + for (int userId : mUserProfiles.getCurrentProfileIds().toArray()) { + String actual = Settings.Secure.getStringForUser( + getContext().getContentResolver(), + service.getConfig().secureSettingName, userId); + assertTrue(TextUtils.isEmpty(actual)); + } + } + } + @Test public void testWriteXml_writesUserSet() throws Exception { for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { @@ -1415,11 +1445,11 @@ public class ManagedServicesTest extends UiServiceTestCase { xml.append("<" + ManagedServices.TAG_MANAGED_SERVICES + " " + ManagedServices.ATT_USER_ID + "=\"99\" " + ManagedServices.ATT_IS_PRIMARY + "=\"true\" " - + ManagedServices.ATT_APPROVED_LIST + "=\"99\" />\n"); + + ManagedServices.ATT_APPROVED_LIST + "=\"990\" />\n"); xml.append("<" + ManagedServices.TAG_MANAGED_SERVICES + " " + ManagedServices.ATT_USER_ID + "=\"98\" " + ManagedServices.ATT_IS_PRIMARY + "=\"false\" " - + ManagedServices.ATT_APPROVED_LIST + "=\"98\" />\n"); + + ManagedServices.ATT_APPROVED_LIST + "=\"981\" />\n"); xml.append(""); return xml.toString(); @@ -1483,7 +1513,7 @@ public class ManagedServicesTest extends UiServiceTestCase { private void assertContentsInAnyOrder(Collection expected, Collection actual) { assertNotNull(actual); - assertEquals(expected.size(), actual.size()); + assertEquals(expected + " : " + actual, expected.size(), actual.size()); for (Object o : expected) { assertTrue("Actual missing " + o, actual.contains(o)); @@ -1665,4 +1695,17 @@ public class ManagedServicesTest extends UiServiceTestCase { return null; } } + + class TestManagedServicesSettings extends TestManagedServices { + + public TestManagedServicesSettings(Context context, Object mutex, UserProfiles userProfiles, + IPackageManager pm, int approvedServiceType) { + super(context, mutex, userProfiles, pm, approvedServiceType); + } + + @Override + public boolean shouldReflectToSettings() { + return true; + } + } }