wm命令(wm size)修改屏幕尺寸

转载: https://blog.csdn.net/kc58236582/article/details/54315007

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. try {
  36. if (w >= 0 && h >= 0) {
  37. // TODO(multidisplay): For now Configuration only applies to main screen.
  38. mWm.setForcedDisplaySize(Display.DEFAULT_DISPLAY, w, h);
  39. } else {
  40. mWm.clearForcedDisplaySize(Display.DEFAULT_DISPLAY);
  41. }
  42. } catch (RemoteException e) {
  43. }
  44. }

当没有参数时会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. synchronized(displayContent.mDisplaySizeLock) {
  4. displayContent.mBaseDisplayWidth = width;
  5. displayContent.mBaseDisplayHeight = height;
  6. }
  7. reconfigureDisplayLocked(displayContent);
  8. }

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. boolean configChanged = updateOrientationFromAppTokensLocked( false);
  9. mTempConfiguration.setToDefaults();
  10. mTempConfiguration.fontScale = mCurConfiguration.fontScale;
  11. computeScreenConfigurationLocked(mTempConfiguration);
  12. configChanged |= mCurConfiguration.diff(mTempConfiguration) != 0;
  13. if (configChanged) {
  14. mWaitingForConfig = true;
  15. startFreezingDisplayLocked( false, 0, 0);
  16. mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
  17. }
  18. performLayoutAndPlaceSurfacesLocked();
  19. }
因此我们先看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. // Use the effective "visual" dimensions based on current rotation
  5. final boolean rotated = (mRotation == Surface.ROTATION_90
  6. || mRotation == Surface.ROTATION_270);
  7. final int realdw = rotated ?
  8. displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
  9. final int realdh = rotated ?
  10. displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
  11. int dw = realdw;
  12. int dh = realdh;
  13. if (mAltOrientation) {
  14. if (realdw > realdh) {
  15. // Turn landscape into portrait.
  16. int maxw = ( int)(realdh/ 1.3f);
  17. if (maxw < realdw) {
  18. dw = maxw;
  19. }
  20. } else {
  21. // Turn portrait into landscape.
  22. int maxh = ( int)(realdw/ 1.3f);
  23. if (maxh < realdh) {
  24. dh = maxh;
  25. }
  26. }
  27. }
  28. // Update application display metrics.
  29. final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
  30. final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
  31. final DisplayInfo displayInfo = displayContent.getDisplayInfo();
  32. synchronized(displayContent.mDisplaySizeLock) {
  33. displayInfo.rotation = mRotation;
  34. displayInfo.logicalWidth = dw;
  35. displayInfo.logicalHeight = dh;
  36. displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
  37. displayInfo.appWidth = appWidth;
  38. displayInfo.appHeight = appHeight;
  39. displayInfo.getLogicalMetrics(mRealDisplayMetrics,
  40. CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
  41. displayInfo.getAppMetrics(mDisplayMetrics);
  42. if (displayContent.mDisplayScalingDisabled) {
  43. displayInfo.flags |= Display.FLAG_SCALING_DISABLED;
  44. } else {
  45. displayInfo.flags &= ~Display.FLAG_SCALING_DISABLED;
  46. }
  47. mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager //设置到DisplayManagerService中去
  48. displayContent.getDisplayId(), displayInfo);
  49. displayContent.mBaseDisplayRect. set( 0, 0, dw, dh);
  50. }
  51. if ( false) {
  52. Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight);
  53. }
  54. mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics,
  55. mCompatDisplayMetrics);
  56. return displayInfo;
  57. }

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调用了如下代码:

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. performTraversalInTransactionLocked();
  8. }
  9. // List is self-synchronized copy-on-write.
  10. for (DisplayTransactionListener listener : mDisplayTransactionListeners) {
  11. listener.onDisplayTransaction();
  12. }
  13. }

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. // Configure each display device.
  6. final int count = mDisplayDevices.size();
  7. for ( int i = 0; i < count; i++) {
  8. DisplayDevice device = mDisplayDevices.get(i);
  9. configureDisplayInTransactionLocked(device);
  10. device.performTraversalInTransactionLocked();
  11. }
  12. // Tell the input system about these new viewports.
  13. if (mInputManagerInternal != null) {
  14. mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
  15. }
  16. }

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. }
我们最后再来看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. mTempLayerStackRect. set( 0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
  7. // Set the orientation.
  8. // The orientation specifies how the physical coordinate system of the display
  9. // is rotated when the contents of the logical display are rendered.
  10. int orientation = Surface.ROTATION_0;
  11. if ((displayDeviceInfo.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) != 0) {
  12. orientation = displayInfo.rotation;
  13. }
  14. // Apply the physical rotation of the display device itself.
  15. orientation = (orientation + displayDeviceInfo.rotation) % 4;
  16. // Set the frame.
  17. // The frame specifies the rotated physical coordinates into which the viewport
  18. // is mapped. We need to take care to preserve the aspect ratio of the viewport.
  19. // Currently we maximize the area to fill the display, but we could try to be
  20. // more clever and match resolutions.
  21. boolean rotated = (orientation == Surface.ROTATION_90
  22. || orientation == Surface.ROTATION_270);
  23. int physWidth = rotated ? displayDeviceInfo.height : displayDeviceInfo.width;
  24. int physHeight = rotated ? displayDeviceInfo.width : displayDeviceInfo.height;
  25. // Determine whether the width or height is more constrained to be scaled.
  26. // physWidth / displayInfo.logicalWidth => letter box
  27. // or physHeight / displayInfo.logicalHeight => pillar box
  28. //
  29. // We avoid a division (and possible floating point imprecision) here by
  30. // multiplying the fractions by the product of their denominators before
  31. // comparing them.
  32. int displayRectWidth, displayRectHeight;
  33. if ((displayInfo.flags & Display.FLAG_SCALING_DISABLED) != 0) {
  34. displayRectWidth = displayInfo.logicalWidth;
  35. displayRectHeight = displayInfo.logicalHeight;
  36. } else if (physWidth * displayInfo.logicalHeight
  37. < physHeight * displayInfo.logicalWidth) {
  38. // Letter box.
  39. displayRectWidth = physWidth;
  40. displayRectHeight = displayInfo.logicalHeight * physWidth / displayInfo.logicalWidth;
  41. } else {
  42. // Pillar box.
  43. displayRectWidth = displayInfo.logicalWidth * physHeight / displayInfo.logicalHeight;
  44. displayRectHeight = physHeight;
  45. }
  46. int displayRectTop = (physHeight - displayRectHeight) / 2;
  47. int displayRectLeft = (physWidth - displayRectWidth) / 2;
  48. mTempDisplayRect. set(displayRectLeft, displayRectTop,
  49. displayRectLeft + displayRectWidth, displayRectTop + displayRectHeight);
  50. mTempDisplayRect.left += mDisplayOffsetX;
  51. mTempDisplayRect.right += mDisplayOffsetX;
  52. mTempDisplayRect.top += mDisplayOffsetY;
  53. mTempDisplayRect.bottom += mDisplayOffsetY;
  54. device.setProjectionInTransactionLocked(orientation, mTempLayerStackRect, mTempDisplayRect);
  55. }
而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. }






  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值