diff options
author | Jeff Brown <jeffbrown@google.com> | 2015-04-15 19:02:36 -0700 |
---|---|---|
committer | Jeff Brown <jeffbrown@google.com> | 2015-04-15 19:02:36 -0700 |
commit | d46747a1c64b6ca3282e8841833980ab91829436 (patch) | |
tree | feca484f9f10ee91399a12b41a524fb7f20a3eb5 | |
parent | 10acf6d3efde60977d2d2e82b90c53d722d9d357 (diff) |
Add support for disabling display scaling for development.
Added two new options to the wm command.
1. Set the screen size based on dips rather than pixels using the
current screen density.
eg. adb shell wm size 320dpx320dp
2. Disable automatic scaling of the contents of the display.
When combined with the previous command, this is useful for seeing
how the UI would behave if the screen remained at its current density
but changed physical size.
eg. adb shell wm scaling off
Bug: 19899223
Change-Id: I545f893ba4861494e995cf0457ebeba1050d28dc
9 files changed, 135 insertions, 7 deletions
diff --git a/cmds/wm/src/com/android/commands/wm/Wm.java b/cmds/wm/src/com/android/commands/wm/Wm.java index 815a0ac999eb..64f023f16abf 100644 --- a/cmds/wm/src/com/android/commands/wm/Wm.java +++ b/cmds/wm/src/com/android/commands/wm/Wm.java @@ -24,6 +24,7 @@ import android.graphics.Rect; import android.os.RemoteException; import android.os.ServiceManager; import android.util.AndroidException; +import android.util.DisplayMetrics; import android.view.Display; import android.view.IWindowManager; import com.android.internal.os.BaseCommand; @@ -45,21 +46,27 @@ public class Wm extends BaseCommand { (new Wm()).run(args); } + @Override public void onShowUsage(PrintStream out) { out.println( "usage: wm [subcommand] [options]\n" + - " wm size [reset|WxH]\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" + "\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" + "wm overscan: set overscan area for display.\n" + + "\n" + + "wm scaling: set display scaling mode.\n" ); } + @Override public void onRun() throws Exception { mWm = IWindowManager.Stub.asInterface(ServiceManager.checkService( Context.WINDOW_SERVICE)); @@ -76,6 +83,8 @@ public class Wm extends BaseCommand { runDisplayDensity(); } else if (op.equals("overscan")) { runDisplayOverscan(); + } else if (op.equals("scaling")) { + runDisplayScaling(); } else { showError("Error: unknown command '" + op + "'"); return; @@ -85,6 +94,7 @@ public class Wm extends BaseCommand { private void runDisplaySize() throws Exception { String size = nextArg(); int w, h; + boolean scale = true; if (size == null) { Point initialSize = new Point(); Point baseSize = new Point(); @@ -109,8 +119,8 @@ public class Wm extends BaseCommand { String wstr = size.substring(0, div); String hstr = size.substring(div+1); try { - w = Integer.parseInt(wstr); - h = Integer.parseInt(hstr); + w = parseDimension(wstr); + h = parseDimension(hstr); } catch (NumberFormatException e) { System.err.println("Error: bad number " + e); return; @@ -193,4 +203,32 @@ public class Wm extends BaseCommand { } 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 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/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 109c23be4ff2..cf1a5d1bc556 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -6036,6 +6036,13 @@ public final class Settings { public static final String DISPLAY_SIZE_FORCED = "display_size_forced"; /** + * The saved value for WindowManagerService.setForcedDisplayScalingMode(). + * 0 or unset if scaling is automatic, 1 if scaling is disabled. + * @hide + */ + public static final String DISPLAY_SCALING_FORCE = "display_scaling_force"; + + /** * The maximum size, in bytes, of a download that the download manager will transfer over * a non-wifi connection. * @hide diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 71863b7022e8..71e2251a8020 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -170,6 +170,15 @@ public final class Display { public static final int FLAG_PRESENTATION = 1 << 3; /** + * Display flag: Indicates that the contents of the display should not be scaled + * to fit the physical screen dimensions. Used for development only to emulate + * devices with smaller physicals screens while preserving density. + * + * @hide + */ + public static final int FLAG_SCALING_DISABLED = 1 << 30; + + /** * Display type: Unknown display type. * @hide */ diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index ecf45b446e11..243961c15dc4 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -538,6 +538,9 @@ public final class DisplayInfo implements Parcelable { if ((flags & Display.FLAG_PRESENTATION) != 0) { result.append(", FLAG_PRESENTATION"); } + if ((flags & Display.FLAG_SCALING_DISABLED) != 0) { + result.append(", FLAG_SCALING_DISABLED"); + } return result.toString(); } } diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index d6625c837128..5994d4fbae39 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -70,6 +70,7 @@ interface IWindowManager int getBaseDisplayDensity(int displayId); void setForcedDisplayDensity(int displayId, int density); void clearForcedDisplayDensity(int displayId); + void setForcedDisplayScalingMode(int displayId, int mode); // 0 = auto, 1 = disable void setOverscan(int displayId, int left, int top, int right, int bottom); diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java index 3bb7818c339a..65dc72f4280a 100644 --- a/services/core/java/com/android/server/display/LogicalDisplay.java +++ b/services/core/java/com/android/server/display/LogicalDisplay.java @@ -302,7 +302,10 @@ final class LogicalDisplay { // multiplying the fractions by the product of their denominators before // comparing them. int displayRectWidth, displayRectHeight; - if (physWidth * displayInfo.logicalHeight + if ((displayInfo.flags & Display.FLAG_SCALING_DISABLED) != 0) { + displayRectWidth = displayInfo.logicalWidth; + displayRectHeight = displayInfo.logicalHeight; + } else if (physWidth * displayInfo.logicalHeight < physHeight * displayInfo.logicalWidth) { // Letter box. displayRectWidth = physWidth; diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index f073c23878a6..f914369df6ef 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -66,6 +66,7 @@ class DisplayContent { int mBaseDisplayWidth = 0; int mBaseDisplayHeight = 0; int mBaseDisplayDensity = 0; + boolean mDisplayScalingDisabled; private final DisplayInfo mDisplayInfo = new DisplayInfo(); private final Display mDisplay; @@ -360,6 +361,9 @@ class DisplayContent { pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight); pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi"); } + if (mDisplayScalingDisabled) { + pw.println(" noscale"); + } pw.print(" cur="); pw.print(mDisplayInfo.logicalWidth); pw.print("x"); pw.print(mDisplayInfo.logicalHeight); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index e790fb02502e..04b71a47a920 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -7249,8 +7249,15 @@ public class WindowManagerService extends IWindowManager.Stub displayInfo.getLogicalMetrics(mRealDisplayMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); displayInfo.getAppMetrics(mDisplayMetrics); + if (displayContent.mDisplayScalingDisabled) { + displayInfo.flags |= Display.FLAG_SCALING_DISABLED; + } else { + displayInfo.flags &= ~Display.FLAG_SCALING_DISABLED; + } + mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( displayContent.getDisplayId(), displayInfo); + displayContent.mBaseDisplayRect.set(0, 0, dw, dh); } if (false) { @@ -7547,7 +7554,7 @@ public class WindowManagerService extends IWindowManager.Stub synchronized(mWindowMap) { final DisplayContent displayContent = getDefaultDisplayContentLocked(); - readForcedDisplaySizeAndDensityLocked(displayContent); + readForcedDisplayPropertiesLocked(displayContent); mDisplayReady = true; } @@ -8320,7 +8327,47 @@ public class WindowManagerService extends IWindowManager.Stub } } - private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) { + @Override + public void setForcedDisplayScalingMode(int displayId, int mode) { + if (mContext.checkCallingOrSelfPermission( + android.Manifest.permission.WRITE_SECURE_SETTINGS) != + PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Must hold permission " + + android.Manifest.permission.WRITE_SECURE_SETTINGS); + } + if (displayId != Display.DEFAULT_DISPLAY) { + throw new IllegalArgumentException("Can only set the default display"); + } + final long ident = Binder.clearCallingIdentity(); + try { + synchronized(mWindowMap) { + final DisplayContent displayContent = getDisplayContentLocked(displayId); + if (displayContent != null) { + if (mode < 0 || mode > 1) { + mode = 0; + } + setForcedDisplayScalingModeLocked(displayContent, mode); + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.DISPLAY_SCALING_FORCE, mode); + } + } + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + private void setForcedDisplayScalingModeLocked(DisplayContent displayContent, + int mode) { + Slog.i(TAG, "Using display scaling mode: " + (mode == 0 ? "auto" : "off")); + + synchronized(displayContent.mDisplaySizeLock) { + displayContent.mDisplayScalingDisabled = (mode != 0); + } + reconfigureDisplayLocked(displayContent); + } + + private void readForcedDisplayPropertiesLocked(final DisplayContent displayContent) { + // Display size. String sizeStr = Settings.Global.getString(mContext.getContentResolver(), Settings.Global.DISPLAY_SIZE_FORCED); if (sizeStr == null || sizeStr.length() == 0) { @@ -8345,6 +8392,8 @@ public class WindowManagerService extends IWindowManager.Stub } } } + + // Display density. String densityStr = Settings.Global.getString(mContext.getContentResolver(), Settings.Global.DISPLAY_DENSITY_FORCED); if (densityStr == null || densityStr.length() == 0) { @@ -8363,6 +8412,16 @@ public class WindowManagerService extends IWindowManager.Stub } catch (NumberFormatException ex) { } } + + // Display scaling mode. + int mode = Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.DISPLAY_SCALING_FORCE, 0); + if (mode != 0) { + synchronized(displayContent.mDisplaySizeLock) { + Slog.i(TAG, "FORCED DISPLAY SCALING DISABLED"); + displayContent.mDisplayScalingDisabled = true; + } + } } // displayContent must not be null diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java index 818940d768dd..82012c1e2767 100644 --- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java +++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java @@ -376,6 +376,10 @@ public class IWindowManagerImpl implements IWindowManager { } @Override + public void setForcedDisplayScalingMode(int displayId, int mode) { + } + + @Override public void setInTouchMode(boolean arg0) throws RemoteException { // TODO Auto-generated method stub } |