Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6c5b33ff authored by Sudheer Shanka's avatar Sudheer Shanka
Browse files

Allow logging additional msgs for debugging broadcast delivery.

Bug: 385438310
Bug: 383643354
Bug: 385796541
Test: manual
Flag: EXEMPT add logs
Change-Id: I9829125fee623e89750dd4d464192a24db90358e
parent 61b95774
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -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.
@@ -1081,6 +1084,34 @@ public class BroadcastOptions extends ComponentOptions {
        return super.getPendingIntentBackgroundActivityStartMode();
    }

    /**
     * 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)
+24 −1
Original line number Diff line number Diff line
@@ -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,
+18 −7
Original line number Diff line number Diff line
@@ -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);
+21 −9
Original line number Diff line number Diff line
@@ -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) {
            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();
        }
            mCachedToShortString = Integer.toHexString(System.identityHashCode(this))
                    + " " + label + "/u" + userId;
        return label;
    }
        return mCachedToShortString;

    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());
+5 −0
Original line number Diff line number Diff line
@@ -1004,6 +1004,11 @@ class ProcessRecord implements WindowProcessListener {
        return mInstr;
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    boolean hasActiveInstrumentation() {
        return mInstr != null;
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    boolean isKilledByAm() {
        return mKilledByAm;