summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/BroadcastOptions.java31
-rw-r--r--services/core/java/com/android/server/am/BroadcastController.java25
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueueModernImpl.java25
-rw-r--r--services/core/java/com/android/server/am/BroadcastRecord.java30
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java5
5 files changed, 99 insertions, 17 deletions
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index 4db3727e3de2..0e459027102e 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -38,6 +38,7 @@ import android.os.BundleMerger;
import android.os.PowerExemptionManager;
import android.os.PowerExemptionManager.ReasonCode;
import android.os.PowerExemptionManager.TempAllowListType;
+import android.os.Process;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -76,6 +77,7 @@ public class BroadcastOptions extends ComponentOptions {
FLAG_IS_ALARM_BROADCAST,
FLAG_SHARE_IDENTITY,
FLAG_INTERACTIVE,
+ FLAG_DEBUG_LOG,
})
@Retention(RetentionPolicy.SOURCE)
public @interface Flags {}
@@ -86,6 +88,7 @@ public class BroadcastOptions extends ComponentOptions {
private static final int FLAG_IS_ALARM_BROADCAST = 1 << 3;
private static final int FLAG_SHARE_IDENTITY = 1 << 4;
private static final int FLAG_INTERACTIVE = 1 << 5;
+ private static final int FLAG_DEBUG_LOG = 1 << 6;
/**
* Change ID which is invalid.
@@ -1082,6 +1085,34 @@ public class BroadcastOptions extends ComponentOptions {
}
/**
+ * If enabled, additional debug messages for broadcast delivery will be logged.
+ *
+ * <p> This will only take effect when used by {@link Process#SHELL_UID}
+ * or {@link Process#ROOT_UID} or by apps under instrumentation.
+ *
+ * @hide
+ */
+ @NonNull
+ public BroadcastOptions setDebugLogEnabled(boolean enabled) {
+ if (enabled) {
+ mFlags |= FLAG_DEBUG_LOG;
+ } else {
+ mFlags &= ~FLAG_DEBUG_LOG;
+ }
+ return this;
+ }
+
+ /**
+ * @return if additional debug messages for broadcast delivery are enabled.
+ *
+ * @see #setDebugLogEnabled(boolean)
+ * @hide
+ */
+ public boolean isDebugLogEnabled() {
+ return (mFlags & FLAG_DEBUG_LOG) != 0;
+ }
+
+ /**
* Returns the created options as a Bundle, which can be passed to
* {@link android.content.Context#sendBroadcast(android.content.Intent)
* Context.sendBroadcast(Intent)} and related methods.
diff --git a/services/core/java/com/android/server/am/BroadcastController.java b/services/core/java/com/android/server/am/BroadcastController.java
index aa06b7ecf76c..7734ff3690a7 100644
--- a/services/core/java/com/android/server/am/BroadcastController.java
+++ b/services/core/java/com/android/server/am/BroadcastController.java
@@ -47,6 +47,8 @@ import static com.android.server.am.ActivityManagerService.UPDATE_HTTP_PROXY_MSG
import static com.android.server.am.ActivityManagerService.UPDATE_TIME_PREFERENCE_MSG;
import static com.android.server.am.ActivityManagerService.UPDATE_TIME_ZONE;
import static com.android.server.am.ActivityManagerService.checkComponentPermission;
+import static com.android.server.am.BroadcastRecord.debugLog;
+import static com.android.server.am.BroadcastRecord.intentToString;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -1017,6 +1019,13 @@ class BroadcastController {
android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS,
callingPid, callingUid, "recordResponseEventWhileInBackground");
}
+
+ if (brOptions.isDebugLogEnabled()) {
+ if (!isShellOrRoot(callingUid)
+ && (callerApp == null || !callerApp.hasActiveInstrumentation())) {
+ brOptions.setDebugLogEnabled(false);
+ }
+ }
}
// Verify that protected broadcasts are only being sent by system code,
@@ -1622,6 +1631,10 @@ class BroadcastController {
}
}
while (ir < NR) {
+ // Instant Apps cannot use FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS
+ if (callerInstantApp) {
+ intent.setFlags(intent.getFlags() & ~Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
+ }
if (receivers == null) {
receivers = new ArrayList();
}
@@ -1647,7 +1660,9 @@ class BroadcastController {
callerAppProcessState, mService.mPlatformCompat);
broadcastSentEventRecord.setBroadcastRecord(r);
- if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r);
+ if (DEBUG_BROADCAST || r.debugLog()) {
+ Slog.v(TAG_BROADCAST, "Enqueueing broadcast " + r);
+ }
queue.enqueueBroadcastLocked(r);
} else {
// There was nobody interested in the broadcast, but we still want to record
@@ -1657,11 +1672,19 @@ class BroadcastController {
// This was an implicit broadcast... let's record it for posterity.
addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0);
}
+ if (DEBUG_BROADCAST || debugLog(brOptions)) {
+ Slog.v(TAG_BROADCAST, "Skipping broadcast " + intentToString(intent)
+ + " due to no receivers");
+ }
}
return ActivityManager.BROADCAST_SUCCESS;
}
+ private boolean isShellOrRoot(int uid) {
+ return uid == SHELL_UID || uid == ROOT_UID;
+ }
+
@GuardedBy("mService")
private void scheduleCanceledResultTo(ProcessRecord resultToApp, IIntentReceiver resultTo,
Intent intent, int userId, BroadcastOptions options, int callingUid,
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index 9e4666cca140..a5f83a832c53 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -798,7 +798,9 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
mService.mOomAdjuster.mCachedAppOptimizer.freezeAppAsyncImmediateLSP(r.callerApp);
return;
}
- if (DEBUG_BROADCAST) logv("Enqueuing " + r + " for " + r.receivers.size() + " receivers");
+ if (DEBUG_BROADCAST || r.debugLog()) {
+ logv("Enqueuing " + r + " for " + r.receivers.size() + " receivers");
+ }
final int cookie = traceBegin("enqueueBroadcast");
r.applySingletonPolicy(mService);
@@ -1019,7 +1021,9 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
& Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0;
long startTimeNs = SystemClock.uptimeNanos();
- if (DEBUG_BROADCAST) logv("Scheduling " + r + " to cold " + queue);
+ if (DEBUG_BROADCAST || r.debugLog()) {
+ logv("Scheduling " + r + " to cold " + queue);
+ }
queue.app = mService.startProcessLocked(queue.processName, info, true, intentFlags,
hostingRecord, zygotePolicyFlags, allowWhileBooting, false);
if (queue.app == null) {
@@ -1176,7 +1180,9 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
}
}
- if (DEBUG_BROADCAST) logv("Scheduling " + r + " to warm " + app);
+ if (DEBUG_BROADCAST || r.debugLog()) {
+ logv("Scheduling " + r + " to warm " + app);
+ }
setDeliveryState(queue, app, r, index, receiver, BroadcastRecord.DELIVERY_SCHEDULED,
"scheduleReceiverWarmLocked");
@@ -1562,12 +1568,17 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
// bookkeeping to update for ordered broadcasts
if (!isDeliveryStateTerminal(oldDeliveryState)
&& isDeliveryStateTerminal(newDeliveryState)) {
- if (DEBUG_BROADCAST
- && newDeliveryState != BroadcastRecord.DELIVERY_DELIVERED) {
- logw("Delivery state of " + r + " to " + receiver
+ if ((DEBUG_BROADCAST && newDeliveryState != BroadcastRecord.DELIVERY_DELIVERED)
+ || r.debugLog()) {
+ final String msg = "Delivery state of " + r + " to " + receiver
+ " via " + app + " changed from "
+ deliveryStateToString(oldDeliveryState) + " to "
- + deliveryStateToString(newDeliveryState) + " because " + reason);
+ + deliveryStateToString(newDeliveryState) + " because " + reason;
+ if (newDeliveryState == BroadcastRecord.DELIVERY_DELIVERED) {
+ logv(msg);
+ } else {
+ logw(msg);
+ }
}
notifyFinishReceiver(queue, app, r, index, receiver);
diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java
index 8d0805d3fa13..c1b0a76b24af 100644
--- a/services/core/java/com/android/server/am/BroadcastRecord.java
+++ b/services/core/java/com/android/server/am/BroadcastRecord.java
@@ -1285,31 +1285,43 @@ final class BroadcastRecord extends Binder {
}
@Override
+ @NonNull
public String toString() {
if (mCachedToString == null) {
- String label = intent.getAction();
- if (label == null) {
- label = intent.toString();
- }
mCachedToString = "BroadcastRecord{" + toShortString() + "}";
}
return mCachedToString;
}
+ @NonNull
public String toShortString() {
if (mCachedToShortString == null) {
- String label = intent.getAction();
- if (label == null) {
- label = intent.toString();
- }
+ final String label = intentToString(intent);
mCachedToShortString = Integer.toHexString(System.identityHashCode(this))
+ " " + label + "/u" + userId;
}
return mCachedToShortString;
}
+ @NonNull
+ public static String intentToString(@NonNull Intent intent) {
+ String label = intent.getAction();
+ if (label == null) {
+ label = intent.toString();
+ }
+ return label;
+ }
+
+ public boolean debugLog() {
+ return debugLog(options);
+ }
+
+ public static boolean debugLog(@Nullable BroadcastOptions options) {
+ return options != null && options.isDebugLogEnabled();
+ }
+
@NeverCompile
- public void dumpDebug(ProtoOutputStream proto, long fieldId) {
+ public void dumpDebug(@NonNull ProtoOutputStream proto, long fieldId) {
long token = proto.start(fieldId);
proto.write(BroadcastRecordProto.USER_ID, userId);
proto.write(BroadcastRecordProto.INTENT_ACTION, intent.getAction());
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 49149e1fa415..1503d889c298 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -1005,6 +1005,11 @@ class ProcessRecord implements WindowProcessListener {
}
@GuardedBy(anyOf = {"mService", "mProcLock"})
+ boolean hasActiveInstrumentation() {
+ return mInstr != null;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
boolean isKilledByAm() {
return mKilledByAm;
}