辅助设置中自动旋转

来源:互联网 发布:访问nginx 403 编辑:程序博客网 时间:2024/04/25 07:55

补充:4.4.4bug已经被修改

切入正题

AccessibilitySettings.java中,点击自动旋转的调用以下函数

private void handleLockScreenRotationPreferenceClick() {        RotationPolicy.setRotationLockForAccessibility(getActivity(),                !mToggleLockScreenRotationPreference.isChecked());}

很自然的跟踪到RotationPolicy.java

public static void setRotationLockForAccessibility(Context context, final boolean enabled) {        Settings.System.putIntForUser(context.getContentResolver(),                Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, enabled ? 1 : 0,                        UserHandle.USER_CURRENT);         AsyncTask.execute(new Runnable() {            @Override            public void run() {                try {                    IWindowManager wm = WindowManagerGlobal.getWindowManagerService();                    if (enabled) {                        wm.freezeRotation(Surface.ROTATION_0);                    } else {                        wm.thawRotation();                    }                } catch (RemoteException exc) {                    Log.w(TAG, "Unable to save auto-rotate setting");                }            }        });}


 

这里首先保存了设置的状态。然后,就根据状态做相应的设置。

1.     wm.freezeRotation(Surface.ROTATION_0);强制定死一个方向不旋转

2.     wm.thawRotation();我们重点看这个

 

 

WindowManagerService.java中看到这个函数

    public void thawRotation() {        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,                "thawRotation()")) {            throw new SecurityException("Requires SET_ORIENTATION permission");        }         if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation);         mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 777); // rot not used        updateRotationUnchecked(false, false);}

 

关键点来了:mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 777); // rot not used

看样子这个是主要部分。控制着旋转

 

updateRotationUnchecked(false, false);看起来是个状态更新。到时候更下去看看

 

 

紧跟着PhoneWindowManager.java

public void setUserRotationMode(int mode, int rot) {        ContentResolver res = mContext.getContentResolver();         // mUserRotationMode and mUserRotation will be assigned by the content observer        if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {            Settings.System.putIntForUser(res,                    Settings.System.USER_ROTATION,                    rot,                    UserHandle.USER_CURRENT);            Settings.System.putIntForUser(res,                    Settings.System.ACCELEROMETER_ROTATION,                    0,                    UserHandle.USER_CURRENT);        } else {            Settings.System.putIntForUser(res,                    Settings.System.ACCELEROMETER_ROTATION,                    1,                    UserHandle.USER_CURRENT);        }}



这个函数居然也只是状态更新啊。蛋疼。那在哪里做的.

 

 

重新回到WindowManagerService.java分析updateRotationUnchecked

public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {        if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked("                   + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");         long origId = Binder.clearCallingIdentity();        boolean changed;        synchronized(mWindowMap) {            changed = updateRotationUncheckedLocked(false);            if (!changed || forceRelayout) {                getDefaultDisplayContentLocked().layoutNeeded = true;                performLayoutAndPlaceSurfacesLocked();            }        }         if (changed || alwaysSendConfiguration) {            sendNewConfiguration();        }         Binder.restoreCallingIdentity(origId);}

 

一句句分析

long origId = Binder.clearCallingIdentity();---à清除调用进程的UIDPID,重置为被调用进程的UIDPID

 

updateRotationUncheckedLockedfalse)又是什么呢

贴源码

// TODO(multidisplay): Rotate any display?    public boolean updateRotationUncheckedLocked(boolean inTransaction) {        if (mDeferredRotationPauseCount > 0) {            // Rotation updates have been paused temporarily.  Defer the update until            // updates have been resumed.            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused.");            return false;        }         ScreenRotationAnimation screenRotationAnimation =            mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);//这玩意儿是旋转的动画,mAnimator是singleton,保存了ScreenRotationAnimation,同时,又持有DimSurface,想来这个就是最终要使用的Surface了吧。这里不做详细解释。        if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {            // Rotation updates cannot be performed while the previous rotation change            // animation is still in progress.  Skip this update.  We will try updating            // again after the animation is finished and the display is unfrozen.            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress.");            return false;        }         if (!mDisplayEnabled) {            // No point choosing a rotation if the display is not enabled.            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled.");            return false;        }         // 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);         if (DEBUG_ORIENTATION) {            Slog.v(TAG, "Application requested orientation "                    + mForcedAppOrientation + ", got rotation " + rotation                    + " which has " + (altOrientation ? "incompatible" : "compatible")                    + " metrics");        }         if (mRotation == rotation && mAltOrientation == altOrientation) {            // No change.            return false;        }         if (DEBUG_ORIENTATION) {            Slog.v(TAG,                "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")                + " from " + mRotation + (mAltOrientation ? " (alt)" : "")                + ", forceApp=" + mForcedAppOrientation);        }         mRotation = rotation;        mAltOrientation = altOrientation;        mPolicy.setRotationLw(mRotation);//更新旋转状态,同步到WindowOrientationListener中---------------系统默认设置中的旋转bug就在这里没做好。         mWindowsFreezingScreen = true;        mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);        mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT),                WINDOW_FREEZE_TIMEOUT_DURATION);//重新保存window信息        mWaitingForConfig = true;        getDefaultDisplayContentLocked().layoutNeeded = true;        startFreezingDisplayLocked(inTransaction, 0, 0);//保存状态,初始化        // startFreezingDisplayLocked can reset the ScreenRotationAnimation.        screenRotationAnimation =                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);         // We need to update our screen size information to match the new        // rotation.  Note that this is redundant with the later call to        // sendNewConfiguration() that must be called after this function        // returns...  however we need to do the screen size part of that        // before then so we have the correct size to use when initializing        // the rotation animation for the new rotation.        computeScreenConfigurationLocked(null);         final DisplayContent displayContent = getDefaultDisplayContentLocked();        final DisplayInfo displayInfo = displayContent.getDisplayInfo();        if (!inTransaction) {            if (SHOW_TRANSACTIONS) {                Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked");            }            Surface.openTransaction();        }        try {            // NOTE: We disable the rotation in the emulator because            //       it doesn't support hardware OpenGL emulation yet.            if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null                    && screenRotationAnimation.hasScreenshot()) {                if (screenRotationAnimation.setRotationInTransaction(                        rotation, mFxSession,                        MAX_ANIMATION_DURATION, mTransitionAnimationScale,                        displayInfo.logicalWidth, displayInfo.logicalHeight)) {                    updateLayoutToAnimationLocked();                }            }             mDisplayManagerService.performTraversalInTransactionFromWindowManager();        } finally {            if (!inTransaction) {                Surface.closeTransaction();                if (SHOW_LIGHT_TRANSACTIONS) {                    Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked");                }            }        }         final WindowList windows = displayContent.getWindowList();        for (int i = windows.size() - 1; i >= 0; i--) {            WindowState w = windows.get(i);            if (w.mHasSurface) {                if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w);                w.mOrientationChanging = true;                mInnerFields.mOrientationChangeComplete = false;            }        }         for (int i=mRotationWatchers.size()-1; i>=0; i--) {            try {                mRotationWatchers.get(i).onRotationChanged(rotation);            } catch (RemoteException e) {            }        }         scheduleNotifyRotationChangedIfNeededLocked(displayContent, rotation);         return true;    }

 

补充下Surface.java中,四个方向的定义

    public static final int ROTATION_0 = 0;    public static final int ROTATION_90 = 1;    public static final int ROTATION_180 = 2;    public static final int ROTATION_270 = 3;

  

int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation);//#这里比较重要。后续的计算都基于这个值。看下取到的是什么?

 

切换到PhoneWindowManager.java

@Override    public int rotationForOrientationLw(int orientation, int lastRotation) {        if (true) {            Slog.v("WindowManager", "aaaaaaaaaa  rotationForOrientationLw(orient="                        + orientation + ", last=" + lastRotation                        + "); user=" + mUserRotation + " "                        + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)                            ? "USER_ROTATION_LOCKED" : "")                        );        }         synchronized (mLock) {            int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1            if (sensorRotation < 0) {                sensorRotation = lastRotation;            }……这部分都是些系统旋转的东西……}


而这里是getProposedRotation,是在WindowOrientationListener.java中,

直接返回mProposedRotation

 

mPolicy.setRotationLw(mRotation);

更新了这个listener的状态。

那么。WindowOrientationListener.java是何方神圣

跟进去后发现,在disable的状态中,没有重新初始化数字,依旧保存了上次的数值。导致了这个问题

    public void disable() {        if (mSensor == null) {            Log.w(TAG, "Cannot detect sensors. Invalid disable");            return;        }        if (mEnabled == true) {            if (LOG) {                Log.d(TAG, "WindowOrientationListener disabled");            }        mSensorEventListener.reset();////添加这句            mSensorManager.unregisterListener(mSensorEventListener);            mEnabled = false;        }    }


0 0
原创粉丝点击