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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user