资讯动态

全志A133 Android14 开机默认横屏方向链路与配置

发布时间:2026/9/29 4:57:59 来源:尧图企业网站定制
前阵子接了一块全志 A133 的开发板跑的是 Android 14客户提的需求特别直白开机启动之后主屏幕必须横着显示竖屏看着别扭他们那套外壳是横向装进去的。听起来就一行配置的事结果我从 uboot 的 logo 一直追到 Launcher 的 manifest中间翻了 SurfaceFlinger、DisplayManagerService、WindowManagerService 一堆代码才发现开机默认旋转方向这件事根本不是单一开关而是一条从上电到桌面被接力了好几手的链路。任何一个环节没对齐你看到的症状就是开机闪一下、转一下、或者干脆纹丝不动。这篇先讲清楚链路和思路重点是让你知道方向到底在哪一层被决定、被谁覆盖、被什么时机读走。因为安卓屏幕方向这个事最容易踩的坑不是不知道怎么改而是改错层了。我见过太多人一上来就改 Launcher 的screenOrientation结果开机动画和锁屏还是竖的桌面横过来那一瞬间黑一下就转视觉上像是故障。也见过有人只在驱动层把 panel 转了 90 度结果触摸全乱套点左边响应右边。适合读这篇的人大致三类做定制 ROM 和固件移植的兄弟、做平板和一体机这类固定形态设备的系统工程师、以及被开机方向不对这种看起来很小但返工成本极高的需求烦过的应用侧同学。不管你是刚接手 A133 这块板子的新手还是已经在 frameworks 里泡了几年的老手下面这套拆解方式应该都能用得上。1. 先把链路拆开一次开机方向被改了几手很多人一提到开机启动默认旋转主屏幕方向脑子里第一反应是去找那个叫user_rotation的设置项。但实际上一台设备从上电到桌面画出来方向至少被四个不同的层碰过而且它们的生效时机完全不同。你把顺序理清了排查效率会成倍提升因为你能通过症状出现的时刻直接定位到层。1.1 硬件层panel 的物理走向决定了零度到底是什么A133 这类 SoC 配的通常是 MIPI DSI 或者 RGB 接口的屏。屏厂出货的时候面板本身有一个天然扫描方向这个方向就是驱动眼里的 0 度。手机用的屏天然是竖的比如 1080x2400平板和一体机用的屏天然是横的比如 1280x800。如果你的板子上插的是一块 1280x800 的横屏但系统按 800x1280 竖着跑那就说明中间某层做了 90 度旋转。判断当前真实状态最直接的两条命令是adb shell wm size adb shell dumpsys display | grep -A 20 Display 0wm size打出来的Physical size是未经旋转的底板尺寸而dumpsys display里能看到real 1280 x 800这样的信息加上当前的rotation值。这两者配合看你就能判断出驱动报的尺寸和上层认为的方向是否一致。这里有个经验如果wm size报 1280x800而dumpsys display里rotation是 1也就是 90 度那说明框架层在做旋转屏本身是横的如果wm size报 800x1280那很可能是驱动或者 panel 配置里已经转过一次了。这个区分极其关键因为它决定了你后面该往哪个方向改是加一层旋转还是减一层旋转。1.2 内核与显示驱动层初始方向在这里定型在 Android 的用户空间起来之前屏幕方向由内核显示驱动和 uboot 决定。这个时候 uboot 要画开机 logo内核要画 kernel logo随后 bootanimation 接管。这三段画面如果方向不一致用户就会看到logo 正着、开机动画转 90 度、桌面又转回来这种三连跳。A133 平台上panel 的初始方向通常在设备树里描述。全志的 SDK 里 board 相关的 dts 里会有 panel 或 disp 节点其中带 rotate 语义的属性就是干这个的。具体字段名在不同 SDK 版本里叫法有出入别背名字直接 grepgrep -rn rotate arch/arm64/boot/dts/sunxi/board.dts grep -rn rotation drivers/video/fbdev/sunxi/ 2/dev/null | head -30搜出来之后你要做的是把它和物理屏幕的安装方向对齐。这里有个判断原则值得记住能在驱动层解决的问题不要留到框架层。因为驱动层转了整个显示链路从 logo 到桌面都是统一的中间不会有跳变而框架层转只影响用户空间开机早期那段画面是管不到的。但驱动层旋转也有代价。最典型的是性能如果显示控制器本身不支持硬件旋转那驱动层就可能退化成软件旋转直接吃掉带宽和帧率播放视频的时候尤其明显。所以选哪层得先确认硬件的旋转单元支不支持。1.3 系统服务层DisplayManagerService 与 WindowManagerService 的交接用户空间起来之后方向的控制权会交到DisplayManagerServiceDMS和WindowManagerServiceWMS手里。真正做决策的代码在DisplayRotation这个类里路径大致是frameworks/base/services/core/java/com/android/server/wm/DisplayRotation.java。它决定了当前的rotation是 0/1/2/3 中的哪一个然后把结果写进DisplayInfo再通知所有窗口重新布局。这里有个很多人不知道的细节DisplayRotation在决定方向的时候会先看一个设备默认方向再看传感器再看用户设置。这几者的优先级不是随便排的而且顺序会随着系统启动阶段变化。开机早期传感器服务还没起来DisplayRotation只能靠默认值兜底这就是为什么有些板子开机前几秒是竖的、几秒后才转横——不是 bug是传感器还没上报数据。另外AOSP 里有个属性对早期方向影响特别大ro.surface_flinger.primary_display_orientationORIENTATION_90这个属性是给 SurfaceFlinger 读的用来设定主显示设备的初始投影方向。它生效的时间比 WMS 早得多所以如果你想让 bootanimation 阶段就是横的这个属性往往是必须动的。取值就是ORIENTATION_0、ORIENTATION_90、ORIENTATION_180、ORIENTATION_270这四种。实测下来它对开机动画方向不对这类问题的改善最直接。1.4 应用层桌面和 Activity 自己的方向声明最后一层是应用。Launcher 在 AndroidManifest 里可以声明android:screenOrientation一旦声明成landscape那不管系统怎么转桌面都是横的。听起来很省事但它只是结果看起来对了中间过程照样会跳。更麻烦的是应用层锁定方向会掩盖真正的系统问题。比如你把 Launcher 锁成横屏自测看起来没问题但客户一装第三方应用那个应用的 Activity 没声明方向跟着系统走于是又竖过来了。所以我的建议一直是应用层声明只作为最后一道保险不作为主方案。主方案要在系统层或者驱动层解决。2. 默认方向到底是从哪儿读出来的理清链路之后下一个问题就是系统启动时那个默认方向具体存在哪、谁写进去的、什么时候被读。这一节讲的是根上的东西搞懂了它你改起来才不会瞎试。2.1 SettingsProvider 里的默认值是源头Android 的用户设置都存在SettingsProvider维护的数据库里。和方向相关的核心有两项都在Settings.System命名空间下ACCELEROMETER_ROTATION自动旋转开关1 表示跟随传感器0 表示锁定。USER_ROTATION锁定时的方向0/1/2/3 分别对应 0 度、90 度、180 度、270 度。这两项的初始值不是硬编码在 Java 里的而是从资源里读的。对应关系在SettingsProvider的DatabaseHelper里loadBooleanSetting(stmt, Settings.System.ACCELEROMETER_ROTATION, R.bool.def_accelerometer_rotation); loadIntegerSetting(stmt, Settings.System.USER_ROTATION, R.integer.def_user_rotation);也就是说默认值定义在frameworks/base/packages/SettingsProvider/res/values/defaults.xml里。你要改开机默认方向正确的姿势是在设备自己的 overlay 目录里覆盖这个资源而不是直接动 AOSP 原文件。overlay 的典型路径是device/vendor/product/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml内容长这样resources bool namedef_accelerometer_rotationfalse/bool integer namedef_user_rotation1/integer /resources注意这里的def_user_rotation只在自动旋转关闭def_accelerometer_rotation为 false时才有意义。如果你把自动旋转开成 true那系统还是听传感器的你设的默认角度会被覆盖掉。这是最常见的改了不生效原因之一。2.2 这个默认值只在数据库第一次创建时写入这是个大坑必须单独说。defaults.xml里的值不是每次开机都读而是只在 SettingsProvider 的数据库首次被创建时写进去一次。一旦数据库存在了后面开机只会读数据库里已有的值不会再回头看资源文件。所以你会遇到这种情况改了 overlay重新编译刷机发现方向还是老样子。因为你的/data分区没清数据库还在。解决办法有三个执行恢复出厂设置清掉/data。手动清 SettingsProvider 的数据。调试阶段直接用settings put命令改验证效果后再落到 overlay。第三条在调试时最省时间# 关闭自动旋转 adb shell settings put system accelerometer_rotation 0 # 设置锁定方向为 90 度横屏的一种 adb shell settings put system user_rotation 1 # 验证 adb shell settings get system user_rotation改完一般立刻生效不需要重启。如果立刻生效了说明链路是通的你可以放心去做 overlay如果没反应那问题就不在这一层别白费劲。2.3 传感器服务就绪前后的策略切换ACCELEROMETER_ROTATION为 1 的时候方向由WindowOrientationListener根据加速度计数据算出来。开机早期传感器服务还没就绪这时候系统会退回到一个默认值。这个退回的行为在不同 Android 版本上表现不完全一样Android 14 上整体比较克制通常不会再乱转但如果你在 framework 里做过定制就得回头看是不是被人为改过。验证传感器是否参与了方向决策可以看这两个输出adb shell dumpsys sensorservice | head -60 adb shell dumpsys window | grep -i mLastOrientation\|mRotation如果dumpsys window里的mRotation在你物理转动板子时会变那传感器链路是活的。如果无论怎么转都是固定值要么是自动旋转关着要么是传感器没数据。2.4 一个容易被忽略的开关config_reverseDefaultRotationAOSP 里还有个布尔资源配置叫config_reverseDefaultRotation它在frameworks/base/core/res/res/values/config.xml里默认是 false。打开之后系统对默认旋转方向的理解会反过来简单说就是把 90 度和 270 度对调。这个开关本来是给某些设备形态准备的但实际项目里经常被拿来当快速翻转的偷懒方案。我不太推荐这么用因为它会让代码语义变得很模糊后来接手的人看到这个为 true完全不知道到底是在补偿硬件还是在补偿驱动。真要用至少写清楚注释说明是为了补偿哪块屏的哪个方向。3. 三种主流方案怎么选别一上来就动手知道了链路接下来就是选方案。同一个开机横屏的需求至少有三条路可以走它们的成本、影响面、可维护性差别很大。下面这张表是我自己项目里总结的对比你可以直接拿来对着自己的场景选。方案改哪里生效时机影响面主要风险驱动/设备树旋转board dts、panel 配置从上电第一帧开始全系统含 logo 和恢复模式触摸坐标可能不同步可能有性能损耗系统层改默认值SettingsProvider overlay SF 属性用户空间启动后桌面、锁屏、所有未声明方向的应用已有数据不清则无效应用层锁定Launcher manifest桌面绘制时只影响该应用掩盖问题第三方应用不受控3.1 驱动层旋转干净但有代价驱动层旋转最大的价值是全链路一致。开机 logo、kernel logo、开机动画、锁屏、桌面全都是一个方向用户看不到任何跳变体验上最舒服。而且它顺便把恢复模式recovery的方向也解决了这在售后和产线测试环节很重要——产线工人看到歪着的画面会直接判不良。代价主要在两方面。第一是触摸。显示转了触摸如果没跟着转坐标就全错。Android 的输入子系统里触摸设备可以通过.idc文件声明touch.orientationAware让 InputReader 在分发坐标时跟随显示方向做变换。这个文件一般放/system/usr/idc/设备名.idc设备名可以用getevent -p查出来。但要注意这个机制在老平台上不一定被完整支持改完必须实测不能只看理论。第二是性能。硬件旋转单元能用就用用不上就只能软件转那帧率和功耗都会受影响。做视频播放类应用的设备尤其要注意这一点。3.2 系统层改默认值最省事但管不到开机早期系统层方案就是在 SettingsProvider 的 overlay 里改def_accelerometer_rotation和def_user_rotation再配合ro.surface_flinger.primary_display_orientation把早期方向也拉齐。这套组合拳的好处是改动量小、语义清晰、不影响应用兼容性升级 AOSP 版本的时候冲突也少。它的短板是生效时机偏晚。从开机到 SettingsProvider 提供数据中间有个时间窗bootanimation 那段是在这之前的。所以如果你遇到动画竖着、桌面横着光改 SettingsProvider 是没用的必须动 SF 那个属性。3.3 应用层锁定只当兜底前面说过应用层锁定的问题在于它只解决一个应用。如果你的设备形态是固定的比如工业一体机而且只跑自家应用那把所有自家应用的 manifest 都加screenOrientationlandscape也不是不行但这就是治标。系统一次方向抖动用户可能看不到但截图工具、投屏、外接显示器这些场景会暴露出来。我的实际做法是应用层声明保留但只在系统层方案的基础上加作为一道保险而不是替代。3.4 选型建议给个粗糙但好用的决策顺序。如果你的设备形态固定、只在自家硬件上跑优先走驱动层一次到位。如果驱动层旋转有性能或触摸问题绕不过去退到系统层组合方案。如果你只是想在最短时间内让客户看到效果那先用settings put验证再决定最终落哪层。应用层锁定永远放在最后。4. 实操A133 Android 14 上把默认方向改成横屏下面这套流程是我在那块板子上实际跑通的你照着做基本能复现。前提是你的 SDK 已经能正常编译出 boot 和 system 镜像。4.1 环境确认先别急着改第一步永远是确认现状不要凭感觉。把这三条命令的输出记下来后面改完要做对比adb shell getprop | grep -i rotation\|orientation adb shell dumpsys display | grep -i rotation\|real adb shell settings get system accelerometer_rotation adb shell settings get system user_rotation重点看第一行的属性里有没有ro.surface_flinger.primary_display_orientation以及dumpsys display里 display 0 的 real size 和 rotation 值。这一步花两分钟能省你后面两小时。4.2 确定设备形态需要的目标方向A133 配 1280x800 的横屏目标是开机就是横的。这里有几种做法我选的是驱动层不转、系统层拉齐的组合因为这块板子的显示控制器做硬件旋转后帧率掉得比较明显而客户应用对流畅度有要求。具体改动分三处。第一处添加 SF 早期方向属性在设备的system.prop或者device.mk里加PRODUCT_PROPERTY_OVERRIDES \ ro.surface_flinger.primary_display_orientationORIENTATION_0因为屏本身是横的SF 不需要额外旋转取 0 就行。如果你的屏物理是竖的而系统要横着跑那这里就要填ORIENTATION_90或ORIENTATION_270具体是哪个取决于你要往哪边转实测两次就能确定。第二处加一个 SettingsProvider 的 overlay路径放在设备目录下device/vendor/产品名/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml内容resources bool namedef_accelerometer_rotationfalse/bool integer namedef_user_rotation0/integer /resources这里的def_user_rotation填 0 还是 1取决于你的横屏是屏的天然横还是需要转 90 度的横。判断方法如果dumpsys display里 real size 已经是宽大于高1280x800那 rotation 0 就是横的如果 real size 是高大于宽800x1280那你要填 1 或 3 才能横过来。第三处把这个 overlay 挂到产品配置里。不同 Android 版本的语法略有差别Android 14 上一般是PRODUCT_PACKAGE_OVERLAYS device/vendor/产品名/overlay或者用DEVICE_PACKAGE_OVERLAYS看你的构建树用的是哪套。改完记得确认 overlay 确实被应用了否则你会发现编出来的镜像和没改一样。4.3 烧录之后先别急着清数据刷完镜像第一次开机先别清/data因为旧数据库可能还在能帮你判断 overlay 是不是真的编进去了。如果开机方向变了说明 overlay 生效了如果没变先别怀疑方向值填错先去验证 overlay 有没有被应用adb shell dumpsys package com.android.providers.settings | grep -i overlay确认 overlay 挂上之后再清数据验证默认值adb shell pm clear com.android.providers.settings adb reboot重启之后立刻看adb shell settings get system user_rotation adb shell settings get system accelerometer_rotation如果打出来的值就是你 overlay 里写的那这条链路彻底通了。4.4 用 dumpsys 读懂当前状态改完之后最值得看的是dumpsys window里和方向相关的几行。mRotation是当前实际旋转值mLastOrientation是上次的窗口方向还有个mDisplayRotation之类的字段。它们如果在你锁定之后一直保持常量不再随板子倾斜变化说明自动旋转确实被关掉了。另外建议顺手看一眼开机动画阶段的方向。简单办法是重启之后立刻录屏或者用连拍截图把 logo、animation、锁屏、桌面四个时刻截下来横向对比。如果四张图方向一致这个需求就算真正完成了如果中间有跳变说明还有一层没对齐通常就是 SF 属性那处。5. 踩过的坑和排查套路这一节是我觉得最有价值的部分因为下面这些问题文档里基本不会写但实际项目里几乎每个都会遇到。5.1 开机闪一下再转方向跳变的根因这是最典型的症状。表现是开机动画正着一到桌面瞬间黑一下再横过来。根因就是早期方向和后期方向不一致bootanimation 用的是 SF 的初始投影桌面用的是 WMS 算出来的方向。两者不一致切换的时候必然有一次重新布局。解决思路只有一条让这两者对齐。具体做法就是把ro.surface_flinger.primary_display_orientation的值调整成和 SettingsProvider 默认值对应的方向一致。比如你的系统层默认是 rotation 1而屏物理是竖的那 SF 那边就要填ORIENTATION_90。顺带说一句有些平台在 uboot 里也会画 logo那个阶段的方向和内核、用户空间又是独立的。如果你发现 logo 也是歪的那就得回去看 uboot 的显示配置这属于更底层的一环跟 Android 框架没关系了。5.2 改了不生效的五个常见原因我把这类问题整理成了一张速查表按排查顺序排列表现最可能的原因验证方式改 overlay 完全没反应overlay 没被挂上dumpsys package查 overlay 信息刷机后还是老方向/data里旧数据库没清pm clear后重启再看开机前几秒不对SF 早期属性没配getprop查 primary_display_orientation桌面对了但应用不对应用自己声明了方向查目标应用的 manifest自动旋转关不掉传感器服务在抢控制权dumpsys sensorservice看是否有数据提示这五个原因里第一条和第二条占了实际案例的一大半。所以每次改完先验证 overlay 生效再验证数据库被重建别跳过这两步直接去怀疑方向值填错了。5.3 触摸坐标跟着拧巴显示转了触摸没转是驱动层旋转方案里最常见的副作用。症状很好认点屏幕左边响应出现在右边或者上下滑动变成左右滑动。判断方法是进开发者选项打开显示触摸位置然后点几个角看看白点对不对得上。如果对不上去查对应触摸设备的.idc文件。设备名用getevent -p看找到add device那一行里的名字然后到/system/usr/idc/下找同名文件。里面可以加touch.orientationAware 1改完重启验证。要注意的是不是所有平台都完整支持这个属性有些老驱动需要在外层自己做坐标变换。所以这一步必须实测别信理论。5.4 多屏和热插拔带来的干扰如果板子上有 HDMI 输出那情况会复杂一层。Display 0 是内置屏HDMI 是另一个 display两者的方向策略是独立的。有些实现里HDMI 的热插拔事件会触发一次全局的显示重配置如果这时候方向逻辑写得不够严谨主屏方向可能被顺手改掉。验证方式是插拔 HDMI 前后分别看dumpsys display里 display 0 的 rotation 值有没有变化。如果变了那就去查你的显示策略代码里有没有在插拔事件里重新设置方向。这类问题在只跑单屏的板子上永远暴露不出来一定要在整机形态下测。6. 几个容易忽略但很要命的细节6.1 升级和 OTA 之后设置被覆盖如果你的设备已经出货后面推 OTA 改了方向逻辑要注意老设备的/data里存的是老值不会自动跟着新 overlay 走。这时候要么在 OTA 包里带一段一次性迁移逻辑去重置这两个设置项要么在系统启动的早期做一次版本比对发现配置版本变了就强制覆盖一次。这个逻辑很多人不写结果就是新固件在老机器上方向不对新机器上正常特别难查。6.2 别把方向写死在 framework 里我见过有人为了省事直接改DisplayRotation.java把默认值硬编码进去。短期确实快但下次升 AOSP 版本这个冲突会让你怀疑人生而且别人完全看不出这是定制。所有和设备形态相关的配置都应该放在设备目录的 overlay 或属性里framework 保持尽量干净。6.3 把验证脚本固化下来方向这种东西改一次就得测一次靠手动敲命令太累也容易漏。我在项目里会写一个很小的 shell 脚本一次性把getprop、dumpsys display、settings get的输出都抓下来存成文件改前改后各跑一次用 diff 对比。这个方法看起来朴素但它在排查改了到底有没有效果的时候比反复盯着屏幕看可靠得多。#!/system/bin/sh echo props getprop | grep -i rotation\|orientation echo display dumpsys display | grep -i rotation\|real echo settings settings get system accelerometer_rotation settings get system user_rotation我个人在这块 A133 板子上折腾下来最深的体会是开机方向这个问题最难的部分从来不是改哪一行代码而是先搞清楚当前这一帧是谁画的。把 uboot、内核、SurfaceFlinger、WMS、应用这五层的职责和时机在脑子里排成一条线剩下的就是按症状定位。定位准了改动往往只有几行定位不准改十处都不一定管用。下一篇我会接着讲分屏和热插拔场景下方向策略怎么写以及触摸坐标变换的具体实测数据。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑