天天看點

如何将螢幕鎖定橫屏先看GIF簡要分析二、updateOrientationFromAppTokensLocked(boolean)函數代碼三、updateRotationUncheckedLocked(boolean)函數代碼四、小結

先看GIF

這是修改之前

如何将螢幕鎖定橫屏先看GIF簡要分析二、updateOrientationFromAppTokensLocked(boolean)函數代碼三、updateRotationUncheckedLocked(boolean)函數代碼四、小結

這是修改之後

如何将螢幕鎖定橫屏先看GIF簡要分析二、updateOrientationFromAppTokensLocked(boolean)函數代碼三、updateRotationUncheckedLocked(boolean)函數代碼四、小結

需要修改的檔案

   frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java   

簡要分析

在點開Activity時,會調用到視窗relayout。就自然到了WindowManagerService.java。這部分就不分析了。

一、relayoutWindow函數代碼

    public int relayoutWindow(Session session, IWindow client, int seq,

            WindowManager.LayoutParams attrs, int requestedWidth,

            int requestedHeight, int viewVisibility, int flags,

            Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,

            Rect outVisibleInsets, Rect outStableInsets, Configuration outConfig,

            Surface outSurface) {

        boolean toBeDisplayed = false;

        boolean inTouchMode;

        boolean configChanged;

        boolean surfaceChanged = false;

        boolean animating;

        boolean hasStatusBarPermission =

                mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)

                        == PackageManager.PERMISSION_GRANTED;

        long origId = Binder.clearCallingIdentity();

        synchronized(mWindowMap) {

            ......

            configChanged = updateOrientationFromAppTokensLocked(false);

            performLayoutAndPlaceSurfacesLocked();

            ......

        }

        if (configChanged) {

            sendNewConfiguration();

        }

        Binder.restoreCallingIdentity(origId);

        return (inTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0)

                | (toBeDisplayed ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0)

                | (surfaceChanged ? WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED : 0)

                | (animating ? WindowManagerGlobal.RELAYOUT_RES_ANIMATING : 0);

    }

執行到relayoutWindow後,核心部分看updateOrientationFromAppTokensLocked。

二、updateOrientationFromAppTokensLocked(boolean)函數代碼

    boolean updateOrientationFromAppTokensLocked(boolean inTransaction) {

        long ident = Binder.clearCallingIdentity();

        try {

            int req = getOrientationFromWindowsLocked();

            if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {

                req = getOrientationFromAppTokensLocked();

            }

            if (req != mForcedAppOrientation) {

                mForcedAppOrientation = req;

                //send a message to Policy indicating orientation change to take

                //action like disabling/enabling sensors etc.,

                mPolicy.setCurrentOrientationLw(req);

                if (updateRotationUncheckedLocked(inTransaction)) {

                    // changed

                    return true;

                }

            }

            return false;

        } finally {

            Binder.restoreCallingIdentity(ident);

        }

    }

注釋是一定要看的。Determine the new desired orientation of the display

可以看到,mForcedAppOrientation會被指派。然後,通過mPolicy的setCurentOrientationLw方法将新的orientation值作為新參數設定上去。

updateRotationUncheckedLocked(inTransaction)函數會mForcedAppOrientation用起來。

三、updateRotationUncheckedLocked(boolean)函數代碼

    // TODO(multidisplay): Rotate any display?

    public boolean updateRotationUncheckedLocked(boolean inTransaction) {

        ......

        // TODO: Implement forced rotation changes.

        //       Set mAltOrientation to indicate that the application is receiving

        //       an orientation that has different metrics than it expected.

        //       eg. Portrait instead of Landscape.

        int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation);

        boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(

                mForcedAppOrientation, rotation);

        ......

        return true;

}

注意看紅色字型。

四、小結

如何讓螢幕強制橫屏。

    boolean updateOrientationFromAppTokensLocked(boolean inTransaction) {

        long ident = Binder.clearCallingIdentity();

        try {

            int req = getOrientationFromWindowsLocked();

            if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {

                req = getOrientationFromAppTokensLocked();

            }

           req = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;

            if (req != mForcedAppOrientation) {

                mForcedAppOrientation = req;

                //send a message to Policy indicating orientation change to take

                //action like disabling/enabling sensors etc.,

                mPolicy.setCurrentOrientationLw(req);

                if (updateRotationUncheckedLocked(inTransaction)) {

                    // changed

                    return true;

                }

            }

            return false;

        } finally {

            Binder.restoreCallingIdentity(ident);

        }

    }

要強制橫屏。隻需要在 boolean updateOrientationFromAppTokensLocked(boolean inTransaction)中,将req強制成ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE即可。

具體效果,可以看文章頭的gif動态圖。

繼續閱讀