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

Commit 13c2764c authored by Dianne Hackborn's avatar Dianne Hackborn Committed by android-build-merger
Browse files

Fix issue #29006049: Add logging for implicit broadcasts

am: bc02a390

* commit 'bc02a390':
  Fix issue #29006049: Add logging for implicit broadcasts

Change-Id: Ifd88a4ce68bd9c2853d085bb10f74df682ae8ee6
parents ba3428f0 bc02a390
Loading
Loading
Loading
Loading
+117 −5
Original line number Diff line number Diff line
@@ -41,7 +41,6 @@ import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.MemInfoReader;
import com.android.internal.util.Preconditions;
import com.android.internal.util.ProgressReporter;
import com.android.server.AppOpsService;
import com.android.server.AttributeCache;
import com.android.server.DeviceIdleController;
@@ -98,7 +97,6 @@ import android.app.IUiAutomationConnection;
import android.app.IUidObserver;
import android.app.IUserSwitchObserver;
import android.app.Instrumentation;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -259,12 +257,10 @@ import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.RESIZE_MODE_PRESERVE_WINDOW;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FIRST_STATIC_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.LAST_STATIC_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
import static android.content.pm.PackageManager.FEATURE_LEANBACK_ONLY;
@@ -570,6 +566,9 @@ public final class ActivityManagerService extends ActivityManagerNative
    // so that dispatch of foreground broadcasts gets precedence.
    final BroadcastQueue[] mBroadcastQueues = new BroadcastQueue[2];
    BroadcastStats mLastBroadcastStats;
    BroadcastStats mCurBroadcastStats;
    BroadcastQueue broadcastQueueForIntent(Intent intent) {
        final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
        if (DEBUG_BROADCAST_BACKGROUND) Slog.i(TAG_BROADCAST,
@@ -13771,6 +13770,8 @@ public final class ActivityManagerService extends ActivityManagerNative
        boolean dumpAll = false;
        boolean dumpClient = false;
        boolean dumpCheckin = false;
        boolean dumpCheckinFormat = false;
        String dumpPackage = null;
        int opti = 0;
@@ -13793,6 +13794,10 @@ public final class ActivityManagerService extends ActivityManagerNative
                    return;
                }
                dumpClient = true;
            } else if ("--checkin".equals(opt)) {
                dumpCheckin = dumpCheckinFormat = true;
            } else if ("-C".equals(opt)) {
                dumpCheckinFormat = true;
            } else if ("-h".equals(opt)) {
                ActivityManagerShellCommand.dumpHelp(pw, true);
                return;
@@ -13831,6 +13836,22 @@ public final class ActivityManagerService extends ActivityManagerNative
                synchronized (this) {
                    dumpBroadcastsLocked(fd, pw, args, opti, true, dumpPackage);
                }
            } else if ("broadcast-stats".equals(cmd)) {
                String[] newArgs;
                String name;
                if (opti >= args.length) {
                    name = null;
                    newArgs = EMPTY_STRING_ARRAY;
                } else {
                    dumpPackage = args[opti];
                    opti++;
                    newArgs = new String[args.length - opti];
                    if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
                            args.length - opti);
                }
                synchronized (this) {
                    dumpBroadcastStatsLocked(fd, pw, args, opti, true, dumpPackage);
                }
            } else if ("intents".equals(cmd) || "i".equals(cmd)) {
                String[] newArgs;
                String name;
@@ -13961,7 +13982,9 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
        // No piece of data specified, dump everything.
        if (dumpClient) {
        if (dumpCheckinFormat) {
            dumpBroadcastStatsCheckinLocked(fd, pw, args, opti, dumpCheckin, dumpPackage);
        } else if (dumpClient) {
            ActiveServices.ServiceDumper sdumper;
            synchronized (this) {
                dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
@@ -13974,6 +13997,13 @@ public final class ActivityManagerService extends ActivityManagerNative
                if (dumpAll) {
                    pw.println("-------------------------------------------------------------------------------");
                }
                if (dumpAll || dumpPackage != null) {
                    dumpBroadcastStatsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
                    pw.println();
                    if (dumpAll) {
                        pw.println("-------------------------------------------------------------------------------");
                    }
                }
                dumpProvidersLocked(fd, pw, args, opti, dumpAll, dumpPackage);
                pw.println();
                if (dumpAll) {
@@ -14025,6 +14055,13 @@ public final class ActivityManagerService extends ActivityManagerNative
                if (dumpAll) {
                    pw.println("-------------------------------------------------------------------------------");
                }
                if (dumpAll || dumpPackage != null) {
                    dumpBroadcastStatsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
                    pw.println();
                    if (dumpAll) {
                        pw.println("-------------------------------------------------------------------------------");
                    }
                }
                dumpProvidersLocked(fd, pw, args, opti, dumpAll, dumpPackage);
                pw.println();
                if (dumpAll) {
@@ -14975,6 +15012,58 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
    }
    void dumpBroadcastStatsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
            int opti, boolean dumpAll, String dumpPackage) {
        if (mCurBroadcastStats == null) {
            return;
        }
        pw.println("ACTIVITY MANAGER BROADCAST STATS STATE (dumpsys activity broadcast-stats)");
        final long now = SystemClock.elapsedRealtime();
        if (mLastBroadcastStats != null) {
            pw.print("  Last stats (from ");
            TimeUtils.formatDuration(mLastBroadcastStats.mStartRealtime, now, pw);
            pw.print(" to ");
            TimeUtils.formatDuration(mLastBroadcastStats.mEndRealtime, now, pw);
            pw.print(", ");
            TimeUtils.formatDuration(mLastBroadcastStats.mEndUptime
                    - mLastBroadcastStats.mStartUptime, pw);
            pw.println(" uptime):");
            if (!mLastBroadcastStats.dumpStats(pw, "    ", dumpPackage)) {
                pw.println("    (nothing)");
            }
            pw.println();
        }
        pw.print("  Current stats (from ");
        TimeUtils.formatDuration(mCurBroadcastStats.mStartRealtime, now, pw);
        pw.print(" to now, ");
        TimeUtils.formatDuration(SystemClock.uptimeMillis()
                - mCurBroadcastStats.mStartUptime, pw);
        pw.println(" uptime):");
        if (!mCurBroadcastStats.dumpStats(pw, "    ", dumpPackage)) {
            pw.println("    (nothing)");
        }
    }
    void dumpBroadcastStatsCheckinLocked(FileDescriptor fd, PrintWriter pw, String[] args,
            int opti, boolean fullCheckin, String dumpPackage) {
        if (mCurBroadcastStats == null) {
            return;
        }
        if (mLastBroadcastStats != null) {
            mLastBroadcastStats.dumpCheckinStats(pw, dumpPackage);
            if (fullCheckin) {
                mLastBroadcastStats = null;
                return;
            }
        }
        mCurBroadcastStats.dumpCheckinStats(pw, dumpPackage);
        if (fullCheckin) {
            mCurBroadcastStats = null;
        }
    }
    void dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
            int opti, boolean dumpAll, String dumpPackage) {
        boolean needSep;
@@ -17943,11 +18032,34 @@ public final class ActivityManagerService extends ActivityManagerNative
                queue.enqueueOrderedBroadcastLocked(r);
                queue.scheduleBroadcastsLocked();
            }
        } else {
            // There was nobody interested in the broadcast, but we still want to record
            // that it happened.
            if (intent.getComponent() == null && intent.getPackage() == null
                    && (intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
                // This was an implicit broadcast... let's record it for posterity.
                addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0);
            }
        }
        return ActivityManager.BROADCAST_SUCCESS;
    }
    final void addBroadcastStatLocked(String action, String srcPackage, int receiveCount,
            int skipCount, long dispatchTime) {
        final long now = SystemClock.elapsedRealtime();
        if (mCurBroadcastStats == null ||
                (mCurBroadcastStats.mStartRealtime +(24*60*60*1000) < now)) {
            mLastBroadcastStats = mCurBroadcastStats;
            if (mLastBroadcastStats != null) {
                mLastBroadcastStats.mEndRealtime = SystemClock.elapsedRealtime();
                mLastBroadcastStats.mEndUptime = SystemClock.uptimeMillis();
            }
            mCurBroadcastStats = new BroadcastStats();
        }
        mCurBroadcastStats.addBroadcast(action, srcPackage, receiveCount, skipCount, dispatchTime);
    }
    final Intent verifyBroadcastLocked(Intent intent) {
        // Refuse possible leaked file descriptors
        if (intent != null && intent.hasFileDescriptors() == true) {
+4 −1
Original line number Diff line number Diff line
@@ -197,6 +197,7 @@ class ActivityManagerShellCommand extends ShellCommand {
            pw.println("    a[ctivities]: activity stack state");
            pw.println("    r[recents]: recent activities state");
            pw.println("    b[roadcasts] [PACKAGE_NAME] [history [-s]]: broadcast state");
            pw.println("    broadcast-stats [PACKAGE_NAME]: aggregated broadcast statistics");
            pw.println("    i[ntents] [PACKAGE_NAME]: pending intent state");
            pw.println("    p[rocesses] [PACKAGE_NAME]: process state");
            pw.println("    o[om]: out of memory management");
@@ -216,12 +217,14 @@ class ActivityManagerShellCommand extends ShellCommand {
            pw.println("  -a: include all available server state.");
            pw.println("  -c: include client state.");
            pw.println("  -p: limit output to given package.");
            pw.println("  --checkin: output checkin format, resetting data.");
            pw.println("  --C: output checkin format, not resetting data.");
        } else {
            pw.println("Activity manager (activity) commands:");
            pw.println("  help");
            pw.println("    Print this help text.");
            pw.println("  force-stop [--user <USER_ID> | all | current] <PACKAGE>");
            pw.println("    Complete stop the given application package.");
            pw.println("    Completely stop the given application package.");
            pw.println("  kill [--user <USER_ID> | all | current] <PACKAGE>");
            pw.println("    Kill all processes associated with the given application.");
            pw.println("  kill-all");
+11 −0
Original line number Diff line number Diff line
@@ -898,6 +898,12 @@ public final class BroadcastQueue {

                    // ... and on to the next...
                    addBroadcastToHistoryLocked(r);
                    if (r.intent.getComponent() == null && r.intent.getPackage() == null
                            && (r.intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
                        // This was an implicit broadcast... let's record it for posterity.
                        mService.addBroadcastStatLocked(r.intent.getAction(), r.callerPackage,
                                r.manifestCount, r.manifestSkipCount, r.finishTime-r.dispatchTime);
                    }
                    mOrderedBroadcasts.remove(0);
                    r = null;
                    looped = true;
@@ -1083,6 +1089,11 @@ public final class BroadcastQueue {
                    skip = true;
                }
            }
            if (!skip) {
                r.manifestCount++;
            } else {
                r.manifestSkipCount++;
            }
            if (r.curApp != null && r.curApp.crashing) {
                // If the target process is crashing, just skip it.
                Slog.w(TAG, "Skipping deliver ordered [" + mQueueName + "] " + r
+2 −0
Original line number Diff line number Diff line
@@ -72,6 +72,8 @@ final class BroadcastRecord extends Binder {
    IBinder receiver;       // who is currently running, null if none.
    int state;
    int anrCount;           // has this broadcast record hit any ANRs?
    int manifestCount;      // number of manifest receivers dispatched.
    int manifestSkipCount;  // number of manifest receivers skipped.
    BroadcastQueue queue;   // the outbound queue handling this broadcast

    static final int IDLE = 0;
+163 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.am;

import android.os.SystemClock;
import android.util.ArrayMap;
import android.util.TimeUtils;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public final class BroadcastStats {
    final long mStartRealtime;
    final long mStartUptime;
    long mEndRealtime;
    long mEndUptime;
    final ArrayMap<String, ActionEntry> mActions = new ArrayMap<>();

    static final Comparator<ActionEntry> ACTIONS_COMPARATOR = new Comparator<ActionEntry>() {
        @Override public int compare(ActionEntry o1, ActionEntry o2) {
            if (o1.mTotalDispatchTime < o2.mTotalDispatchTime) {
                return -1;
            }
            if (o1.mTotalDispatchTime > o2.mTotalDispatchTime) {
                return 1;
            }
            return 0;
        }
    };

    static final class ActionEntry {
        final String mAction;
        final ArrayMap<String, PackageEntry> mPackages = new ArrayMap<>();
        int mReceiveCount;
        int mSkipCount;
        long mTotalDispatchTime;
        long mMaxDispatchTime;

        ActionEntry(String action) {
            mAction = action;
        }
    }

    static final class PackageEntry {
        int mSendCount;
    }

    public BroadcastStats() {
        mStartRealtime = SystemClock.elapsedRealtime();
        mStartUptime = SystemClock.uptimeMillis();
    }

    public void addBroadcast(String action, String srcPackage, int receiveCount,
            int skipCount, long dispatchTime) {
        ActionEntry ae = mActions.get(action);
        if (ae == null) {
            ae = new ActionEntry(action);
            mActions.put(action, ae);
        }
        ae.mReceiveCount += receiveCount;
        ae.mSkipCount += skipCount;
        ae.mTotalDispatchTime += dispatchTime;
        if (ae.mMaxDispatchTime < dispatchTime) {
            ae.mMaxDispatchTime = dispatchTime;
        }
        PackageEntry pe = ae.mPackages.get(srcPackage);
        if (pe == null) {
            pe = new PackageEntry();
            ae.mPackages.put(srcPackage, pe);
        }
        pe.mSendCount++;
    }

    public boolean dumpStats(PrintWriter pw, String prefix, String dumpPackage) {
        boolean printedSomething = false;
        ArrayList<ActionEntry> actions = new ArrayList<>(mActions.size());
        for (int i=mActions.size()-1; i>=0; i--) {
            actions.add(mActions.valueAt(i));
        }
        Collections.sort(actions, ACTIONS_COMPARATOR);
        for (int i=actions.size()-1; i>=0; i--) {
            ActionEntry ae = actions.get(i);
            if (dumpPackage != null && !ae.mPackages.containsKey(dumpPackage)) {
                continue;
            }
            printedSomething = true;
            pw.print(prefix);
            pw.print(ae.mAction);
            pw.println(":");
            pw.print(prefix);
            pw.print("  Number received: ");
            pw.print(ae.mReceiveCount);
            pw.print(", skipped: ");
            pw.println(ae.mSkipCount);
            pw.print(prefix);
            pw.print("  Total dispatch time: ");
            TimeUtils.formatDuration(ae.mTotalDispatchTime, pw);
            pw.print(", max: ");
            TimeUtils.formatDuration(ae.mMaxDispatchTime, pw);
            pw.println();
            for (int j=ae.mPackages.size()-1; j>=0; j--) {
                pw.print(prefix);
                pw.print("  Package ");
                pw.print(ae.mPackages.keyAt(j));
                pw.print(": ");
                PackageEntry pe = ae.mPackages.valueAt(j);
                pw.print(pe.mSendCount);
                pw.println(" times");
            }
        }
        return printedSomething;
    }

    public void dumpCheckinStats(PrintWriter pw, String dumpPackage) {
        pw.print("broadcast-stats,1,");
        pw.print(mStartRealtime);
        pw.print(",");
        pw.print(mEndRealtime == 0 ? SystemClock.elapsedRealtime() : mEndRealtime);
        pw.print(",");
        pw.println((mEndUptime == 0 ? SystemClock.uptimeMillis() : mEndUptime) - mStartUptime);
        for (int i=mActions.size()-1; i>=0; i--) {
            ActionEntry ae = mActions.valueAt(i);
            if (dumpPackage != null && !ae.mPackages.containsKey(dumpPackage)) {
                continue;
            }
            pw.print("a,");
            pw.print(mActions.keyAt(i));
            pw.print(",");
            pw.print(ae.mReceiveCount);
            pw.print(",");
            pw.print(ae.mSkipCount);
            pw.print(",");
            pw.print(ae.mTotalDispatchTime);
            pw.print(",");
            pw.print(ae.mMaxDispatchTime);
            pw.println();
            for (int j=ae.mPackages.size()-1; j>=0; j--) {
                pw.print("p,");
                pw.print(ae.mPackages.keyAt(j));
                PackageEntry pe = ae.mPackages.valueAt(j);
                pw.print(",");
                pw.print(pe.mSendCount);
                pw.println();
            }
        }
    }
}
Loading