diff options
author | Andy Mast <andy@cyngn.com> | 2015-03-30 09:09:29 -0700 |
---|---|---|
committer | Andy Mast <andy@cyngn.com> | 2015-07-23 08:33:26 -0700 |
commit | 6ae1d3b6cb7e6580a8707cbab9cd514ccb975df8 (patch) | |
tree | 2ab287000ed48194361c87c74d83ba0095901101 | |
parent | de75b0da1cbc68b61e0b309cd1d49c2945c3555c (diff) | |
download | android_frameworks_base-previewgen2.tar.gz android_frameworks_base-previewgen2.tar.bz2 android_frameworks_base-previewgen2.zip |
*DO NOT SUBMIT* Allow screenshots through 3rd party appspreviewgen2
This is for internal use only. Do not submit as a patch
for the general public as it has security holes.
For emulator instances where screencap does not work,
one can use this patch to allow 3rd party applications
to take a screenshot. It uses the same code as HiearchyViewer
but with ParcelFileDescriptors instead. The client side
should make the call on a separate thread from the reader
of the PFD so that the app does not get blocked.
Change-Id: I5bfb210e07aacc56e46e87cbe88ed31e73c61f83
-rw-r--r-- | core/java/android/view/IWindowManager.aidl | 5 | ||||
-rw-r--r-- | core/java/android/view/ViewDebug.java | 3 | ||||
-rw-r--r-- | core/java/android/view/WindowManagerGlobal.java | 20 | ||||
-rw-r--r-- | services/core/java/com/android/server/wm/WindowManagerService.java | 115 |
4 files changed, 143 insertions, 0 deletions
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 68776650d6d..ef9540600e6 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -26,6 +26,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.IOnKeyguardExitResult; import android.view.IRotationWatcher; @@ -279,4 +280,8 @@ interface IWindowManager * @return The frame statistics or null if the window does not exist. */ WindowContentFrameStats getWindowContentFrameStats(IBinder token); + + String viewServerListWindows2(); + + String viewServerWindowCommand2(in ParcelFileDescriptor fd, String command, String parameters); } diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index 50e64c6ea6f..1870ec71aaf 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -315,6 +315,7 @@ public class ViewDebug { private static final int CAPTURE_TIMEOUT = 4000; private static final String REMOTE_COMMAND_CAPTURE = "CAPTURE"; + private static final String REMOTE_COMMAND_CAPTURE_ROOT = "CAPTURE_ROOT"; private static final String REMOTE_COMMAND_DUMP = "DUMP"; private static final String REMOTE_COMMAND_DUMP_THEME = "DUMP_THEME"; private static final String REMOTE_COMMAND_INVALIDATE = "INVALIDATE"; @@ -440,6 +441,8 @@ public class ViewDebug { final String[] params = parameters.split(" "); if (REMOTE_COMMAND_CAPTURE.equalsIgnoreCase(command)) { capture(view, clientStream, params[0]); + } else if (REMOTE_COMMAND_CAPTURE_ROOT.equalsIgnoreCase(command)) { + capture(view, clientStream, view); } else if (REMOTE_COMMAND_OUTPUT_DISPLAYLIST.equalsIgnoreCase(command)) { outputDisplayList(view, params[0]); } else if (REMOTE_COMMAND_INVALIDATE.equalsIgnoreCase(command)) { diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java index a14c7661fb4..e8194fccb83 100644 --- a/core/java/android/view/WindowManagerGlobal.java +++ b/core/java/android/view/WindowManagerGlobal.java @@ -23,6 +23,7 @@ import android.content.Context; import android.content.res.Configuration; import android.os.Build; import android.os.IBinder; +import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; @@ -35,6 +36,7 @@ import com.android.internal.util.FastPrintWriter; import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.PrintWriter; +import java.net.Socket; import java.util.ArrayList; /** @@ -550,6 +552,24 @@ public final class WindowManagerGlobal { } } } + + public static String viewServerListWindows() { + try { + return sWindowManagerService.viewServerListWindows2(); + } catch(RemoteException e) { + Log.e(TAG, "Could not viewServerListWindows", e); + } + return null; + } + + public static String viewServerWindowCommand(ParcelFileDescriptor fd, String command, String parameters) { + try { + return sWindowManagerService.viewServerWindowCommand2(fd, command, parameters); + } catch(RemoteException e) { + Log.e(TAG, "Could not viewServerListWIndows ", e); + } + return null; + } } final class WindowLeaked extends AndroidRuntimeException { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 584f01496d7..bbbc43f3922 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -146,6 +146,7 @@ import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; @@ -6934,6 +6935,41 @@ public class WindowManagerService extends IWindowManager.Stub return mViewServer != null && mViewServer.isRunning(); } + public String viewServerListWindows2() { + boolean result = true; + + WindowList windows = new WindowList(); + synchronized (mWindowMap) { + //noinspection unchecked + final int numDisplays = mDisplayContents.size(); + for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { + final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); + windows.addAll(displayContent.getWindowList()); + } + } + + // Any uncaught exception will crash the system process + StringBuffer sb = new StringBuffer(); + try { + + + final int count = windows.size(); + for (int i = 0; i < count; i++) { + final WindowState w = windows.get(i); + sb.append(Integer.toHexString(System.identityHashCode(w))); + sb.append(' '); + sb.append(w.mAttrs.getTitle()); + sb.append('\n'); + } + + sb.append("DONE.\n"); + } catch (Exception e) { + result = false; + } + + return sb.toString(); + } + /** * Lists all availble windows in the system. The listing is written in the * specified Socket's output stream with the following syntax: @@ -7135,6 +7171,85 @@ public class WindowManagerService extends IWindowManager.Stub return success; } + public String viewServerWindowCommand2(ParcelFileDescriptor fd, String command, String parameters) { + if (isSystemSecure()) { + return null; + } + + boolean success = true; + Parcel data = null; + Parcel reply = null; + + BufferedWriter out = null; + + // Any uncaught exception will crash the system process + try { + // Find the hashcode of the window + int index = parameters.indexOf(' '); + if (index == -1) { + index = parameters.length(); + } + final String code = parameters.substring(0, index); + int hashCode = (int) Long.parseLong(code, 16); + + // Extract the command's parameter after the window description + if (index < parameters.length()) { + parameters = parameters.substring(index + 1); + } else { + parameters = ""; + } + + final WindowState window = findWindow(hashCode); + if (window == null) { + return null; + } + + data = Parcel.obtain(); + data.writeInterfaceToken("android.view.IWindow"); + data.writeString(command); + data.writeString(parameters); + data.writeInt(1); + + //ParcelFileDescriptor[] fds = ParcelFileDescriptor.createReliableSocketPair(); + fd.writeToParcel(data, 0); + + reply = Parcel.obtain(); + + final IBinder binder = window.mClient.asBinder(); + // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER + binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); + + reply.readException(); + + //FileOutputStream appendOut = new FileOutputStream(fd.getFileDescriptor()); + //OutputStreamWriter writer = new OutputStreamWriter(appendOut); + //writer.write("DONE\n"); + + //writer.close(); + //appendOut.flush(); + //appendOut.close(); + } catch (Exception e) { + Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e); + success = false; + } finally { + if (data != null) { + data.recycle(); + } + if (reply != null) { + reply.recycle(); + } + if (out != null) { + try { + out.close(); + } catch (IOException e) { + + } + } + } + + return ""; + } + public void addWindowChangeListener(WindowChangeListener listener) { synchronized(mWindowMap) { mWindowChangeListeners.add(listener); |