Shift execution of Intent.ACTION_LOCALE_CHANGED broadcast to a new broadcast queue dedicated to offload foreground broadcast queue
Bug: b/200765359
Test: Check broadcast related bugs such as b/200765359 wherein foreground broadcasts are taking long time to execute in case when Intent.ACTION_LOCAL_CHANGED is sent by the platform just before them
Change-Id: Ic9cf30cdb0b6d18815b043f1094fb46762fee7d6
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index e838d93..88be2d9 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -6405,6 +6405,7 @@
FLAG_RECEIVER_FROM_SHELL,
FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS,
FLAG_RECEIVER_OFFLOAD,
+ FLAG_RECEIVER_OFFLOAD_FOREGROUND,
})
@Retention(RetentionPolicy.SOURCE)
public @interface Flags {}
@@ -6450,6 +6451,7 @@
FLAG_RECEIVER_FROM_SHELL,
FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS,
FLAG_RECEIVER_OFFLOAD,
+ FLAG_RECEIVER_OFFLOAD_FOREGROUND,
})
@Retention(RetentionPolicy.SOURCE)
public @interface MutableFlags {}
@@ -6904,6 +6906,14 @@
*/
public static final int FLAG_RECEIVER_OFFLOAD = 0x80000000;
/**
+ /**
+ * If set, when sending a broadcast the recipient will run on the system dedicated queue.
+ *
+ * @hide
+ */
+ public static final int FLAG_RECEIVER_OFFLOAD_FOREGROUND = 0x00000800;
+
+ /**
* If this is an ordered broadcast, don't allow receivers to abort the broadcast.
* They can still propagate results through to later receivers, but they can not prevent
* later receivers from seeing the broadcast.
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0eed190..30a4cf5 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -643,10 +643,11 @@
final BroadcastQueue mFgBroadcastQueue;
final BroadcastQueue mBgBroadcastQueue;
- final BroadcastQueue mOffloadBroadcastQueue;
+ final BroadcastQueue mBgOffloadBroadcastQueue;
+ final BroadcastQueue mFgOffloadBroadcastQueue;
// Convenient for easy iteration over the queues. Foreground is first
// so that dispatch of foreground broadcasts gets precedence.
- final BroadcastQueue[] mBroadcastQueues = new BroadcastQueue[3];
+ final BroadcastQueue[] mBroadcastQueues = new BroadcastQueue[4];
@GuardedBy("this")
BroadcastStats mLastBroadcastStats;
@@ -657,12 +658,20 @@
TraceErrorLogger mTraceErrorLogger;
BroadcastQueue broadcastQueueForIntent(Intent intent) {
- if (isOnOffloadQueue(intent.getFlags())) {
+ if (isOnFgOffloadQueue(intent.getFlags())) {
if (DEBUG_BROADCAST_BACKGROUND) {
Slog.i(TAG_BROADCAST,
- "Broadcast intent " + intent + " on offload queue");
+ "Broadcast intent " + intent + " on foreground offload queue");
}
- return mOffloadBroadcastQueue;
+ return mFgOffloadBroadcastQueue;
+ }
+
+ if (isOnBgOffloadQueue(intent.getFlags())) {
+ if (DEBUG_BROADCAST_BACKGROUND) {
+ Slog.i(TAG_BROADCAST,
+ "Broadcast intent " + intent + " on background offload queue");
+ }
+ return mBgOffloadBroadcastQueue;
}
final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
@@ -2264,7 +2273,8 @@
mPendingStartActivityUids = new PendingStartActivityUids(mContext);
mUseFifoUiScheduling = false;
mEnableOffloadQueue = false;
- mFgBroadcastQueue = mBgBroadcastQueue = mOffloadBroadcastQueue = null;
+ mFgBroadcastQueue = mBgBroadcastQueue = mBgOffloadBroadcastQueue =
+ mFgOffloadBroadcastQueue = null;
mComponentAliasResolver = new ComponentAliasResolver(this);
}
@@ -2325,11 +2335,14 @@
"foreground", foreConstants, false);
mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
"background", backConstants, true);
- mOffloadBroadcastQueue = new BroadcastQueue(this, mHandler,
- "offload", offloadConstants, true);
+ mBgOffloadBroadcastQueue = new BroadcastQueue(this, mHandler,
+ "offload_bg", offloadConstants, true);
+ mFgOffloadBroadcastQueue = new BroadcastQueue(this, mHandler,
+ "offload_fg", foreConstants, true);
mBroadcastQueues[0] = mFgBroadcastQueue;
mBroadcastQueues[1] = mBgBroadcastQueue;
- mBroadcastQueues[2] = mOffloadBroadcastQueue;
+ mBroadcastQueues[2] = mBgOffloadBroadcastQueue;
+ mBroadcastQueues[3] = mFgOffloadBroadcastQueue;
mServices = new ActiveServices(this);
mCpHelper = new ContentProviderHelper(this, true);
@@ -12539,13 +12552,15 @@
boolean isPendingBroadcastProcessLocked(int pid) {
return mFgBroadcastQueue.isPendingBroadcastProcessLocked(pid)
|| mBgBroadcastQueue.isPendingBroadcastProcessLocked(pid)
- || mOffloadBroadcastQueue.isPendingBroadcastProcessLocked(pid);
+ || mBgOffloadBroadcastQueue.isPendingBroadcastProcessLocked(pid)
+ || mFgOffloadBroadcastQueue.isPendingBroadcastProcessLocked(pid);
}
boolean isPendingBroadcastProcessLocked(ProcessRecord app) {
return mFgBroadcastQueue.isPendingBroadcastProcessLocked(app)
|| mBgBroadcastQueue.isPendingBroadcastProcessLocked(app)
- || mOffloadBroadcastQueue.isPendingBroadcastProcessLocked(app);
+ || mBgOffloadBroadcastQueue.isPendingBroadcastProcessLocked(app)
+ || mFgOffloadBroadcastQueue.isPendingBroadcastProcessLocked(app);
}
void skipPendingBroadcastLocked(int pid) {
@@ -13994,8 +14009,10 @@
BroadcastQueue queue;
synchronized(this) {
- if (isOnOffloadQueue(flags)) {
- queue = mOffloadBroadcastQueue;
+ if (isOnFgOffloadQueue(flags)) {
+ queue = mFgOffloadBroadcastQueue;
+ } else if (isOnBgOffloadQueue(flags)) {
+ queue = mBgOffloadBroadcastQueue;
} else {
queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
? mFgBroadcastQueue : mBgBroadcastQueue;
@@ -16289,7 +16306,7 @@
Binder.getCallingUid(), Binder.getCallingPid(), UserHandle.USER_ALL);
if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) {
intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND
+ intent.addFlags(Intent.FLAG_RECEIVER_OFFLOAD_FOREGROUND
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
| Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
if (initLocale || !mProcessesReady) {
@@ -17466,7 +17483,11 @@
}
}
- private boolean isOnOffloadQueue(int flags) {
+ private boolean isOnFgOffloadQueue(int flags) {
+ return ((flags & Intent.FLAG_RECEIVER_OFFLOAD_FOREGROUND) != 0);
+ }
+
+ private boolean isOnBgOffloadQueue(int flags) {
return (mEnableOffloadQueue && ((flags & Intent.FLAG_RECEIVER_OFFLOAD) != 0));
}