Android(安卓)fw修改让app方向跟随系统方向
平台:qcom msm8953 android7.1
现象:客户app或者应用商城下载的app在我们自己的Android板上运行是,会出现反方向显示的情况,如系统方向是90°,运行某些app,app打开后会是270°的方向。
解决方法:
思路1:理清AndroidGUI系统显示框架,刚开始从底层想去理清AndroidGUI系统显示框架,结果越看涉及的知识越来愈多,最后看的头脑一点都不清醒了,越看越糊涂,更别说解决这个bug了。于是开始转向思路2;
思路2:之前有了解过Android系统屏幕旋转是基于WMS和PMS的,另外,做过一段时间的Android应用开发,知道在Android应用中是可以通过xml去设置应用显示的方向的,于是结合这两点,开始往这方面靠。
首先找到一篇文章https://blog.csdn.net/jinzhuojun/article/details/50085491,大家可以结合这个阅读下源码,我在PMS,和WMS中分别加了点打印,然后抓取打开会出现问题的app,找到了一些信息,发现 在我打开app的时候产生屏幕旋转的现象在WMS中会进入
updateRotationUncheckedLocked这个方法,紧接着在这个方法中,我发现在该方法中运行到如图所示的时候,对屏幕方向进行了修改
那么看到这里图中第一句赋值语句中的右值的值是从何而来呢?往上跟踪源码发现,是经过rotationForOrientationLw这个方法而来,那这个方法在哪定义和实现的呢?继续跟踪可以看到是mPolicy中的一个方法,那么继续找到何处继承了这个代理类,最终跟踪到PMS中找到了该方法的实现。
@Override public int rotationForOrientationLw(int orientation, int lastRotation) { if (true) { Slog.v(TAG, "rotationForOrientationLw(orient=" + orientation + ", last=" + lastRotation + "); user=" + mUserRotation + " " + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) ? "USER_ROTATION_LOCKED" : "") ); } ....... if (DEBUG_LAYOUT) Slog.i(TAG, "orientation: " + orientation); if (getScreenWidth(mContext) < getScreenHeight(mContext)) { //Determine the physical screen direction Slog.v(TAG, "width < height"); switch (lastRotation) //Make the app direction follow system { case Surface.ROTATION_0: mPortraitRotation = Surface.ROTATION_0; //shu portrait mUpsideDownRotation = Surface.ROTATION_180; // fan shu mLandscapeRotation = Surface.ROTATION_90; // heng landscape mSeascapeRotation = Surface.ROTATION_270; //fan heng break; case Surface.ROTATION_90: mPortraitRotation = Surface.ROTATION_90; //shu portrait mUpsideDownRotation = Surface.ROTATION_270; // fan shu mLandscapeRotation = Surface.ROTATION_0; // heng landscape mSeascapeRotation = Surface.ROTATION_180; //fan heng break; case Surface.ROTATION_180: mPortraitRotation = Surface.ROTATION_180; //shu portrait mUpsideDownRotation = Surface.ROTATION_0; // fan shu mLandscapeRotation = Surface.ROTATION_270; // heng landscape mSeascapeRotation = Surface.ROTATION_90; //fan heng break; case Surface.ROTATION_270: mPortraitRotation = Surface.ROTATION_270; //shu portrait mUpsideDownRotation = Surface.ROTATION_90; // fan shu mLandscapeRotation = Surface.ROTATION_180; // heng landscape mSeascapeRotation = Surface.ROTATION_0; //fan heng break; } } else { Slog.v(TAG, "width > height"); switch (lastRotation)//Make the app direction follow system { case Surface.ROTATION_0: mPortraitRotation = Surface.ROTATION_0; //shu portrait mUpsideDownRotation = Surface.ROTATION_180; // fan shu mLandscapeRotation = Surface.ROTATION_90; // heng landscape mSeascapeRotation = Surface.ROTATION_270; //fan heng break; case Surface.ROTATION_90: mPortraitRotation = Surface.ROTATION_90; //shu portrait mUpsideDownRotation = Surface.ROTATION_270; // fan shu mLandscapeRotation = Surface.ROTATION_0; // heng landscape mSeascapeRotation = Surface.ROTATION_180; //fan heng break; case Surface.ROTATION_180: mPortraitRotation = Surface.ROTATION_180; //shu portrait mUpsideDownRotation = Surface.ROTATION_0; // fan shu mLandscapeRotation = Surface.ROTATION_270; // heng landscape mSeascapeRotation = Surface.ROTATION_90; //fan heng break; case Surface.ROTATION_270: mPortraitRotation = Surface.ROTATION_270; mUpsideDownRotation = Surface.ROTATION_90; mLandscapeRotation = Surface.ROTATION_180; mSeascapeRotation = Surface.ROTATION_0; break; } } switch (orientation) { case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: //portrait // Return portrait unless overridden. if (isAnyPortrait(preferredRotation)) { Slog.v(TAG, "preferredRotation:" + preferredRotation); return preferredRotation; } Slog.v(TAG, "mPortraitRotation:" + mPortraitRotation); return mPortraitRotation; case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: //landscape // Return landscape unless overridden. if (isLandscapeOrSeascape(preferredRotation)) { return preferredRotation; } return mLandscapeRotation; case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: //reversePortrait >= api 9 // Return reverse portrait unless overridden. if (isAnyPortrait(preferredRotation)) { return preferredRotation; } return mUpsideDownRotation; case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: //reverseLandscape >= api 9 // Return seascape unless overridden. if (isLandscapeOrSeascape(preferredRotation)) { return preferredRotation; } return mSeascapeRotation; case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE: // Return either landscape rotation. if (isLandscapeOrSeascape(preferredRotation)) { return preferredRotation; } if (isLandscapeOrSeascape(lastRotation)) { return lastRotation; } return mLandscapeRotation; case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT: // Return either portrait rotation. if (isAnyPortrait(preferredRotation)) { return preferredRotation; } if (isAnyPortrait(lastRotation)) { return lastRotation; } return mPortraitRotation; default: // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR, // just return the preferred orientation we already calculated. if (preferredRotation >= 0) { return preferredRotation; } //return Surface.ROTATION_0; return mDefaultOrientation; } } }
代码略长,省略部分,只看重点,在这个方法中添加一些打印发现,这里正是对app 通过设置xml配置屏幕方向的一些分类情况处理,我们可以看到图中 switch (orientation) 处,这里分别对应了应用层的一些设置,如:“portrait”,"landscape"等,
那么分析到这里,我想是不是可以在这个分类处理之前做些处理,让app跟随系统方向,于是进行了标红处的代码添加,最终运行测试,OK,测试通过!!
PS: 横屏好像还有点问题,后面再细查。
PMS:frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
WMS:frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
更多相关文章
- Android(安卓)为何比 iOS 卡?
- 更新操作系统Google 修正 Android(安卓)碎片化新法:多更新组件少
- Android异步消息处理机制完全解析,带你从源码的角度彻底理解
- 安卓自定义相机,使用系统相机教程源码都有
- 处女男学Android(三)---Handler简介以及初步应用
- Android(安卓)来电(包括铃声),短信拦截的实现方法
- IPv6升级测试指南(Android/iOS/Mac)
- 从零开始--系统深入学习android(实践-让我们开始写代码-Android框
- Android(安卓)BSP成长计划随笔之虚拟设备搭建和input系统