Merge "Relax delivery group policy constraints for resultTo bcasts." into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
e12e7292f8
@@ -33,6 +33,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.LOG_WRITER_INFO;
|
|||||||
import static com.android.server.am.BroadcastProcessQueue.insertIntoRunnableList;
|
import static com.android.server.am.BroadcastProcessQueue.insertIntoRunnableList;
|
||||||
import static com.android.server.am.BroadcastProcessQueue.reasonToString;
|
import static com.android.server.am.BroadcastProcessQueue.reasonToString;
|
||||||
import static com.android.server.am.BroadcastProcessQueue.removeFromRunnableList;
|
import static com.android.server.am.BroadcastProcessQueue.removeFromRunnableList;
|
||||||
|
import static com.android.server.am.BroadcastRecord.DELIVERY_DEFERRED;
|
||||||
import static com.android.server.am.BroadcastRecord.deliveryStateToString;
|
import static com.android.server.am.BroadcastRecord.deliveryStateToString;
|
||||||
import static com.android.server.am.BroadcastRecord.getReceiverClassName;
|
import static com.android.server.am.BroadcastRecord.getReceiverClassName;
|
||||||
import static com.android.server.am.BroadcastRecord.getReceiverPackageName;
|
import static com.android.server.am.BroadcastRecord.getReceiverPackageName;
|
||||||
@@ -68,6 +69,7 @@ import android.os.RemoteException;
|
|||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.text.format.DateUtils;
|
import android.text.format.DateUtils;
|
||||||
|
import android.util.ArrayMap;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.IndentingPrintWriter;
|
import android.util.IndentingPrintWriter;
|
||||||
import android.util.MathUtils;
|
import android.util.MathUtils;
|
||||||
@@ -212,6 +214,13 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
|||||||
private final AtomicReference<ArraySet<BroadcastRecord>> mReplacedBroadcastsCache =
|
private final AtomicReference<ArraySet<BroadcastRecord>> mReplacedBroadcastsCache =
|
||||||
new AtomicReference<>();
|
new AtomicReference<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Container for holding the set of broadcast records that satisfied a certain criteria.
|
||||||
|
*/
|
||||||
|
@GuardedBy("mService")
|
||||||
|
private final AtomicReference<ArrayMap<BroadcastRecord, Boolean>> mRecordsLookupCache =
|
||||||
|
new AtomicReference<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map from UID to its last known "foreground" state. A UID is considered to be in
|
* Map from UID to its last known "foreground" state. A UID is considered to be in
|
||||||
* "foreground" state when it's procState is {@link ActivityManager#PROCESS_STATE_TOP}.
|
* "foreground" state when it's procState is {@link ActivityManager#PROCESS_STATE_TOP}.
|
||||||
@@ -742,13 +751,16 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
|||||||
broadcastConsumer = mBroadcastConsumerSkipAndCanceled;
|
broadcastConsumer = mBroadcastConsumerSkipAndCanceled;
|
||||||
break;
|
break;
|
||||||
case BroadcastOptions.DELIVERY_GROUP_POLICY_MERGED:
|
case BroadcastOptions.DELIVERY_GROUP_POLICY_MERGED:
|
||||||
|
// TODO: Allow applying MERGED policy for broadcasts with more than one receiver.
|
||||||
|
if (r.receivers.size() > 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
final BundleMerger extrasMerger = r.options.getDeliveryGroupExtrasMerger();
|
final BundleMerger extrasMerger = r.options.getDeliveryGroupExtrasMerger();
|
||||||
if (extrasMerger == null) {
|
if (extrasMerger == null) {
|
||||||
// Extras merger is required to be able to merge the extras. So, if it's not
|
// Extras merger is required to be able to merge the extras. So, if it's not
|
||||||
// supplied, then ignore the delivery group policy.
|
// supplied, then ignore the delivery group policy.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO: Don't merge with the same BroadcastRecord more than once.
|
|
||||||
broadcastConsumer = (record, recordIndex) -> {
|
broadcastConsumer = (record, recordIndex) -> {
|
||||||
r.intent.mergeExtras(record.intent, extrasMerger);
|
r.intent.mergeExtras(record.intent, extrasMerger);
|
||||||
mBroadcastConsumerSkipAndCanceled.accept(record, recordIndex);
|
mBroadcastConsumerSkipAndCanceled.accept(record, recordIndex);
|
||||||
@@ -758,6 +770,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
|||||||
logw("Unknown delivery group policy: " + policy);
|
logw("Unknown delivery group policy: " + policy);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
final ArrayMap<BroadcastRecord, Boolean> recordsLookupCache = getRecordsLookupCache();
|
||||||
forEachMatchingBroadcast(QUEUE_PREDICATE_ANY, (testRecord, testIndex) -> {
|
forEachMatchingBroadcast(QUEUE_PREDICATE_ANY, (testRecord, testIndex) -> {
|
||||||
// If the receiver is already in a terminal state, then ignore it.
|
// If the receiver is already in a terminal state, then ignore it.
|
||||||
if (isDeliveryStateTerminal(testRecord.getDeliveryState(testIndex))) {
|
if (isDeliveryStateTerminal(testRecord.getDeliveryState(testIndex))) {
|
||||||
@@ -769,22 +782,44 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
|||||||
|| !r.matchesDeliveryGroup(testRecord)) {
|
|| !r.matchesDeliveryGroup(testRecord)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// TODO: If a process is in a deferred state, we can always apply the policy as long
|
|
||||||
// as it is one of the receivers for the new broadcast.
|
|
||||||
|
|
||||||
// For ordered broadcast, check if the receivers for the new broadcast is a superset
|
// For ordered broadcast, check if the receivers for the new broadcast is a superset
|
||||||
// of those for the previous one as skipping and removing only one of them could result
|
// of those for the previous one as skipping and removing only one of them could result
|
||||||
// in an inconsistent state.
|
// in an inconsistent state.
|
||||||
if (testRecord.ordered || testRecord.resultTo != null) {
|
if (testRecord.ordered || testRecord.prioritized) {
|
||||||
// TODO: Cache this result in some way so that we don't have to perform the
|
return containsAllReceivers(r, testRecord, recordsLookupCache);
|
||||||
// same check for all the broadcast receivers.
|
} else if (testRecord.resultTo != null) {
|
||||||
return r.containsAllReceivers(testRecord.receivers);
|
return testRecord.getDeliveryState(testIndex) == DELIVERY_DEFERRED
|
||||||
} else if (testRecord.prioritized) {
|
? r.containsReceiver(testRecord.receivers.get(testIndex))
|
||||||
return r.containsAllReceivers(testRecord.receivers);
|
: containsAllReceivers(r, testRecord, recordsLookupCache);
|
||||||
} else {
|
} else {
|
||||||
return r.containsReceiver(testRecord.receivers.get(testIndex));
|
return r.containsReceiver(testRecord.receivers.get(testIndex));
|
||||||
}
|
}
|
||||||
}, broadcastConsumer, true);
|
}, broadcastConsumer, true);
|
||||||
|
recordsLookupCache.clear();
|
||||||
|
mRecordsLookupCache.compareAndSet(null, recordsLookupCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private ArrayMap<BroadcastRecord, Boolean> getRecordsLookupCache() {
|
||||||
|
ArrayMap<BroadcastRecord, Boolean> recordsLookupCache =
|
||||||
|
mRecordsLookupCache.getAndSet(null);
|
||||||
|
if (recordsLookupCache == null) {
|
||||||
|
recordsLookupCache = new ArrayMap<>();
|
||||||
|
}
|
||||||
|
return recordsLookupCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean containsAllReceivers(@NonNull BroadcastRecord record,
|
||||||
|
@NonNull BroadcastRecord testRecord,
|
||||||
|
@NonNull ArrayMap<BroadcastRecord, Boolean> recordsLookupCache) {
|
||||||
|
final int idx = recordsLookupCache.indexOfKey(testRecord);
|
||||||
|
if (idx > 0) {
|
||||||
|
return recordsLookupCache.valueAt(idx);
|
||||||
|
}
|
||||||
|
final boolean containsAll = record.containsAllReceivers(testRecord.receivers);
|
||||||
|
recordsLookupCache.put(testRecord, containsAll);
|
||||||
|
return containsAll;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1094,6 +1094,17 @@ public final class BroadcastQueueModernImplTest {
|
|||||||
verifyPendingRecords(greenQueue, List.of(screenOff, screenOn));
|
verifyPendingRecords(greenQueue, List.of(screenOff, screenOn));
|
||||||
verifyPendingRecords(redQueue, List.of(screenOff));
|
verifyPendingRecords(redQueue, List.of(screenOff));
|
||||||
verifyPendingRecords(blueQueue, List.of(screenOff, screenOn));
|
verifyPendingRecords(blueQueue, List.of(screenOff, screenOn));
|
||||||
|
|
||||||
|
final BroadcastRecord screenOffRecord = makeBroadcastRecord(screenOff, screenOnOffOptions,
|
||||||
|
List.of(greenReceiver, redReceiver, blueReceiver), resultTo, false);
|
||||||
|
screenOffRecord.setDeliveryState(2, BroadcastRecord.DELIVERY_DEFERRED,
|
||||||
|
"testDeliveryGroupPolicy_resultTo_diffReceivers");
|
||||||
|
mImpl.enqueueBroadcastLocked(screenOffRecord);
|
||||||
|
mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOn, screenOnOffOptions,
|
||||||
|
List.of(greenReceiver, blueReceiver), resultTo, false));
|
||||||
|
verifyPendingRecords(greenQueue, List.of(screenOff, screenOn));
|
||||||
|
verifyPendingRecords(redQueue, List.of(screenOff));
|
||||||
|
verifyPendingRecords(blueQueue, List.of(screenOn));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -1278,6 +1289,36 @@ public final class BroadcastQueueModernImplTest {
|
|||||||
dropboxEntryBroadcast2.first, expectedMergedBroadcast.first));
|
dropboxEntryBroadcast2.first, expectedMergedBroadcast.first));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeliveryGroupPolicy_merged_multipleReceivers() {
|
||||||
|
final long now = SystemClock.elapsedRealtime();
|
||||||
|
final Pair<Intent, BroadcastOptions> dropboxEntryBroadcast1 = createDropboxBroadcast(
|
||||||
|
"TAG_A", now, 2);
|
||||||
|
final Pair<Intent, BroadcastOptions> dropboxEntryBroadcast2 = createDropboxBroadcast(
|
||||||
|
"TAG_A", now + 1000, 4);
|
||||||
|
|
||||||
|
mImpl.enqueueBroadcastLocked(makeBroadcastRecord(dropboxEntryBroadcast1.first,
|
||||||
|
dropboxEntryBroadcast1.second,
|
||||||
|
List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN),
|
||||||
|
makeManifestReceiver(PACKAGE_RED, CLASS_RED)),
|
||||||
|
false));
|
||||||
|
mImpl.enqueueBroadcastLocked(makeBroadcastRecord(dropboxEntryBroadcast2.first,
|
||||||
|
dropboxEntryBroadcast2.second,
|
||||||
|
List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN),
|
||||||
|
makeManifestReceiver(PACKAGE_RED, CLASS_RED)),
|
||||||
|
false));
|
||||||
|
|
||||||
|
final BroadcastProcessQueue greenQueue = mImpl.getProcessQueue(PACKAGE_GREEN,
|
||||||
|
getUidForPackage(PACKAGE_GREEN));
|
||||||
|
final BroadcastProcessQueue redQueue = mImpl.getProcessQueue(PACKAGE_RED,
|
||||||
|
getUidForPackage(PACKAGE_RED));
|
||||||
|
|
||||||
|
verifyPendingRecords(greenQueue,
|
||||||
|
List.of(dropboxEntryBroadcast1.first, dropboxEntryBroadcast2.first));
|
||||||
|
verifyPendingRecords(redQueue,
|
||||||
|
List.of(dropboxEntryBroadcast1.first, dropboxEntryBroadcast2.first));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeliveryGroupPolicy_sameAction_differentMatchingCriteria() {
|
public void testDeliveryGroupPolicy_sameAction_differentMatchingCriteria() {
|
||||||
final Intent closeSystemDialogs1 = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
|
final Intent closeSystemDialogs1 = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
|
||||||
|
|||||||
Reference in New Issue
Block a user