wm命令(wm size)修改屏幕尺寸
来源:互联网 发布:mac os 百度云 编辑:程序博客网 时间:2024/06/05 15:17
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; }
- wm命令(wm size)修改屏幕尺寸
- wm/ce 模拟器 内存 屏幕 修改
- wm命令使用方法(修改android 分辨率)修改
- WM size work flow
- WM有约(四):处理屏幕旋转
- wm屏幕校准
- C# wm 注册表修改
- 使用wm命令修改Dragonboard410c Android的显示分辨率
- web2(wm)修改之——模板
- web2(wm)修改之——中文重复标签
- 强制跳过WM调整屏幕的方法
- WM平台旋转屏幕的编程实现
- Kitkat小屏幕模式单手操作研究之wm命令的实现方式分析
- 每天一个adb命令:wm命令详解
- WM性能优化(一)
- ucgui窗体管理(WM)
- ucgui窗体管理(WM)
- ucgui窗体管理(WM)
- Unity Shader (五)混合(Blend)
- 1233: 华科版C语言程序设计教程(第二版)习题6.7
- Java正则表达式应用
- Microsoft's Rich Signature (undocumented)
- kafka源码分析(持续更新)
- wm命令(wm size)修改屏幕尺寸
- googlemaps自定义infowindow
- 正式开始我的微博之路--swift
- Intellij Idea的日常
- mysql数据库基础--未完
- JS显示时间
- CXF系列(六):CXF实现REST接口开发
- c++中基类虚函数表的深入解析
- ClassLoader