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

Commit 97c8746c authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Adding shell command to dump view hierarchies of all visible windows"

parents 28c7e9c2 b217bded
Loading
Loading
Loading
Loading
+19 −1
Original line number Diff line number Diff line
@@ -415,6 +415,11 @@ public class ViewDebug {
    private static final String REMOTE_COMMAND_CAPTURE = "CAPTURE";
    private static final String REMOTE_COMMAND_DUMP = "DUMP";
    private static final String REMOTE_COMMAND_DUMP_THEME = "DUMP_THEME";
    /**
     * Similar to REMOTE_COMMAND_DUMP but uses ViewHierarchyEncoder instead of flat text
     * @hide
     */
    public static final String REMOTE_COMMAND_DUMP_ENCODED = "DUMP_ENCODED";
    private static final String REMOTE_COMMAND_INVALIDATE = "INVALIDATE";
    private static final String REMOTE_COMMAND_REQUEST_LAYOUT = "REQUEST_LAYOUT";
    private static final String REMOTE_PROFILE = "PROFILE";
@@ -527,7 +532,6 @@ public class ViewDebug {
    @UnsupportedAppUsage
    static void dispatchCommand(View view, String command, String parameters,
            OutputStream clientStream) throws IOException {

        // Paranoid but safe...
        view = view.getRootView();

@@ -535,6 +539,8 @@ public class ViewDebug {
            dump(view, false, true, clientStream);
        } else if (REMOTE_COMMAND_DUMP_THEME.equalsIgnoreCase(command)) {
            dumpTheme(view, clientStream);
        } else if (REMOTE_COMMAND_DUMP_ENCODED.equalsIgnoreCase(command)) {
            dumpEncoded(view, clientStream);
        } else if (REMOTE_COMMAND_CAPTURE_LAYERS.equalsIgnoreCase(command)) {
            captureLayers(view, new DataOutputStream(clientStream));
        } else {
@@ -1198,6 +1204,18 @@ public class ViewDebug {
        encoder.endStream();
    }

    private static void dumpEncoded(@NonNull final View view, @NonNull OutputStream out)
            throws IOException {
        ByteArrayOutputStream baOut = new ByteArrayOutputStream();

        final ViewHierarchyEncoder encoder = new ViewHierarchyEncoder(baOut);
        encoder.addProperty("window:left", view.mAttachInfo.mWindowLeft);
        encoder.addProperty("window:top", view.mAttachInfo.mWindowTop);
        view.encode(encoder);
        encoder.endStream();
        out.write(baOut.toByteArray());
    }

    /**
     * Dumps the theme attributes from the given View.
     * @hide
+56 −0
Original line number Diff line number Diff line
@@ -20,19 +20,27 @@ import static android.os.Build.IS_USER;

import android.graphics.Point;
import android.graphics.Rect;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ShellCommand;
import android.os.UserHandle;
import android.util.DisplayMetrics;
import android.util.Pair;
import android.view.Display;
import android.view.IWindowManager;
import android.view.Surface;
import android.view.ViewDebug;

import com.android.internal.os.ByteTransferPipe;
import com.android.server.protolog.ProtoLogImpl;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * ShellCommands for WindowManagerService.
@@ -81,6 +89,8 @@ public class WindowManagerShellCommand extends ShellCommand {
                    return runSetDisplayUserRotation(pw);
                case "set-fix-to-user-rotation":
                    return runSetFixToUserRotation(pw);
                case "dump-visible-window-views":
                    return runDumpVisibleWindowViews(pw);
                default:
                    return handleDefaultCommands(cmd);
            }
@@ -341,6 +351,50 @@ public class WindowManagerShellCommand extends ShellCommand {
        return 0;
    }

    private int runDumpVisibleWindowViews(PrintWriter pw) {
        ParcelFileDescriptor outFile = openFileForSystem(getNextArgRequired(), "w");
        try (ZipOutputStream out = new ZipOutputStream(
                new ParcelFileDescriptor.AutoCloseOutputStream(outFile))) {
            ArrayList<Pair<String, ByteTransferPipe>> requestList = new ArrayList<>();
            synchronized (mInternal.mGlobalLock) {
                // Request dump from all windows parallelly before writing to disk.
                mInternal.mRoot.forAllWindows(w -> {
                    if (w.isVisible()) {
                        ByteTransferPipe pipe = null;
                        try {
                            pipe = new ByteTransferPipe();
                            w.mClient.executeCommand(ViewDebug.REMOTE_COMMAND_DUMP_ENCODED, null,
                                    pipe.getWriteFd());
                            requestList.add(Pair.create(w.getName(), pipe));
                        } catch (IOException | RemoteException e) {
                            // Skip this window
                            pw.println("Error for window " + w.getName() + " : " + e.getMessage());
                            if (pipe != null) {
                                pipe.kill();
                            }
                        }
                    }
                }, false /* traverseTopToBottom */);
            }
            for (Pair<String, ByteTransferPipe> entry : requestList) {
                byte[] data;
                try {
                    data = entry.second.get();
                } catch (IOException e) {
                    // Ignore this window
                    pw.println(
                            "Error for window " + entry.first + " : " + e.getMessage());
                    continue;
                }
                out.putNextEntry(new ZipEntry(entry.first));
                out.write(data);
            }
        } catch (IOException e) {
            pw.println("Error fetching dump " + e.getMessage());
        }
        return 0;
    }

    @Override
    public void onHelp() {
        PrintWriter pw = getOutPrintWriter();
@@ -360,6 +414,8 @@ public class WindowManagerShellCommand extends ShellCommand {
        pw.println("    Dismiss the keyguard, prompting user for auth if necessary.");
        pw.println("  set-user-rotation [free|lock] [-d DISPLAY_ID] [rotation]");
        pw.println("    Set user rotation mode and user rotation.");
        pw.println("  dump-visible-window-views out-file");
        pw.println("    Dumps the encoded view hierarchies of visible windows");
        pw.println("  set-fix-to-user-rotation [-d DISPLAY_ID] [enabled|disabled]");
        pw.println("    Enable or disable rotating display for app requested orientation.");
        if (!IS_USER) {