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

Commit 17d71385 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Better dumpsys results of activity tasks" into sc-v2-dev am: 5a7e021c

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14928724

Change-Id: I174c34b8c94d2062dbb319bbfe6ccf682ac73b53
parents 8e92cdb5 5a7e021c
Loading
Loading
Loading
Loading
+72 −0
Original line number Diff line number Diff line
@@ -319,6 +319,7 @@ import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ResolverActivity;
import com.android.internal.content.ReferrerIntent;
import com.android.internal.os.TransferPipe;
import com.android.internal.policy.AttributeCache;
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ToBooleanFunction;
@@ -342,6 +343,7 @@ import com.google.android.collect.Sets;
import org.xmlpull.v1.XmlPullParserException;

import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
@@ -1142,6 +1144,76 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        mLetterboxUiController.dump(pw, prefix);
    }

    static boolean dumpActivity(FileDescriptor fd, PrintWriter pw, int index, ActivityRecord r,
            String prefix, String label, boolean complete, boolean brief, boolean client,
            String dumpPackage, boolean needNL, Runnable header, Task lastTask) {
        if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
            return false;
        }

        final boolean full = !brief && (complete || !r.isInHistory());
        if (needNL) {
            pw.println("");
        }
        if (header != null) {
            header.run();
        }

        String innerPrefix = prefix + "      ";
        String[] args = new String[0];
        if (lastTask != r.getTask()) {
            lastTask = r.getTask();
            pw.print(prefix);
            pw.print(full ? "* " : "  ");
            pw.println(lastTask);
            if (full) {
                lastTask.dump(pw, prefix + "  ");
            } else if (complete) {
                // Complete + brief == give a summary.  Isn't that obvious?!?
                if (lastTask.intent != null) {
                    pw.print(prefix);
                    pw.print("  ");
                    pw.println(lastTask.intent.toInsecureString());
                }
            }
        }
        pw.print(prefix); pw.print(full ? "  * " : "    "); pw.print(label);
        pw.print(" #"); pw.print(index); pw.print(": ");
        pw.println(r);
        if (full) {
            r.dump(pw, innerPrefix, true /* dumpAll */);
        } else if (complete) {
            // Complete + brief == give a summary.  Isn't that obvious?!?
            pw.print(innerPrefix);
            pw.println(r.intent.toInsecureString());
            if (r.app != null) {
                pw.print(innerPrefix);
                pw.println(r.app);
            }
        }
        if (client && r.attachedToProcess()) {
            // flush anything that is already in the PrintWriter since the thread is going
            // to write to the file descriptor directly
            pw.flush();
            try {
                TransferPipe tp = new TransferPipe();
                try {
                    r.app.getThread().dumpActivity(
                            tp.getWriteFd(), r.appToken, innerPrefix, args);
                    // Short timeout, since blocking here can deadlock with the application.
                    tp.go(fd, 2000);
                } finally {
                    tp.kill();
                }
            } catch (IOException e) {
                pw.println(innerPrefix + "Failure while dumping the activity: " + e);
            } catch (RemoteException e) {
                pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
            }
        }
        return true;
    }

    void setAppTimeTracker(AppTimeTracker att) {
        appTimeTracker = att;
    }
+6 −70
Original line number Diff line number Diff line
@@ -137,7 +137,6 @@ import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.ReferrerIntent;
import com.android.internal.os.TransferPipe;
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.function.pooled.PooledConsumer;
@@ -147,7 +146,6 @@ import com.android.server.am.UserState;
import com.android.server.wm.ActivityMetricsLogger.LaunchingState;

import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -1969,76 +1967,14 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
    static boolean dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
            String prefix, String label, boolean complete, boolean brief, boolean client,
            String dumpPackage, boolean needNL, Runnable header, Task lastTask) {
        String innerPrefix = null;
        String[] args = null;
        boolean printed = false;
        for (int i = list.size() - 1; i >= 0; i--) {
            final ActivityRecord r = list.get(i);
            if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
                continue;
            }
            if (innerPrefix == null) {
                innerPrefix = prefix + "      ";
                args = new String[0];
            }
            printed = true;
            final boolean full = !brief && (complete || !r.isInHistory());
            if (needNL) {
                pw.println("");
                needNL = false;
            }
            if (header != null) {
                header.run();
                header = null;
            }
            if (lastTask != r.getTask()) {
            ActivityRecord.dumpActivity(fd, pw, i, r, prefix, label, complete, brief,
                    client, dumpPackage, needNL, header, lastTask);
            lastTask = r.getTask();
                pw.print(prefix);
                pw.print(full ? "* " : "  ");
                pw.println(lastTask);
                if (full) {
                    lastTask.dump(pw, prefix + "  ");
                } else if (complete) {
                    // Complete + brief == give a summary.  Isn't that obvious?!?
                    if (lastTask.intent != null) {
                        pw.print(prefix); pw.print("  ");
                                pw.println(lastTask.intent.toInsecureString());
                    }
                }
            }
            pw.print(prefix); pw.print(full ? "  * " : "    "); pw.print(label);
            pw.print(" #"); pw.print(i); pw.print(": ");
            pw.println(r);
            if (full) {
                r.dump(pw, innerPrefix, true /* dumpAll */);
            } else if (complete) {
                // Complete + brief == give a summary.  Isn't that obvious?!?
                pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
                if (r.app != null) {
                    pw.print(innerPrefix); pw.println(r.app);
                }
            }
            if (client && r.attachedToProcess()) {
                // flush anything that is already in the PrintWriter since the thread is going
                // to write to the file descriptor directly
                pw.flush();
                try {
                    TransferPipe tp = new TransferPipe();
                    try {
                        r.app.getThread().dumpActivity(
                                tp.getWriteFd(), r.appToken, innerPrefix, args);
                        // Short timeout, since blocking here can deadlock with the application.
                        tp.go(fd, 2000);
                    } finally {
                        tp.kill();
                    }
                } catch (IOException e) {
                    pw.println(innerPrefix + "Failure while dumping the activity: " + e);
                } catch (RemoteException e) {
                    pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
                }
                needNL = true;
            }
            header = null;
            needNL = client && r.attachedToProcess();
        }
        return printed;
    }
+22 −80
Original line number Diff line number Diff line
@@ -99,7 +99,6 @@ import static com.android.server.wm.ActivityTaskSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityTaskSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.wm.ActivityTaskSupervisor.dumpHistoryList;
import static com.android.server.wm.ActivityTaskSupervisor.printThisActivity;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
@@ -221,7 +220,6 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -5594,89 +5592,33 @@ class Task extends TaskFragment {

    boolean dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient,
            String dumpPackage, final boolean needSep) {
        Runnable headerPrinter = () -> {
            if (needSep) {
                pw.println();
        return dump("  ", fd, pw, dumpAll, dumpClient, dumpPackage, needSep, null /* header */);
    }
            pw.println("  RootTask #" + getRootTaskId()
                    + ": type=" + activityTypeToString(getActivityType())
                    + " mode=" + windowingModeToString(getWindowingMode()));
            pw.println("  isSleeping=" + shouldSleepActivities());
            pw.println("  mBounds=" + getRequestedOverrideBounds());
            pw.println("  mCreatedByOrganizer=" + mCreatedByOrganizer);
        };

        boolean printed = false;

        if (dumpPackage == null) {
            // If we are not filtering by package, we want to print absolutely everything,
            // so always print the header even if there are no tasks/activities inside.
            headerPrinter.run();
            headerPrinter = null;
            printed = true;
    @Override
    void dumpInner(String prefix, PrintWriter pw, boolean dumpAll, String dumpPackage) {
        pw.print(prefix); pw.print("* "); pw.println(this);
        pw.println(prefix + "  mBounds=" + getRequestedOverrideBounds());
        pw.println(prefix + "  mCreatedByOrganizer=" + mCreatedByOrganizer);
        if (mLastNonFullscreenBounds != null) {
            pw.print(prefix); pw.print("  mLastNonFullscreenBounds=");
            pw.println(mLastNonFullscreenBounds);
        }

        printed |= printThisActivity(pw, getTopPausingActivity(), dumpPackage, false,
                "    mPausingActivity: ", null);
        printed |= printThisActivity(pw, getTopResumedActivity(), dumpPackage, false,
                "    mResumedActivity: ", null);
        if (dumpAll) {
            printed |= printThisActivity(pw, mLastPausedActivity, dumpPackage, false,
                    "    mLastPausedActivity: ", null);
            printThisActivity(pw, mLastPausedActivity, dumpPackage, false,
                    prefix + "  mLastPausedActivity: ", null);
        }

        printed |= dumpActivities(fd, pw, dumpAll, dumpClient, dumpPackage, false, headerPrinter);

        return printed;
        if (isLeafTask()) {
            pw.println(prefix + "  isSleeping=" + shouldSleepActivities());
            printThisActivity(pw, getTopPausingActivity(), dumpPackage, false,
                    prefix + "  topPausingActivity=", null);
            printThisActivity(pw, getTopResumedActivity(), dumpPackage, false,
                    prefix + "  topResumedActivity=", null);
            if (mMinWidth != INVALID_MIN_SIZE || mMinHeight != INVALID_MIN_SIZE) {
                pw.print(prefix); pw.print("  mMinWidth="); pw.print(mMinWidth);
                pw.print(" mMinHeight="); pw.println(mMinHeight);
            }

    private boolean dumpActivities(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
            boolean dumpClient, String dumpPackage, boolean needSep, Runnable header) {
        if (!hasChild()) {
            return false;
        }
        final AtomicBoolean printedHeader = new AtomicBoolean(false);
        final AtomicBoolean printed = new AtomicBoolean(false);
        forAllLeafTasks((task) -> {
            final String prefix = "    ";
            Runnable headerPrinter = () -> {
                printed.set(true);
                if (!printedHeader.get()) {
                    if (needSep) {
                        pw.println("");
                    }
                    if (header != null) {
                        header.run();
                    }
                    printedHeader.set(true);
                }
                pw.print(prefix); pw.print("* "); pw.println(task);
                pw.print(prefix); pw.print("  mBounds=");
                pw.println(task.getRequestedOverrideBounds());
                pw.print(prefix); pw.print("  mMinWidth="); pw.print(task.mMinWidth);
                pw.print(" mMinHeight="); pw.println(task.mMinHeight);
                if (mLastNonFullscreenBounds != null) {
                    pw.print(prefix);
                    pw.print("  mLastNonFullscreenBounds=");
                    pw.println(task.mLastNonFullscreenBounds);
                }
                task.dump(pw, prefix + "  ");
            };
            if (dumpPackage == null) {
                // If we are not filtering by package, we want to print absolutely everything,
                // so always print the header even if there are no activities inside.
                headerPrinter.run();
                headerPrinter = null;
            }
            final ArrayList<ActivityRecord> activities = new ArrayList<>();
            // Add activities by traversing the hierarchy from bottom to top, since activities
            // are dumped in reverse order in {@link ActivityTaskSupervisor#dumpHistoryList()}.
            task.forAllActivities((Consumer<ActivityRecord>) activities::add,
                    false /* traverseTopToBottom */);
            dumpHistoryList(fd, pw, activities, prefix, "Hist", true, !dumpAll, dumpClient,
                    dumpPackage, false, headerPrinter, task);
        }, true /* traverseTopToBottom */);
        return printed.get();
    }

    ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
+44 −0
Original line number Diff line number Diff line
@@ -76,6 +76,8 @@ import com.android.internal.util.function.pooled.PooledFunction;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.util.function.pooled.PooledPredicate;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
@@ -1885,4 +1887,46 @@ class TaskFragment extends WindowContainer<WindowContainer> {
        }
        return getTopChild().getActivityType();
    }

    boolean dump(String prefix, FileDescriptor fd, PrintWriter pw, boolean dumpAll,
            boolean dumpClient, String dumpPackage, final boolean needSep, Runnable header) {
        boolean printed = false;
        Runnable headerPrinter = () -> {
            if (needSep) {
                pw.println();
            }
            if (header != null) {
                header.run();
            }

            dumpInner(prefix, pw, dumpAll, dumpPackage);
        };

        if (dumpPackage == null) {
            // If we are not filtering by package, we want to print absolutely everything,
            // so always print the header even if there are no tasks/activities inside.
            headerPrinter.run();
            headerPrinter = null;
            printed = true;
        }

        for (int i = mChildren.size() - 1; i >= 0; --i) {
            WindowContainer child = mChildren.get(i);
            if (child.asTaskFragment() != null) {
                printed |= child.asTaskFragment().dump(prefix + "      ", fd, pw, dumpAll,
                        dumpClient, dumpPackage, needSep, headerPrinter);
            } else if (child.asActivityRecord() != null) {
                ActivityRecord.dumpActivity(fd, pw, i, child.asActivityRecord(), prefix + "      ",
                        "Hist ", true, !dumpAll, dumpClient, dumpPackage, false, headerPrinter,
                        getTask());
            }
        }

        return printed;
    }

    void dumpInner(String prefix, PrintWriter pw, boolean dumpAll, String dumpPackage) {
        pw.print(prefix); pw.print("* "); pw.println(this);
        pw.println(prefix + "  mBounds=" + getRequestedOverrideBounds());
    }
}