Send DND related broadcasts to the correct destinations
Previously, broadcasts such as ACTION_INTERRUPTION_FILTER_CHANGED were sent to every ConditionProvider package for all started users, even if the package had DND Access only for some subset of them. Now, they are sent only to the profiles of the current user, and only to the packages that have such access. Fixes: 270338618 Test: New unit tests + manual verification Change-Id: I4909a76a1f160eb5fb0be734a170982ffd2c0a69
This commit is contained in:
@@ -892,6 +892,7 @@ abstract public class ManagedServices {
|
||||
return allowedComponents;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
protected List<String> getAllowedPackages(int userId) {
|
||||
final List<String> allowedPackages = new ArrayList<>();
|
||||
synchronized (mApproved) {
|
||||
@@ -1181,25 +1182,6 @@ abstract public class ManagedServices {
|
||||
return installed;
|
||||
}
|
||||
|
||||
protected Set<String> getAllowedPackages() {
|
||||
final Set<String> allowedPackages = new ArraySet<>();
|
||||
synchronized (mApproved) {
|
||||
for (int k = 0; k < mApproved.size(); k++) {
|
||||
ArrayMap<Boolean, ArraySet<String>> allowedByType = mApproved.valueAt(k);
|
||||
for (int i = 0; i < allowedByType.size(); i++) {
|
||||
final ArraySet<String> allowed = allowedByType.valueAt(i);
|
||||
for (int j = 0; j < allowed.size(); j++) {
|
||||
String pkgName = getPackageName(allowed.valueAt(j));
|
||||
if (!TextUtils.isEmpty(pkgName)) {
|
||||
allowedPackages.add(pkgName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return allowedPackages;
|
||||
}
|
||||
|
||||
private void trimApprovedListsAccordingToInstalledServices(int userId) {
|
||||
synchronized (mApproved) {
|
||||
final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId);
|
||||
|
||||
@@ -2709,16 +2709,18 @@ public class NotificationManagerService extends SystemService {
|
||||
}
|
||||
|
||||
private void sendRegisteredOnlyBroadcast(String action) {
|
||||
Intent intent = new Intent(action);
|
||||
getContext().sendBroadcastAsUser(intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY),
|
||||
UserHandle.ALL, null);
|
||||
int[] userIds = mUmInternal.getProfileIds(mAmi.getCurrentUserId(), true);
|
||||
Intent intent = new Intent(action).addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
|
||||
for (int userId : userIds) {
|
||||
getContext().sendBroadcastAsUser(intent, UserHandle.of(userId), null);
|
||||
}
|
||||
// explicitly send the broadcast to all DND packages, even if they aren't currently running
|
||||
intent.setFlags(0);
|
||||
final Set<String> dndApprovedPackages = mConditionProviders.getAllowedPackages();
|
||||
for (String pkg : dndApprovedPackages) {
|
||||
intent.setPackage(pkg);
|
||||
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
|
||||
getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
|
||||
for (int userId : userIds) {
|
||||
for (String pkg : mConditionProviders.getAllowedPackages(userId)) {
|
||||
Intent pkgIntent = new Intent(action).setPackage(pkg).setFlags(
|
||||
Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
|
||||
getContext().sendBroadcastAsUser(pkgIntent, UserHandle.of(userId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@ import static android.service.notification.NotificationListenerService.META_DATA
|
||||
import static com.android.server.notification.ManagedServices.APPROVAL_BY_COMPONENT;
|
||||
import static com.android.server.notification.ManagedServices.APPROVAL_BY_PACKAGE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
@@ -1201,28 +1203,11 @@ public class ManagedServicesTest extends UiServiceTestCase {
|
||||
mIpm, approvalLevel);
|
||||
loadXml(service);
|
||||
|
||||
List<String> allowedPackagesForUser0 = new ArrayList<>();
|
||||
allowedPackagesForUser0.add("this.is.a.package.name");
|
||||
allowedPackagesForUser0.add("another.package");
|
||||
allowedPackagesForUser0.add("secondary");
|
||||
|
||||
List<String> actual = service.getAllowedPackages(0);
|
||||
assertEquals(3, actual.size());
|
||||
for (String pkg : allowedPackagesForUser0) {
|
||||
assertTrue(actual.contains(pkg));
|
||||
}
|
||||
|
||||
List<String> allowedPackagesForUser10 = new ArrayList<>();
|
||||
allowedPackagesForUser10.add("this.is.another.package");
|
||||
allowedPackagesForUser10.add("package");
|
||||
allowedPackagesForUser10.add("this.is.another.package");
|
||||
allowedPackagesForUser10.add("component");
|
||||
|
||||
actual = service.getAllowedPackages(10);
|
||||
assertEquals(4, actual.size());
|
||||
for (String pkg : allowedPackagesForUser10) {
|
||||
assertTrue(actual.contains(pkg));
|
||||
}
|
||||
assertThat(service.getAllowedPackages(0)).containsExactly("this.is.a.package.name",
|
||||
"another.package", "secondary");
|
||||
assertThat(service.getAllowedPackages(10)).containsExactly("this.is.another.package",
|
||||
"package", "this.is.another.package", "component");
|
||||
assertThat(service.getAllowedPackages(999)).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1262,31 +1247,6 @@ public class ManagedServicesTest extends UiServiceTestCase {
|
||||
assertEquals(0, service.getAllowedComponents(10).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAllowedPackages() throws Exception {
|
||||
ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
|
||||
mIpm, APPROVAL_BY_COMPONENT);
|
||||
loadXml(service);
|
||||
service.mApprovalLevel = APPROVAL_BY_PACKAGE;
|
||||
loadXml(service);
|
||||
|
||||
List<String> allowedPackages = new ArrayList<>();
|
||||
allowedPackages.add("this.is.a.package.name");
|
||||
allowedPackages.add("another.package");
|
||||
allowedPackages.add("secondary");
|
||||
allowedPackages.add("this.is.another.package");
|
||||
allowedPackages.add("package");
|
||||
allowedPackages.add("component");
|
||||
allowedPackages.add("bananas!");
|
||||
allowedPackages.add("non.user.set.package");
|
||||
|
||||
Set<String> actual = service.getAllowedPackages();
|
||||
assertEquals(allowedPackages.size(), actual.size());
|
||||
for (String pkg : allowedPackages) {
|
||||
assertTrue(actual.contains(pkg));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnUserRemoved() throws Exception {
|
||||
for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
|
||||
|
||||
@@ -29,6 +29,7 @@ import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
|
||||
import static android.app.Notification.FLAG_NO_CLEAR;
|
||||
import static android.app.Notification.FLAG_ONGOING_EVENT;
|
||||
import static android.app.NotificationChannel.USER_LOCKED_ALLOW_BUBBLE;
|
||||
import static android.app.NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED;
|
||||
import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
|
||||
import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
|
||||
import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
|
||||
@@ -50,7 +51,6 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
|
||||
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
|
||||
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
|
||||
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
|
||||
|
||||
import static android.app.PendingIntent.FLAG_IMMUTABLE;
|
||||
import static android.app.PendingIntent.FLAG_MUTABLE;
|
||||
import static android.app.PendingIntent.FLAG_ONE_SHOT;
|
||||
@@ -237,6 +237,7 @@ import com.android.server.utils.quota.MultiRateLimiter;
|
||||
import com.android.server.wm.ActivityTaskManagerInternal;
|
||||
import com.android.server.wm.WindowManagerInternal;
|
||||
|
||||
import com.google.android.collect.Lists;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import org.junit.After;
|
||||
@@ -245,10 +246,13 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.ArgumentMatcher;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
@@ -440,6 +444,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
|
||||
mContext.addMockSystemService(Context.ALARM_SERVICE, mAlarmManager);
|
||||
mContext.addMockSystemService(NotificationManager.class, mMockNm);
|
||||
|
||||
doNothing().when(mContext).sendBroadcastAsUser(any(), any());
|
||||
doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
|
||||
|
||||
setDpmAppOppsExemptFromDismissal(false);
|
||||
@@ -7827,6 +7832,75 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
|
||||
eq("another.package"), eq(rule), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onZenModeChanged_sendsBroadcasts() throws Exception {
|
||||
when(mAmi.getCurrentUserId()).thenReturn(100);
|
||||
when(mUmInternal.getProfileIds(eq(100), anyBoolean())).thenReturn(new int[]{100, 101, 102});
|
||||
when(mConditionProviders.getAllowedPackages(anyInt())).then(new Answer<List<String>>() {
|
||||
@Override
|
||||
public List<String> answer(InvocationOnMock invocation) {
|
||||
int userId = invocation.getArgument(0);
|
||||
switch (userId) {
|
||||
case 100:
|
||||
return Lists.newArrayList("a", "b", "c");
|
||||
case 101:
|
||||
return Lists.newArrayList();
|
||||
case 102:
|
||||
return Lists.newArrayList("b");
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"Why would you ask for packages of userId " + userId + "?");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mService.getBinderService().setZenMode(Settings.Global.ZEN_MODE_NO_INTERRUPTIONS, null,
|
||||
"testing!");
|
||||
waitForIdle();
|
||||
|
||||
InOrder inOrder = inOrder(mContext);
|
||||
// Verify broadcasts for registered receivers
|
||||
inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(
|
||||
new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags(
|
||||
Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(100)), eq(null));
|
||||
inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(
|
||||
new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags(
|
||||
Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(101)), eq(null));
|
||||
inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(
|
||||
new Intent(ACTION_INTERRUPTION_FILTER_CHANGED).setFlags(
|
||||
Intent.FLAG_RECEIVER_REGISTERED_ONLY)), eq(UserHandle.of(102)), eq(null));
|
||||
|
||||
// Verify broadcast for packages that manage DND.
|
||||
inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
|
||||
ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("a").setFlags(
|
||||
Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100)));
|
||||
inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
|
||||
ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("b").setFlags(
|
||||
Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100)));
|
||||
inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
|
||||
ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("c").setFlags(
|
||||
Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(100)));
|
||||
inOrder.verify(mContext).sendBroadcastAsUser(eqIntent(new Intent(
|
||||
ACTION_INTERRUPTION_FILTER_CHANGED).setPackage("b").setFlags(
|
||||
Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)), eq(UserHandle.of(102)));
|
||||
}
|
||||
|
||||
private static Intent eqIntent(Intent wanted) {
|
||||
return ArgumentMatchers.argThat(
|
||||
new ArgumentMatcher<Intent>() {
|
||||
@Override
|
||||
public boolean matches(Intent argument) {
|
||||
return wanted.filterEquals(argument)
|
||||
&& wanted.getFlags() == argument.getFlags();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return wanted.toString();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAreNotificationsEnabledForPackage() throws Exception {
|
||||
mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
|
||||
|
||||
Reference in New Issue
Block a user