summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 815a0ac..64f023f 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 109c23b..cf1a5d1 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 71863b7..71e2251 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 ecf45b4..243961c 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 d6625c8..5994d4f 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 3bb7818..65dc72f 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 f073c23..f914369 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 e790fb0..04b71a4 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 818940d..82012c1 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
}