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

Commit 3b716249 authored by Robert Carr's avatar Robert Carr
Browse files

WindowManager RemoteSurfaceTrace infrastructure

Add "wm surface-trace" command which enables tracing of surface
commands to be switched on at runtime. Primarily intended for use
by WM CTS tests. First target in CTS will be to use show/hide
events to eliminate polling in WM tests and increase speed. Next up
looking at things like verifying various transitions and relaunch
scenarios are flicker free. Later we may want to look at a smarter
or more structured format...but it's really not much hassle to parse
the commands off a pipe so I wanted to get us started.

Test: cts-tradefed run singleCommand cts -o --module CtsWindowManagerHostTestCases --test android.server.cts.SurfaceViewMovementTests#testSurfaceMovesWithParent
Change-Id: I1ff912c405a6cb9996ee9b6e2c465d57706191ba
parent fcdcf7f6
Loading
Loading
Loading
Loading
+57 −1
Original line number Diff line number Diff line
@@ -21,16 +21,22 @@ package com.android.commands.wm;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.AndroidException;
import android.util.DisplayMetrics;
import android.system.Os;
import android.view.Display;
import android.view.IWindowManager;
import com.android.internal.os.BaseCommand;

import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.DataInputStream;
import java.io.PrintStream;
import java.lang.Runtime;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@@ -69,7 +75,9 @@ public class Wm extends BaseCommand {
                "wm screen-capture: enable/disable screen capture.\n" +
                "\n" +
                "wm dismiss-keyguard: dismiss the keyguard, prompting the user for auth if " +
                "necessary.\n"
                "necessary.\n" +
                "\n" +
                "wm surface-trace: log surface commands to stdout.\n"
                );
    }

@@ -96,12 +104,60 @@ public class Wm extends BaseCommand {
            runSetScreenCapture();
        } else if (op.equals("dismiss-keyguard")) {
            runDismissKeyguard();
        } else if (op.equals("surface-trace")) {
            runSurfaceTrace();
        } else {
            showError("Error: unknown command '" + op + "'");
            return;
        }
    }

    private void parseTrace(String next, DataInputStream is) throws Exception {
        switch (next) {
        case "Alpha":
            System.out.println(is.readFloat());
            break;
        case "Layer":
            System.out.println(is.readInt());
            break;
        case "Position":
            System.out.println(is.readFloat() + ", " + is.readFloat());
            break;
        case "Size":
            System.out.println(is.readInt() + ", " + is.readInt());
            break;
        case "LayerStack":
            System.out.println(is.readInt());
            break;
        case "Matrix":
            System.out.println(is.readFloat() + "," + is.readFloat() + "," + is.readFloat() + "," +
                    is.readFloat());
            break;
        case "Hide":
        case "Show":
        case "GeometryAppliesWithResize":
            break;
        }
    }

    private void runSurfaceTrace() throws Exception {
        ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe();

        mWm.enableSurfaceTrace(fds[1]);
        DataInputStream is = new DataInputStream(new FileInputStream(fds[0].getFileDescriptor()));

        try {
            while (true) {
                String cmd = is.readUTF();
                String window = is.readUTF();
                System.out.print(cmd + "(" + window + "): ");
                parseTrace(cmd, is);
            }
        } finally {
            mWm.disableSurfaceTrace();
        }
    }

    private void runSetScreenCapture() throws Exception {
        String userIdStr = nextArg();
        String enableStr = nextArg();
+8 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.IRemoteCallback;
import android.os.ParcelFileDescriptor;
import android.view.IApplicationToken;
import android.view.IAppTransitionAnimationSpecsFuture;
import android.view.IDockedStackListener;
@@ -255,6 +256,13 @@ interface IWindowManager
     */
    void setScreenCaptureDisabled(int userId, boolean disabled);

    /**
     * Testing and debugging infrastructure for writing surface events
     * to given FD. See RemoteSurfaceTrace.java or Wm.java for format.
     */
    void enableSurfaceTrace(in ParcelFileDescriptor fd);
    void disableSurfaceTrace();

    /**
     * Cancels the window transitions for the given task.
     */
+11 −0
Original line number Diff line number Diff line
@@ -308,6 +308,17 @@ public class SurfaceControl {
        mCloseGuard.open("release");
    }

    // This is a transfer constructor, useful for transferring a live SurfaceControl native
    // object to another Java wrapper which could have some different behavior, e.g.
    // event logging.
    public SurfaceControl(SurfaceControl other) {
        mName = other.mName;
        mNativeObject = other.mNativeObject;
        other.mCloseGuard.close();
        other.mNativeObject = 0;
        mCloseGuard.open("release");
    }

    @Override
    protected void finalize() throws Throwable {
        try {
+15 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ import android.view.Surface;
import android.view.animation.Animation;
import com.android.internal.util.FastPrintWriter;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
@@ -1179,4 +1180,18 @@ class DisplayContent {
            taskForResize = null;
        }
    }

    void enableSurfaceTrace(FileDescriptor fd) {
        for (int i = mWindows.size()  - 1; i >= 0; i--) {
            final WindowState win = mWindows.get(i);
            win.mWinAnimator.enableSurfaceTrace(fd);
        }
    }

    void disableSurfaceTrace() {
        for (int i = mWindows.size()  - 1; i >= 0; i--) {
            final WindowState win = mWindows.get(i);
            win.mWinAnimator.disableSurfaceTrace();
        }
    }
}
+156 −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.wm;

import android.graphics.Rect;
import android.graphics.Region;
import android.os.IBinder;
import android.os.Parcel;
import android.util.Slog;
import android.view.SurfaceControl;

import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.DataOutputStream;

// A surface control subclass which logs events to a FD in binary format.
// This can be used in our CTS tests to enable a pattern similar to mocking
// the surface control.
//
// See cts/hostsidetests/../../SurfaceTraceReceiver.java for parsing side.
class RemoteSurfaceTrace extends SurfaceControl {
    static final String TAG = "RemoteSurfaceTrace";

    final FileDescriptor mWriteFd;
    final DataOutputStream mOut;

    final WindowManagerService mService;
    final WindowState mWindow;

    RemoteSurfaceTrace(FileDescriptor fd, SurfaceControl wrapped, WindowState window) {
        super(wrapped);

        mWriteFd = fd;
        mOut = new DataOutputStream(new FileOutputStream(fd, false));

        mWindow = window;
        mService = mWindow.mService;
    }

    @Override
    public void setAlpha(float alpha) {
        writeFloatEvent("Alpha", alpha);
        super.setAlpha(alpha);
    }

    @Override
    public void setLayer(int zorder) {
        writeIntEvent("Layer", zorder);
        super.setLayer(zorder);
    }

    @Override
    public void setPosition(float x, float y) {
        writeFloatEvent("Position", x, y);
        super.setPosition(x, y);
    }

    @Override
    public void setGeometryAppliesWithResize() {
        writeEvent("GeometryAppliesWithResize");
        super.setGeometryAppliesWithResize();
    }

    @Override
    public void setSize(int w, int h) {
        writeIntEvent("Size", w, h);
        super.setSize(w, h);
    }

    @Override
    public void setWindowCrop(Rect crop) {
        writeRectEvent("WindowCrop", crop);
        super.setWindowCrop(crop);
    }

    @Override
    public void setFinalCrop(Rect crop) {
        writeRectEvent("FinalCrop", crop);
        super.setFinalCrop(crop);
    }

    @Override
    public void setLayerStack(int layerStack) {
        writeIntEvent("LayerStack", layerStack);
        super.setLayerStack(layerStack);
    }

    @Override
    public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
        writeFloatEvent("Matrix", dsdx, dtdx, dsdy, dtdy);
        super.setMatrix(dsdx, dtdx, dsdy, dtdy);
    }

    @Override
    public void hide() {
        writeEvent("hide");
        super.hide();
    }

    @Override
    public void show() {
        writeEvent("show");
        super.show();
    }

    private void writeEvent(String tag) {
        try {
            mOut.writeUTF(tag);
            mOut.writeUTF(mWindow.getWindowTag().toString());
        } catch (Exception e) {
            mService.disableSurfaceTrace();
        }
    }

    private void writeIntEvent(String tag, int... values) {
        try {
            mOut.writeUTF(tag);
            mOut.writeUTF(mWindow.getWindowTag().toString());
            for (int value: values) {
                mOut.writeInt(value);
            }
        } catch (Exception e) {
            mService.disableSurfaceTrace();
        }
    }

    private void writeFloatEvent(String tag, float... values) {
        try {
            mOut.writeUTF(tag);
            mOut.writeUTF(mWindow.getWindowTag().toString());
            for (float value: values) {
                mOut.writeFloat(value);
            }
        } catch (Exception e) {
            mService.disableSurfaceTrace();
        }
    }

    private void writeRectEvent(String tag, Rect value) {
        writeFloatEvent(tag, value.top, value.left, value.right, value.bottom);
    }
}
Loading