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)