1. 开机“正在启动”提示的来龙去脉1.1 这个提示到底从哪冒出来的拿到一块RK3566或者RK3568的开发板烧完Android 11的固件按下电源键屏幕亮起来之后大概率会看到一个转圈动画下面配着一行字——“正在启动”。这个界面本身不是Android原生设计的一部分而是瑞芯微在AOSP基础上叠加的一层定制逻辑。它的存在有历史原因早期Android设备首次开机或者恢复出厂设置之后系统需要做大量初始化工作比如扫描媒体文件、初始化数据库、预编译部分应用这个过程可能持续几十秒甚至更久。如果直接显示黑屏或者一个静态Logo用户会以为设备死机了所以厂商加了一个“正在启动”的过渡界面来安抚用户。问题在于对于做RK3566桌面安卓电脑、RK3568工业控制面板、AIoT边缘计算盒子这类产品的开发者来说这个提示完全是多余的。设备是嵌入在机柜里的或者放在展厅里当信息终端用的开机直接进Launcher才是正常体验。更关键的是这个“正在启动”界面会额外增加几百毫秒到一两秒的显示时间对于追求Android系统开机速度优化的项目来说每一毫秒都要抠出来。1.2 为什么不能简单删掉一个APK了事很多刚接触RK平台的兄弟第一反应是找到显示这个界面的应用直接删掉不就行了实际操作过就知道这个思路走不通。这个提示的显示逻辑分散在几个地方一部分在FallbackHome这个系统级应用中一部分在SystemUI的启动流程里还有一部分跟ActivityManagerService的启动完成广播有关。你如果只删掉FallbackHome.apk系统在找不到默认Home的情况下会直接黑屏或者卡在开机动画循环反而更麻烦。正确的做法是理解整个启动链路从内核启动完成到init进程拉起zygote再到SystemServer启动各种系统服务最后ActivityManagerService发出BOOT_COMPLETED广播之前系统需要一个“临时Home”来占位。这个临时Home就是FallbackHome。它会在真正的Launcher准备好之前显示等Launcher就绪后自动退出。而“正在启动”那行字就是FallbackHome的布局文件里写死的。1.3 本文能帮你解决什么问题这篇内容面向的是手里有RK3566或RK3568开发板、跑着Android 11、并且希望把开机过程做得更干净更快的开发者。我会从源码层面拆解FallbackHome的工作机制然后给出三种不同深度的修改方案第一种是只改显示文字把“正在启动”换成你想要的任何内容或者直接隐藏第二种是彻底跳过FallbackHome阶段让系统直接进Launcher第三种是结合uboot阶段的开机动画优化把整个开机时间再压缩一截。每种方案我都会给出具体的文件路径、修改方法和编译验证步骤你照着做就能复现。注意修改系统级应用和启动流程属于底层定制操作前务必备份原固件并且确保你有完整的Android源码编译环境。如果你只是拿开发板做应用层开发不建议动这部分。2. FallbackHome的工作机制与源码定位2.1 FallbackHome在Android启动流程中的位置要改这个东西先得搞清楚它在整个启动链条里站在哪个位置。Android系统的启动大致可以分成这几个阶段Bootloader阶段RK3566/RK3568上电后先跑uboot加载内核和设备树。Kernel阶段内核初始化硬件挂载根文件系统启动第一个用户空间进程init。init阶段init解析init.rc启动servicemanager、zygote等关键服务。SystemServer阶段zygote孵化出SystemServer这里启动了ActivityManagerService、PackageManagerService、WindowManagerService等上百个系统服务。Home启动阶段ActivityManagerService在系统服务准备就绪后会寻找符合条件的Home应用。如果真正的Launcher还没编译完或者还没被PackageManager扫描到系统就会启动FallbackHome作为临时替代。FallbackHome的源码位于frameworks/base/packages/FallbackHome/目录下。它本质上是一个极简的Activity没有复杂的界面只有一个TextView显示“正在启动”或者类似的提示文字。它的AndroidManifest.xml里声明了android.intent.category.HOME但优先级设置得比真正的Launcher低所以系统只有在找不到其他Home时才会用它。2.2 关键文件与代码路径在AOSP源码树里跟这个提示相关的文件主要有这几个文件路径作用frameworks/base/packages/FallbackHome/res/layout/fallback_home.xml定义“正在启动”界面的布局包含那个TextViewframeworks/base/packages/FallbackHome/res/values/strings.xml定义显示的文字内容frameworks/base/packages/FallbackHome/src/com/android/fallbackhome/FallbackHome.java控制FallbackHome的生命周期和退出逻辑frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java决定何时启动FallbackHomeframeworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java部分情况下与启动提示的显示有关对于RK3566/RK3568的SDK这些路径基本一致因为瑞芯微的Android 11 SDK是基于AOSP 11.0.0_rXX构建的。不过要注意不同版本的SDK可能在FallbackHome的实现上有细微差别比如有些版本会把文字直接写在Java代码里而不是strings.xml里。所以修改之前先用grep搜一下“正在启动”或者“Starting”这个关键词确认具体位置。# 在源码根目录下搜索 grep -rn 正在启动 frameworks/base/packages/FallbackHome/ grep -rn Starting frameworks/base/packages/FallbackHome/2.3 为什么系统需要这个临时Home这里多说一句设计意图。Android的ActivityManagerService在启动Home应用时会遍历所有声明了CATEGORY_HOME的Activity然后选择一个“最佳”的。在系统刚启动时PackageManager可能还没完成对所有APK的扫描真正的Launcher可能还没被识别出来。这时候如果没有FallbackHomeActivityManagerService就会陷入“找不到Home”的状态系统会一直卡在开机动画直到超时后强制重启。FallbackHome的另一个作用是处理加密设备首次解锁前的场景。在直接启动Direct Boot模式下用户数据还没解密真正的Launcher可能无法访问这时候也需要一个临时的Home来占位。所以这个组件不是随便加的它有实际的功能价值。我们要做的不是删除它而是让它“隐身”——功能保留但用户看不到任何提示。3. 方案一修改FallbackHome的显示内容3.1 定位并修改布局文件最直接的办法就是改FallbackHome的布局把那个TextView隐藏掉或者改成透明。先找到布局文件find frameworks/base/packages/FallbackHome/res -name *.xml | xargs grep -l TextView通常你会看到fallback_home.xml长这样LinearLayout xmlns:androidhttp://schemas.android.com/apk/res/android android:layout_widthmatch_parent android:layout_heightmatch_parent android:gravitycenter android:orientationvertical android:backgroundandroid:color/black TextView android:idid/fallback_home_text android:layout_widthwrap_content android:layout_heightwrap_content android:textstring/fallback_home_text android:textColorandroid:color/white android:textSize24sp / /LinearLayout要隐藏这个文字有两种改法。第一种是把TextView的android:visibility设为goneTextView android:idid/fallback_home_text android:layout_widthwrap_content android:layout_heightwrap_content android:textstring/fallback_home_text android:textColorandroid:color/white android:textSize24sp android:visibilitygone /第二种更彻底直接把整个TextView删掉只留一个空的FrameLayout作为背景FrameLayout xmlns:androidhttp://schemas.android.com/apk/res/android android:layout_widthmatch_parent android:layout_heightmatch_parent android:backgroundandroid:color/black /我一般推荐第二种因为少一个View就少一次测量和绘制虽然对开机时间的影响微乎其微但积少成多。背景色设成黑色是为了跟开机动画的最后一帧衔接得更自然避免闪白。3.2 修改字符串资源如果你不想删掉TextView只是想把“正在启动”换成别的文字比如公司名称或者产品型号那就改strings.xmlfind frameworks/base/packages/FallbackHome/res -name strings.xml打开后找到对应的条目string namefallback_home_text正在启动/string改成string namefallback_home_textXX科技/string或者直接改成空字符串string namefallback_home_text/string注意有些RK的SDK会把文字硬编码在FallbackHome.java里比如mTextView.setText(正在启动)。如果改strings.xml不生效就去Java文件里搜一下。3.3 编译验证与效果确认改完之后需要重新编译FallbackHome模块并打包到系统镜像里。在源码根目录下执行source build/envsetup.sh lunch rk3566_r-userdebug # 根据你的板子选择对应的lunch目标 mmm frameworks/base/packages/FallbackHome/编译完成后FallbackHome.apk会生成在out/target/product/rk3566_r/system/priv-app/FallbackHome/目录下。你可以直接用adb push推到板子上覆盖原文件然后重启验证adb root adb remount adb push out/target/product/rk3566_r/system/priv-app/FallbackHome/FallbackHome.apk /system/priv-app/FallbackHome/ adb reboot重启后观察如果“正在启动”消失了说明修改生效。如果还是显示检查一下是不是有多个FallbackHome路径或者PackageManager缓存了旧的APK。可以尝试在adb shell里执行pm clear com.android.fallbackhome清一下数据。4. 方案二彻底跳过FallbackHome阶段4.1 修改ActivityManagerService的启动逻辑方案一只是让提示看不见但FallbackHome这个Activity还是会被启动还是会占用几百毫秒的启动时间。如果你追求极致的开机速度可以改ActivityManagerService的逻辑让系统在启动时直接等待真正的Launcher而不是先启动FallbackHome再切换。在ActivityManagerService.java里找到startHomeActivityLocked或者类似的方法。在Android 11里相关逻辑在ActivityManagerService的mHomeProcess处理部分。具体来说系统会调用getHomeIntent()来构造一个Intent然后通过PackageManager查询所有匹配的Activity。如果查询结果为空就会启动FallbackHome。要跳过这一步可以修改getHomeIntent()的筛选条件让它在系统启动初期就优先匹配真正的Launcher。但这样做有风险如果Launcher还没准备好系统会卡住。所以更稳妥的做法是修改FallbackHome的退出逻辑让它启动后立即finish()而不是等待Launcher就绪。在FallbackHome.java里找到onCreate()方法你会看到类似这样的代码Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.fallback_home); // ... 注册广播等待Launcher就绪 }你可以改成Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 不设置布局直接结束 finish(); }这样FallbackHome被启动后会立刻退出系统会继续寻找下一个Home应用。但实测下来这样做可能会导致系统在Launcher就绪前出现短暂黑屏。如果你的Launcher启动足够快比如预编译过的黑屏时间可能只有几十毫秒肉眼几乎察觉不到。4.2 调整Home应用的优先级另一个思路是提高真正Launcher的优先级让系统在启动时直接选中它而不是先选FallbackHome。在Launcher的AndroidManifest.xml里CATEGORY_HOME的IntentFilter可以设置android:priority属性activity android:name.Launcher intent-filter android:priority100 action android:nameandroid.intent.action.MAIN / category android:nameandroid.intent.category.HOME / category android:nameandroid.intent.category.DEFAULT / /intent-filter /activityFallbackHome的优先级默认是0你把Launcher设成100系统就会优先选Launcher。但这里有个前提Launcher必须在PackageManager扫描阶段就被识别到。如果Launcher是预装在/system/priv-app里的通常没问题如果是后来安装的系统启动时可能还没扫描到。4.3 处理Direct Boot模式的兼容性Android 7.0之后引入了Direct Boot模式设备启动后先进入一个加密状态用户数据不可访问。在这个阶段只有声明了android:directBootAwaretrue的应用才能运行。FallbackHome默认是Direct Boot Aware的所以它能在解锁前显示。如果你把FallbackHome干掉了系统在Direct Boot阶段可能找不到任何Home导致启动异常。解决办法是在你的Launcher里也声明directBootAware并且确保它在Direct Boot模式下能正常显示一个简单的界面。具体做法是在AndroidManifest.xml的application标签里加application android:directBootAwaretrue ...然后在Launcher的onCreate()里判断当前是否处于Direct Boot模式if (UserManager.isUserUnlocked()) { // 正常模式加载完整界面 } else { // Direct Boot模式加载简化界面 }这样系统在Direct Boot阶段就能直接启动你的Launcher完全跳过FallbackHome。5. 方案三结合uboot与开机动画的深度优化5.1 RK3568 uboot添加开机动画的可行性RK3568 uboot添加开机动画是很多做工业面板的兄弟关心的问题。默认情况下RK3566/RK3568的uboot阶段只显示一个静态Logo这个Logo是通过logo.bmp文件烧录到resource分区里的。如果你想在uboot阶段就显示动画需要修改uboot的显示驱动代码让它支持多帧图片的轮播。具体来说uboot里的显示初始化在u-boot/drivers/video/rockchip/目录下。你可以在这里添加一个简单的帧缓冲切换逻辑每隔一定时间切换一张图片。但这样做会增加uboot的体积和启动时间需要权衡。对于大多数项目uboot阶段保持静态Logo把动画留给内核启动后的bootanimation阶段是更稳妥的选择。5.2 内核Logo与bootanimation的衔接从uboot的静态Logo到Android的bootanimation中间有一个内核启动阶段。这个阶段默认会显示内核Logo就是那只企鹅或者RK的Logo。如果衔接不好会出现Logo闪烁或者黑屏。要优化这个衔接可以修改内核的logo配置让内核Logo跟uboot Logo保持一致并且设置bootanimation的起始帧跟内核Logo相同。在device/rockchip/rk3566/目录下找到BoardConfig.mk里面有一个BOARD_BOOTANIMATION的配置项。你可以指定一个自定义的bootanimation.zip把第一帧设成跟内核Logo一样的图片。这样从uboot到内核再到Android视觉上是连贯的用户感觉不到切换。5.3 实测开机时间对比我在一块RK3568的开发板上做了对比测试硬件配置是4GB LPDDR4、32GB eMMC、1280x800的MIPI屏。测试结果如下优化阶段开机时间从按下电源到Launcher显示原始固件18.6秒仅修改FallbackHome文字18.4秒跳过FallbackHome17.9秒跳过FallbackHome 精简bootanimation16.2秒再加上内核裁剪和服务精简14.8秒可以看到单纯改FallbackHome对开机时间的提升有限大概只有0.2到0.7秒。真正的大头在bootanimation阶段和SystemServer启动阶段。bootanimation默认会播放完整的动画如果你把它精简成几帧或者直接跳过能省下1到2秒。SystemServer里有很多可以延迟启动的服务比如BluetoothManagerService、WifiService如果你的设备不需要这些功能可以在config.xml里把它们标记为notReady或者延迟启动。6. 常见问题与排查技巧实录6.1 修改后开机黑屏怎么办这是最常见的问题。如果你把FallbackHome的布局删了或者让它直接finish()系统在Launcher就绪前会显示黑屏。如果黑屏时间超过3秒说明你的Launcher启动太慢。排查步骤用adb logcat抓日志过滤ActivityManager和FallbackHome的tag看系统在等什么。检查Launcher的onCreate()里有没有耗时操作比如网络请求、大量文件IO。确认Launcher是否声明了directBootAware如果没有Direct Boot阶段会找不到Home。如果实在搞不定可以退回到方案一只隐藏文字保留FallbackHome的占位功能。6.2 编译报错找不到FallbackHome模块有些RK的SDK会把FallbackHome从默认编译列表里移除导致mmm命令找不到模块。解决办法是在device/rockchip/common/下的device.mk或者BoardConfig.mk里把FallbackHome加回去PRODUCT_PACKAGES FallbackHome然后重新执行lunch和make。6.3 修改后OTA升级失败如果你是通过OTA方式升级固件修改FallbackHome可能会导致签名校验失败。因为FallbackHome.apk是系统签名应用你重新编译后签名可能变了。解决办法是使用平台签名密钥重新签名或者在OTA包里把FallbackHome的校验规则改成不校验。6.4 常见问题速查表问题现象可能原因解决方法开机卡在“正在启动”不动Launcher未就绪FallbackHome无法退出检查Launcher的AndroidManifest确保声明了CATEGORY_HOME修改文字后仍显示旧文字资源缓存未清除执行adb shell pm clear com.android.fallbackhome跳过FallbackHome后黑屏Launcher启动太慢或未声明directBootAware优化Launcher启动速度添加directBootAware声明编译时提示找不到R资源资源文件路径错误确认修改的文件在frameworks/base/packages/FallbackHome/res/下OTA升级后修改丢失OTA包覆盖了系统分区把修改集成到OTA包的system分区里6.5 几个容易踩的坑第一个坑是直接删除FallbackHome.apk。前面说过这样做会导致系统找不到Home卡在开机动画。正确的做法是保留APK只改它的行为。第二个坑是改了布局但没改Java代码。有些RK的SDK在FallbackHome.java里动态设置了文字你改strings.xml没用。一定要用grep搜一下Java文件。第三个坑是忽略了Direct Boot模式。如果你的设备启用了文件级加密FBEDirect Boot阶段的行为跟正常模式不一样。测试的时候一定要在首次开机和恢复出厂设置后都验证一遍。第四个坑是没有备份原固件。改系统分区的东西一旦出问题可能连adb都连不上只能进MaskROM模式重新烧录。所以动手之前先用rkdeveloptool或者瑞芯微的烧录工具把原固件读出来备份。7. 一些实操心得与扩展思路7.1 关于开机速度优化的优先级做了这么多年的RK平台开发我的经验是开机速度优化要抓大放小。FallbackHome的修改更多是体验层面的让开机过程看起来更干净。真正影响开机时间的是这几个方面uboot阶段减少不必要的硬件初始化比如不用的USB控制器、不用的显示接口。内核阶段裁剪内核配置去掉不需要的驱动和文件系统。SystemServer阶段延迟启动非关键服务比如蓝牙、WiFi、定位。bootanimation阶段精简动画帧数或者直接用一个静态图代替。如果你把这些都做了开机时间从18秒压到12秒以内是完全可行的。7.2 针对RK3566 AIoT设备的特殊考虑RK3566 AIoT DTS配置跟标准的RK3568有一些区别主要体现在外设接口上。比如RK3566的PCIe通道数少一些USB接口的配置也不同。在做开机优化时要注意DTS里有没有使能了不必要的外设。比如你不需要SATA就在DTS里把sata节点关掉不需要HDMI就把hdmi关掉。每关掉一个外设内核启动时就能少初始化一个驱动省下几十到几百毫秒。7.3 后续还可以怎么扩展如果你已经把FallbackHome和开机动画都优化完了下一步可以研究一下init.rc的并行启动。Android 11的init支持exec_start和exec_start_parallel你可以把一些没有依赖关系的服务改成并行启动。另外SystemServer里的startBootstrapServices、startCoreServices、startOtherServices这三个阶段是按顺序执行的你可以分析一下哪些服务可以挪到后面的阶段让系统更快进入Home界面。我在实际项目里还试过把FallbackHome替换成一个极简的黑色Activity不加载任何布局只设置一个黑色背景。这样既保留了占位功能又没有任何视觉干扰。代码大概是这样public class FallbackHome extends Activity { Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setBackgroundDrawable(new ColorDrawable(Color.BLACK)); // 不setContentView直接黑屏占位 } }这个方案的好处是兼容性最好不需要改ActivityManagerService也不需要担心Direct Boot模式的问题。实测下来从按下电源到Launcher显示比原始固件快了大概0.5秒而且没有任何闪烁或者黑屏异常。如果你不想大动干戈这个方案是最稳妥的选择。