diff options
2 files changed, 74 insertions, 6 deletions
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 4b18add39999..c6d4c0098f60 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -61,6 +61,7 @@ import static android.content.pm.PackageManager.FEATURE_LEANBACK; import static android.content.pm.PackageManager.FEATURE_TELECOM; import static android.content.pm.PackageManager.FEATURE_TELEVISION; import static android.content.pm.PackageManager.MATCH_ALL; +import static android.content.pm.PackageManager.MATCH_ANY_USER; import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE; import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE; import static android.content.pm.PackageManager.PERMISSION_GRANTED; @@ -10693,10 +10694,18 @@ public class NotificationManagerService extends SystemService { private final ArraySet<ManagedServiceInfo> mLightTrimListeners = new ArraySet<>(); ArrayMap<Pair<ComponentName, Integer>, NotificationListenerFilter> mRequestedNotificationListeners = new ArrayMap<>(); + private final boolean mIsHeadlessSystemUserMode; public NotificationListeners(Context context, Object lock, UserProfiles userProfiles, IPackageManager pm) { + this(context, lock, userProfiles, pm, UserManager.isHeadlessSystemUserMode()); + } + + @VisibleForTesting + public NotificationListeners(Context context, Object lock, UserProfiles userProfiles, + IPackageManager pm, boolean isHeadlessSystemUserMode) { super(context, lock, userProfiles, pm); + this.mIsHeadlessSystemUserMode = isHeadlessSystemUserMode; } @Override @@ -10721,10 +10730,16 @@ public class NotificationManagerService extends SystemService { if (TextUtils.isEmpty(listeners[i])) { continue; } + int packageQueryFlags = MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE; + // In the headless system user mode, packages might not be installed for the + // system user. Match packages for any user since apps can be installed only for + // non-system users and would be considering uninstalled for the system user. + if (mIsHeadlessSystemUserMode) { + packageQueryFlags += MATCH_ANY_USER; + } ArraySet<ComponentName> approvedListeners = - this.queryPackageForServices(listeners[i], - MATCH_DIRECT_BOOT_AWARE - | MATCH_DIRECT_BOOT_UNAWARE, USER_SYSTEM); + this.queryPackageForServices(listeners[i], packageQueryFlags, + USER_SYSTEM); for (int k = 0; k < approvedListeners.size(); k++) { ComponentName cn = approvedListeners.valueAt(k); addDefaultComponentOrPackage(cn.flattenToString()); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java index 1e945776cf40..248a3fc8b3b1 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java @@ -15,6 +15,7 @@ */ package com.android.server.notification; +import static android.content.pm.PackageManager.MATCH_ANY_USER; import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ALERTING; import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_CONVERSATIONS; import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ONGOING; @@ -30,9 +31,11 @@ import static junit.framework.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.intThat; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; @@ -49,6 +52,7 @@ import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; import android.content.pm.VersionedPackage; +import android.content.res.Resources; import android.os.Bundle; import android.os.UserHandle; import android.service.notification.NotificationListenerFilter; @@ -69,6 +73,7 @@ import com.google.common.collect.ImmutableList; import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentMatcher; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.internal.util.reflection.FieldSetter; @@ -77,6 +82,7 @@ import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.util.Arrays; import java.util.List; public class NotificationListenersTest extends UiServiceTestCase { @@ -85,6 +91,8 @@ public class NotificationListenersTest extends UiServiceTestCase { private PackageManager mPm; @Mock private IPackageManager miPm; + @Mock + private Resources mResources; @Mock NotificationManagerService mNm; @@ -96,7 +104,8 @@ public class NotificationListenersTest extends UiServiceTestCase { private ComponentName mCn1 = new ComponentName("pkg", "pkg.cmp"); private ComponentName mCn2 = new ComponentName("pkg2", "pkg2.cmp2"); - + private ComponentName mUninstalledComponent = new ComponentName("pkg3", + "pkg3.NotificationListenerService"); @Before public void setUp() throws Exception { @@ -111,7 +120,7 @@ public class NotificationListenersTest extends UiServiceTestCase { @Test public void testReadExtraTag() throws Exception { - String xml = "<" + TAG_REQUESTED_LISTENERS+ ">" + String xml = "<" + TAG_REQUESTED_LISTENERS + ">" + "<listener component=\"" + mCn1.flattenToString() + "\" user=\"0\">" + "<allowed types=\"7\" />" + "</listener>" @@ -131,11 +140,55 @@ public class NotificationListenersTest extends UiServiceTestCase { } @Test + public void loadDefaultsFromConfig_forHeadlessSystemUser_loadUninstalled() throws Exception { + // setup with headless system user mode + mListeners = spy(mNm.new NotificationListeners( + mContext, new Object(), mock(ManagedServices.UserProfiles.class), miPm, + /* isHeadlessSystemUserMode= */ true)); + mockDefaultListenerConfigForUninstalledComponent(mUninstalledComponent); + + mListeners.loadDefaultsFromConfig(); + + assertThat(mListeners.getDefaultComponents()).contains(mUninstalledComponent); + } + + @Test + public void loadDefaultsFromConfig_forNonHeadlessSystemUser_ignoreUninstalled() + throws Exception { + // setup without headless system user mode + mListeners = spy(mNm.new NotificationListeners( + mContext, new Object(), mock(ManagedServices.UserProfiles.class), miPm, + /* isHeadlessSystemUserMode= */ false)); + mockDefaultListenerConfigForUninstalledComponent(mUninstalledComponent); + + mListeners.loadDefaultsFromConfig(); + + assertThat(mListeners.getDefaultComponents()).doesNotContain(mUninstalledComponent); + } + + private void mockDefaultListenerConfigForUninstalledComponent(ComponentName componentName) { + ArraySet<ComponentName> components = new ArraySet<>(Arrays.asList(componentName)); + when(mResources + .getString( + com.android.internal.R.string.config_defaultListenerAccessPackages)) + .thenReturn(componentName.getPackageName()); + when(mContext.getResources()).thenReturn(mResources); + doReturn(components).when(mListeners).queryPackageForServices( + eq(componentName.getPackageName()), + intThat(hasIntBitFlag(MATCH_ANY_USER)), + anyInt()); + } + + public static ArgumentMatcher<Integer> hasIntBitFlag(int flag) { + return arg -> arg != null && ((arg & flag) == flag); + } + + @Test public void testWriteExtraTag() throws Exception { NotificationListenerFilter nlf = new NotificationListenerFilter(7, new ArraySet<>()); VersionedPackage a1 = new VersionedPackage("pkg1", 243); NotificationListenerFilter nlf2 = - new NotificationListenerFilter(4, new ArraySet<>(new VersionedPackage[] {a1})); + new NotificationListenerFilter(4, new ArraySet<>(new VersionedPackage[]{a1})); mListeners.setNotificationListenerFilter(Pair.create(mCn1, 0), nlf); mListeners.setNotificationListenerFilter(Pair.create(mCn2, 10), nlf2); |