Android FW启动优化说明

网上关于启动优化的分析等文章应该很多了,比如启动时序、耗时统计、分析工具啥,这里就不再过多说明。本文旨在告诉你如何有效进行系统优化启动(分析版本Android P),仅供参考。

目录

Android系统正常开机时序

zygote

systemserver

    服务启动阶段(优化)

    PMS扫描(优化)

    服务就绪阶段

    用户数据解锁     提前解锁用户数据(优化)

关于预读


Android系统正常开机时序

上电 > bootloader > kernel > init > file system mount > zygote > system server

既然叫FW启动优化说明,那这里不对zygote之前的流程做分析。

zygote

网上文章应该也不少,比如异步、延迟加载资源。而google源码就已经实现了延迟加载,至于是否异步,则取决与CPU性能,因为zygote最后会拉起systemserver进程,资源异步加载可能会影响systemserver进程创建(而且后续systemserver进程也会启动大量系统server),而导致整体启动时间拉长。

systemserver

上面说了它会启动大量server,此过程大概需要5-6s左右,此阶段又可以分二个阶段来看,systemReady之前的服务启动阶段(服务启动) + 最后systemReady阶段(服务就绪)。

    服务启动阶段(优化)

google默认是通过串行 + 并行方式启动系统服务,但是考虑到服务的依赖关系,并行的服务数量很少,这里存在一定优化空间,即并行启动一些服务。(当然还可以裁剪部分原生服务)。

    PMS扫描(优化)

这里需要特殊说明一些PMS服务,它占据整个服务启动阶段大量时间,主要花费在pkg扫描、解析上,基于此,可以对解析做一个缓存策略,从而优化解析时间,缩短整个PMS启动时间。(详情见PackageParser.java,google其实原生已实现了此策略,但由于时间戳问题,导致并没有生效)

    服务就绪阶段

此阶段相对之前流程比较复杂,建议跟着代码流程,在关键部分加日志以理清其逻辑关系(至少需要知道是如何从systemReady启动Launcher的)。

    用户数据解锁

这里为了方便理解,简要说明一下用户数据解锁概念(可以认为是 用户解锁 的子集),在高版本的Android系统中,基于安全考虑,在系统启动之前,需要对用户数据做解锁。之后就可以启动系统常规的应用了,如果想在数据解锁之前启动,可以通过配置

    android:directBootAware="true"

来实现,但是此时启动的应用不能访问数据。(FallbackHome就是如此)

     提前解锁用户数据(优化)

假设你已理解从systemReady到启动Launcher流程,就可以知道启动launcher前最后一个步骤就是解锁用户数据,然后拉起系统正常(非bootAware)服务。那么如果可以提前解锁用户数据,意味着你可以跳过启动FallbackHome动作,直接启动Launcher,虽然Launcher非bootAware,但是用户数据已解锁,所以此时启动也完全正常,可以访问用户数据。

      用户数据解锁动作可以提前至systemserver启动服务阶段,注意由于此过程比较耗时,需要异步执行。然后在systemReady时,就可以快速启动真实UI(比如launcher或其它定制化界面等)。

看起来是不是很简单?但是这里有如下几个问题需要对应:

  1.     由于去掉了FallbackHome,用户数据解锁虽然提前了,但是用户解锁并没有提前,而且它也依赖FallbackHome消息,所以需要在systemReady过程中(前期)主动解锁用户。
  2.     同样还是由于去掉了FallbackHome,由于直接启动真实UI,Activity无法处于IDEL状态(需要理解启动Launcher流程),不会触发WMS解锁动作,所以需要在systemReady过程中(最后)主动解锁WMS。
  3.    由于主动解锁WMS,你会发现它依赖系统一些服务(锁屏、壁纸、开机动画),其中壁纸可以通过属性配置去掉依赖,开机动画则相对麻烦,建议去掉依赖,然后选择一个合适的时机(比如真实UI显示时)主动销毁。至于锁屏,因为它依赖systemui,但是一般来说真实UI就是锁屏,则完全可以定制化此界面来解除对systemui的依赖(如果是车机版,则直接去掉锁屏依赖即可)。(这里建议对着代码看,见WMS的performEnableScreen函数,基本原则就是快速解锁WMS,否则系统部分功能,如触摸事件会暂不可用)
  4.    最后一点就是需要解决前提解锁用户数据,带来的BUG。比如,因为解锁用户数据在解锁用户之前,会导致一些服务接收相关消息时序错乱等(见CertificateMonitor.java的mRootCaReceiver流程),同时由于前提解锁用户数据,会占用大量系统资源,导致一些服务后台消息处理延迟而出现异常(见LocationManagerService.java的LocationWorkerHandler构造)。

    最后本文只是列出优化思路,没由对具体步骤做详细说明。

 

======================================2020.6.12更新================================================

关于预读

采用预读机制(treadhead)来减少启动时间,是否采用,需要根据实际情况来看,即根据当前系统 bootchart 的IO Wait来定,如果在启动过程中出现大量IO Wait,则可以尝试采用此优化机制,原理就不说了,网上也有不少类似文章,本人在项目中实际测试,(部分系统)大概可以减少1-2s左右。下面是具体操作流程,自取:

源码:bionic/libc/treadahead-1.3 (需要新建目录)
编译:有二个模块mincore、treadahead,按照模块方式编译集成即可.
├── Android.mk        编译脚本
├── mincore        可执行
├── mincore.c        源码
├── readahead.S        无用
├── treadahead        可执行
└── treadahead.c    源码

用法:
先将可执行文件push到/system/bin

1. 生成预读文件,如预读当前目录下的所有apk文件,并将文件生成到/system/etc目录
    find -name "*.apk" | xargs mincore > /system/etc/treadhead.txt

  (mincore代码实现不全,只能通过其它方式来生成,读者可自行完善)

2. 预读命令 treadahead -f/system/etc/treadhead.txt

如果需要实机测试,需要通过rc文件方式自启动,注意要加到init.rc合适位置(fstab之后)。

资源:https://download.csdn.net/download/pshebing/12517742

参考:https://www.baidu.com/link?url=4L0QRd2Iyz__TWkjUT-HXhfnnKX9hXRjqwpc7NNeIlUGYxsNs7IW8LftK0iIUvGX5qjLVukOlFFLY2488b2xo_&wd=&eqid=cb1cba3e0000f501000000055ee323e9

你可能感兴趣的:(android,c++)