summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 {
+ }
}