diff options
-rw-r--r-- | cmds/wm/Android.mk | 5 | ||||
-rw-r--r-- | cmds/wm/src/com/android/commands/wm/Wm.java | 296 | ||||
-rwxr-xr-x | cmds/wm/wm | 7 | ||||
-rw-r--r-- | core/java/android/view/ViewRootImpl.java | 177 | ||||
-rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerShellCommand.java | 87 | ||||
-rw-r--r-- | services/core/java/com/android/server/wm/RemoteEventTrace.java | 7 | ||||
-rw-r--r-- | services/core/java/com/android/server/wm/RemoteSurfaceTrace.java | 78 | ||||
-rw-r--r-- | services/core/java/com/android/server/wm/WindowManagerShellCommand.java | 286 |
8 files changed, 507 insertions, 436 deletions
diff --git a/cmds/wm/Android.mk b/cmds/wm/Android.mk index 3f3795fc4460..693c6e77d317 100644 --- a/cmds/wm/Android.mk +++ b/cmds/wm/Android.mk @@ -3,11 +3,6 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_SRC_FILES := $(call all-subdir-java-files) -LOCAL_MODULE := wm -include $(BUILD_JAVA_LIBRARY) - -include $(CLEAR_VARS) LOCAL_MODULE := wm LOCAL_SRC_FILES := wm LOCAL_MODULE_CLASS := EXECUTABLES diff --git a/cmds/wm/src/com/android/commands/wm/Wm.java b/cmds/wm/src/com/android/commands/wm/Wm.java deleted file mode 100644 index 8defb331e289..000000000000 --- a/cmds/wm/src/com/android/commands/wm/Wm.java +++ /dev/null @@ -1,296 +0,0 @@ -/* -** -** Copyright 2013, 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.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; - -public class Wm extends BaseCommand { - - private IWindowManager mWm; - - /** - * Command-line entry point. - * - * @param args The command-line arguments - */ - public static void main(String[] args) { - (new Wm()).run(args); - } - - @Override - public void onShowUsage(PrintStream out) { - out.println( - "usage: wm [subcommand] [options]\n" + - " wm size [reset|WxH|WdpxHdp]\n" + - " wm density [reset|DENSITY]\n" + - " wm overscan [reset|LEFT,TOP,RIGHT,BOTTOM]\n" + - " wm scaling [off|auto]\n" + - " wm screen-capture [userId] [true|false]\n" + - "\n" + - "wm size: return or override display size.\n" + - " width and height in pixels unless suffixed with 'dp'.\n" + - "\n" + - "wm density: override display density.\n" + - "\n" + - "wm overscan: set overscan area for display.\n" + - "\n" + - "wm scaling: set display scaling mode.\n" + - "\n" + - "wm screen-capture: enable/disable screen capture.\n" + - "\n" + - "wm dismiss-keyguard: dismiss the keyguard, prompting the user for auth if " + - "necessary.\n" + - "\n" + - "wm surface-trace: log surface commands to stdout in a binary format.\n" - ); - } - - @Override - public void onRun() throws Exception { - mWm = IWindowManager.Stub.asInterface(ServiceManager.checkService( - Context.WINDOW_SERVICE)); - if (mWm == null) { - System.err.println(NO_SYSTEM_ERROR_CODE); - throw new AndroidException("Can't connect to window manager; is the system running?"); - } - - String op = nextArgRequired(); - - if (op.equals("size")) { - runDisplaySize(); - } else if (op.equals("density")) { - runDisplayDensity(); - } else if (op.equals("overscan")) { - runDisplayOverscan(); - } else if (op.equals("scaling")) { - runDisplayScaling(); - } else if (op.equals("screen-capture")) { - runSetScreenCapture(); - } else if (op.equals("dismiss-keyguard")) { - runDismissKeyguard(); - } else if (op.equals("surface-trace")) { - runSurfaceTrace(); - } else { - showError("Error: unknown command '" + op + "'"); - return; - } - } - - private void runSurfaceTrace() throws Exception { - ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(FileDescriptor.out); - mWm.enableSurfaceTrace(pfd); - - try { - // No one is going to wake us up, we are just waiting on SIGINT. Otherwise - // the WM can happily continue writing to our stdout. - synchronized (this) { - this.wait(); - } - } finally { - mWm.disableSurfaceTrace(); - } - } - - private void runSetScreenCapture() throws Exception { - String userIdStr = nextArg(); - String enableStr = nextArg(); - int userId; - boolean disable; - - try { - userId = Integer.parseInt(userIdStr); - } catch (NumberFormatException e) { - System.err.println("Error: bad number " + e); - return; - } - - disable = !Boolean.parseBoolean(enableStr); - - try { - mWm.setScreenCaptureDisabled(userId, disable); - } catch (RemoteException e) { - System.err.println("Error: Can't set screen capture " + e); - } - } - - private void runDisplaySize() throws Exception { - String size = nextArg(); - int w, h; - if (size == null) { - Point initialSize = new Point(); - Point baseSize = new Point(); - try { - mWm.getInitialDisplaySize(Display.DEFAULT_DISPLAY, initialSize); - mWm.getBaseDisplaySize(Display.DEFAULT_DISPLAY, baseSize); - System.out.println("Physical size: " + initialSize.x + "x" + initialSize.y); - if (!initialSize.equals(baseSize)) { - System.out.println("Override size: " + baseSize.x + "x" + baseSize.y); - } - } catch (RemoteException e) { - } - return; - } else if ("reset".equals(size)) { - w = h = -1; - } else { - int div = size.indexOf('x'); - if (div <= 0 || div >= (size.length()-1)) { - System.err.println("Error: bad size " + size); - return; - } - String wstr = size.substring(0, div); - String hstr = size.substring(div+1); - try { - w = parseDimension(wstr); - h = parseDimension(hstr); - } catch (NumberFormatException e) { - System.err.println("Error: bad number " + e); - return; - } - } - - try { - if (w >= 0 && h >= 0) { - // TODO(multidisplay): For now Configuration only applies to main screen. - mWm.setForcedDisplaySize(Display.DEFAULT_DISPLAY, w, h); - } else { - mWm.clearForcedDisplaySize(Display.DEFAULT_DISPLAY); - } - } catch (RemoteException e) { - } - } - - private void runDisplayDensity() throws Exception { - String densityStr = nextArg(); - int density; - if (densityStr == null) { - try { - int initialDensity = mWm.getInitialDisplayDensity(Display.DEFAULT_DISPLAY); - int baseDensity = mWm.getBaseDisplayDensity(Display.DEFAULT_DISPLAY); - System.out.println("Physical density: " + initialDensity); - if (initialDensity != baseDensity) { - System.out.println("Override density: " + baseDensity); - } - } catch (RemoteException e) { - } - return; - } else if ("reset".equals(densityStr)) { - density = -1; - } else { - try { - density = Integer.parseInt(densityStr); - } catch (NumberFormatException e) { - System.err.println("Error: bad number " + e); - return; - } - if (density < 72) { - System.err.println("Error: density must be >= 72"); - return; - } - } - - try { - if (density > 0) { - // TODO(multidisplay): For now Configuration only applies to main screen. - mWm.setForcedDisplayDensityForUser(Display.DEFAULT_DISPLAY, density, - UserHandle.USER_CURRENT); - } else { - mWm.clearForcedDisplayDensityForUser(Display.DEFAULT_DISPLAY, - UserHandle.USER_CURRENT); - } - } catch (RemoteException e) { - } - } - - private void runDisplayOverscan() throws Exception { - String overscanStr = nextArgRequired(); - Rect rect = new Rect(); - if ("reset".equals(overscanStr)) { - rect.set(0, 0, 0, 0); - } else { - final Pattern FLATTENED_PATTERN = Pattern.compile( - "(-?\\d+),(-?\\d+),(-?\\d+),(-?\\d+)"); - Matcher matcher = FLATTENED_PATTERN.matcher(overscanStr); - if (!matcher.matches()) { - System.err.println("Error: bad rectangle arg: " + overscanStr); - return; - } - rect.left = Integer.parseInt(matcher.group(1)); - rect.top = Integer.parseInt(matcher.group(2)); - rect.right = Integer.parseInt(matcher.group(3)); - rect.bottom = Integer.parseInt(matcher.group(4)); - } - - try { - mWm.setOverscan(Display.DEFAULT_DISPLAY, rect.left, rect.top, rect.right, rect.bottom); - } catch (RemoteException e) { - } - } - - private void runDisplayScaling() throws Exception { - String scalingStr = nextArgRequired(); - if ("auto".equals(scalingStr)) { - mWm.setForcedDisplayScalingMode(Display.DEFAULT_DISPLAY, 0); - } else if ("off".equals(scalingStr)) { - mWm.setForcedDisplayScalingMode(Display.DEFAULT_DISPLAY, 1); - } else { - System.err.println("Error: scaling must be 'auto' or 'off'"); - } - } - - private void runDismissKeyguard() throws Exception { - mWm.dismissKeyguard(null /* callback */); - } - - private int parseDimension(String s) throws NumberFormatException { - if (s.endsWith("px")) { - return Integer.parseInt(s.substring(0, s.length() - 2)); - } - if (s.endsWith("dp")) { - int density; - try { - density = mWm.getBaseDisplayDensity(Display.DEFAULT_DISPLAY); - } catch (RemoteException e) { - density = DisplayMetrics.DENSITY_DEFAULT; - } - return Integer.parseInt(s.substring(0, s.length() - 2)) * density / - DisplayMetrics.DENSITY_DEFAULT; - } - return Integer.parseInt(s); - } -} diff --git a/cmds/wm/wm b/cmds/wm/wm index 16d6bd649ef2..cb45be20c24a 100755 --- a/cmds/wm/wm +++ b/cmds/wm/wm @@ -1,7 +1,2 @@ #!/system/bin/sh -# Script to start "wm" on the device, which has a very rudimentary -# shell. -# -base=/system -export CLASSPATH=$base/framework/wm.jar -exec app_process $base/bin com.android.commands.wm.Wm "$@" +cmd window "$@" diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 129a255c1989..adfc1ba4e15f 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -323,6 +323,13 @@ public final class ViewRootImpl implements ViewParent, final Rect mTempRect; // used in the transaction to not thrash the heap. final Rect mVisRect; // used to retrieve visible rect of focused view. + // This is used to reduce the race between window focus changes being dispatched from + // the window manager and input events coming through the input system. + @GuardedBy("this") + boolean mUpcomingWindowFocus; + @GuardedBy("this") + boolean mUpcomingInTouchMode; + public boolean mTraversalScheduled; int mTraversalBarrier; boolean mWillDrawSoon; @@ -2452,6 +2459,93 @@ public final class ViewRootImpl implements ViewParent, } } + private void handleWindowFocusChanged() { + final boolean hasWindowFocus; + final boolean inTouchMode; + synchronized (this) { + hasWindowFocus = mUpcomingWindowFocus; + inTouchMode = mUpcomingInTouchMode; + } + + if (mAttachInfo.mHasWindowFocus == hasWindowFocus) { + return; + } + + if (mAdded) { + profileRendering(hasWindowFocus); + + if (hasWindowFocus) { + ensureTouchModeLocally(inTouchMode); + if (mAttachInfo.mThreadedRenderer != null && mSurface.isValid()) { + mFullRedrawNeeded = true; + try { + final WindowManager.LayoutParams lp = mWindowAttributes; + final Rect surfaceInsets = lp != null ? lp.surfaceInsets : null; + mAttachInfo.mThreadedRenderer.initializeIfNeeded( + mWidth, mHeight, mAttachInfo, mSurface, surfaceInsets); + } catch (OutOfResourcesException e) { + Log.e(mTag, "OutOfResourcesException locking surface", e); + try { + if (!mWindowSession.outOfMemory(mWindow)) { + Slog.w(mTag, "No processes killed for memory;" + + " killing self"); + Process.killProcess(Process.myPid()); + } + } catch (RemoteException ex) { + } + // Retry in a bit. + mHandler.sendMessageDelayed(mHandler.obtainMessage( + MSG_WINDOW_FOCUS_CHANGED), 500); + return; + } + } + } + + mAttachInfo.mHasWindowFocus = hasWindowFocus; + + mLastWasImTarget = WindowManager.LayoutParams + .mayUseInputMethod(mWindowAttributes.flags); + + InputMethodManager imm = InputMethodManager.peekInstance(); + if (imm != null && mLastWasImTarget && !isInLocalFocusMode()) { + imm.onPreWindowFocus(mView, hasWindowFocus); + } + if (mView != null) { + mAttachInfo.mKeyDispatchState.reset(); + mView.dispatchWindowFocusChanged(hasWindowFocus); + mAttachInfo.mTreeObserver.dispatchOnWindowFocusChange(hasWindowFocus); + + if (mAttachInfo.mTooltipHost != null) { + mAttachInfo.mTooltipHost.hideTooltip(); + } + } + + // Note: must be done after the focus change callbacks, + // so all of the view state is set up correctly. + if (hasWindowFocus) { + if (imm != null && mLastWasImTarget && !isInLocalFocusMode()) { + imm.onPostWindowFocus(mView, mView.findFocus(), + mWindowAttributes.softInputMode, + !mHasHadWindowFocus, mWindowAttributes.flags); + } + // Clear the forward bit. We can just do this directly, since + // the window manager doesn't care about it. + mWindowAttributes.softInputMode &= + ~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION; + ((WindowManager.LayoutParams) mView.getLayoutParams()) + .softInputMode &= + ~WindowManager.LayoutParams + .SOFT_INPUT_IS_FORWARD_NAVIGATION; + mHasHadWindowFocus = true; + } else { + if (mPointerCapture) { + handlePointerCaptureChanged(false); + } + } + } + mFirstInputStage.onWindowFocusChanged(hasWindowFocus); + } + private void handleOutOfResourcesException(Surface.OutOfResourcesException e) { Log.e(mTag, "OutOfResourcesException initializing HW surface", e); try { @@ -3900,81 +3994,7 @@ public final class ViewRootImpl implements ViewParent, } break; case MSG_WINDOW_FOCUS_CHANGED: { - final boolean hasWindowFocus = msg.arg1 != 0; - if (mAdded) { - mAttachInfo.mHasWindowFocus = hasWindowFocus; - - profileRendering(hasWindowFocus); - - if (hasWindowFocus) { - boolean inTouchMode = msg.arg2 != 0; - ensureTouchModeLocally(inTouchMode); - if (mAttachInfo.mThreadedRenderer != null && mSurface.isValid()) { - mFullRedrawNeeded = true; - try { - final WindowManager.LayoutParams lp = mWindowAttributes; - final Rect surfaceInsets = lp != null ? lp.surfaceInsets : null; - mAttachInfo.mThreadedRenderer.initializeIfNeeded( - mWidth, mHeight, mAttachInfo, mSurface, surfaceInsets); - } catch (OutOfResourcesException e) { - Log.e(mTag, "OutOfResourcesException locking surface", e); - try { - if (!mWindowSession.outOfMemory(mWindow)) { - Slog.w(mTag, "No processes killed for memory;" - + " killing self"); - Process.killProcess(Process.myPid()); - } - } catch (RemoteException ex) { - } - // Retry in a bit. - sendMessageDelayed(obtainMessage(msg.what, msg.arg1, msg.arg2), - 500); - return; - } - } - } - - mLastWasImTarget = WindowManager.LayoutParams - .mayUseInputMethod(mWindowAttributes.flags); - - InputMethodManager imm = InputMethodManager.peekInstance(); - if (imm != null && mLastWasImTarget && !isInLocalFocusMode()) { - imm.onPreWindowFocus(mView, hasWindowFocus); - } - if (mView != null) { - mAttachInfo.mKeyDispatchState.reset(); - mView.dispatchWindowFocusChanged(hasWindowFocus); - mAttachInfo.mTreeObserver.dispatchOnWindowFocusChange(hasWindowFocus); - - if (mAttachInfo.mTooltipHost != null) { - mAttachInfo.mTooltipHost.hideTooltip(); - } - } - - // Note: must be done after the focus change callbacks, - // so all of the view state is set up correctly. - if (hasWindowFocus) { - if (imm != null && mLastWasImTarget && !isInLocalFocusMode()) { - imm.onPostWindowFocus(mView, mView.findFocus(), - mWindowAttributes.softInputMode, - !mHasHadWindowFocus, mWindowAttributes.flags); - } - // Clear the forward bit. We can just do this directly, since - // the window manager doesn't care about it. - mWindowAttributes.softInputMode &= - ~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION; - ((WindowManager.LayoutParams) mView.getLayoutParams()) - .softInputMode &= - ~WindowManager.LayoutParams - .SOFT_INPUT_IS_FORWARD_NAVIGATION; - mHasHadWindowFocus = true; - } else { - if (mPointerCapture) { - handlePointerCaptureChanged(false); - } - } - } - mFirstInputStage.onWindowFocusChanged(hasWindowFocus); + handleWindowFocusChanged(); } break; case MSG_DIE: doDie(); @@ -6845,6 +6865,7 @@ public final class ViewRootImpl implements ViewParent, } if (stage != null) { + handleWindowFocusChanged(); stage.deliver(q); } else { finishInputEvent(q); @@ -7150,10 +7171,12 @@ public final class ViewRootImpl implements ViewParent, } public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) { + synchronized (this) { + mUpcomingWindowFocus = hasFocus; + mUpcomingInTouchMode = inTouchMode; + } Message msg = Message.obtain(); msg.what = MSG_WINDOW_FOCUS_CHANGED; - msg.arg1 = hasFocus ? 1 : 0; - msg.arg2 = inTouchMode ? 1 : 0; mHandler.sendMessage(msg); } diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 979323fc8408..51121fbcfb6b 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -48,6 +48,7 @@ import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ShellCommand; +import android.os.StrictMode; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; @@ -126,7 +127,7 @@ final class ActivityManagerShellCommand extends ShellCommand { if (cmd == null) { return handleDefaultCommands(cmd); } - PrintWriter pw = getOutPrintWriter(); + final PrintWriter pw = getOutPrintWriter(); try { switch (cmd) { case "start": @@ -1326,65 +1327,95 @@ final class ActivityManagerShellCommand extends ShellCommand { @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) throws RemoteException { synchronized (this) { - mPw.print(uid); - mPw.print(" procstate "); - mPw.print(ProcessList.makeProcStateString(procState)); - mPw.print(" seq "); - mPw.println(procStateSeq); - mPw.flush(); + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + try { + mPw.print(uid); + mPw.print(" procstate "); + mPw.print(ProcessList.makeProcStateString(procState)); + mPw.print(" seq "); + mPw.println(procStateSeq); + mPw.flush(); + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } } } @Override public void onUidGone(int uid, boolean disabled) throws RemoteException { synchronized (this) { - mPw.print(uid); - mPw.print(" gone"); - if (disabled) { - mPw.print(" disabled"); + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + try { + mPw.print(uid); + mPw.print(" gone"); + if (disabled) { + mPw.print(" disabled"); + } + mPw.println(); + mPw.flush(); + } finally { + StrictMode.setThreadPolicy(oldPolicy); } - mPw.println(); - mPw.flush(); } } @Override public void onUidActive(int uid) throws RemoteException { synchronized (this) { - mPw.print(uid); - mPw.println(" active"); - mPw.flush(); + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + try { + mPw.print(uid); + mPw.println(" active"); + mPw.flush(); + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } } } @Override public void onUidIdle(int uid, boolean disabled) throws RemoteException { synchronized (this) { - mPw.print(uid); - mPw.print(" idle"); - if (disabled) { - mPw.print(" disabled"); + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + try { + mPw.print(uid); + mPw.print(" idle"); + if (disabled) { + mPw.print(" disabled"); + } + mPw.println(); + mPw.flush(); + } finally { + StrictMode.setThreadPolicy(oldPolicy); } - mPw.println(); - mPw.flush(); } } @Override public void onUidCachedChanged(int uid, boolean cached) throws RemoteException { synchronized (this) { - mPw.print(uid); - mPw.println(cached ? " cached" : " uncached"); - mPw.flush(); + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + try { + mPw.print(uid); + mPw.println(cached ? " cached" : " uncached"); + mPw.flush(); + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } } } @Override public void onOomAdjMessage(String msg) { synchronized (this) { - mPw.print("# "); - mPw.println(msg); - mPw.flush(); + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + try { + mPw.print("# "); + mPw.println(msg); + mPw.flush(); + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } } } diff --git a/services/core/java/com/android/server/wm/RemoteEventTrace.java b/services/core/java/com/android/server/wm/RemoteEventTrace.java index 9f65ba36f311..b214d35f208c 100644 --- a/services/core/java/com/android/server/wm/RemoteEventTrace.java +++ b/services/core/java/com/android/server/wm/RemoteEventTrace.java @@ -20,6 +20,7 @@ import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.DataOutputStream; +import android.os.StrictMode; import android.util.Slog; import android.os.Debug; @@ -40,22 +41,28 @@ class RemoteEventTrace { } void openSurfaceTransaction() { + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); try { mOut.writeUTF("OpenTransaction"); writeSigil(); } catch (Exception e) { logException(e); mService.disableSurfaceTrace(); + } finally { + StrictMode.setThreadPolicy(oldPolicy); } } void closeSurfaceTransaction() { + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); try { mOut.writeUTF("CloseTransaction"); writeSigil(); } catch (Exception e) { logException(e); mService.disableSurfaceTrace(); + } finally { + StrictMode.setThreadPolicy(oldPolicy); } } diff --git a/services/core/java/com/android/server/wm/RemoteSurfaceTrace.java b/services/core/java/com/android/server/wm/RemoteSurfaceTrace.java index a12c2c40152d..d2cbf88aac58 100644 --- a/services/core/java/com/android/server/wm/RemoteSurfaceTrace.java +++ b/services/core/java/com/android/server/wm/RemoteSurfaceTrace.java @@ -20,6 +20,7 @@ import android.graphics.Rect; import android.graphics.Region; import android.os.IBinder; import android.os.Parcel; +import android.os.StrictMode; import android.util.Slog; import android.view.SurfaceControl; @@ -54,67 +55,122 @@ class RemoteSurfaceTrace extends SurfaceControlWithBackground { @Override public void setAlpha(float alpha) { - writeFloatEvent("Alpha", alpha); + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + try { + writeFloatEvent("Alpha", alpha); + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } super.setAlpha(alpha); } @Override public void setLayer(int zorder) { - writeIntEvent("Layer", zorder); + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + try { + writeIntEvent("Layer", zorder); + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } super.setLayer(zorder); } @Override public void setPosition(float x, float y) { - writeFloatEvent("Position", x, y); + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + try { + writeFloatEvent("Position", x, y); + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } super.setPosition(x, y); } @Override public void setGeometryAppliesWithResize() { - writeEvent("GeometryAppliesWithResize"); + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + try { + writeEvent("GeometryAppliesWithResize"); + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } super.setGeometryAppliesWithResize(); } @Override public void setSize(int w, int h) { - writeIntEvent("Size", w, h); + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + try { + writeIntEvent("Size", w, h); + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } super.setSize(w, h); } @Override public void setWindowCrop(Rect crop) { - writeRectEvent("Crop", crop); + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + try { + writeRectEvent("Crop", crop); + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } super.setWindowCrop(crop); } @Override public void setFinalCrop(Rect crop) { - writeRectEvent("FinalCrop", crop); + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + try { + writeRectEvent("FinalCrop", crop); + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } super.setFinalCrop(crop); } @Override public void setLayerStack(int layerStack) { - writeIntEvent("LayerStack", layerStack); + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + try { + writeIntEvent("LayerStack", layerStack); + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } super.setLayerStack(layerStack); } @Override public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { - writeFloatEvent("Matrix", dsdx, dtdx, dsdy, dtdy); + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + try { + writeFloatEvent("Matrix", dsdx, dtdx, dsdy, dtdy); + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } super.setMatrix(dsdx, dtdx, dsdy, dtdy); } @Override public void hide() { - writeEvent("Hide"); + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + try { + writeEvent("Hide"); + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } super.hide(); } @Override public void show() { - writeEvent("Show"); + final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + try { + writeEvent("Show"); + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } super.show(); } diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java index 235869551c73..b9dc9db7c5ee 100644 --- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java +++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java @@ -18,9 +18,23 @@ package com.android.server.wm; 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.view.Display; +import android.view.IWindowManager; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.io.PrintWriter; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * ShellCommands for WindowManagerService. @@ -29,33 +43,279 @@ import java.io.PrintWriter; */ public class WindowManagerShellCommand extends ShellCommand { - private final WindowManagerService mService; + // IPC interface to activity manager -- don't need to do additional security checks. + private final IWindowManager mInterface; + + // Internal service impl -- must perform security checks before touching. + private final WindowManagerService mInternal; public WindowManagerShellCommand(WindowManagerService service) { - mService = service; + mInterface = service; + mInternal = service; } @Override public int onCommand(String cmd) { - switch (cmd) { - case "tracing": - return mService.mWindowTracing.onShellCommand(this, getNextArgRequired()); - default: - return handleDefaultCommands(cmd); + if (cmd == null) { + return handleDefaultCommands(cmd); + } + final PrintWriter pw = getOutPrintWriter(); + try { + switch (cmd) { + case "size": + return runDisplaySize(pw); + case "density": + return runDisplayDensity(pw); + case "overscan": + return runDisplayOverscan(pw); + case "scaling": + return runDisplayScaling(pw); + case "screen-capture": + return runSetScreenCapture(pw); + case "dismiss-keyguard": + return runDismissKeyguard(pw); + case "surface-trace": + return runSurfaceTrace(pw); + case "tracing": + // XXX this should probably be changed to use openFileForSystem() to create + // the output trace file, so the shell gets the correct semantics for where + // trace files can be written. + return mInternal.mWindowTracing.onShellCommand(this, + getNextArgRequired()); + default: + return handleDefaultCommands(cmd); + } + } catch (RemoteException e) { + pw.println("Remote exception: " + e); + } + return -1; + } + + private int runDisplaySize(PrintWriter pw) throws RemoteException { + String size = getNextArg(); + int w, h; + if (size == null) { + Point initialSize = new Point(); + Point baseSize = new Point(); + try { + mInterface.getInitialDisplaySize(Display.DEFAULT_DISPLAY, initialSize); + mInterface.getBaseDisplaySize(Display.DEFAULT_DISPLAY, baseSize); + pw.println("Physical size: " + initialSize.x + "x" + initialSize.y); + if (!initialSize.equals(baseSize)) { + pw.println("Override size: " + baseSize.x + "x" + baseSize.y); + } + } catch (RemoteException e) { + } + return 0; + } else if ("reset".equals(size)) { + w = h = -1; + } else { + int div = size.indexOf('x'); + if (div <= 0 || div >= (size.length()-1)) { + getErrPrintWriter().println("Error: bad size " + size); + return -1; + } + String wstr = size.substring(0, div); + String hstr = size.substring(div+1); + try { + w = parseDimension(wstr); + h = parseDimension(hstr); + } catch (NumberFormatException e) { + getErrPrintWriter().println("Error: bad number " + e); + return -1; + } + } + + if (w >= 0 && h >= 0) { + // TODO(multidisplay): For now Configuration only applies to main screen. + mInterface.setForcedDisplaySize(Display.DEFAULT_DISPLAY, w, h); + } else { + mInterface.clearForcedDisplaySize(Display.DEFAULT_DISPLAY); + } + return 0; + } + + private int runDisplayDensity(PrintWriter pw) throws RemoteException { + String densityStr = getNextArg(); + int density; + if (densityStr == null) { + try { + int initialDensity = mInterface.getInitialDisplayDensity(Display.DEFAULT_DISPLAY); + int baseDensity = mInterface.getBaseDisplayDensity(Display.DEFAULT_DISPLAY); + pw.println("Physical density: " + initialDensity); + if (initialDensity != baseDensity) { + pw.println("Override density: " + baseDensity); + } + } catch (RemoteException e) { + } + return 0; + } else if ("reset".equals(densityStr)) { + density = -1; + } else { + try { + density = Integer.parseInt(densityStr); + } catch (NumberFormatException e) { + getErrPrintWriter().println("Error: bad number " + e); + return -1; + } + if (density < 72) { + getErrPrintWriter().println("Error: density must be >= 72"); + return -1; + } + } + + if (density > 0) { + // TODO(multidisplay): For now Configuration only applies to main screen. + mInterface.setForcedDisplayDensityForUser(Display.DEFAULT_DISPLAY, density, + UserHandle.USER_CURRENT); + } else { + mInterface.clearForcedDisplayDensityForUser(Display.DEFAULT_DISPLAY, + UserHandle.USER_CURRENT); + } + return 0; + } + + private int runDisplayOverscan(PrintWriter pw) throws RemoteException { + String overscanStr = getNextArgRequired(); + Rect rect = new Rect(); + if ("reset".equals(overscanStr)) { + rect.set(0, 0, 0, 0); + } else { + final Pattern FLATTENED_PATTERN = Pattern.compile( + "(-?\\d+),(-?\\d+),(-?\\d+),(-?\\d+)"); + Matcher matcher = FLATTENED_PATTERN.matcher(overscanStr); + if (!matcher.matches()) { + getErrPrintWriter().println("Error: bad rectangle arg: " + overscanStr); + return -1; + } + rect.left = Integer.parseInt(matcher.group(1)); + rect.top = Integer.parseInt(matcher.group(2)); + rect.right = Integer.parseInt(matcher.group(3)); + rect.bottom = Integer.parseInt(matcher.group(4)); + } + + mInterface.setOverscan(Display.DEFAULT_DISPLAY, rect.left, rect.top, rect.right, + rect.bottom); + return 0; + } + + private int runDisplayScaling(PrintWriter pw) throws RemoteException { + String scalingStr = getNextArgRequired(); + if ("auto".equals(scalingStr)) { + mInterface.setForcedDisplayScalingMode(Display.DEFAULT_DISPLAY, 0); + } else if ("off".equals(scalingStr)) { + mInterface.setForcedDisplayScalingMode(Display.DEFAULT_DISPLAY, 1); + } else { + getErrPrintWriter().println("Error: scaling must be 'auto' or 'off'"); + return -1; + } + return 0; + } + + private int runSetScreenCapture(PrintWriter pw) throws RemoteException { + String userIdStr = getNextArg(); + String enableStr = getNextArg(); + int userId; + boolean disable; + + try { + userId = Integer.parseInt(userIdStr); + } catch (NumberFormatException e) { + getErrPrintWriter().println("Error: bad number " + e); + return -1; + } + + disable = !Boolean.parseBoolean(enableStr); + mInternal.setScreenCaptureDisabled(userId, disable); + return 0; + } + + private int runDismissKeyguard(PrintWriter pw) throws RemoteException { + mInterface.dismissKeyguard(null /* callback */); + return 0; + } + + private int runSurfaceTrace(PrintWriter pw) throws RemoteException { + final ParcelFileDescriptor pfd; + try { + pfd = ParcelFileDescriptor.dup(getOutFileDescriptor()); + } catch (IOException e) { + getErrPrintWriter().println("Unable to dup output stream: " + e.getMessage()); + return -1; + } + mInternal.enableSurfaceTrace(pfd); + + // Read input until an explicit quit command is sent or the stream is closed (meaning + // the user killed the command). + try { + InputStream input = getRawInputStream(); + InputStreamReader converter = new InputStreamReader(input); + BufferedReader in = new BufferedReader(converter); + String line; + + while ((line = in.readLine()) != null) { + if (line.length() <= 0) { + // no-op + } else if ("q".equals(line) || "quit".equals(line)) { + break; + } else { + pw.println("Invalid command: " + line); + } + } + } catch (IOException e) { + e.printStackTrace(pw); + } finally { + mInternal.disableSurfaceTrace(); + try { + pfd.close(); + } catch (IOException e) { + } + } + + return 0; + } + + private int parseDimension(String s) throws NumberFormatException { + if (s.endsWith("px")) { + return Integer.parseInt(s.substring(0, s.length() - 2)); + } + if (s.endsWith("dp")) { + int density; + try { + density = mInterface.getBaseDisplayDensity(Display.DEFAULT_DISPLAY); + } catch (RemoteException e) { + density = DisplayMetrics.DENSITY_DEFAULT; + } + return Integer.parseInt(s.substring(0, s.length() - 2)) * density / + DisplayMetrics.DENSITY_DEFAULT; } + return Integer.parseInt(s); } @Override public void onHelp() { PrintWriter pw = getOutPrintWriter(); - pw.println("Window Manager (window) commands:"); + pw.println("Window manager (window) commands:"); pw.println(" help"); - pw.println(" Print this help text."); - pw.println(); - if (!IS_USER){ + pw.println(" Print this help text."); + pw.println(" size [reset|WxH|WdpxHdp]"); + pw.println(" Return or override display size."); + pw.println(" width and height in pixels unless suffixed with 'dp'."); + pw.println(" density [reset|DENSITY]"); + pw.println(" Return or override display density."); + pw.println(" overscan [reset|LEFT,TOP,RIGHT,BOTTOM]"); + pw.println(" Set overscan area for display."); + pw.println(" scaling [off|auto]"); + pw.println(" Set display scaling mode."); + pw.println(" screen-capture [userId] [true|false]"); + pw.println(" Enable or disable screen capture."); + pw.println(" dismiss-keyguard"); + pw.println(" Dismiss the keyguard, prompting user for auth if necessary."); + pw.println(" surface-trace"); + pw.println(" Log surface commands to stdout in a binary format."); + if (!IS_USER) { pw.println(" tracing (start | stop)"); - pw.println(" start or stop window tracing"); - pw.println(); + pw.println(" Start or stop window tracing."); } } } |