Loading services/core/java/com/android/server/notification/NotificationManagerService.java +18 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -10700,10 +10701,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 Loading @@ -10728,10 +10737,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()); Loading services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java +56 −3 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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 { Loading @@ -85,6 +91,8 @@ public class NotificationListenersTest extends UiServiceTestCase { private PackageManager mPm; @Mock private IPackageManager miPm; @Mock private Resources mResources; @Mock NotificationManagerService mNm; Loading @@ -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 { Loading Loading @@ -130,6 +139,50 @@ public class NotificationListenersTest extends UiServiceTestCase { validateListenersFromXml(); } @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<>()); Loading Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +18 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -10700,10 +10701,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 Loading @@ -10728,10 +10737,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()); Loading
services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java +56 −3 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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 { Loading @@ -85,6 +91,8 @@ public class NotificationListenersTest extends UiServiceTestCase { private PackageManager mPm; @Mock private IPackageManager miPm; @Mock private Resources mResources; @Mock NotificationManagerService mNm; Loading @@ -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 { Loading Loading @@ -130,6 +139,50 @@ public class NotificationListenersTest extends UiServiceTestCase { validateListenersFromXml(); } @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<>()); Loading