wm size可以查看当前屏幕分辨率,也可以设置屏幕分辨率(当然也就一般调试问题wm size)。
eg: wm size 720x1280
这里要注意了乘号不是*,是x字母
一、Wm源码
我们先来看下wm源码,中关于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 {
(Display.DEFAULT_DISPLAY, initialSize);
(Display.DEFAULT_DISPLAY, baseSize);
("Physical size: " + + "x" + );
if (!(baseSize)) {
("Override size: " + + "x" + );
}
} catch (RemoteException e) {
}
return;
} else if ("reset".equals(size)) {
w = h = -1;
} else {
int div = ('x');
if (div <= 0 || div >= (()-1)) {
("Error: bad size " + size);
return;
}
String wstr = (0, div);
String hstr = (div+1);
try {
w = parseDimension(wstr);
h = parseDimension(hstr);
} catch (NumberFormatException e) {
("Error: bad number " + e);
return;
}
}
try {
if (w >= 0 && h >= 0) {
// TODO(multidisplay): For now Configuration only applies to main screen.
(Display.DEFAULT_DISPLAY, w, h);
} else {
(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 = ();
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 = ((width, MIN_WIDTH),
* MAX_SCALE);
height = ((height, MIN_HEIGHT),
* MAX_SCALE);
setForcedDisplaySizeLocked(displayContent, width, height);
((),
.DISPLAY_SIZE_FORCED, width + "," + height);
}
}
} finally {
(ident);
}
}
最后调用了setForcedDisplaySizeLocked函数,这个函数主要设置了displayContent的mBaseDisplayWidth和mBaseDisplayHeight变量,然后调用了reconfigureDisplayLocked函数。
private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
(TAG, "Using new display size: " + width + "x" + height);
synchronized() {
= width;
= height;
}
reconfigureDisplayLocked(displayContent);
}
reconfigureDisplayLocked函数先调用了computeScreenConfigurationLocked函数,这个函数会通知DisplayManagerService相关设备的信息改变了,然后发送SEND_NEW_CONFIGURATION消息通知AMS(这个在/kc58236582/article/details/53735136博客中分析过了),以及调用performLayoutAndPlaceSurfacesLocked刷新系统。
private void reconfigureDisplayLocked(DisplayContent displayContent) {
// TODO: Multidisplay: for now only use with default display.
if (!mDisplayReady) {
return;
}
configureDisplayPolicyLocked(displayContent);
= true;
boolean configChanged = updateOrientationFromAppTokensLocked(false);
();
= ;
computeScreenConfigurationLocked(mTempConfiguration);
configChanged |= (mTempConfiguration) != 0;
if (configChanged) {
mWaitingForConfig = true;
startFreezingDisplayLocked(false, 0, 0);
(H.SEND_NEW_CONFIGURATION);
}
performLayoutAndPlaceSurfacesLocked();
}
因此我们先看computeScreenConfigurationLocked函数,第一行就调用了updateDisplayAndOrientationLocked函数。
void computeScreenConfigurationLocked(Configuration config) {
final DisplayInfo displayInfo = updateDisplayAndOrientationLocked();
这个函数会获取displayContent的mBaseDisplayWidth和mBaseDisplayHeight,然后封装在displayInfo,最终调用
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 ?
: ;
final int realdh = rotated ?
: ;
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 = (dw, dh, mRotation);
final int appHeight = (dw, dh, mRotation);
final DisplayInfo displayInfo = ();
synchronized() {
= mRotation;
= dw;
= dh;
= ;
= appWidth;
= appHeight;
(mRealDisplayMetrics,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
(mDisplayMetrics);
if () {
|= Display.FLAG_SCALING_DISABLED;
} else {
&= ~Display.FLAG_SCALING_DISABLED;
}
//设置到DisplayManagerService中去
(), displayInfo);
(0, 0, dw, dh);
}
if (false) {
(TAG, "Set app display size: " + appWidth + " x " + appHeight);
}
mCompatibleScreenScale = (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 = (displayId);
if (display != null) {
if ((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 (!(info)) {
(info);
mInfo = null;
return true;
}
} else if (mOverrideDisplayInfo != null) {
mOverrideDisplayInfo = null;
mInfo = null;
return true;
}
return false;
}
2.2 DisplayManagerService设置信息(屏幕长宽、旋转等)到SurfaceControl
然后会在WMS的刷新核心函数performLayoutAndPlaceSurfacesLockedInner调用了如下代码:
();
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) {
();
}
}
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 = ();
for (int i = 0; i < count; i++) {
DisplayDevice device = (i);
configureDisplayInTransactionLocked(device);
();
}
// Tell the input system about these new viewports.
if (mInputManagerInternal != null) {
(MSG_UPDATE_VIEWPORT);
}
}
configureDisplayInTransactionLocked这个函数会调用LogicalDisplay的configureDisplayInTransactionLocked函数
private void configureDisplayInTransactionLocked(DisplayDevice device) {
final DisplayDeviceInfo info = ();
......
(device, == Display.STATE_OFF);
......
}
我们最后再来看LogicalDisplay的configureDisplayInTransactionLocked函数,会调用getDisplayInfoLocked函数,获取DisplayInfo,然后利用其, ,新建一个矩阵,以及orientation,最后
函数设置到SurfaceControl中去(有旋转、长宽矩阵)。(这里我们之前在
/kc58236582/article/details/53689526博客中分析过)
public void configureDisplayInTransactionLocked(DisplayDevice device,
boolean isBlanked) {
......
final DisplayInfo displayInfo = getDisplayInfoLocked();
final DisplayDeviceInfo displayDeviceInfo = ();
(0, 0, , );
// 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.FLAG_ROTATES_WITH_CONTENT) != 0) {
orientation = ;
}
// Apply the physical rotation of the display device itself.
orientation = (orientation + ) % 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 ? : ;
int physHeight = rotated ? : ;
// Determine whether the width or height is more constrained to be scaled.
// physWidth / => letter box
// or physHeight / => 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 (( & Display.FLAG_SCALING_DISABLED) != 0) {
displayRectWidth = ;
displayRectHeight = ;
} else if (physWidth *
< physHeight * ) {
// Letter box.
displayRectWidth = physWidth;
displayRectHeight = * physWidth / ;
} else {
// Pillar box.
displayRectWidth = * physHeight / ;
displayRectHeight = physHeight;
}
int displayRectTop = (physHeight - displayRectHeight) / 2;
int displayRectLeft = (physWidth - displayRectWidth) / 2;
(displayRectLeft, displayRectTop,
displayRectLeft + displayRectWidth, displayRectTop + displayRectHeight);
+= mDisplayOffsetX;
+= mDisplayOffsetX;
+= mDisplayOffsetY;
+= mDisplayOffsetY;
(orientation, mTempLayerStackRect, mTempDisplayRect);
}
而getDisplayInfoLocked方法就是把mOverrideDisplayInfo数据放到mInfo中返回。mOverrideDisplayInfo就是之前在WMS的updateDisplayAndOrientationLocked调用DisplayManagerService的函数传入的数据。
public DisplayInfo getDisplayInfoLocked() {
if (mInfo == null) {
mInfo = new DisplayInfo();
(mBaseDisplayInfo);
if (mOverrideDisplayInfo != null) {
= ;
= ;
= ;
= ;
= ;
= ;
= ;
= ;
= ;
= ;
= ;
= ;
= ;
= ;
= ;
= ;
}
}
return mInfo;
}