Android6.0 旋转屏幕(四)应用强制设置方向

来源:互联网 发布:比亚乔都市印象150数据 编辑:程序博客网 时间:2024/05/16 08:14

有时候我们也可以强制应用横频,这又是如何做到的?

就是调用了AMS的setRequestedOrientation接口,这个接口先是调用WMS的setAppOrientation函数设置这个Activity在WMS中的方向。然后在调用WMS的updateOrientationFromAppTokens函数旋转屏幕,最后在调用updateConfigurationLocked这个函数之前博客分析过就是是否让Activity重新Launch等。

    @Override    public void setRequestedOrientation(IBinder token, int requestedOrientation) {        synchronized (this) {            ActivityRecord r = ActivityRecord.isInStackLocked(token);            if (r == null) {                return;            }            if (r.task != null && r.task.mResizeable) {                // Fixed screen orientation isn't supported with resizeable activities.                return;            }            final long origId = Binder.clearCallingIdentity();            mWindowManager.setAppOrientation(r.appToken, requestedOrientation);            Configuration config = mWindowManager.updateOrientationFromAppTokens(                    mConfiguration, r.mayFreezeScreenLocked(r.app) ? r.appToken : null);            if (config != null) {                r.frozenBeforeDestroy = true;                if (!updateConfigurationLocked(config, r, false, false)) {                    mStackSupervisor.resumeTopActivitiesLocked();                }            }            Binder.restoreCallingIdentity(origId);        }    }

我们先看下WMS的setAppOrientation函数,很简单就是找到这个apptoken的APPWindowToken,然后将其requestedOrientation值赋值。

    @Override    public void setAppOrientation(IApplicationToken token, int requestedOrientation) {        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,                "setAppOrientation()")) {            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");        }        synchronized(mWindowMap) {            AppWindowToken atoken = findAppWindowToken(token.asBinder());            if (atoken == null) {                Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token);                return;            }            atoken.requestedOrientation = requestedOrientation;        }    }

然后我们再来看WMS的updateOrientationFromAppTokens函数,这个函数主要调用了updateOrientationFromAppTokensLocked函数,这个函数先调用另一个updateOrientationFromAppTokensLocked函数,根据这个函数的返回值,返回true代表要旋转,就调用computeNewConfigurationLocked计算Configuration返回。

    private Configuration updateOrientationFromAppTokensLocked(            Configuration currentConfig, IBinder freezeThisOneIfNeeded) {        if (!mDisplayReady) {            return null;        }        Configuration config = null;        if (updateOrientationFromAppTokensLocked(false)) {            if (freezeThisOneIfNeeded != null) {                AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded);                if (atoken != null) {                    startAppFreezingScreenLocked(atoken);                }            }            config = computeNewConfigurationLocked();        } else if (currentConfig != null) {            // No obvious action we need to take, but if our current            // state mismatches the activity manager's, update it,            // disregarding font scale, which should remain set to            // the value of the previous configuration.            mTempConfiguration.setToDefaults();            mTempConfiguration.fontScale = currentConfig.fontScale;            computeScreenConfigurationLocked(mTempConfiguration);            if (currentConfig.diff(mTempConfiguration) != 0) {                mWaitingForConfig = true;                final DisplayContent displayContent = getDefaultDisplayContentLocked();                displayContent.layoutNeeded = true;                int anim[] = new int[2];                if (displayContent.isDimming()) {                    anim[0] = anim[1] = 0;                } else {                    mPolicy.selectRotationAnimationLw(anim);                }                startFreezingDisplayLocked(false, anim[0], anim[1]);                config = new Configuration(mTempConfiguration);            }        }        return config;    }
我们来看下updateOrientationFromAppTokensLocked函数,我们先调用了getOrientationLocked函数获取上次强制设置的方向,如果不同就调用updateRotationUncheckedLocked函数,这个函数之前博客分析过了,流程就一样了。最后就到DisplayManagerService中设置设备的方向。
    boolean updateOrientationFromAppTokensLocked(boolean inTransaction) {        long ident = Binder.clearCallingIdentity();        try {            int req = getOrientationLocked();            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);        }    }
最后我们回到AMS的setRequestedOrientation函数,我们调用updateConfigurationLocked函数,当返回false,就是现在的状态要改变(比如重启Activity),然后就调用ActivityStackSupervisor的resumeTopActivitiesLocked函数来启动最上面的Activity。
    public void setRequestedOrientation(IBinder token, int requestedOrientation) {        synchronized (this) {            ActivityRecord r = ActivityRecord.isInStackLocked(token);            if (r == null) {                return;            }            if (r.task != null && r.task.mResizeable) {                // Fixed screen orientation isn't supported with resizeable activities.                return;            }            final long origId = Binder.clearCallingIdentity();            mWindowManager.setAppOrientation(r.appToken, requestedOrientation);            Configuration config = mWindowManager.updateOrientationFromAppTokens(                    mConfiguration, r.mayFreezeScreenLocked(r.app) ? r.appToken : null);            if (config != null) {                r.frozenBeforeDestroy = true;                if (!updateConfigurationLocked(config, r, false, false)) {                    mStackSupervisor.resumeTopActivitiesLocked();                }            }            Binder.restoreCallingIdentity(origId);        }    }



2 0
原创粉丝点击