wm size可以查看当前屏幕分辨率,也可以设置屏幕分辨率(当然也就一般调试问题wm size)。
eg: wm size 720x1280
这里要注意了乘号不是*,是x字母
一、Wm源码
我们先来看下wm源码,Wm.java中关于wm size部分。
-
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) {
-
}
-
}
当没有参数时会WMS中的initialSize和baseSize,如果有参数,最终会调用WMS的setForcedDisplaySize函数,如果是reset就调用WMS的clearForcedDisplaySize函数重置分辨率。
二、WMS设置分辨率
下面我们主要看下WMS的setForcedDisplaySize函数:
-
public void setForcedDisplaySize(int displayId, int width, int height) {
-
......
-
final
long ident = Binder.clearCallingIdentity();
-
try {
-
synchronized(mWindowMap) {
-
// Set some sort of reasonable bounds on the size of the display that we
-
// will try to emulate.
-
final
int MIN_WIDTH =
200;
-
final
int MIN_HEIGHT =
200;
-
final
int MAX_SCALE =
2;
-
final DisplayContent displayContent = getDisplayContentLocked(displayId);
-
if (displayContent != null) {
-
width = Math.min(Math.max(width, MIN_WIDTH),
-
displayContent.mInitialDisplayWidth * MAX_SCALE);
-
height = Math.min(Math.max(height, MIN_HEIGHT),
-
displayContent.mInitialDisplayHeight * MAX_SCALE);
-
setForcedDisplaySizeLocked(displayContent, width, height);
-
Settings.Global.putString(mContext.getContentResolver(),
-
Settings.Global.DISPLAY_SIZE_FORCED, width +
"," + height);
-
}
-
}
-
} finally {
-
Binder.restoreCallingIdentity(ident);
-
}
-
}
最后调用了setForcedDisplaySizeLocked函数,这个函数主要设置了displayContent的mBaseDisplayWidth和mBaseDisplayHeight变量,然后调用了reconfigureDisplayLocked函数。
-
private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
-
Slog.i(TAG,
"Using new display size: " + width +
"x" + height);
-
-
synchronized(displayContent.mDisplaySizeLock) {
-
displayContent.mBaseDisplayWidth = width;
-
displayContent.mBaseDisplayHeight = height;
-
}
-
reconfigureDisplayLocked(displayContent);
-
}
reconfigureDisplayLocked函数先调用了computeScreenConfigurationLocked函数,这个函数会通知DisplayManagerService相关设备的信息改变了,然后发送SEND_NEW_CONFIGURATION消息通知AMS(这个在http://blog.csdn.net/kc58236582/article/details/53735136博客中分析过了),以及调用performLayoutAndPlaceSurfacesLocked刷新系统。
-
private void reconfigureDisplayLocked(DisplayContent displayContent) {
-
// TODO: Multidisplay: for now only use with default display.
-
if (!mDisplayReady) {
-
return;
-
}
-
configureDisplayPolicyLocked(displayContent);
-
displayContent.layoutNeeded =
true;
-
-
boolean configChanged = updateOrientationFromAppTokensLocked(
false);
-
mTempConfiguration.setToDefaults();
-
mTempConfiguration.fontScale = mCurConfiguration.fontScale;
-
computeScreenConfigurationLocked(mTempConfiguration);
-
configChanged |= mCurConfiguration.diff(mTempConfiguration) !=
0;
-
-
if (configChanged) {
-
mWaitingForConfig =
true;
-
startFreezingDisplayLocked(
false,
0,
0);
-
mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
-
}
-
-
performLayoutAndPlaceSurfacesLocked();
-
}
因此我们先看computeScreenConfigurationLocked函数,第一行就调用了updateDisplayAndOrientationLocked函数。
-
void computeScreenConfigurationLocked(Configuration config) {
-
final DisplayInfo displayInfo = updateDisplayAndOrientationLocked();
这个函数会获取displayContent的mBaseDisplayWidth和mBaseDisplayHeight,然后封装在displayInfo,最终调用mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager
-
DisplayInfo updateDisplayAndOrientationLocked() {
-
// TODO(multidisplay): For now, apply Configuration to main screen only.
-
final DisplayContent displayContent = getDefaultDisplayContentLocked();
-
-
// Use the effective "visual" dimensions based on current rotation
-
final boolean rotated = (mRotation == Surface.ROTATION_90
-
|| mRotation == Surface.ROTATION_270);
-
final
int realdw = rotated ?
-
displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
-
final
int realdh = rotated ?
-
displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
-
int dw = realdw;
-
int dh = realdh;
-
-
if (mAltOrientation) {
-
if (realdw > realdh) {
-
// Turn landscape into portrait.
-
int maxw = (
int)(realdh/
1.3f);
-
if (maxw < realdw) {
-
dw = maxw;
-
}
-
}
else {
-
// Turn portrait into landscape.
-
int maxh = (
int)(realdw/
1.3f);
-
if (maxh < realdh) {
-
dh = maxh;
-
}
-
}
-
}
-
-
// Update application display metrics.
-
final
int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
-
final
int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
-
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
-
synchronized(displayContent.mDisplaySizeLock) {
-
displayInfo.rotation = mRotation;
-
displayInfo.logicalWidth = dw;
-
displayInfo.logicalHeight = dh;
-
displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
-
displayInfo.appWidth = appWidth;
-
displayInfo.appHeight = appHeight;
-
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
//设置到DisplayManagerService中去
-
displayContent.getDisplayId(), displayInfo);
-
-
displayContent.mBaseDisplayRect.
set(
0,
0, dw, dh);
-
}
-
if (
false) {
-
Slog.i(TAG,
"Set app display size: " + appWidth +
" x " + appHeight);
-
}
-
-
mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics,
-
mCompatDisplayMetrics);
-
return displayInfo;
-
}
2.1 WMS传递DeviceInfo到DisplayManagerService中
WMS通过DeviceManagerService的setDisplayInfoOverrideFromWindowManager函数把DeviceInfo到DisplayManagerService中。
setDisplayInfoOverrideFromWindowManager函数之前分析过,这里我们再看下,直接调用了setDisplayInfoOverrideFromWindowManagerInternal函数
-
@
Override
-
public
void
setDisplayInfoOverrideFromWindowManager
(int displayId, DisplayInfo info) {
-
setDisplayInfoOverrideFromWindowManagerInternal(displayId, info);
-
}
而setDisplayInfoOverrideFromWindowManagerInternal方法,找到合适的LogicalDisplay,然后调用其setDisplayInfoOverrideFromWindowManagerLocked方法把DisplayInfo保存下来。
-
private void setDisplayInfoOverrideFromWindowManagerInternal(
-
int displayId, DisplayInfo info) {
-
synchronized (mSyncRoot) {
-
LogicalDisplay display = mLogicalDisplays.get(displayId);
-
if (display != null) {
-
if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) {
-
sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
-
scheduleTraversalLocked(
false);
-
}
-
}
-
}
-
}
setDisplayInfoOverrideFromWindowManagerLocked只是把DeviceInfo保存在mOverrideDisplayInfo中。
-
public boolean setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo info) {
-
if (info != null) {
-
if (mOverrideDisplayInfo == null) {
-
mOverrideDisplayInfo =
new DisplayInfo(info);
-
mInfo = null;
-
return
true;
-
}
-
if (!mOverrideDisplayInfo.equals(info)) {
-
mOverrideDisplayInfo.copyFrom(info);
-
mInfo = null;
-
return
true;
-
}
-
}
else
if (mOverrideDisplayInfo != null) {
-
mOverrideDisplayInfo = null;
-
mInfo = null;
-
return
true;
-
}
-
return
false;
-
}
2.2 DisplayManagerService设置信息(屏幕长宽、旋转等)到SurfaceControl
然后会在WMS的刷新核心函数performLayoutAndPlaceSurfacesLockedInner调用了如下代码:
mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
performTraversalInTransactionFromWindowManager函数直接调用了performTraversalInTransactionFromWindowManagerInternal函数
-
@
Override
-
public
void
performTraversalInTransactionFromWindowManager
() {
-
performTraversalInTransactionFromWindowManagerInternal();
-
}
performTraversalInTransactionFromWindowManagerInternal函数,我们主要看下performTraversalInTransactionLocked函数。
-
private void performTraversalInTransactionFromWindowManagerInternal() {
-
synchronized (mSyncRoot) {
-
if (!mPendingTraversal) {
-
return;
-
}
-
mPendingTraversal =
false;
-
-
performTraversalInTransactionLocked();
-
}
-
-
// List is self-synchronized copy-on-write.
-
for (DisplayTransactionListener listener : mDisplayTransactionListeners) {
-
listener.onDisplayTransaction();
-
}
-
}
performTraversalInTransactionLocked函数会遍历所有的DisplayDevice,然后调用configureDisplayInTransactionLocked函数。
-
private void performTraversalInTransactionLocked() {
-
// Clear all viewports before configuring displays so that we can keep
-
// track of which ones we have configured.
-
clearViewportsLocked();
-
-
// Configure each display device.
-
final
int count = mDisplayDevices.size();
-
for (
int i =
0; i < count; i++) {
-
DisplayDevice device = mDisplayDevices.get(i);
-
configureDisplayInTransactionLocked(device);
-
device.performTraversalInTransactionLocked();
-
}
-
-
// Tell the input system about these new viewports.
-
if (mInputManagerInternal != null) {
-
mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
-
}
-
}
configureDisplayInTransactionLocked这个函数会调用LogicalDisplay的configureDisplayInTransactionLocked函数
-
private void configureDisplayInTransactionLocked(DisplayDevice device) {
-
final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
-
......
-
display.configureDisplayInTransactionLocked(device, info.state == Display.STATE_OFF);
-
-
......
-
}
我们最后再来看LogicalDisplay的configureDisplayInTransactionLocked函数,会调用getDisplayInfoLocked函数,获取DisplayInfo,然后利用其displayInfo.logicalWidth, displayInfo.logicalHeight,新建一个矩阵,以及orientation,最后
device.setProjectionInTransactionLocked函数设置到SurfaceControl中去(有旋转、长宽矩阵)。(这里我们之前在
http://blog.csdn.net/kc58236582/article/details/53689526博客中分析过)
-
public void configureDisplayInTransactionLocked(DisplayDevice device,
-
boolean isBlanked) {
-
......
-
final DisplayInfo displayInfo = getDisplayInfoLocked();
-
final DisplayDeviceInfo displayDeviceInfo = device.getDisplayDeviceInfoLocked();
-
-
mTempLayerStackRect.
set(
0,
0, displayInfo.logicalWidth, displayInfo.logicalHeight);
-
-
// Set the orientation.
-
// The orientation specifies how the physical coordinate system of the display
-
// is rotated when the contents of the logical display are rendered.
-
int orientation = Surface.ROTATION_0;
-
if ((displayDeviceInfo.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) !=
0) {
-
orientation = displayInfo.rotation;
-
}
-
-
// Apply the physical rotation of the display device itself.
-
orientation = (orientation + displayDeviceInfo.rotation) %
4;
-
-
// Set the frame.
-
// The frame specifies the rotated physical coordinates into which the viewport
-
// is mapped. We need to take care to preserve the aspect ratio of the viewport.
-
// Currently we maximize the area to fill the display, but we could try to be
-
// more clever and match resolutions.
-
boolean rotated = (orientation == Surface.ROTATION_90
-
|| orientation == Surface.ROTATION_270);
-
int physWidth = rotated ? displayDeviceInfo.height : displayDeviceInfo.width;
-
int physHeight = rotated ? displayDeviceInfo.width : displayDeviceInfo.height;
-
-
// Determine whether the width or height is more constrained to be scaled.
-
// physWidth / displayInfo.logicalWidth => letter box
-
// or physHeight / displayInfo.logicalHeight => pillar box
-
//
-
// We avoid a division (and possible floating point imprecision) here by
-
// multiplying the fractions by the product of their denominators before
-
// comparing them.
-
int displayRectWidth, displayRectHeight;
-
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;
-
displayRectHeight = displayInfo.logicalHeight * physWidth / displayInfo.logicalWidth;
-
}
else {
-
// Pillar box.
-
displayRectWidth = displayInfo.logicalWidth * physHeight / displayInfo.logicalHeight;
-
displayRectHeight = physHeight;
-
}
-
int displayRectTop = (physHeight - displayRectHeight) /
2;
-
int displayRectLeft = (physWidth - displayRectWidth) /
2;
-
mTempDisplayRect.
set(displayRectLeft, displayRectTop,
-
displayRectLeft + displayRectWidth, displayRectTop + displayRectHeight);
-
-
mTempDisplayRect.left += mDisplayOffsetX;
-
mTempDisplayRect.right += mDisplayOffsetX;
-
mTempDisplayRect.top += mDisplayOffsetY;
-
mTempDisplayRect.bottom += mDisplayOffsetY;
-
device.setProjectionInTransactionLocked(orientation, mTempLayerStackRect, mTempDisplayRect);
-
}
而getDisplayInfoLocked方法就是把mOverrideDisplayInfo数据放到mInfo中返回。mOverrideDisplayInfo就是之前在WMS的updateDisplayAndOrientationLocked调用DisplayManagerService的函数传入的数据。
-
public DisplayInfo getDisplayInfoLocked() {
-
if (mInfo == null) {
-
mInfo =
new DisplayInfo();
-
mInfo.copyFrom(mBaseDisplayInfo);
-
if (mOverrideDisplayInfo != null) {
-
mInfo.appWidth = mOverrideDisplayInfo.appWidth;
-
mInfo.appHeight = mOverrideDisplayInfo.appHeight;
-
mInfo.smallestNominalAppWidth = mOverrideDisplayInfo.smallestNominalAppWidth;
-
mInfo.smallestNominalAppHeight = mOverrideDisplayInfo.smallestNominalAppHeight;
-
mInfo.largestNominalAppWidth = mOverrideDisplayInfo.largestNominalAppWidth;
-
mInfo.largestNominalAppHeight = mOverrideDisplayInfo.largestNominalAppHeight;
-
mInfo.logicalWidth = mOverrideDisplayInfo.logicalWidth;
-
mInfo.logicalHeight = mOverrideDisplayInfo.logicalHeight;
-
mInfo.overscanLeft = mOverrideDisplayInfo.overscanLeft;
-
mInfo.overscanTop = mOverrideDisplayInfo.overscanTop;
-
mInfo.overscanRight = mOverrideDisplayInfo.overscanRight;
-
mInfo.overscanBottom = mOverrideDisplayInfo.overscanBottom;
-
mInfo.rotation = mOverrideDisplayInfo.rotation;
-
mInfo.logicalDensityDpi = mOverrideDisplayInfo.logicalDensityDpi;
-
mInfo.physicalXDpi = mOverrideDisplayInfo.physicalXDpi;
-
mInfo.physicalYDpi = mOverrideDisplayInfo.physicalYDpi;
-
}
-
}
-
return mInfo;
-
}