Merge changes from topic "oct20"
* changes: Enable "modern" BroadcastQueue by default. BroadcastQueue: misc fixes before dogfooding.
This commit is contained in:
@@ -13373,27 +13373,19 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
int callingPid;
|
||||
boolean instantApp;
|
||||
synchronized(this) {
|
||||
if (caller != null) {
|
||||
callerApp = getRecordForAppLOSP(caller);
|
||||
if (callerApp == null) {
|
||||
throw new SecurityException(
|
||||
"Unable to find app for caller " + caller
|
||||
+ " (pid=" + Binder.getCallingPid()
|
||||
+ ") when registering receiver " + receiver);
|
||||
}
|
||||
if (callerApp.info.uid != SYSTEM_UID
|
||||
&& !callerApp.getPkgList().containsKey(callerPackage)
|
||||
&& !"android".equals(callerPackage)) {
|
||||
throw new SecurityException("Given caller package " + callerPackage
|
||||
+ " is not running in process " + callerApp);
|
||||
}
|
||||
callingUid = callerApp.info.uid;
|
||||
callingPid = callerApp.getPid();
|
||||
} else {
|
||||
callerPackage = null;
|
||||
callingUid = Binder.getCallingUid();
|
||||
callingPid = Binder.getCallingPid();
|
||||
callerApp = getRecordForAppLOSP(caller);
|
||||
if (callerApp == null) {
|
||||
Slog.w(TAG, "registerReceiverWithFeature: no app for " + caller);
|
||||
return null;
|
||||
}
|
||||
if (callerApp.info.uid != SYSTEM_UID
|
||||
&& !callerApp.getPkgList().containsKey(callerPackage)
|
||||
&& !"android".equals(callerPackage)) {
|
||||
throw new SecurityException("Given caller package " + callerPackage
|
||||
+ " is not running in process " + callerApp);
|
||||
}
|
||||
callingUid = callerApp.info.uid;
|
||||
callingPid = callerApp.getPid();
|
||||
|
||||
instantApp = isInstantApp(callerApp, callerPackage, callingUid);
|
||||
userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
|
||||
|
||||
@@ -133,7 +133,7 @@ public class BroadcastConstants {
|
||||
*/
|
||||
public boolean MODERN_QUEUE_ENABLED = DEFAULT_MODERN_QUEUE_ENABLED;
|
||||
private static final String KEY_MODERN_QUEUE_ENABLED = "modern_queue_enabled";
|
||||
private static final boolean DEFAULT_MODERN_QUEUE_ENABLED = false;
|
||||
private static final boolean DEFAULT_MODERN_QUEUE_ENABLED = true;
|
||||
|
||||
/**
|
||||
* For {@link BroadcastQueueModernImpl}: Maximum number of process queues to
|
||||
@@ -167,7 +167,7 @@ public class BroadcastConstants {
|
||||
*/
|
||||
public long DELAY_NORMAL_MILLIS = DEFAULT_DELAY_NORMAL_MILLIS;
|
||||
private static final String KEY_DELAY_NORMAL_MILLIS = "bcast_delay_normal_millis";
|
||||
private static final long DEFAULT_DELAY_NORMAL_MILLIS = 10_000 * Build.HW_TIMEOUT_MULTIPLIER;
|
||||
private static final long DEFAULT_DELAY_NORMAL_MILLIS = 1_000;
|
||||
|
||||
/**
|
||||
* For {@link BroadcastQueueModernImpl}: Delay to apply to broadcasts
|
||||
@@ -175,7 +175,7 @@ public class BroadcastConstants {
|
||||
*/
|
||||
public long DELAY_CACHED_MILLIS = DEFAULT_DELAY_CACHED_MILLIS;
|
||||
private static final String KEY_DELAY_CACHED_MILLIS = "bcast_delay_cached_millis";
|
||||
private static final long DEFAULT_DELAY_CACHED_MILLIS = 30_000 * Build.HW_TIMEOUT_MULTIPLIER;
|
||||
private static final long DEFAULT_DELAY_CACHED_MILLIS = 10_000;
|
||||
|
||||
/**
|
||||
* For {@link BroadcastQueueModernImpl}: Maximum number of complete
|
||||
|
||||
@@ -147,12 +147,16 @@ class BroadcastProcessQueue {
|
||||
private int mCountOrdered;
|
||||
private int mCountAlarm;
|
||||
private int mCountPrioritized;
|
||||
private int mCountInteractive;
|
||||
private int mCountResultTo;
|
||||
private int mCountInstrumented;
|
||||
|
||||
private @UptimeMillisLong long mRunnableAt = Long.MAX_VALUE;
|
||||
private @Reason int mRunnableAtReason = REASON_EMPTY;
|
||||
private boolean mRunnableAtInvalidated;
|
||||
|
||||
private boolean mProcessCached;
|
||||
private boolean mProcessInstrumented;
|
||||
|
||||
private String mCachedToString;
|
||||
private String mCachedToShortString;
|
||||
@@ -296,6 +300,18 @@ class BroadcastProcessQueue {
|
||||
return didSomething;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the actively running "warm" process for this process.
|
||||
*/
|
||||
public void setProcess(@Nullable ProcessRecord app) {
|
||||
this.app = app;
|
||||
if (app != null) {
|
||||
setProcessInstrumented(app.getActiveInstrumentation() != null);
|
||||
} else {
|
||||
setProcessInstrumented(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update if this process is in the "cached" state, typically signaling that
|
||||
* broadcast dispatch should be paused or delayed.
|
||||
@@ -307,6 +323,18 @@ class BroadcastProcessQueue {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update if this process is in the "instrumented" state, typically
|
||||
* signaling that broadcast dispatch should bypass all pauses or delays, to
|
||||
* avoid holding up test suites.
|
||||
*/
|
||||
public void setProcessInstrumented(boolean instrumented) {
|
||||
if (mProcessInstrumented != instrumented) {
|
||||
mProcessInstrumented = instrumented;
|
||||
invalidateRunnableAt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if we know of an actively running "warm" process for this queue.
|
||||
*/
|
||||
@@ -315,13 +343,12 @@ class BroadcastProcessQueue {
|
||||
}
|
||||
|
||||
public int getPreferredSchedulingGroupLocked() {
|
||||
if (mCountForeground > 0 || mCountOrdered > 0 || mCountAlarm > 0) {
|
||||
// We have an important broadcast somewhere down the queue, so
|
||||
if (mCountForeground > 0) {
|
||||
// We have a foreground broadcast somewhere down the queue, so
|
||||
// boost priority until we drain them all
|
||||
return ProcessList.SCHED_GROUP_DEFAULT;
|
||||
} else if ((mActive != null)
|
||||
&& (mActive.isForeground() || mActive.ordered || mActive.alarm)) {
|
||||
// We have an important broadcast right now, so boost priority
|
||||
} else if ((mActive != null) && mActive.isForeground()) {
|
||||
// We have a foreground broadcast right now, so boost priority
|
||||
return ProcessList.SCHED_GROUP_DEFAULT;
|
||||
} else if (!isIdle()) {
|
||||
return ProcessList.SCHED_GROUP_BACKGROUND;
|
||||
@@ -389,6 +416,15 @@ class BroadcastProcessQueue {
|
||||
if (record.prioritized) {
|
||||
mCountPrioritized++;
|
||||
}
|
||||
if (record.interactive) {
|
||||
mCountInteractive++;
|
||||
}
|
||||
if (record.resultTo != null) {
|
||||
mCountResultTo++;
|
||||
}
|
||||
if (record.callerInstrumented) {
|
||||
mCountInstrumented++;
|
||||
}
|
||||
invalidateRunnableAt();
|
||||
}
|
||||
|
||||
@@ -408,6 +444,15 @@ class BroadcastProcessQueue {
|
||||
if (record.prioritized) {
|
||||
mCountPrioritized--;
|
||||
}
|
||||
if (record.interactive) {
|
||||
mCountInteractive--;
|
||||
}
|
||||
if (record.resultTo != null) {
|
||||
mCountResultTo--;
|
||||
}
|
||||
if (record.callerInstrumented) {
|
||||
mCountInstrumented--;
|
||||
}
|
||||
invalidateRunnableAt();
|
||||
}
|
||||
|
||||
@@ -553,25 +598,33 @@ class BroadcastProcessQueue {
|
||||
}
|
||||
|
||||
static final int REASON_EMPTY = 0;
|
||||
static final int REASON_CONTAINS_FOREGROUND = 1;
|
||||
static final int REASON_CONTAINS_ORDERED = 2;
|
||||
static final int REASON_CONTAINS_ALARM = 3;
|
||||
static final int REASON_CONTAINS_PRIORITIZED = 4;
|
||||
static final int REASON_CACHED = 5;
|
||||
static final int REASON_NORMAL = 6;
|
||||
static final int REASON_MAX_PENDING = 7;
|
||||
static final int REASON_BLOCKED = 8;
|
||||
static final int REASON_CACHED = 1;
|
||||
static final int REASON_NORMAL = 2;
|
||||
static final int REASON_MAX_PENDING = 3;
|
||||
static final int REASON_BLOCKED = 4;
|
||||
static final int REASON_INSTRUMENTED = 5;
|
||||
static final int REASON_CONTAINS_FOREGROUND = 10;
|
||||
static final int REASON_CONTAINS_ORDERED = 11;
|
||||
static final int REASON_CONTAINS_ALARM = 12;
|
||||
static final int REASON_CONTAINS_PRIORITIZED = 13;
|
||||
static final int REASON_CONTAINS_INTERACTIVE = 14;
|
||||
static final int REASON_CONTAINS_RESULT_TO = 15;
|
||||
static final int REASON_CONTAINS_INSTRUMENTED = 16;
|
||||
|
||||
@IntDef(flag = false, prefix = { "REASON_" }, value = {
|
||||
REASON_EMPTY,
|
||||
REASON_CONTAINS_FOREGROUND,
|
||||
REASON_CONTAINS_ORDERED,
|
||||
REASON_CONTAINS_ALARM,
|
||||
REASON_CONTAINS_PRIORITIZED,
|
||||
REASON_CACHED,
|
||||
REASON_NORMAL,
|
||||
REASON_MAX_PENDING,
|
||||
REASON_BLOCKED,
|
||||
REASON_INSTRUMENTED,
|
||||
REASON_CONTAINS_FOREGROUND,
|
||||
REASON_CONTAINS_ORDERED,
|
||||
REASON_CONTAINS_ALARM,
|
||||
REASON_CONTAINS_PRIORITIZED,
|
||||
REASON_CONTAINS_INTERACTIVE,
|
||||
REASON_CONTAINS_RESULT_TO,
|
||||
REASON_CONTAINS_INSTRUMENTED,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Reason {}
|
||||
@@ -579,14 +632,18 @@ class BroadcastProcessQueue {
|
||||
static @NonNull String reasonToString(@Reason int reason) {
|
||||
switch (reason) {
|
||||
case REASON_EMPTY: return "EMPTY";
|
||||
case REASON_CONTAINS_FOREGROUND: return "CONTAINS_FOREGROUND";
|
||||
case REASON_CONTAINS_ORDERED: return "CONTAINS_ORDERED";
|
||||
case REASON_CONTAINS_ALARM: return "CONTAINS_ALARM";
|
||||
case REASON_CONTAINS_PRIORITIZED: return "CONTAINS_PRIORITIZED";
|
||||
case REASON_CACHED: return "CACHED";
|
||||
case REASON_NORMAL: return "NORMAL";
|
||||
case REASON_MAX_PENDING: return "MAX_PENDING";
|
||||
case REASON_BLOCKED: return "BLOCKED";
|
||||
case REASON_INSTRUMENTED: return "INSTRUMENTED";
|
||||
case REASON_CONTAINS_FOREGROUND: return "CONTAINS_FOREGROUND";
|
||||
case REASON_CONTAINS_ORDERED: return "CONTAINS_ORDERED";
|
||||
case REASON_CONTAINS_ALARM: return "CONTAINS_ALARM";
|
||||
case REASON_CONTAINS_PRIORITIZED: return "CONTAINS_PRIORITIZED";
|
||||
case REASON_CONTAINS_INTERACTIVE: return "CONTAINS_INTERACTIVE";
|
||||
case REASON_CONTAINS_RESULT_TO: return "CONTAINS_RESULT_TO";
|
||||
case REASON_CONTAINS_INSTRUMENTED: return "CONTAINS_INSTRUMENTED";
|
||||
default: return Integer.toString(reason);
|
||||
}
|
||||
}
|
||||
@@ -631,6 +688,18 @@ class BroadcastProcessQueue {
|
||||
} else if (mCountPrioritized > 0) {
|
||||
mRunnableAt = runnableAt;
|
||||
mRunnableAtReason = REASON_CONTAINS_PRIORITIZED;
|
||||
} else if (mCountInteractive > 0) {
|
||||
mRunnableAt = runnableAt;
|
||||
mRunnableAtReason = REASON_CONTAINS_INTERACTIVE;
|
||||
} else if (mCountResultTo > 0) {
|
||||
mRunnableAt = runnableAt;
|
||||
mRunnableAtReason = REASON_CONTAINS_RESULT_TO;
|
||||
} else if (mCountInstrumented > 0) {
|
||||
mRunnableAt = runnableAt;
|
||||
mRunnableAtReason = REASON_CONTAINS_INSTRUMENTED;
|
||||
} else if (mProcessInstrumented) {
|
||||
mRunnableAt = runnableAt;
|
||||
mRunnableAtReason = REASON_INSTRUMENTED;
|
||||
} else if (mProcessCached) {
|
||||
mRunnableAt = runnableAt + constants.DELAY_CACHED_MILLIS;
|
||||
mRunnableAtReason = REASON_CACHED;
|
||||
|
||||
@@ -441,7 +441,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
// relevant per-process queue
|
||||
final BroadcastProcessQueue queue = getProcessQueue(app);
|
||||
if (queue != null) {
|
||||
queue.app = app;
|
||||
queue.setProcess(app);
|
||||
}
|
||||
|
||||
boolean didSomething = false;
|
||||
@@ -478,7 +478,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
// relevant per-process queue
|
||||
final BroadcastProcessQueue queue = getProcessQueue(app);
|
||||
if (queue != null) {
|
||||
queue.app = null;
|
||||
queue.setProcess(null);
|
||||
}
|
||||
|
||||
if ((mRunningColdStart != null) && (mRunningColdStart == queue)) {
|
||||
@@ -816,19 +816,21 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
}
|
||||
|
||||
final BroadcastRecord r = queue.getActive();
|
||||
r.resultCode = resultCode;
|
||||
r.resultData = resultData;
|
||||
r.resultExtras = resultExtras;
|
||||
if (!r.isNoAbort()) {
|
||||
r.resultAbort = resultAbort;
|
||||
}
|
||||
if (r.ordered) {
|
||||
r.resultCode = resultCode;
|
||||
r.resultData = resultData;
|
||||
r.resultExtras = resultExtras;
|
||||
if (!r.isNoAbort()) {
|
||||
r.resultAbort = resultAbort;
|
||||
}
|
||||
|
||||
// When the caller aborted an ordered broadcast, we mark all remaining
|
||||
// receivers as skipped
|
||||
if (r.ordered && r.resultAbort) {
|
||||
for (int i = r.terminalCount + 1; i < r.receivers.size(); i++) {
|
||||
setDeliveryState(null, null, r, i, r.receivers.get(i),
|
||||
BroadcastRecord.DELIVERY_SKIPPED);
|
||||
// When the caller aborted an ordered broadcast, we mark all
|
||||
// remaining receivers as skipped
|
||||
if (r.resultAbort) {
|
||||
for (int i = r.terminalCount + 1; i < r.receivers.size(); i++) {
|
||||
setDeliveryState(null, null, r, i, r.receivers.get(i),
|
||||
BroadcastRecord.DELIVERY_SKIPPED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -925,7 +927,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
notifyFinishReceiver(queue, r, index, receiver);
|
||||
|
||||
// When entire ordered broadcast finished, deliver final result
|
||||
if (r.ordered && (r.terminalCount == r.receivers.size())) {
|
||||
final boolean recordFinished = (r.terminalCount == r.receivers.size());
|
||||
if (recordFinished) {
|
||||
scheduleResultTo(r);
|
||||
}
|
||||
|
||||
@@ -1217,7 +1220,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
|
||||
|
||||
private void updateWarmProcess(@NonNull BroadcastProcessQueue queue) {
|
||||
if (!queue.isProcessWarm()) {
|
||||
queue.app = mService.getProcessRecordLocked(queue.processName, queue.uid);
|
||||
queue.setProcess(mService.getProcessRecordLocked(queue.processName, queue.uid));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ final class BroadcastRecord extends Binder {
|
||||
final int callingPid; // the pid of who sent this
|
||||
final int callingUid; // the uid of who sent this
|
||||
final boolean callerInstantApp; // caller is an Instant App?
|
||||
final boolean callerInstrumented; // caller is being instrumented
|
||||
final boolean ordered; // serialize the send to receivers?
|
||||
final boolean sticky; // originated from existing sticky data?
|
||||
final boolean alarm; // originated from an alarm triggering?
|
||||
@@ -365,6 +366,8 @@ final class BroadcastRecord extends Binder {
|
||||
callingPid = _callingPid;
|
||||
callingUid = _callingUid;
|
||||
callerInstantApp = _callerInstantApp;
|
||||
callerInstrumented = (_callerApp != null)
|
||||
? (_callerApp.getActiveInstrumentation() != null) : false;
|
||||
resolvedType = _resolvedType;
|
||||
requiredPermissions = _requiredPermissions;
|
||||
excludedPermissions = _excludedPermissions;
|
||||
@@ -411,6 +414,7 @@ final class BroadcastRecord extends Binder {
|
||||
callingPid = from.callingPid;
|
||||
callingUid = from.callingUid;
|
||||
callerInstantApp = from.callerInstantApp;
|
||||
callerInstrumented = from.callerInstrumented;
|
||||
ordered = from.ordered;
|
||||
sticky = from.sticky;
|
||||
initialSticky = from.initialSticky;
|
||||
|
||||
@@ -549,25 +549,31 @@ public class BroadcastQueueTest {
|
||||
receivers, false, null, null, userId);
|
||||
}
|
||||
|
||||
private BroadcastRecord makeOrderedBroadcastRecord(Intent intent, ProcessRecord callerApp,
|
||||
List<Object> receivers, IIntentReceiver orderedResultTo, Bundle orderedExtras) {
|
||||
return makeBroadcastRecord(intent, callerApp, BroadcastOptions.makeBasic(),
|
||||
receivers, true, orderedResultTo, orderedExtras, UserHandle.USER_SYSTEM);
|
||||
}
|
||||
|
||||
private BroadcastRecord makeBroadcastRecord(Intent intent, ProcessRecord callerApp,
|
||||
BroadcastOptions options, List<Object> receivers) {
|
||||
return makeBroadcastRecord(intent, callerApp, options,
|
||||
receivers, false, null, null, UserHandle.USER_SYSTEM);
|
||||
}
|
||||
|
||||
private BroadcastRecord makeBroadcastRecord(Intent intent, ProcessRecord callerApp,
|
||||
List<Object> receivers, IIntentReceiver resultTo) {
|
||||
return makeBroadcastRecord(intent, callerApp, BroadcastOptions.makeBasic(),
|
||||
receivers, false, resultTo, null, UserHandle.USER_SYSTEM);
|
||||
}
|
||||
|
||||
private BroadcastRecord makeOrderedBroadcastRecord(Intent intent, ProcessRecord callerApp,
|
||||
List<Object> receivers, IIntentReceiver resultTo, Bundle resultExtras) {
|
||||
return makeBroadcastRecord(intent, callerApp, BroadcastOptions.makeBasic(),
|
||||
receivers, true, resultTo, resultExtras, UserHandle.USER_SYSTEM);
|
||||
}
|
||||
|
||||
private BroadcastRecord makeBroadcastRecord(Intent intent, ProcessRecord callerApp,
|
||||
BroadcastOptions options, List<Object> receivers, boolean ordered,
|
||||
IIntentReceiver orderedResultTo, Bundle orderedExtras, int userId) {
|
||||
IIntentReceiver resultTo, Bundle resultExtras, int userId) {
|
||||
return new BroadcastRecord(mQueue, intent, callerApp, callerApp.info.packageName, null,
|
||||
callerApp.getPid(), callerApp.info.uid, false, null, null, null, null,
|
||||
AppOpsManager.OP_NONE, options, receivers, callerApp, orderedResultTo,
|
||||
Activity.RESULT_OK, null, orderedExtras, ordered, false, false, userId, false, null,
|
||||
AppOpsManager.OP_NONE, options, receivers, callerApp, resultTo,
|
||||
Activity.RESULT_OK, null, resultExtras, ordered, false, false, userId, false, null,
|
||||
false, null);
|
||||
}
|
||||
|
||||
@@ -1346,6 +1352,26 @@ public class BroadcastQueueTest {
|
||||
anyBoolean(), eq(UserHandle.USER_SYSTEM), anyInt());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that we deliver results for unordered broadcasts.
|
||||
*/
|
||||
@Test
|
||||
public void testUnordered_ResultTo() throws Exception {
|
||||
final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED);
|
||||
final IApplicationThread callerThread = callerApp.getThread();
|
||||
|
||||
final IIntentReceiver resultTo = mock(IIntentReceiver.class);
|
||||
final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
|
||||
enqueueBroadcast(makeBroadcastRecord(airplane, callerApp,
|
||||
List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN),
|
||||
makeManifestReceiver(PACKAGE_BLUE, CLASS_BLUE)), resultTo));
|
||||
|
||||
waitForIdle();
|
||||
verify(callerThread).scheduleRegisteredReceiver(any(), argThat(filterEquals(airplane)),
|
||||
eq(Activity.RESULT_OK), any(), any(), eq(false),
|
||||
anyBoolean(), eq(UserHandle.USER_SYSTEM), anyInt());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that we're not surprised by a process attempting to finishing a
|
||||
* broadcast when none is in progress.
|
||||
|
||||
Reference in New Issue
Block a user