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

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

Change-Id: I174c34b8c94d2062dbb319bbfe6ccf682ac73b53
This commit is contained in:
TreeHugger Robot
2021-06-15 11:56:04 +00:00
committed by Automerger Merge Worker
4 changed files with 145 additions and 151 deletions

View File

@@ -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;
}

View File

@@ -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--) {
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()) {
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;
}
ActivityRecord.dumpActivity(fd, pw, i, r, prefix, label, complete, brief,
client, dumpPackage, needNL, header, lastTask);
lastTask = r.getTask();
header = null;
needNL = client && r.attachedToProcess();
}
return printed;
}

View File

@@ -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();
}
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;
}
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);
}
printed |= dumpActivities(fd, pw, dumpAll, dumpClient, dumpPackage, false, headerPrinter);
return printed;
return dump(" ", fd, pw, dumpAll, dumpClient, dumpPackage, needSep, null /* header */);
}
private boolean dumpActivities(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
boolean dumpClient, String dumpPackage, boolean needSep, Runnable header) {
if (!hasChild()) {
return false;
@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);
}
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;
if (dumpAll) {
printThisActivity(pw, mLastPausedActivity, dumpPackage, false,
prefix + " mLastPausedActivity: ", null);
}
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);
}
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) {

View File

@@ -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());
}
}