Android 4.4 屏幕旋转

本文介绍了一种在Android设备上实现屏幕动态旋转的方法。通过修改persist.sf.hwrotation属性并更新SurfaceFlinger和WindowManagerService相关代码,可以实现在不同方向上的屏幕旋转。此外,还讨论了如何确保启动动画在旋转后的正确显示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

旋转屏幕的办法有两个
1.旋转FB,改framebuffer驱动
2.改Framwork

因为想做到动态旋转,其实看到很多平台也实现了这个功能,如rockchip的修改为,旋转这样就搞定了:

IWindowManager wm = IWindowManager.Stub.asInterface(
                    ServiceManager.getService(Context.WINDOW_SERVICE));

 wm.freezeRotation(OrientationValue);

不过我试了一下并不奏效,不知道还改了什么地方,就没有深究下去了,看到网上有博友的改法,索性试了一下最好磕磕碰碰的还是弄好了,就是不太优雅。

我imx6平台的代码保留着ro.sf.hwrotation 这参数,需要静态旋转直接改这个参数就可以了,就是路径是 system/build.prop
改完了需要重启。

动态修改的办法:

1.frameworks/native/services/surfaceflinger/DisplayDevice.cpp

uint32_t DisplayDevice::getOrientationTransform() const {
        uint32_t transform = 0;
        char property[PROPERTY_VALUE_MAX];
        if (property_get("persist.sf.hwrotation", property, NULL) > 0) {
                switch (atoi(property)) {
                case 0:
                        transform = Transform::ROT_0;
                        break;
                case 90:
                        transform = Transform::ROT_90;
                        break;
                case 180:
                        transform = Transform::ROT_180;
                        break;
                case 270:
                        transform = Transform::ROT_270;
                        break;
                }
        }
        return transform;
}

uint32_t DisplayDevice::getOrientationTransform() const {
        uint32_t transform = 0;
        char property[PROPERTY_VALUE_MAX];
        if (property_get("persist.sf.hwrotation", property, NULL) > 0) {
                switch (atoi(property)) {
                case 0:
                        transform = Transform::ROT_0;
                        break;
                case 90:
                        transform = Transform::ROT_90;
                        break;
                case 180:
                        transform = Transform::ROT_180;
                        break;
                case 270:
                        transform = Transform::ROT_270;
                        break;
                }
        return transform;
}               

void DisplayDevice::setProjection(int orientation,
        const Rect& newViewport, const Rect& newFrame) {
    Rect viewport(newViewport);
    Rect frame(newFrame);

    int displayOrientation = DisplayState::eOrientationDefault;
    char property[PROPERTY_VALUE_MAX];
    if (mType == DISPLAY_PRIMARY) {
      //  if (property_get("ro.sf.hwrotation", property, NULL) > 0) {
          if (property_get("persist.sf.hwrotation", property, NULL) > 0) {
            switch (atoi(property)) {
                case 90:
                    displayOrientation = DisplayState::eOrientation90;
                    break;
                case 180:
                    displayOrientation = DisplayState::eOrientation180;
                    break;
                case 270:
                    displayOrientation = DisplayState::eOrientation270;
                    break;
            }
        }
    }

    orientation = (orientation + displayOrientation) % 4;
    const int w = mDisplayWidth;
    const int h = mDisplayHeight;  
    ..........
} 

2.
frameworks/base/services/java/com/android/server/wm/WindowManagerService.java

boolean updateOrientationFromAppTokensLocked(boolean inTransaction)

int req = getOrientationFromWindowsLocked();
            if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
                req = getOrientationFromAppTokensLocked();
            }

            if (req != mForcedAppOrientation) {
                String str_rotation =SystemProperties.get("persist.sf.hwrotation", "0");
                if ("90".equals(str_rotation))
                         req = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
                else if ("180".equals(str_rotation))
                        req = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
                else if ("270".equals(str_rotation))
                        req = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
                else if ("0".equals(str_rotation))
                        req = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
                else
                        req = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;

                mForcedAppOrientation = req;

这样就修改好了重新编译烧录后 setporp persist.sf.hwrotation 270 点新窗口就发现串口旋转了。

然后再集成到Settng中,为了及时生效点完之后,弹一个Dialog然后再立刻关闭掉,就旋转了,比较简单不演示了。

后面还发现了一个问题,开机动画转了,但是显示的情况不对,后面分析发现在横屏竖屏切换的时候x,y坐标获取我们没有修改,开机动画并不知道这一个情况。

为了方便起见直接改:

frameworks/base/cmds/bootanimation/BootAnimation.cpp
status_t BootAnimation::readyToRun() 里


        char value[PROPERTY_VALUE_MAX];
    property_get(ROTATION_DIR, value, "0");
    uint32_t ortation = atoi(value);
    if(ortation/90%2){
        uint32_t tmp = dinfo.h;
        dinfo.h = dinfo.w;
        dinfo.w = tmp;
    }

    // create the native surface
    **sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
            dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);**

在createSurface 之前切换 dinfo.w和dinfo.h。

最后发现: DisplayInfo这个结构是记录屏幕x,y和旋转的关键结构,如果需要优雅的改变屏幕旋转的方向应该从这个结构下手,分析framwork才是。懒癌发作,等哪天有时间分析再改吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值