实际生活当中,针对某些应用场景,对Android启动时间要求比较严格,比如车载,车都开出去几公里了,IVI系统还没起来,这就比较尴尬,所以,优化Android启动时间是一项非常重要的工作。本文将根据本人实际工作经验,详细讲述Android开机时间相关的内容,基于Android13。
主要内容
-
开机时间检测方法
-
影响开机时间的Android启动流程
-
开机时间优化方案
开机时间检测方法
logcat
长按power键开机,等待adb进程启动后(一般出现Android字样后),执行如下命令抓取开机logcat
shell
adb logcat -b all > logcat.txt
打开logcat.txt,搜索logcat关键字"boot_progress
"、"sf_stop_bootanim"、"wm_boot_animation_done"
或者直接执行以下命令过滤logcat
shell
adb logcat -b events | grep -E "boot_progress|sf_stop_bootanim|wm_boot_animation_done"
以上是Android系统启动的各个阶段耗时,可以看到,整个开机过程耗时23.283秒,其中从按下power键到zygote启动,耗时7.646秒。各阶段的解释如下:
启动阶段 | 说明 |
---|---|
boot_progress_start | Linux kernel启动到Zygote进程启动的时间,包含从kernel启动到Init启动Zygote的时间 |
boot_progress_preload_start | ART虚拟机启动耗时/Zygote开始启动 |
boot_progress_preload_end | 虚拟机资源装载耗时/Zygote启动结束 |
boot_progress_system_run | System Server进程启动耗时 |
boot_progress_pms_start | Android一些在PMS前需要启动服务的启动耗时,package scan开始 |
boot_progress_pms_system_scan_start | system目录开始scan时间点 |
boot_progress_pms_data_scan_start | data目录开始scan时间点/system目录扫描耗时 |
boot_progress_pms_scan_end | 扫描结束时间点/data目录扫描耗时 |
boot_progress_pms_ready | PMS启动扫描包耗时 |
boot_progress_ams_ready | PMS后的系统服务启动时间 |
boot_progress_enable_screen | AMS启动完成后开始激活屏幕 |
sf_stop_bootanim | surfaceflinger结束开机动画 |
wm_boot_animation_done | 从enable_screen到animation_done包含壁纸和keyguard的绘制时间 |
注意,logcat只能看到上层启动后的log,即zygote启动后,开机期间kernel层的耗时无法通过logcat观察。
*
串口log和kernel log
-
串口log可以使用串口线连接Android设备和PC,使用串口工具抓取log,常用的串口工具有很多,xshell、MobaXterm等。
-
kernel log是在开机后执行如下命令抓取:
shell
adb shell dmesg > dmesg.txt
log里面搜关键字 "KPI
" 、"first stage
" 、"second stage
",此关键字为kernel的各个启动阶段。
uart log和kernel log都可以显示整个开机过程时间。
左侧为启动时间轴,右侧为启动log。
*
bootchart
bootchart 是一个用于 linux 启动过程性能分析的开源工具软件,在系统启动过程中自动收集 CPU 占用率、磁盘吞吐率、进程等信息,并以图形方式显示分析结果,可用作指导优化系统启动过程。
bootchart 让用户可以很直观的查看系统启动的过程和各个过程耗费的时间,以便让用户能够分析启动过程,从而进行优化以提高启动时间。
-
安装bootchart
Ubuntu16.04和18.04可通过一下命令安装
shellsudo apt-get install bootchart sudo apt-get install pybootchartgui
Ubuntu20.04上无法定位
pybootchartgui
这时可以手动下载,然后放到python编译器搜寻的目录下。
下载地址:github.com/xrmx/bootch...
下载好后解压
shelltar -zxvf bootchart-0.14.9.tar.gz
得到目录
bootchart-0.14.9
,进入到该目录将图中的
pybootchartgui
目录复制到/usr/lib/python3.8/
目录下shellsudo cp -r /usr/lib/python3.8/bootchart-0.14.9/pybootchartgui/ /usr/lib/python3.8/
/usr/lib/python3.8/
是python编译器搜寻的目录之一,完整的搜寻目录列表可通过以下命令查看shellpython3 -c "import sys;print(sys.path)"
所以,我们可以将
pybootchartgui
目录复制到以上任意目录中,只要能被python编译器搜寻到即可。最后还需要注意一下,复制完后需要将
main.py.in
重命名为main.py
,否者会报如下错误,此问题在github的issue中有提到重命名命令
shellsudo mv /usr/lib/python3.8/pybootchartgui/main.py.in /usr/lib/python3.8/pybootchartgui/main.py
最后我们将
bootchart
和pybootchartgui
这两个文件复制到/usr/bin/
目录下(文件附文末)。这两个文件是一样的,也就意味着你可以通过
bootchart
或者pybootchartgui
来生成bootchart.png
。 -
生成bootchart.png开机图
-
准备userdebug或者userroot设备
-
开启bootchart
shelladb root adb shell touch /data/bootchart/ enabled
-
检查是否生成了enabled
shell# ls /data/bootchart/ enabled
-
重启设备
shelladb reboot
-
等待开机进入Launcher,查看
/data/bootchart/
下是否有生成header文件,即bootchart日志是否生成shelladb root adb shell ls /data/bootchart/
-
拷贝
/data/bootchart/
下的 4 个文件到本地cproc_diskstats.log proc_ps.log proc_stat.log header # Pull指令: adb pull /data/bootchart/
-
进入到 bootchart 目录(刚刚 pull 的文件夹),执行指令将这 4 个文件打包起来(在 bootchart 目录中打开终端)
shelltar -czf bootchart.tgz *
-
执行指令,生成 bootchart.png 文件(./指代当前目录)
shellbootchart ./ bootchart.tgz
-
拷贝 bootchart.png 到你需要的地方,双击查看
-
-
bootchart.png示例图
bootchart图可以很直观的看到整个开机过程的时间节点以及CPU、磁盘的使用情况
-
bootchart.png讲解
第一行:时间
第二行:Linux版本
第三行:odm release fingerprint
第三行:cpu架构
第四行:kernel配置选项
第五行:开机耗时
开机过程中,CPU的使用率、I/O状态、磁盘吞吐量、磁盘使用率
第一行:代表整个机器开机的时间,每一格代表1秒 第二行:代表init从长格子开始的位置开始启动 最后一行:开始zygote的启动,后面就是java 世界:system_server及app进程
kernel相关的启动部分,启动时间看下init什么时候启动的就知道了。
-
影响开机时间的Android启动流程
开机框架
引用Gityuan大佬的一张开机流程图
Android启动流程大体为:BootRom -> BootLoader -> Kernel -> Init -> Zygote -> SystemServer ->Launcher
Loader层
-
Boot ROM
电源按下,引导芯片代码开始从预定义的地方(固化在ROM)开始执行,加载引导程序到RAM,然后执行。
-
Boot Loader
这是Android系统系统之前的引导程序,主要用来检测外部的RAM以及设置网络、内存、初始化硬件参数等。
Kernel层
Kernel层是指Android内核层,到这里才刚刚开始进入Android系统。
- 启动swapper进程(pid=0),该进程又称为idle进程,,系统初始化过程Kernel由无到有开创的第一个进程,,用于初始化进程管理、内存管理,加载Display、Camera Driver、Binder Driver等相关工作(图中kernel层蓝色区块)。
- 启动kthreadd进程(pid=2),是Linux系统的内核进程,会创建内核工作线程kworkder,软中断线程ksoftirqd,thermal等一系列内核守护进程。kthreadd进程是所有内核进程的父进程。
Linux内核加载主要包括初始化kernel核心(内存初始化,打开中断,初始化进程表等)、初始化驱动、启动内核后台(daemons)线程、安装根(root)文件系统等。后续启动第一个用户级进程init(pid=1)。
Native层
Native层主要包括启动init进程(Android的第一个用户空间进程)、HAL层(硬件抽象层)以及开机动画等。init进程是所有用户进程的鼻祖。同时init进程也会孵化一系列用户进程,还会启动关键的服务以及孵化Zygote进程。
- init进程会孵化出ueventd、logd、healthd、installd、adbd、lmkd等用户守护进程。
- init进程还启动servicemanager(binder服务管家)、bootanim(开机动画)等重要服务。
- init进程孵化出Zygote进程,Zygote进程是Android系统的第一个Java进程,Zygote是所有Java进程的父进程,Zygote进程本身是由init进程孵化而来的。
Framework层
Framework层分为Java frameword和C++ framework,分别由system_server进程和media_server进程负责启动和管理。
zygote本身是一个native的应用程序,刚开始的名字为"app_process",运行过程中,通过系统调用将自己名字改为zygote。在上图中的红色线,便是zygote fork出来的进程,所有的app进程都是由zygote fork产生的。
下面列举Zygote进程孵化的部分子进程:
进程名 | 解释 |
---|---|
system_server | Java framework的各种service都依赖此进程 |
com.android.phone | 电话应用进程 |
android.process.acore | 通讯录进程 |
android.process.media | 多媒体应用进程 |
com.android.settings | 设置进程 |
com.android.wifi | wifi应用进程 |
-
zygote进程
由init进程通过解析init.rc文件后fork生成的,Zygote进程主要包含:
- 加载ZygoteInit类,注册Zygote Socket服务端套接字
- 加载虚拟机
- preloadClasses
- preloadResouces
-
system_server进程
由zygote进程fork而来,system_server是zygote孵化的第一个进程,system_server负责启动和管理整个java framework,包含ActivityManager、PowerManager等服务。
-
media_server进程
由init进程fork而来,负责启动和管理整个C++ framework,包含SurfaceFlinger、AudioFlinger、Camera Service等服务。
app层
- zygote进程孵化出的第一个app进程是Launcher,这是用户看到的桌面app。
- zygote进程还会创建Browser,Phone,Email等app进程,每个app至少运行在一个进程上。
- 所有的app进程都是由zygote进程fork生成的。
具体的启动过程,此文不便详述,都是代码分析,复杂且枯燥。
开机时间优化方案
以下均为framework层的优化,kernel层优化不在研究范围。
精简方向
精简初始化脚本:减少开机时的初始化时间。
高通平台关注以下.rc & .sh文件:
csharp
init.rc
init.target.rc
init.qcom.rc
init.sh
init.qcom.sh
init.qcom.post_boot.sh
裁剪方向
移除非必须Apks、Features、Sensor等,减少PackageScan时间。
-
裁剪预置APK
针对具体应用场景,可以将没用的apk裁剪掉,比如automotive可以裁掉Launcher,因为automotive自带CarLauncher。
可通过如下命令查看设备中所有的apk:
shelladb shell pm list package -f
Android中的内置APK介绍见:Android主要应用和进程说明
裁剪方法:
diffdiff --git /build/make/core/main.mk /build/make/core/main.mk index a8f46c1..d9d507b 100644 --- a/core/main.mk +++ b/core/main.mk @@ -1267,6 +1267,7 @@ define product-installed-files $(eval ### Filter out the overridden packages and executables before doing expansion) \ $(eval _pif_overrides := $(call module-overrides,$(_pif_modules))) \ $(eval _pif_modules := $(filter-out $(_pif_overrides), $(_pif_modules))) \ + $(eval _pif_modules := $(filter-out $(modules_product_packages_remove), $(_pif_modules))) \ $(eval _pif_modules := $(filter-out $(PRODUCT_PACKAGES_DEL), $(_pif_modules))) \ $(eval ### Resolve the :32 :64 module name) \ $(eval _pif_modules := $(sort $(call resolve-bitness-for-modules,TARGET,$(_pif_modules)))) \ @@ -1363,6 +1364,9 @@ else ifdef FULL_BUILD endif endif + # App removal list + modules_product_packages_remove := $(PRODUCT_PACKAGES_REMOVE)
diffdiff --git /device/qcom/{product}/{product}.mk /device/qcom/{product}/{product}.mk index 163cac2..89a3078 100755 --- a/{product}.mk +++ b/{product}.mk @@ -60,6 +60,8 @@ PRODUCT_BUILD_USERDATA_IMAGE := true +# App removal list +PRODUCT_PACKAGES_REMOVE += \ + Calendar \ + Email \ + SnapdragonMusic \ + DeskClock \
注意:
/device/qcom/{product}/{product}.mk
取决于厂商的产品名称 -
移除不需要的Features
针对具体应用场景,可以将没用的Features裁剪掉,比如automotive可以裁掉
<feature name="android.software.print" />
可通过如下命令查看设备中所有的Features:
shelladb shell pm list features
裁剪方法:
diffdiff --git /frameworks/native/data/etc/android.software.print.xml /frameworks/native/data/etc/android.software.print.xml index 713a7f7..e76bb88 100644 --- /frameworks/native/data/etc/android.software.print.xml +++ /frameworks/native/data/etc/android.software.print.xml @@ -15,5 +15,5 @@ --> <permissions> - <feature name="android.software.print" /> +<!-- <feature name="android.software.print" />--> </permissions>
-
禁用不需要的Sensors
针对具体应用场景,可以将没用的Features裁剪掉。
可通过如下命令查看设备中所有支持的Sensor:
shelladb shell dumpsys sensorservice
配置优化方向
-
优化PinnerService配置
PinnerService是用于锁定某些模块在内存中,避免这些模块被移出\移入内存从而提高程序的运行效率。
优化目的是减少非首次开机启动Service的时间。
修改
/frameworks/base/core/res/res/values/config.xml
,添加如下配置:xml<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> ... ... <!-- Default files to pin via Pinner Service --> <string-array translatable="false" name="config_defaultPinnerServiceFiles"> <item>"/system/framework/arm/boot-framework.art"</item> <item>"/system/lib/libjavacrypto.so"</item> <item>"/system/lib/libhidltransport.so"</item> <item>"/system/framework/arm/boot-core-libart.oat"</item> <item>"/system/framework/arm/boot-conscrypt.oat"</item> <item>"/system/framework/arm/boot-core-libart.art"</item> <item>"/system/framework/arm/boot-ext.art"</item> <item>"/system/framework/arm/boot.art"</item> <item>"/system/framework/arm/boot-framework.art"</item> </string-array> ... ... </resources>
注意:芯片商(例如高通)的代码可能会存在客制化,AOSP的位置可能会被覆盖,如果有,则以芯片商的代码为准。
-
使用32Bit程序
定义了32Bit的程序,机器在apk的使用及服务的申明都会有略微的精简,在设备启动时加载的资源会少,故加载时间会少。
修改方式:
/device/qcom/{product}/BoardConfig.mk
makefileTARGET_ARCH := arm TARGET_ARCH_VARIANT := armv8-2a TARGET_CPU_ABI := armeabi-v7a TARGET_CPU_ABI2 := armeabi TARGET_CPU_VARIANT := cortex-a9 #TARGET_2ND_ARCH := arm #TARGET_2ND_ARCH_VARIANT := armv8-2a #TARGET_2ND_CPU_ABI := armeabi-v7a #TARGET_2ND_CPU_ABI2 := armeabi #TARGET_2ND_CPU_VARIANT := cortex-a9
device/generic/art/armv8/armv8.mk
makefile# Force 32bits executables. PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.zygote=zygote32
-
关闭默认开关
默认关闭功能开关,开启期间不再自动开启,加快开机进度。
主要修改
/frameworks/base/packages/SettingsProvider/res/values/defaults.xml
-
关闭锁屏显示通知
xml<!-- Default for Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1==on --> - <integer name="def_lock_screen_show_notifications">1</integer> + <integer name="def_lock_screen_show_notifications">0</integer>
-
关闭手势唤醒
xml<!-- Default for Settings.Secure.WAKE_GESTURE_ENABLED --> - <bool name="def_wake_gesture_enabled">true</bool> + <bool name="def_wake_gesture_enabled">false</bool>
-
关闭双击唤醒
xml<!-- Default state of tap to wake --> - <bool name="def_double_tap_to_wake">true</bool> + <bool name="def_double_tap_to_wake">false</bool>
-
关闭充电振动
xml<!-- Default for Settings.Secure.CHARGING_VIBRATION_ENABLED --> - <bool name="def_charging_vibration_enabled">true</bool> + <bool name="def_charging_vibration_enabled">false</bool>
-
关闭充电提示音
xml<!-- Default for Settings.Secure.CHARGING_SOUNDS_ENABLED --> - <bool name="def_charging_sounds_enabled">true</bool> + <bool name="def_charging_sounds_enabled">false</bool>
-
关闭蓝牙和wifi
xml<bool name="def_bluetooth_on">false</bool> <bool name="def_wifi_display_on">false</bool>
-
关闭自动旋转
xml<bool name="def_accelerometer_rotation">false</bool>
-
关闭Wifi Debugging
xml<!-- Disable WiFi Debugging --> <bool translatable="false" name="config_wifi_enable_wifi_firmware_debugging">false</bool>
-
删除开机动画
Animation的资源大小和播放时长一直是影响开机时间的重要因素之一,移除开机动画将有效地加快开机速度。
frameworks/base/cmds/bootanimation/BootAnimationUtil.cpp
cpp
bool bootAnimationDisabled() {
char value[PROPERTY_VALUE_MAX];
//将获取结果改为1,则无法进入到开机动画流程中
//property_get("debug.sf.nobootanimation", value, "0");
property_get("debug.sf.nobootanimation", value, "1");
if (atoi(value) > 0) {
return true;
}
property_get("ro.boot.quiescent", value, "0");
if (atoi(value) > 0) {
// Only show the bootanimation for quiescent boots if this system property is set to enabled
if (!property_get_bool("ro.bootanim.quiescent.enabled", false)) {
return true;
}
}
return false;
}
开机过程CPU满载
开机过程中让CPU火力全开,能有效减少开机时间
/device/qcom/common/rootdir/etc/init.qcom.rc
yaml
on early-init
+ write /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor performance
+ write /sys/devices/system/cpu/cpu1/cpufreq/scaling_governor performance
+ write /sys/devices/system/cpu/cpu2/cpufreq/scaling_governor performance
+ write /sys/devices/system/cpu/cpu3/cpufreq/scaling_governor performance
+ write /sys/devices/system/cpu/cpu4/cpufreq/scaling_governor performance
+ write /sys/devices/system/cpu/cpu5/cpufreq/scaling_governor performance
+ write /sys/devices/system/cpu/cpu6/cpufreq/scaling_governor performance
+ write /sys/devices/system/cpu/cpu7/cpufreq/scaling_governor performance
注意:
init.qcom.rc
是高通定制的init脚本,是开机时必然执行的。- 如果CPU原本就已经满载了,那么此修改则无效果。
- 不同平台CPU的配置不尽相同。
移除SystemService
SystemServer进程启动后,会启动很多SystemService,根据实际场景,裁剪非必要的Service
frameworks/base/services/java/com/android/server/SystemServer.java
java
// Start services.
try {
t.traceBegin("StartServices");
startBootstrapServices(t);
startCoreServices(t);
startOtherServices(t);
startApexServices(t);
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
t.traceEnd(); // StartServices
}
可裁剪的Service如下,仅供参考
1.VibratorService 震动器服务
2.ClipboardService 粘贴板服务
3.FingerprintService 指纹
4.BatteryService 电池服务,当电量不足时发广播
5.AlarmManagerService 闹钟服务
6.WallpaperManagerService 壁纸管理服务
7.StatusBarManagerService 状态栏管理服务
注意:
-
从framework层的角度去看问题,我们会发现功能及服务的裁剪,是最直接、最有效地时间及空间优化方法,它可以做到时间与空间的两者兼顾。
-
注意app与Service,Service与Service之间的耦合性,避免引起机器的异常,无法开机;
移除app源码
修改下面文件中的 PRODUCT_PACKAGES 字段的内容,将不需要的内置应用的名称删除,这样可以缩短 scan packages 的过程。
bash
1.build/target/product/core.mk
2.build/target/product/full_base.mk
3.build/target/product/full_base_telephony.mk
4.build/target/product/generic_no_telephony.mk
同时,可以删除 /packages/apps/
路径下不必要的 app 源码,这样可以缩短编译时间。
*
apk odex
apk odex优化就是以空间换时间,加快apk启动速度,缺点是会消耗内存。
在/device/qcom/{product}/{product}.mk
加入WITH_DEXPREOPT=true
, 打开odex优化
Android.bp中添加
makefile
android_app {
dex_preopt: {
enabled: true,
},
}
Android.mk中添加
makefile
LOCAL_DEX_PREOPT := true
PMS优化
Apk的扫描安装耗时是大头。通常采用多线程方案,针对Dir或者Dir中的package进行多线程扫描.
PMS多线程扫描apk,4线程改成8线程,注意,如果客户做了CPU绑核, Android所分配的CPU资源受到限制,导致改成8线程之后反向优化了。
frameworks/base/services/core/java/com/android/server/pm/ParallelPackageParser.java
java
class ParallelPackageParser {
private static final int QUEUE_CAPACITY = 30;
// private static final int MAX_THREADS = 4;
private static final int MAX_THREADS = 8;
//省略部分代码
}
Zygote优化
Zygote主要是优化class和resource的预加载,可以减少部分不需要预加载的class和resource,具体优化哪些,根据实际需求来添加。
注意:并不是预加载越少越好,如果开机必须启动的进程所需要的class和resource在zygote阶段被优化了,那么也会在该进程自启动时也会去加载,这样优化就是无效的。
diff
diff --git /frameworks/base/config/preloaded-classes /frameworks/base/config/preloaded-classes
index f2530519247..d6ac1e22e3f 100644
--- /frameworks/base/config/preloaded-classes
+++ /frameworks/base/config/preloaded-classes
@@ -806,7 +806,6 @@ android.app.VoiceInteractor$Request
android.app.VoiceInteractor
android.app.Vr2dDisplayProperties$1
android.app.Vr2dDisplayProperties
-android.app.VrManager
android.app.WaitResult$1
android.app.WaitResult
android.app.WallpaperColors$1
@@ -2471,12 +2470,6 @@ android.hardware.display.Time$1
android.hardware.display.Time
android.hardware.display.VirtualDisplayConfig$1
android.hardware.display.VirtualDisplayConfig
-android.hardware.display.WifiDisplay$1
-android.hardware.display.WifiDisplay
-android.hardware.display.WifiDisplaySessionInfo$1
-android.hardware.display.WifiDisplaySessionInfo
-android.hardware.display.WifiDisplayStatus$1
-android.hardware.display.WifiDisplayStatus
android.hardware.face.Face$1
android.hardware.face.Face
android.hardware.face.FaceManager$1
移除手势导航
diff
diff --git /frameworks/base/packages/overlays/Android.mk /frameworks/base/packages/overlays/Android.mk
index 69641e69a9f..71f5fd00520 100644
--- /frameworks/base/packages/overlays/Android.mk
+++ /frameworks/base/packages/overlays/Android.mk
@@ -20,17 +20,8 @@ LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
LOCAL_LICENSE_CONDITIONS := notice
LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
LOCAL_REQUIRED_MODULES := \
- DisplayCutoutEmulationCornerOverlay \
- DisplayCutoutEmulationDoubleOverlay \
- DisplayCutoutEmulationHoleOverlay \
- DisplayCutoutEmulationTallOverlay \
- DisplayCutoutEmulationWaterfallOverlay \
FontNotoSerifSourceOverlay \
NavigationBarMode3ButtonOverlay \
- NavigationBarModeGesturalOverlay \
- NavigationBarModeGesturalOverlayNarrowBack \
- NavigationBarModeGesturalOverlayWideBack \
- NavigationBarModeGesturalOverlayExtraWideBack \
preinstalled-packages-platform-overlays.xml
include $(BUILD_PHONY_PACKAGE)
关闭壁纸服务
frameworks/base/core/res/res/values/config.xml
xml
<!-- True if WallpaperService is enabled -->
<bool name="config_enableWallpaperService">true</bool>
调整窗口动画渲染
frameworks/base/packages/SettingsProvider/res/values/defaults.xml
diff
- <fraction name="def_window_animation_scale">100%</fraction>
- <fraction name="def_window_transition_scale">100%</fraction>
+ <fraction name="def_window_animation_scale">25%</fraction>
+ <fraction name="def_window_transition_scale">25%</fraction>
如果想关闭animaton,直接将数值改为0即可。
注意:芯片商可能会定制defaults.xml
,所以在修改时请留意是否改全。
*
专项优化
针对实际项目,如果加了自定义的开机自启动项,那么可以抓trace,看看整个开机过程哪个启动项耗时较长
例如:
上图可以看到 avm_worker
存在耗时异常, 该进程为 android 侧的 360 环视功能, 可以找对应开发确认是否需要开机启动。
*
Google优化方案
详见:source.android.google.cn/docs/core/p...
实战总结
对于Android开机时间优化,framework层可优化的空间较小,通过trace可以看到,一个Service的启动或者众多apk的扫描操作,往往都是在几毫秒或者几十毫秒内完成的,所以,即使关闭某个service的启动或者裁剪部分apk,优化效果也是毫秒级别的,不是很明显,但聚少成多,通过多种优化方案,累加优化时间,最终呈现出来的优化效果就是肉眼可见的。
而Kernel层的优化空间往往是较大的,都是秒级别的优化幅度,通过底层和上层双向优化,最终能达到比较理想的优化效果。
bootchart安装包
链接:pan.baidu.com/s/14odQxa2G... 提取码:x6a8