辅助设置中自动旋转
来源:互联网 发布:访问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.
2.
在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();---à清除调用进程的UID、PID,重置为被调用进程的UID、PID
updateRotationUncheckedL
贴源码
// 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
切换到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,是在WindowOrientationListene
直接返回mProposedRotation。
mPolicy.setRotationLw(mRotation);
更新了这个listener的状态。
那么。WindowOrientationListene
跟进去后发现,在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; } }
- 辅助设置中自动旋转
- Eclipse代码自动辅助提示功能的设置
- Unity3D研究院之设置自动旋转屏幕默认旋转方向
- 打包发布关于设置自动旋转屏幕默认旋转方向
- iphone应用程序中禁止屏幕自动旋转 自定义屏幕旋转
- 自动泊车辅助系统
- 自动旋转
- 导航控制器 中 代码设置屏幕旋转
- osg中设置模移动旋转缩放
- UIWebView中视频播放屏幕自动旋转,app不支持旋转但是某一个页面需要旋转等
- UIWebView中视频播放屏幕自动旋转,app不支持旋转但是某一个页面需要旋转等
- eclipse的自动提醒,内容辅助不好用了,修改快捷键设置
- 层中设置自动关闭
- vim中设置自动缩进
- Eclipse输入辅助,自动提示
- Accessibility 辅助功能 自动下载
- Unity3D中使用ITween对模型进行自动旋转(RotateBy)
- 跳转到设置辅助功能
- Activity组件
- Eclipse导入外部项目无法识别为web项目并且无法在部署到tomcat下解决方法
- UML类图几种关系的总结
- UVa 10002 Center of Masses(Andrew或Graham_scan)
- github版本库使用教程&& APP Index
- 辅助设置中自动旋转
- android5.0联系人 sort_key改成phonebook_label
- outclick 点击div外部触发事件
- Qt程序国际化工具使用和相关代码编写规范
- SPFA模板
- The Falling Leaves
- 日期辅助类
- 【C/C++学院】(18)QT文件读写/主窗口类/获取host信息
- Android应用性能优化小结