WM size work flow

wm size可以查看当前屏幕分辨率,也可以设置屏幕分辨率(当然也就一般调试问题wm size)。

eg: wm size 720x1280

这里要注意了乘号不是*,是x字母

一、Wm源码

我们先来看下wm源码,Wm.java中关于wm size部分。

  1. private void runDisplaySize() throws Exception {  
  2.     String size = nextArg();  
  3.     int w, h;  
  4.     if (size == null) {  
  5.         Point initialSize = new Point();  
  6.         Point baseSize = new Point();  
  7.         try {  
  8.             mWm.getInitialDisplaySize(Display.DEFAULT_DISPLAY, initialSize);  
  9.             mWm.getBaseDisplaySize(Display.DEFAULT_DISPLAY, baseSize);  
  10.             System.out.println("Physical size: " + initialSize.x + "x" + initialSize.y);  
  11.             if (!initialSize.equals(baseSize)) {  
  12.                 System.out.println("Override size: " + baseSize.x + "x" + baseSize.y);  
  13.             }  
  14.         } catch (RemoteException e) {  
  15.         }  
  16.         return;  
  17.     } else if ("reset".equals(size)) {  
  18.         w = h = -1;  
  19.     } else {  
  20.         int div = size.indexOf('x');  
  21.         if (div <= 0 || div >= (size.length()-1)) {  
  22.             System.err.println("Error: bad size " + size);  
  23.             return;  
  24.         }  
  25.         String wstr = size.substring(0, div);  
  26.         String hstr = size.substring(div+1);  
  27.         try {  
  28.             w = parseDimension(wstr);  
  29.             h = parseDimension(hstr);  
  30.         } catch (NumberFormatException e) {  
  31.             System.err.println("Error: bad number " + e);  
  32.             return;  
  33.         }  
  34.     }  
  35.   
  36.     try {  
  37.         if (w >= 0 && h >= 0) {  
  38.             // TODO(multidisplay): For now Configuration only applies to main screen.  
  39.             mWm.setForcedDisplaySize(Display.DEFAULT_DISPLAY, w, h);  
  40.         } else {  
  41.             mWm.clearForcedDisplaySize(Display.DEFAULT_DISPLAY);  
  42.         }  
  43.     } catch (RemoteException e) {  
  44.     }  
  45. }  

当没有参数时会WMS中的initialSize和baseSize,如果有参数,最终会调用WMS的setForcedDisplaySize函数,如果是reset就调用WMS的clearForcedDisplaySize函数重置分辨率。

二、WMS设置分辨率

下面我们主要看下WMS的setForcedDisplaySize函数:

  1. public void setForcedDisplaySize(int displayId, int width, int height) {  
  2.     ......  
  3.     final long ident = Binder.clearCallingIdentity();  
  4.     try {  
  5.         synchronized(mWindowMap) {  
  6.             // Set some sort of reasonable bounds on the size of the display that we  
  7.             // will try to emulate.  
  8.             final int MIN_WIDTH = 200;  
  9.             final int MIN_HEIGHT = 200;  
  10.             final int MAX_SCALE = 2;  
  11.             final DisplayContent displayContent = getDisplayContentLocked(displayId);  
  12.             if (displayContent != null) {  
  13.                 width = Math.min(Math.max(width, MIN_WIDTH),  
  14.                         displayContent.mInitialDisplayWidth * MAX_SCALE);  
  15.                 height = Math.min(Math.max(height, MIN_HEIGHT),  
  16.                         displayContent.mInitialDisplayHeight * MAX_SCALE);  
  17.                 setForcedDisplaySizeLocked(displayContent, width, height);  
  18.                 Settings.Global.putString(mContext.getContentResolver(),  
  19.                         Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);  
  20.             }  
  21.         }  
  22.     } finally {  
  23.         Binder.restoreCallingIdentity(ident);  
  24.     }  
  25. }  

最后调用了setForcedDisplaySizeLocked函数,这个函数主要设置了displayContent的mBaseDisplayWidth和mBaseDisplayHeight变量,然后调用了reconfigureDisplayLocked函数。

  1. private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {  
  2.     Slog.i(TAG, "Using new display size: " + width + "x" + height);  
  3.   
  4.     synchronized(displayContent.mDisplaySizeLock) {  
  5.         displayContent.mBaseDisplayWidth = width;  
  6.         displayContent.mBaseDisplayHeight = height;  
  7.     }  
  8.     reconfigureDisplayLocked(displayContent);  
  9. }  

reconfigureDisplayLocked函数先调用了computeScreenConfigurationLocked函数,这个函数会通知DisplayManagerService相关设备的信息改变了,然后发送SEND_NEW_CONFIGURATION消息通知AMS(这个在http://blog.csdn.net/kc58236582/article/details/53735136博客中分析过了),以及调用performLayoutAndPlaceSurfacesLocked刷新系统。

  1. private void reconfigureDisplayLocked(DisplayContent displayContent) {  
  2.     // TODO: Multidisplay: for now only use with default display.  
  3.     if (!mDisplayReady) {  
  4.         return;  
  5.     }  
  6.     configureDisplayPolicyLocked(displayContent);  
  7.     displayContent.layoutNeeded = true;  
  8.   
  9.     boolean configChanged = updateOrientationFromAppTokensLocked(false);  
  10.     mTempConfiguration.setToDefaults();  
  11.     mTempConfiguration.fontScale = mCurConfiguration.fontScale;  
  12.     computeScreenConfigurationLocked(mTempConfiguration);  
  13.     configChanged |= mCurConfiguration.diff(mTempConfiguration) != 0;  
  14.   
  15.     if (configChanged) {  
  16.         mWaitingForConfig = true;  
  17.         startFreezingDisplayLocked(false, 0, 0);  
  18.         mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);  
  19.     }  
  20.   
  21.     performLayoutAndPlaceSurfacesLocked();  
  22. }  
因此我们先看computeScreenConfigurationLocked函数,第一行就调用了updateDisplayAndOrientationLocked函数。
  1. void computeScreenConfigurationLocked(Configuration config) {  
  2.     final DisplayInfo displayInfo = updateDisplayAndOrientationLocked();  

这个函数会获取displayContent的mBaseDisplayWidth和mBaseDisplayHeight,然后封装在displayInfo,最终调用mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager

  1. DisplayInfo updateDisplayAndOrientationLocked() {  
  2.     // TODO(multidisplay): For now, apply Configuration to main screen only.  
  3.     final DisplayContent displayContent = getDefaultDisplayContentLocked();  
  4.   
  5.     // Use the effective "visual" dimensions based on current rotation  
  6.     final boolean rotated = (mRotation == Surface.ROTATION_90  
  7.             || mRotation == Surface.ROTATION_270);  
  8.     final int realdw = rotated ?  
  9.             displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;  
  10.     final int realdh = rotated ?  
  11.             displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;  
  12.     int dw = realdw;  
  13.     int dh = realdh;  
  14.   
  15.     if (mAltOrientation) {  
  16.         if (realdw > realdh) {  
  17.             // Turn landscape into portrait.  
  18.             int maxw = (int)(realdh/1.3f);  
  19.             if (maxw < realdw) {  
  20.                 dw = maxw;  
  21.             }  
  22.         } else {  
  23.             // Turn portrait into landscape.  
  24.             int maxh = (int)(realdw/1.3f);  
  25.             if (maxh < realdh) {  
  26.                 dh = maxh;  
  27.             }  
  28.         }  
  29.     }  
  30.   
  31.     // Update application display metrics.  
  32.     final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);  
  33.     final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);  
  34.     final DisplayInfo displayInfo = displayContent.getDisplayInfo();  
  35.     synchronized(displayContent.mDisplaySizeLock) {  
  36.         displayInfo.rotation = mRotation;  
  37.         displayInfo.logicalWidth = dw;  
  38.         displayInfo.logicalHeight = dh;  
  39.         displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;  
  40.         displayInfo.appWidth = appWidth;  
  41.         displayInfo.appHeight = appHeight;  
  42.         displayInfo.getLogicalMetrics(mRealDisplayMetrics,  
  43.                 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);  
  44.         displayInfo.getAppMetrics(mDisplayMetrics);  
  45.         if (displayContent.mDisplayScalingDisabled) {  
  46.             displayInfo.flags |= Display.FLAG_SCALING_DISABLED;  
  47.         } else {  
  48.             displayInfo.flags &= ~Display.FLAG_SCALING_DISABLED;  
  49.         }  
  50.   
  51.         mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager//设置到DisplayManagerService中去  
  52.                 displayContent.getDisplayId(), displayInfo);  
  53.   
  54.         displayContent.mBaseDisplayRect.set(0, 0, dw, dh);  
  55.     }  
  56.     if (false) {  
  57.         Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight);  
  58.     }  
  59.   
  60.     mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics,  
  61.             mCompatDisplayMetrics);  
  62.     return displayInfo;  
  63. }  

2.1 WMS传递DeviceInfo到DisplayManagerService中

WMS通过DeviceManagerService的setDisplayInfoOverrideFromWindowManager函数把DeviceInfo到DisplayManagerService中。

setDisplayInfoOverrideFromWindowManager函数之前分析过,这里我们再看下,直接调用了setDisplayInfoOverrideFromWindowManagerInternal函数

  1. @Override  
  2. public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) {  
  3.     setDisplayInfoOverrideFromWindowManagerInternal(displayId, info);  
  4. }  

而setDisplayInfoOverrideFromWindowManagerInternal方法,找到合适的LogicalDisplay,然后调用其setDisplayInfoOverrideFromWindowManagerLocked方法把DisplayInfo保存下来。

  1. private void setDisplayInfoOverrideFromWindowManagerInternal(  
  2.         int displayId, DisplayInfo info) {  
  3.     synchronized (mSyncRoot) {  
  4.         LogicalDisplay display = mLogicalDisplays.get(displayId);  
  5.         if (display != null) {  
  6.             if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) {  
  7.                 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);  
  8.                 scheduleTraversalLocked(false);  
  9.             }  
  10.         }  
  11.     }  
  12. }  
setDisplayInfoOverrideFromWindowManagerLocked只是把DeviceInfo保存在mOverrideDisplayInfo中。
  1. public boolean setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo info) {  
  2.     if (info != null) {  
  3.         if (mOverrideDisplayInfo == null) {  
  4.             mOverrideDisplayInfo = new DisplayInfo(info);  
  5.             mInfo = null;  
  6.             return true;  
  7.         }  
  8.         if (!mOverrideDisplayInfo.equals(info)) {  
  9.             mOverrideDisplayInfo.copyFrom(info);  
  10.             mInfo = null;  
  11.             return true;  
  12.         }  
  13.     } else if (mOverrideDisplayInfo != null) {  
  14.         mOverrideDisplayInfo = null;  
  15.         mInfo = null;  
  16.         return true;  
  17.     }  
  18.     return false;  
  19. }  

2.2 DisplayManagerService设置信息(屏幕长宽、旋转等)到SurfaceControl

然后会在WMS的刷新核心函数performLayoutAndPlaceSurfacesLockedInner调用了如下代码:

  1. mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();  

performTraversalInTransactionFromWindowManager函数直接调用了performTraversalInTransactionFromWindowManagerInternal函数

  1. @Override  
  2. public void performTraversalInTransactionFromWindowManager() {  
  3.     performTraversalInTransactionFromWindowManagerInternal();  
  4. }  

performTraversalInTransactionFromWindowManagerInternal函数,我们主要看下performTraversalInTransactionLocked函数。

  1. private void performTraversalInTransactionFromWindowManagerInternal() {  
  2.     synchronized (mSyncRoot) {  
  3.         if (!mPendingTraversal) {  
  4.             return;  
  5.         }  
  6.         mPendingTraversal = false;  
  7.   
  8.         performTraversalInTransactionLocked();  
  9.     }  
  10.   
  11.     // List is self-synchronized copy-on-write.  
  12.     for (DisplayTransactionListener listener : mDisplayTransactionListeners) {  
  13.         listener.onDisplayTransaction();  
  14.     }  
  15. }  

performTraversalInTransactionLocked函数会遍历所有的DisplayDevice,然后调用configureDisplayInTransactionLocked函数。

  1. private void performTraversalInTransactionLocked() {  
  2.     // Clear all viewports before configuring displays so that we can keep  
  3.     // track of which ones we have configured.  
  4.     clearViewportsLocked();  
  5.   
  6.     // Configure each display device.  
  7.     final int count = mDisplayDevices.size();  
  8.     for (int i = 0; i < count; i++) {  
  9.         DisplayDevice device = mDisplayDevices.get(i);  
  10.         configureDisplayInTransactionLocked(device);  
  11.         device.performTraversalInTransactionLocked();  
  12.     }  
  13.   
  14.     // Tell the input system about these new viewports.  
  15.     if (mInputManagerInternal != null) {  
  16.         mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);  
  17.     }  
  18. }  

configureDisplayInTransactionLocked这个函数会调用LogicalDisplay的configureDisplayInTransactionLocked函数

  1. private void configureDisplayInTransactionLocked(DisplayDevice device) {  
  2.     final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();  
  3.     ......  
  4.     display.configureDisplayInTransactionLocked(device, info.state == Display.STATE_OFF);  
  5.   
  6.     ......  
  7. }  
我们最后再来看LogicalDisplay的configureDisplayInTransactionLocked函数,会调用getDisplayInfoLocked函数,获取DisplayInfo,然后利用其displayInfo.logicalWidth, displayInfo.logicalHeight,新建一个矩阵,以及orientation,最后 device.setProjectionInTransactionLocked函数设置到SurfaceControl中去(有旋转、长宽矩阵)。(这里我们之前在 http://blog.csdn.net/kc58236582/article/details/53689526博客中分析过)
  1. public void configureDisplayInTransactionLocked(DisplayDevice device,  
  2.         boolean isBlanked) {  
  3.     ......  
  4.     final DisplayInfo displayInfo = getDisplayInfoLocked();  
  5.     final DisplayDeviceInfo displayDeviceInfo = device.getDisplayDeviceInfoLocked();  
  6.   
  7.     mTempLayerStackRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);  
  8.   
  9.     // Set the orientation.  
  10.     // The orientation specifies how the physical coordinate system of the display  
  11.     // is rotated when the contents of the logical display are rendered.  
  12.     int orientation = Surface.ROTATION_0;  
  13.     if ((displayDeviceInfo.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) != 0) {  
  14.         orientation = displayInfo.rotation;  
  15.     }  
  16.   
  17.     // Apply the physical rotation of the display device itself.  
  18.     orientation = (orientation + displayDeviceInfo.rotation) % 4;  
  19.   
  20.     // Set the frame.  
  21.     // The frame specifies the rotated physical coordinates into which the viewport  
  22.     // is mapped.  We need to take care to preserve the aspect ratio of the viewport.  
  23.     // Currently we maximize the area to fill the display, but we could try to be  
  24.     // more clever and match resolutions.  
  25.     boolean rotated = (orientation == Surface.ROTATION_90  
  26.             || orientation == Surface.ROTATION_270);  
  27.     int physWidth = rotated ? displayDeviceInfo.height : displayDeviceInfo.width;  
  28.     int physHeight = rotated ? displayDeviceInfo.width : displayDeviceInfo.height;  
  29.   
  30.     // Determine whether the width or height is more constrained to be scaled.  
  31.     //    physWidth / displayInfo.logicalWidth    => letter box  
  32.     // or physHeight / displayInfo.logicalHeight  => pillar box  
  33.     //  
  34.     // We avoid a division (and possible floating point imprecision) here by  
  35.     // multiplying the fractions by the product of their denominators before  
  36.     // comparing them.  
  37.     int displayRectWidth, displayRectHeight;  
  38.     if ((displayInfo.flags & Display.FLAG_SCALING_DISABLED) != 0) {  
  39.         displayRectWidth = displayInfo.logicalWidth;  
  40.         displayRectHeight = displayInfo.logicalHeight;  
  41.     } else if (physWidth * displayInfo.logicalHeight  
  42.             < physHeight * displayInfo.logicalWidth) {  
  43.         // Letter box.  
  44.         displayRectWidth = physWidth;  
  45.         displayRectHeight = displayInfo.logicalHeight * physWidth / displayInfo.logicalWidth;  
  46.     } else {  
  47.         // Pillar box.  
  48.         displayRectWidth = displayInfo.logicalWidth * physHeight / displayInfo.logicalHeight;  
  49.         displayRectHeight = physHeight;  
  50.     }  
  51.     int displayRectTop = (physHeight - displayRectHeight) / 2;  
  52.     int displayRectLeft = (physWidth - displayRectWidth) / 2;  
  53.     mTempDisplayRect.set(displayRectLeft, displayRectTop,  
  54.             displayRectLeft + displayRectWidth, displayRectTop + displayRectHeight);  
  55.   
  56.     mTempDisplayRect.left += mDisplayOffsetX;  
  57.     mTempDisplayRect.right += mDisplayOffsetX;  
  58.     mTempDisplayRect.top += mDisplayOffsetY;  
  59.     mTempDisplayRect.bottom += mDisplayOffsetY;  
  60.     device.setProjectionInTransactionLocked(orientation, mTempLayerStackRect, mTempDisplayRect);  
  61. }  
而getDisplayInfoLocked方法就是把mOverrideDisplayInfo数据放到mInfo中返回。mOverrideDisplayInfo就是之前在WMS的updateDisplayAndOrientationLocked调用DisplayManagerService的函数传入的数据。
  1. public DisplayInfo getDisplayInfoLocked() {  
  2.     if (mInfo == null) {  
  3.         mInfo = new DisplayInfo();  
  4.         mInfo.copyFrom(mBaseDisplayInfo);  
  5.         if (mOverrideDisplayInfo != null) {  
  6.             mInfo.appWidth = mOverrideDisplayInfo.appWidth;  
  7.             mInfo.appHeight = mOverrideDisplayInfo.appHeight;  
  8.             mInfo.smallestNominalAppWidth = mOverrideDisplayInfo.smallestNominalAppWidth;  
  9.             mInfo.smallestNominalAppHeight = mOverrideDisplayInfo.smallestNominalAppHeight;  
  10.             mInfo.largestNominalAppWidth = mOverrideDisplayInfo.largestNominalAppWidth;  
  11.             mInfo.largestNominalAppHeight = mOverrideDisplayInfo.largestNominalAppHeight;  
  12.             mInfo.logicalWidth = mOverrideDisplayInfo.logicalWidth;  
  13.             mInfo.logicalHeight = mOverrideDisplayInfo.logicalHeight;  
  14.             mInfo.overscanLeft = mOverrideDisplayInfo.overscanLeft;  
  15.             mInfo.overscanTop = mOverrideDisplayInfo.overscanTop;  
  16.             mInfo.overscanRight = mOverrideDisplayInfo.overscanRight;  
  17.             mInfo.overscanBottom = mOverrideDisplayInfo.overscanBottom;  
  18.             mInfo.rotation = mOverrideDisplayInfo.rotation;  
  19.             mInfo.logicalDensityDpi = mOverrideDisplayInfo.logicalDensityDpi;  
  20.             mInfo.physicalXDpi = mOverrideDisplayInfo.physicalXDpi;  
  21.             mInfo.physicalYDpi = mOverrideDisplayInfo.physicalYDpi;  
  22.         }  
  23.     }  
  24.     return mInfo;  
  25. }  






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值