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;    }






1 0
原创粉丝点击