Merge "Apply delivery group policies to ACTION_DROPBOX_ENTRY_ADDED."

This commit is contained in:
Sudheer Shanka
2023-02-10 18:54:55 +00:00
committed by Android (Google) Code Review
5 changed files with 145 additions and 12 deletions

View File

@@ -85,37 +85,43 @@ public class BundleMerger implements Parcelable {
/**
* Merge strategy that numerically adds both conflicting values.
*/
public static final int STRATEGY_NUMBER_ADD = 5;
public static final int STRATEGY_NUMBER_ADD = 10;
/**
* Merge strategy that numerically increments the first conflicting value by
* {@code 1} and ignores the last conflicting value.
*/
public static final int STRATEGY_NUMBER_INCREMENT_FIRST = 6;
public static final int STRATEGY_NUMBER_INCREMENT_FIRST = 20;
/**
* Merge strategy that numerically increments the first conflicting value by
* {@code 1} and also numerically adds both conflicting values.
*/
public static final int STRATEGY_NUMBER_INCREMENT_FIRST_AND_ADD = 25;
/**
* Merge strategy that combines conflicting values using a boolean "and"
* operation.
*/
public static final int STRATEGY_BOOLEAN_AND = 7;
public static final int STRATEGY_BOOLEAN_AND = 30;
/**
* Merge strategy that combines conflicting values using a boolean "or"
* operation.
*/
public static final int STRATEGY_BOOLEAN_OR = 8;
public static final int STRATEGY_BOOLEAN_OR = 40;
/**
* Merge strategy that combines two conflicting array values by appending
* the last array after the first array.
*/
public static final int STRATEGY_ARRAY_APPEND = 9;
public static final int STRATEGY_ARRAY_APPEND = 50;
/**
* Merge strategy that combines two conflicting {@link ArrayList} values by
* appending the last {@link ArrayList} after the first {@link ArrayList}.
*/
public static final int STRATEGY_ARRAY_LIST_APPEND = 10;
public static final int STRATEGY_ARRAY_LIST_APPEND = 60;
@IntDef(flag = false, prefix = { "STRATEGY_" }, value = {
STRATEGY_REJECT,
@@ -125,6 +131,7 @@ public class BundleMerger implements Parcelable {
STRATEGY_COMPARABLE_MAX,
STRATEGY_NUMBER_ADD,
STRATEGY_NUMBER_INCREMENT_FIRST,
STRATEGY_NUMBER_INCREMENT_FIRST_AND_ADD,
STRATEGY_BOOLEAN_AND,
STRATEGY_BOOLEAN_OR,
STRATEGY_ARRAY_APPEND,
@@ -282,6 +289,8 @@ public class BundleMerger implements Parcelable {
return numberAdd(first, last);
case STRATEGY_NUMBER_INCREMENT_FIRST:
return numberIncrementFirst(first, last);
case STRATEGY_NUMBER_INCREMENT_FIRST_AND_ADD:
return numberAdd(numberIncrementFirst(first, last), last);
case STRATEGY_BOOLEAN_AND:
return booleanAnd(first, last);
case STRATEGY_BOOLEAN_OR:

View File

@@ -26,6 +26,7 @@ import static android.os.BundleMerger.STRATEGY_FIRST;
import static android.os.BundleMerger.STRATEGY_LAST;
import static android.os.BundleMerger.STRATEGY_NUMBER_ADD;
import static android.os.BundleMerger.STRATEGY_NUMBER_INCREMENT_FIRST;
import static android.os.BundleMerger.STRATEGY_NUMBER_INCREMENT_FIRST_AND_ADD;
import static android.os.BundleMerger.STRATEGY_REJECT;
import static android.os.BundleMerger.merge;
@@ -150,6 +151,14 @@ public class BundleMergerTest {
assertEquals(21L, merge(STRATEGY_NUMBER_INCREMENT_FIRST, 20L, 10L));
}
@Test
public void testStrategyNumberIncrementFirstAndAdd() throws Exception {
assertEquals(31, merge(STRATEGY_NUMBER_INCREMENT_FIRST_AND_ADD, 10, 20));
assertEquals(31, merge(STRATEGY_NUMBER_INCREMENT_FIRST_AND_ADD, 20, 10));
assertEquals(31L, merge(STRATEGY_NUMBER_INCREMENT_FIRST_AND_ADD, 10L, 20L));
assertEquals(31L, merge(STRATEGY_NUMBER_INCREMENT_FIRST_AND_ADD, 20L, 10L));
}
@Test
public void testStrategyBooleanAnd() throws Exception {
assertEquals(false, merge(STRATEGY_BOOLEAN_AND, false, false));
@@ -214,6 +223,29 @@ public class BundleMergerTest {
});
}
@Test
public void testSetDefaultMergeStrategy() throws Exception {
final BundleMerger merger = new BundleMerger();
merger.setDefaultMergeStrategy(STRATEGY_FIRST);
merger.setMergeStrategy(Intent.EXTRA_INDEX, STRATEGY_COMPARABLE_MAX);
Bundle a = new Bundle();
a.putString(Intent.EXTRA_SUBJECT, "SubjectA");
a.putInt(Intent.EXTRA_INDEX, 10);
Bundle b = new Bundle();
b.putString(Intent.EXTRA_SUBJECT, "SubjectB");
b.putInt(Intent.EXTRA_INDEX, 20);
Bundle ab = merger.merge(a, b);
assertEquals("SubjectA", ab.getString(Intent.EXTRA_SUBJECT));
assertEquals(20, ab.getInt(Intent.EXTRA_INDEX));
Bundle ba = merger.merge(b, a);
assertEquals("SubjectB", ba.getString(Intent.EXTRA_SUBJECT));
assertEquals(20, ba.getInt(Intent.EXTRA_INDEX));
}
@Test
public void testMerge_Simple() throws Exception {
final BundleMerger merger = new BundleMerger();
@@ -323,7 +355,7 @@ public class BundleMergerTest {
merger.setMergeStrategy(DropBoxManager.EXTRA_TIME,
STRATEGY_COMPARABLE_MAX);
merger.setMergeStrategy(DropBoxManager.EXTRA_DROPPED_COUNT,
STRATEGY_NUMBER_INCREMENT_FIRST);
STRATEGY_NUMBER_INCREMENT_FIRST_AND_ADD);
final long now = System.currentTimeMillis();
final Bundle a = new Bundle();
@@ -341,6 +373,11 @@ public class BundleMergerTest {
c.putLong(DropBoxManager.EXTRA_TIME, now + 2000);
c.putInt(DropBoxManager.EXTRA_DROPPED_COUNT, 0);
final Bundle d = new Bundle();
d.putString(DropBoxManager.EXTRA_TAG, "system_server_strictmode");
d.putLong(DropBoxManager.EXTRA_TIME, now + 3000);
d.putInt(DropBoxManager.EXTRA_DROPPED_COUNT, 5);
final Bundle ab = merger.merge(a, b);
assertEquals("system_server_strictmode", ab.getString(DropBoxManager.EXTRA_TAG));
assertEquals(now + 1000, ab.getLong(DropBoxManager.EXTRA_TIME));
@@ -350,6 +387,11 @@ public class BundleMergerTest {
assertEquals("system_server_strictmode", abc.getString(DropBoxManager.EXTRA_TAG));
assertEquals(now + 2000, abc.getLong(DropBoxManager.EXTRA_TIME));
assertEquals(2, abc.getInt(DropBoxManager.EXTRA_DROPPED_COUNT));
final Bundle abcd = merger.merge(abc, d);
assertEquals("system_server_strictmode", abcd.getString(DropBoxManager.EXTRA_TAG));
assertEquals(now + 3000, abcd.getLong(DropBoxManager.EXTRA_TIME));
assertEquals(8, abcd.getInt(DropBoxManager.EXTRA_DROPPED_COUNT));
}
private static ArrayList<Object> arrayListOf(Object... values) {

View File

@@ -19,6 +19,7 @@ package com.android.server;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -29,6 +30,8 @@ import android.content.res.Resources;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.BundleMerger;
import android.os.Debug;
import android.os.DropBoxManager;
import android.os.FileUtils;
@@ -264,7 +267,7 @@ public final class DropBoxManagerService extends SystemService {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SEND_BROADCAST:
prepareAndSendBroadcast((Intent) msg.obj);
prepareAndSendBroadcast((Intent) msg.obj, null);
break;
case MSG_SEND_DEFERRED_BROADCAST:
Intent deferredIntent;
@@ -272,27 +275,50 @@ public final class DropBoxManagerService extends SystemService {
deferredIntent = mDeferredMap.remove((String) msg.obj);
}
if (deferredIntent != null) {
prepareAndSendBroadcast(deferredIntent);
prepareAndSendBroadcast(deferredIntent,
createBroadcastOptions(deferredIntent));
}
break;
}
}
private void prepareAndSendBroadcast(Intent intent) {
private void prepareAndSendBroadcast(Intent intent, Bundle options) {
if (!DropBoxManagerService.this.mBooted) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
}
getContext().sendBroadcastAsUser(intent, UserHandle.ALL,
android.Manifest.permission.READ_LOGS);
android.Manifest.permission.READ_LOGS, options);
}
private Intent createIntent(String tag, long time) {
final Intent dropboxIntent = new Intent(DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED);
dropboxIntent.putExtra(DropBoxManager.EXTRA_TAG, tag);
dropboxIntent.putExtra(DropBoxManager.EXTRA_TIME, time);
dropboxIntent.putExtra(DropBoxManager.EXTRA_DROPPED_COUNT, 0);
return dropboxIntent;
}
private Bundle createBroadcastOptions(Intent intent) {
final BundleMerger extrasMerger = new BundleMerger();
extrasMerger.setDefaultMergeStrategy(BundleMerger.STRATEGY_FIRST);
extrasMerger.setMergeStrategy(DropBoxManager.EXTRA_TIME,
BundleMerger.STRATEGY_COMPARABLE_MAX);
extrasMerger.setMergeStrategy(DropBoxManager.EXTRA_DROPPED_COUNT,
BundleMerger.STRATEGY_NUMBER_INCREMENT_FIRST_AND_ADD);
final String tag = intent.getStringExtra(DropBoxManager.EXTRA_TAG);
final IntentFilter matchingFilter = new IntentFilter(
DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED);
matchingFilter.addExtra(DropBoxManager.EXTRA_TAG, tag);
return BroadcastOptions.makeBasic()
.setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MERGED)
.setDeliveryGroupMatchingFilter(matchingFilter)
.setDeliveryGroupExtrasMerger(extrasMerger)
.setDeferUntilActive(true)
.toBundle();
}
/**
* Schedule a dropbox broadcast to be sent asynchronously.
*/

View File

@@ -60,11 +60,13 @@ import android.content.pm.ResolveInfo;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.BundleMerger;
import android.os.DropBoxManager;
import android.os.HandlerThread;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.IndentingPrintWriter;
import android.util.Pair;
import androidx.test.filters.SmallTest;
@@ -977,6 +979,59 @@ public class BroadcastQueueModernImplTest {
List.of(musicVolumeChanged, alarmVolumeChanged, timeTick));
}
@Test
public void testDeliveryGroupPolicy_merged_matchingFilter() {
final long now = SystemClock.elapsedRealtime();
final Pair<Intent, BroadcastOptions> dropboxEntryBroadcast1 = createDropboxBroadcast(
"TAG_A", now, 2);
final Pair<Intent, BroadcastOptions> dropboxEntryBroadcast2 = createDropboxBroadcast(
"TAG_B", now + 1000, 4);
final Pair<Intent, BroadcastOptions> dropboxEntryBroadcast3 = createDropboxBroadcast(
"TAG_A", now + 2000, 7);
// Halt all processing so that we get a consistent view
mHandlerThread.getLooper().getQueue().postSyncBarrier();
mImpl.enqueueBroadcastLocked(makeBroadcastRecord(dropboxEntryBroadcast1.first,
dropboxEntryBroadcast1.second));
mImpl.enqueueBroadcastLocked(makeBroadcastRecord(dropboxEntryBroadcast2.first,
dropboxEntryBroadcast2.second));
mImpl.enqueueBroadcastLocked(makeBroadcastRecord(dropboxEntryBroadcast3.first,
dropboxEntryBroadcast3.second));
final BroadcastProcessQueue queue = mImpl.getProcessQueue(PACKAGE_GREEN,
getUidForPackage(PACKAGE_GREEN));
// dropboxEntryBroadcast1 and dropboxEntryBroadcast3 should be merged as they use the same
// tag and there shouldn't be a change to dropboxEntryBroadcast2.
final Pair<Intent, BroadcastOptions> expectedMergedBroadcast = createDropboxBroadcast(
"TAG_A", now + 2000, 10);
verifyPendingRecords(queue, List.of(
dropboxEntryBroadcast2.first, expectedMergedBroadcast.first));
}
private Pair<Intent, BroadcastOptions> createDropboxBroadcast(String tag, long timestampMs,
int droppedCount) {
final Intent dropboxEntryAdded = new Intent(DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED);
dropboxEntryAdded.putExtra(DropBoxManager.EXTRA_TAG, tag);
dropboxEntryAdded.putExtra(DropBoxManager.EXTRA_TIME, timestampMs);
dropboxEntryAdded.putExtra(DropBoxManager.EXTRA_DROPPED_COUNT, droppedCount);
final BundleMerger extrasMerger = new BundleMerger();
extrasMerger.setDefaultMergeStrategy(BundleMerger.STRATEGY_FIRST);
extrasMerger.setMergeStrategy(DropBoxManager.EXTRA_TIME,
BundleMerger.STRATEGY_COMPARABLE_MAX);
extrasMerger.setMergeStrategy(DropBoxManager.EXTRA_DROPPED_COUNT,
BundleMerger.STRATEGY_NUMBER_INCREMENT_FIRST_AND_ADD);
final IntentFilter matchingFilter = new IntentFilter(
DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED);
matchingFilter.addExtra(DropBoxManager.EXTRA_TAG, tag);
final BroadcastOptions optionsDropboxEntryAdded = BroadcastOptions.makeBasic()
.setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MERGED)
.setDeliveryGroupMatchingFilter(matchingFilter)
.setDeliveryGroupExtrasMerger(extrasMerger);
return Pair.create(dropboxEntryAdded, optionsDropboxEntryAdded);
}
@Test
public void testVerifyEnqueuedTime_withReplacePending() {
final Intent userPresent = new Intent(Intent.ACTION_USER_PRESENT);

View File

@@ -20,6 +20,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.os.Bundle;
import android.os.DropBoxManager;
import android.os.Looper;
import android.os.Parcel;
@@ -66,7 +67,7 @@ public class DropBoxTest extends AndroidTestCase {
mContext = new ContextWrapper(super.getContext()) {
@Override
public void sendBroadcastAsUser(Intent intent,
UserHandle user, String receiverPermission) {
UserHandle user, String receiverPermission, Bundle options) {
// Don't actually send broadcasts.
}
};