summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/provider/Settings.java1
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java2
-rw-r--r--services/core/java/com/android/server/am/BroadcastConstants.java10
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueue.java63
4 files changed, 55 insertions, 21 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 48957dcd7970..8acdc8c1255f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11946,6 +11946,7 @@ public final class Settings {
* bcast_deferral (long)
* bcast_deferral_decay_factor (float)
* bcast_deferral_floor (long)
+ * bcast_allow_bg_activity_start_timeout (long)
* </pre>
*
* @hide
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index bbef6c51f01c..f2902b172502 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15039,7 +15039,7 @@ public class ActivityManagerService extends IActivityManager.Stub
oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,
oldRecord.intent,
Activity.RESULT_CANCELED, null, null,
- false, false, oldRecord.userId, oldRecord);
+ false, false, oldRecord.userId);
} catch (RemoteException e) {
Slog.w(TAG, "Failure ["
+ queue.mQueueName + "] sending broadcast result of "
diff --git a/services/core/java/com/android/server/am/BroadcastConstants.java b/services/core/java/com/android/server/am/BroadcastConstants.java
index 820caf12ac84..be17b1bc600c 100644
--- a/services/core/java/com/android/server/am/BroadcastConstants.java
+++ b/services/core/java/com/android/server/am/BroadcastConstants.java
@@ -38,6 +38,8 @@ public class BroadcastConstants {
static final String KEY_DEFERRAL = "bcast_deferral";
static final String KEY_DEFERRAL_DECAY_FACTOR = "bcast_deferral_decay_factor";
static final String KEY_DEFERRAL_FLOOR = "bcast_deferral_floor";
+ static final String KEY_ALLOW_BG_ACTIVITY_START_TIMEOUT =
+ "bcast_allow_bg_activity_start_timeout";
// All time intervals are in milliseconds
private static final long DEFAULT_TIMEOUT = 10_000;
@@ -45,6 +47,7 @@ public class BroadcastConstants {
private static final long DEFAULT_DEFERRAL = 5_000;
private static final float DEFAULT_DEFERRAL_DECAY_FACTOR = 0.75f;
private static final long DEFAULT_DEFERRAL_FLOOR = 0;
+ private static final long DEFAULT_ALLOW_BG_ACTIVITY_START_TIMEOUT = 10_000;
// All time constants are in milliseconds
@@ -59,6 +62,8 @@ public class BroadcastConstants {
public float DEFERRAL_DECAY_FACTOR = DEFAULT_DEFERRAL_DECAY_FACTOR;
// Minimum that the deferral time can decay to until the backlog fully clears
public long DEFERRAL_FLOOR = DEFAULT_DEFERRAL_FLOOR;
+ // For how long after a whitelisted receiver's start its process can start a background activity
+ public long ALLOW_BG_ACTIVITY_START_TIMEOUT = DEFAULT_ALLOW_BG_ACTIVITY_START_TIMEOUT;
// Settings override tracking for this instance
private String mSettingsKey;
@@ -113,6 +118,8 @@ public class BroadcastConstants {
DEFERRAL_DECAY_FACTOR = mParser.getFloat(KEY_DEFERRAL_DECAY_FACTOR,
DEFERRAL_DECAY_FACTOR);
DEFERRAL_FLOOR = mParser.getLong(KEY_DEFERRAL_FLOOR, DEFERRAL_FLOOR);
+ ALLOW_BG_ACTIVITY_START_TIMEOUT = mParser.getLong(KEY_ALLOW_BG_ACTIVITY_START_TIMEOUT,
+ ALLOW_BG_ACTIVITY_START_TIMEOUT);
}
}
@@ -145,6 +152,9 @@ public class BroadcastConstants {
pw.print(" "); pw.print(KEY_DEFERRAL_FLOOR); pw.print(" = ");
TimeUtils.formatDuration(DEFERRAL_FLOOR, pw);
+
+ pw.print(" "); pw.print(KEY_ALLOW_BG_ACTIVITY_START_TIMEOUT); pw.print(" = ");
+ TimeUtils.formatDuration(ALLOW_BG_ACTIVITY_START_TIMEOUT, pw);
pw.println();
}
}
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index d9ea1da79f56..efb1c445925f 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -74,9 +74,6 @@ public final class BroadcastQueue {
static final int MAX_BROADCAST_SUMMARY_HISTORY
= ActivityManager.isLowRamDeviceStatic() ? 25 : 300;
- // For how long after a whitelisted receiver's start its process can start a background activity
- private static final int RECEIVER_BG_ACTIVITY_START_TIMEOUT_MS = 10_000;
-
final ActivityManagerService mService;
/**
@@ -310,9 +307,6 @@ public final class BroadcastQueue {
r.curApp = app;
app.curReceivers.add(r);
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
- if (r.allowBackgroundActivityStarts) {
- app.addAllowBackgroundActivityStartsToken(r);
- }
mService.mProcessList.updateLruProcessLocked(app, false, null);
if (!skipOomAdj) {
mService.updateOomAdjLocked();
@@ -454,8 +448,25 @@ public final class BroadcastQueue {
Slog.w(TAG, "finishReceiver [" + mQueueName + "] called but state is IDLE");
}
if (r.allowBackgroundActivityStarts && r.curApp != null) {
- r.curApp.removeAllowBackgroundActivityStartsToken(r);
- }
+ if (elapsed > mConstants.ALLOW_BG_ACTIVITY_START_TIMEOUT) {
+ // if the receiver has run for more than allowed bg activity start timeout,
+ // just remove the token for this process now and we're done
+ r.curApp.removeAllowBackgroundActivityStartsToken(r);
+ } else {
+ // the receiver had run for less than allowed bg activity start timeout,
+ // so allow the process to still start activities from bg for some more time
+ String msgToken = (r.curApp.toShortString() + r.toString()).intern();
+ // first, if there exists a past scheduled request to remove this token, drop
+ // that request - we don't want the token to be swept from under our feet...
+ mHandler.removeCallbacksAndMessages(msgToken);
+ // ...then schedule the removal of the token after the extended timeout
+ mHandler.postAtTime(() -> {
+ if (r.curApp != null) {
+ r.curApp.removeAllowBackgroundActivityStartsToken(r);
+ }
+ }, msgToken, (r.receiverTime + mConstants.ALLOW_BG_ACTIVITY_START_TIMEOUT));
+ }
+ }
// If we're abandoning this broadcast before any receivers were actually spun up,
// nextReceiver is zero; in which case time-to-process bookkeeping doesn't apply.
if (r.nextReceiver > 0) {
@@ -554,7 +565,7 @@ public final class BroadcastQueue {
void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
- boolean ordered, boolean sticky, int sendingUser, BroadcastRecord br)
+ boolean ordered, boolean sticky, int sendingUser)
throws RemoteException {
// Send the intent to the receiver asynchronously using one-way binder calls.
if (app != null) {
@@ -562,15 +573,6 @@ public final class BroadcastQueue {
// If we have an app thread, do the call through that so it is
// correctly ordered with other one-way calls.
try {
- if (br.allowBackgroundActivityStarts) {
- app.addAllowBackgroundActivityStartsToken(br);
- // schedule removal of the whitelisting token after the timeout
- mHandler.postDelayed(() -> {
- if (app != null) {
- app.removeAllowBackgroundActivityStartsToken(br);
- }
- }, RECEIVER_BG_ACTIVITY_START_TIMEOUT_MS);
- }
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.getReportedProcState());
// TODO: Uncomment this when (b/28322359) is fixed and we aren't getting
@@ -794,9 +796,13 @@ public final class BroadcastQueue {
skipReceiverLocked(r);
}
} else {
+ if (r.receiverTime == 0) {
+ r.receiverTime = SystemClock.uptimeMillis();
+ }
+ maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode, r.resultData,
- r.resultExtras, r.ordered, r.initialSticky, r.userId, r);
+ r.resultExtras, r.ordered, r.initialSticky, r.userId);
}
if (ordered) {
r.state = BroadcastRecord.CALL_DONE_RECEIVE;
@@ -1100,7 +1106,7 @@ public final class BroadcastQueue {
}
performReceiveLocked(r.callerApp, r.resultTo,
new Intent(r.intent), r.resultCode,
- r.resultData, r.resultExtras, false, false, r.userId, r);
+ r.resultData, r.resultExtras, false, false, r.userId);
// Set this to null so that the reference
// (local and remote) isn't kept in the mBroadcastHistory.
r.resultTo = null;
@@ -1255,6 +1261,9 @@ public final class BroadcastQueue {
r.state = BroadcastRecord.IDLE;
scheduleBroadcastsLocked();
} else {
+ if (filter.receiverList != null) {
+ maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
+ }
if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
scheduleTempWhitelistLocked(filter.owningUid,
brOptions.getTemporaryAppWhitelistDuration(), r);
@@ -1561,6 +1570,7 @@ public final class BroadcastQueue {
try {
app.addPackage(info.activityInfo.packageName,
info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
+ maybeAddAllowBackgroundActivityStartsToken(app, r);
processCurBroadcastLocked(r, app, skipOomAdj);
return;
} catch (RemoteException e) {
@@ -1611,10 +1621,23 @@ public final class BroadcastQueue {
return;
}
+ maybeAddAllowBackgroundActivityStartsToken(r.curApp, r);
mPendingBroadcast = r;
mPendingBroadcastRecvIndex = recIdx;
}
+ private void maybeAddAllowBackgroundActivityStartsToken(ProcessRecord proc, BroadcastRecord r) {
+ if (r == null || proc == null || !r.allowBackgroundActivityStarts) {
+ return;
+ }
+ String msgToken = (proc.toShortString() + r.toString()).intern();
+ // first, if there exists a past scheduled request to remove this token, drop
+ // that request - we don't want the token to be swept from under our feet...
+ mHandler.removeCallbacksAndMessages(msgToken);
+ // ...then add the token
+ proc.addAllowBackgroundActivityStartsToken(r);
+ }
+
final void setBroadcastTimeoutLocked(long timeoutTime) {
if (! mPendingBroadcastTimeoutMessage) {
Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG, this);