android开机,分为三个阶段,
1.
2.linux内核启动,开机动画开始显示
3.开始进入android的世界
4.android部分启动完成,开始初始化一些系统进程

1. Bootloader引导
       这个引导就是把os启动起来的代码,就是这段代码能够让下面的linux内核跑起来,这部分内容基本上都是mtk给到我们之后,就不需要去修改了,所以不做具体介绍

2.linux内核启动
     大家都知道,android本身的内核是linux内核,开机启动自然是从linux内核启动开始。这部分由于是涉及的内核比较多,而且从目前来看,能够优化的部分不多,且风险比较大,就不具体介绍,
目前,我所知道的linux内核启动速度优化的方法,通过一个比gzip更快的方式去解压内核映射,可以加快开机速度



3.android的世界
    先来说init进程的内容,为什么要说这个进程呢? 因为这个进程非常特殊,它基本控制了android系统里面的propertity,native service等...,   首先,从linux  kernel启动完成之后,第一个启动的用户进程就是init进程,具体的代码会在system/core/init/init.cpp里面,这个进程会去解析init.rc及init.xxx.rc之类的文件,并根据这些配置文件的关键字进行系列操作,如启动进程,只是设置服务等待启动之类....,   需要注意的是android世界的第一个进程zygote也是在这里面定义的,并通过init进程启动的,
64 位:
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    class main
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd

service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
    class main
    socket zygote_secondary stream 660 root system
    onrestart restart zygote

32位:

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd


从上面的配置可以看到,实际上zygote进程也是通过init进程启动,实际上执行的是/system/bin/app_process的一个bin文件,64位的机器比较特殊,它是能够支持32位apk和64位apk,所以会有两个zygote进程

如果想在mtklog中搜索开机log,一般有下面的内容(针对64位):
01-01 12:56:30.427526   881   881 D AndroidRuntime: >>>>>> START com.android.internal.os.ZygoteInit uid 0 <<<<<<
01-01 12:56:30.894456   882   882 D AndroidRuntime: >>>>>> START com.android.internal.os.ZygoteInit uid 0 <<<<<<
一般是两个,第一个是64位的,第二个32位的


启动到了这一步,我们现在可以通过看event_log.boot进一步分析,

01-01 12:56:30.427702   881   881 I boot_progress_start: 26858
01-01 12:56:33.985307   881   881 I boot_progress_preload_start: 30415
01-01 12:56:34.063756   882   882 I boot_progress_preload_start: 30494
01-01 12:56:36.573528   881   881 I boot_progress_preload_end: 33003
01-01 12:56:36.903491   882   882 I boot_progress_preload_end: 33333


此阶段为zygote进程加载一些常用的类,这个步骤可以使应用启动的时候,不需要再去加载一些类对象

01-01 12:56:36.965987  1386  1386 I boot_progress_system_run: 33396

01-01 12:56:37.478227  1386  1386 I boot_progress_pms_start: 33908

01-01 12:56:37.571837  1386  1386 I boot_progress_pms_system_scan_start: 34002
01-01 12:57:24.897414  1386  1386 I boot_progress_pms_data_scan_start: 81327
01-01 12:57:24.920992  1386  1386 I boot_progress_pms_scan_end: 81351
01-01 12:57:26.433115  1386  1386 I boot_progress_pms_ready: 82863


此阶段为pms对各种路径下的apk包进行扫描

01-01 12:57:27.233841  1386  1386 I wm_stack_created: [0,0,0,0,0]
01-01 12:57:27.365301  1386  1386 I configuration_changed: 7672
01-01 12:57:27.381441  1386  1386 I configuration_changed: 1032
01-01 12:57:27.923816  1386  1386 I configuration_changed: 512
01-01 12:58:40.760186  1386  1386 I free_storage_left: [10827628544,463716352,397475840]
01-01 12:58:40.760295  1386  1386 I free_storage_changed: 10827628544

01-01 12:58:45.829452  1386  1421 I boot_progress_ams_ready: 162259

此阶段,系统进程基本已经准备好了,可以去启动一些系统应用了

可以看到,这一部分是相当耗时的,我们从main log里面看一下,在做什么

搜索dex2oat,会发现,其实这个时候,大部分的时间是在做编译apk的动作,


如果预置的三方应用很多,这样启动的时间就会越长,比如Facebook编译的时间长达220s以上,
还有就是编译一些在/system/framework下的jar包,以及编译一些应用内部自己添加的jar包,

01-01 00:00:25.697944  3916  3916 I dex2oat : /system/bin/dex2oat --compiler-filter=interpret-only --dex-file=/data/user/0/com.google.android.googlequicksearchbox/files/extradex_jars/XJDyz7eY4OZBOGABJHxSaFQ/verified/ondevicewebsuggest/ondevicewebsuggest-0.jar --oat-file=/data/user/0/com.google.android.googlequicksearchbox/files/extradex_jars/XJDyz7eY4OZBOGABJHxSaFQ/verified/ondevicewebsuggest/ondevicewebsuggest-0.dex


01-01 12:57:27.941746  1386  1386 I PackageManager.DexOptimizer: Running dexopt (dex2oat) on: /system/app/Twitter/Twitter.apk pkg=com.twitter.android isa=arm vmSafeMode=false debuggable=false oatDir = null

01-01 12:57:39.723015  1386  1386 I PackageManager.DexOptimizer: Running dexopt (dex2oat) on: /system/app/NoteBook/NoteBook.apk pkg=com.fly.android.notes isa=arm64 vmSafeMode=false debuggable=false oatDir = null

从上面的数据可以证明,我们上述的一些观点,



实际上从sys_log里面,是可以看到启动的阶段的,关键字:SystemServiceManager,Starting phase
具体的启动阶段代表的含义在SystemService.java中
    public static final int PHASE_WAIT_FOR_DEFAULT_DISPLAY = 100; // maybe should be a dependency?

    /**
     * After receiving this boot phase, services can obtain lock settings data.
     */
    public static final int PHASE_LOCK_SETTINGS_READY = 480;

    /**
     * After receiving this boot phase, services can safely call into core system services
     * such as the PowerManager or PackageManager.
     */
    public static final int PHASE_SYSTEM_SERVICES_READY = 500;

    /**
     * After receiving this boot phase, services can broadcast Intents.
     */
    public static final int PHASE_ACTIVITY_MANAGER_READY = 550;

    /**
     * After receiving this boot phase, services can start/bind to third party apps.
     * Apps will be able to make Binder calls into services at this point.
     */
    public static final int PHASE_THIRD_PARTY_APPS_CAN_START = 600;

    /**
     * After receiving this boot phase, services can allow user interaction with the device.
     * This phase occurs when boot has completed and the home application has started.
     * System services may prefer to listen to this phase rather than registering a
     * broadcast receiver for ACTION_BOOT_COMPLETED to reduce overall latency.
     */
    public static final int PHASE_BOOT_COMPLETED = 1000;

可以看到,只有在跑到值为1000的PHASE_BOOT_COMPLETED 阶段,才算系统基本启动完成的,之前有一个SD卡performance比较差的问题,也是看这个启动
阶段,可以发现,正常的机器与异常的机器,时间差得非常多,这样就可以从启动的阶段去排查,看哪个阶段时间长了,







那我们优化点的建议:

  预置应用:
比如在:/system/app下的应用,如果是预置应用,在Android.mk建议加上LOCAL_DEX_PREOPT := true控制,
在/system/vendor下的预置应用,如果此应用编译时间比较长的,也使用上LOCAL_DEX_PREOPT := true

目前已采用新的策略,


/system/framework/下的jar包:
这部分的jar包,因为本身jar文件是在/system/framework下的,所以无身也无法通过升级,因为/system分区是只读,不可写的,
所以建议,在make的时候,我们就可以编译这部分的jar包,而不是等到手机第一次开机的时候才去编译,增加了第一次开机的时间

此方案,对启动速度有一定的优化作用

应用内置的额外的jar包:
这部分jar包的一般是在应用加载启动的时候编译的,会增加应用第一次启动的时间,建议,第一次加载的时候,不编译这部分jar ,而是放在之后才进行编译,对应用本身运行并不会造成影响,



新策略:
目前是通过,在第一次开机的时候,我们并不通过主线程去优化APK,而是通过另起线程在一定的时间内去优化APK,这样的好处是,不会阻塞主线程,这样开机的速度自然就加快了,

目前代码还在测试中,之后的一段时间这些代码将会上传。。


上面的优化点建议是基于android6.0的,也适用于5.0,5.1


Android5.0,5.1上,在系统第一次启动的时候,会做一个patchoat的动作,此操作基本相当于做了两次dex2oat的时间,这个优化点,我们建议是去掉这个patchoat,

后续关于这部分的内容,我们会继续添加,敬请关注....


更多相关文章

  1. android mainfest 属性详解
  2. android中的binder通信机制
  3. Android快速调试方法
  4. Android(安卓)判断应用 第一次启动
  5. Android(安卓)启动时 出现黑屏
  6. HOWTO install and setup Android(安卓)NDK for Windows(Android
  7. [日更-2019.4.22、23、24] cm-14.1 Android系统启动过程分析(三)-S
  8. Android进程的内存管理分析
  9. Android(安卓)多进程通信

随机推荐

  1. Android UI性能问题探讨
  2. 下载 android 源码错误curl: (6) couldn'
  3. 聚焦 Android 11:游戏开发新工具
  4. Android-透明状态栏
  5. android jni (jni_onload方式)
  6. Android中使用SQLite数据库详解
  7. Android之Activity概述
  8. 为什么要在 Windows 10 系统上运行 Andro
  9. Android 中文API:Signing Your Applicatio
  10. 初探Android Scroll——scrollTo()与scro