summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2015-04-15 19:02:36 -0700
committerJeff Brown <jeffbrown@google.com>2015-04-15 19:02:36 -0700
commitd46747a1c64b6ca3282e8841833980ab91829436 (patch)
treefeca484f9f10ee91399a12b41a524fb7f20a3eb5
parent10acf6d3efde60977d2d2e82b90c53d722d9d357 (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
-rw-r--r--cmds/wm/src/com/android/commands/wm/Wm.java46
-rw-r--r--core/java/android/provider/Settings.java7
-rw-r--r--core/java/android/view/Display.java9
-rw-r--r--core/java/android/view/DisplayInfo.java3
-rw-r--r--core/java/android/view/IWindowManager.aidl1
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplay.java5
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java63
-rw-r--r--tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java4
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
}