Merge "Match any user pkgs for headless sys user mode" into tm-qpr-dev

This commit is contained in:
TreeHugger Robot
2022-10-21 02:12:36 +00:00
committed by Android (Google) Code Review
2 changed files with 74 additions and 6 deletions

View File

@@ -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;
@@ -10633,10 +10634,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
@@ -10661,10 +10670,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());

View File

@@ -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>"
@@ -130,12 +139,56 @@ 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<>());
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);