summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Carr <racarr@google.com>2016-08-16 16:02:21 -0700
committerRobert Carr <racarr@google.com>2016-09-19 11:19:31 -0700
commit3b716249cc2f94aa9842576b618998c28593be90 (patch)
treed4621c132d21655fe67852975c63d858d5998c59
parentfcdcf7f636ada244a635328e25fdc03959468c8e (diff)
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
-rw-r--r--cmds/wm/src/com/android/commands/wm/Wm.java58
-rw-r--r--core/java/android/view/IWindowManager.aidl8
-rw-r--r--core/java/android/view/SurfaceControl.java11
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java15
-rw-r--r--services/core/java/com/android/server/wm/RemoteSurfaceTrace.java156
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java42
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java17
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfaceController.java14
-rw-r--r--tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java9
9 files changed, 329 insertions, 1 deletions
diff --git a/cmds/wm/src/com/android/commands/wm/Wm.java b/cmds/wm/src/com/android/commands/wm/Wm.java
index 383cd01ddcd6..b46cd6767a73 100644
--- a/cmds/wm/src/com/android/commands/wm/Wm.java
+++ b/cmds/wm/src/com/android/commands/wm/Wm.java
@@ -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();
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 1d9f99fa7b12..c16339380294 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -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;
@@ -256,6 +257,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.
*/
void cancelTaskWindowTransition(int taskId);
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index e778a7f16f25..64568260c022 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -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 {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index ee73deee5a38..6e1cb378b4b1 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -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();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/RemoteSurfaceTrace.java b/services/core/java/com/android/server/wm/RemoteSurfaceTrace.java
new file mode 100644
index 000000000000..53bb5e60808b
--- /dev/null
+++ b/services/core/java/com/android/server/wm/RemoteSurfaceTrace.java
@@ -0,0 +1,156 @@
+/*
+ * 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);
+ }
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index a0b74f807910..5180e99b1d88 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -893,6 +893,12 @@ public class WindowManagerService extends IWindowManager.Stub
// current configuration.
private final DisplayContentList mReconfigureOnConfigurationChanged = new DisplayContentList();
+ // State for the RemoteSurfaceTrace system used in testing. If this is enabled SurfaceControl
+ // instances will be replaced with an instance that writes a binary representation of all
+ // commands to mSurfaceTraceFd.
+ boolean mSurfaceTraceEnabled;
+ ParcelFileDescriptor mSurfaceTraceFd;
+
/** Listener to notify activity manager about app transitions. */
final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier
= new WindowManagerInternal.AppTransitionListener() {
@@ -1935,6 +1941,42 @@ public class WindowManagerService extends IWindowManager.Stub
return false;
}
+ @Override
+ public void enableSurfaceTrace(ParcelFileDescriptor pfd) {
+ int callingUid = Binder.getCallingUid();
+ if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID) {
+ throw new SecurityException("Only shell can call enableSurfaceTrace");
+ }
+ final FileDescriptor fd = pfd.getFileDescriptor();
+
+ synchronized (mWindowMap) {
+ if (mSurfaceTraceEnabled) {
+ disableSurfaceTrace();
+ }
+ mSurfaceTraceEnabled = true;
+ mSurfaceTraceFd = pfd;
+ for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
+ DisplayContent dc = mDisplayContents.valueAt(displayNdx);
+ dc.enableSurfaceTrace(fd);
+ }
+ }
+ }
+
+ @Override
+ public void disableSurfaceTrace() {
+ int callingUid = Binder.getCallingUid();
+ if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID &&
+ callingUid != Process.SYSTEM_UID) {
+ throw new SecurityException("Only shell can call disableSurfaceTrace");
+ }
+ mSurfaceTraceEnabled = false;
+ mSurfaceTraceFd = null;
+ for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
+ DisplayContent dc = mDisplayContents.valueAt(displayNdx);
+ dc.disableSurfaceTrace();
+ }
+ }
+
/**
* Set mScreenCaptureDisabled for specific user
*/
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 788f28dadfeb..4f6cf2ff85cb 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -70,6 +70,7 @@ import android.view.animation.Transformation;
import com.android.server.wm.WindowManagerService.H;
import java.io.PrintWriter;
+import java.io.FileDescriptor;
/**
* Keep track of animations and surface operations for a single WindowState.
@@ -2006,4 +2007,20 @@ class WindowStateAnimator {
DtDy * w.mVScale, false);
}
}
+
+ void enableSurfaceTrace(FileDescriptor fd) {
+ if (mSurfaceController != null) {
+ mSurfaceController.installRemoteTrace(fd);
+ }
+ }
+
+ void disableSurfaceTrace() {
+ if (mSurfaceController != null) {
+ try {
+ mSurfaceController.removeRemoteTrace();
+ } catch (ClassCastException e) {
+ Slog.e(TAG, "Disable surface trace for " + this + " but its not enabled");
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index f5ed9d1b8650..60bdf2aae068 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -41,6 +41,7 @@ import android.view.Surface.OutOfResourcesException;
import android.util.Slog;
+import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -95,6 +96,19 @@ class WindowSurfaceController {
mSurfaceControl = new SurfaceControl(
s, name, w, h, format, flags);
}
+
+ if (animator.mService.mSurfaceTraceEnabled) {
+ mSurfaceControl = new RemoteSurfaceTrace(animator.mService.mSurfaceTraceFd.getFileDescriptor(),
+ mSurfaceControl, animator.mWin);
+ }
+ }
+
+ void installRemoteTrace(FileDescriptor fd) {
+ mSurfaceControl = new RemoteSurfaceTrace(fd, mSurfaceControl, mAnimator.mWin);
+ }
+
+ void removeRemoteTrace() {
+ mSurfaceControl = new SurfaceControl(mSurfaceControl);
}
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 6ca13d68c316..4a70060d5097 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -30,6 +30,7 @@ import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IRemoteCallback;
+import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.DisplayMetrics;
import android.view.AppTransitionAnimationSpec;
@@ -610,4 +611,12 @@ public class IWindowManagerImpl implements IWindowManager {
public Bitmap screenshotWallpaper() throws RemoteException {
return null;
}
+
+ @Override
+ public void enableSurfaceTrace(ParcelFileDescriptor fd) throws RemoteException {
+ }
+
+ @Override
+ public void disableSurfaceTrace() throws RemoteException {
+ }
}