开机流程

Step 1启动电源以及系统启动

当电源按下,引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序到RAM,然后执行。

Step2 : bootloader

引导程序是在Android操作系统开始运行前的一个小程序。引导程序是运行的第一个程序,因此它是针对特定的主板与芯片的。

引导程序分两个阶段执行。第一个阶段,检测外部的RAM以及加载对第二阶段有用的程序;第二阶段,引导程序设置网络、内存等等。这些对于运行内核是必要的,为了达到特殊的目标,引导程序可以根据配置参数或者输入数据设置内核。

Android引导程序可以在bootable\bootloader

Step3: kernel

内核启动时,设置缓存、被保护存储器、计划列表,加载驱动。当内核完成系统设置,它首先在系统文件中寻找”init”文件,然后启动root进程或者系统的第一个进程。

Step4:init进程

init是第一个进程,我们可以说它是root进程或者说有进程的父进程。init进程有两个责任,一是挂载目录,比如/sys、/dev、/proc,二是运行init.rc脚本。

  • init进程可以在/system/core/init找到。

  • init.rc文件可以在/system/core/rootdir/init.rc 。

Step 5 : Native service 启动

在此阶段,会启动android Native service 包括 Zygote,sufaceFlinger,media server,bootanimation 等。

Step 6:Javaservice 启动

在此阶段,android 会启动java的service。并进行package的扫描,包括所有的app以及其所有的package,并且会 check所有的app是否进行了oat的优化如果没有则进行oat的优化。

Step 7:启动Home界面

一旦系统服务在内存中跑起来了,Android便启动home界面。Home界面启动完成后,会check wallpaper和 keygurd 是否 draw 完,如果已经draw完,则会设置service.bootanim.exit
为1,然后bootanimation 结束,界面显示完毕。

Debug

从上面的流程知道,开机问题分为kernel
部分和user
space 部分,下面讨论之。

Kernel

Kernel 又可分为两部分,包括bootloader 部分和driver 加载部分。

  1. bootloader

    我们可以从dmesg 中发现bootloder的KPI并且计算其时间如:

    [   0.416193] KPI: Bootloader start count = 23762   //A 为LK 开始时间

    [   0.416205] KPI: Bootloader end count = 239354   //B 为LK 结束时间

    [   0.416212] KPI: Bootloader display count = 37127

    [   0.416219] KPI: Bootloader load kernel count = 2321

    [   0.416226] KPI: Kernel XXX timestamp = 260735 // C bootloader 完成时间

    [   0.416232] KPI: Kernel XXX Clock frequency = 32768   //D clock

    我们可以通过下面的算法来确认相关的时间。如果发现时间太长,请debug 相关部分。

    Step1 时间:A/D=23762 /32768=0.72s

    LK 时间:(B-A)/D=(239354-23762 )/32768=6.57s

    Bootloader 时间:C/D-kmsg(C)= 260735 /32768-0.416226=7.54s

    需要注意的是如果是eng 版本Bootloader的时间会多增加5s。

  2. driver

    在上面linux启动阶段(step3),linux会加载很多driver,以及console等。加载console是比较耗时的操作(0.5s到4s),所以如果没有必要,可以去掉console来优化启动时间。对于其他driver需要注意的是touchdriver,camera sensor,LCD driver。

    我们也可以通过添加打印module init的log,来check每个module初始化时的时间。从而找到花费时间比较多的module。

--- a/init/main.c

+++ b/init/main.c

@@ -785,7 +785,7 @@ int __init_or_module
do_one_initcall(initcall_t fn)

if (initcall_blacklisted(fn))

return
-EPERM;

-       if (initcall_debug)

+       if (1)

ret =
do_one_initcall_debug(fn);

static int __init_or_module do_one_initcall_debug(initcall_t fn)
{
 ktime_t calltime, delta, rettime;
 unsigned long long duration;
 int ret;

printk(KERN_DEBUG "calling  %pF @ %i\n", fn, task_pid_nr(current));
 calltime = ktime_get();
 ret = fn();
 rettime = ktime_get();
 delta = ktime_sub(rettime, calltime);
 duration = (unsigned long long) ktime_to_ns(delta) >> 10;
 printk(KERN_DEBUG "initcall %pF returned %d after %lld usecs\n",
   fn, ret, duration);

return ret;
}

User Space

adb logcat -v threadtime -b events > logcat_envents.txt

adb logcat -v threadtime > logcat.txt

Boot Event

我们可以通过查看event来确定是哪部分花时比较多。

// user space 开始时间

07-06 22:18:00.136 I/boot_progress_start(  407): 15528  //systemclock.uptimemillis(),开机到当前时间,毫秒。

//Zygote 进程preload 开始时间 32bit zygote

07-06 22:18:03.846 I/boot_progress_preload_start(  407): 19238

//Zygote 进程preload 开始时间64bit zygote

07-06 22:18:04.551 I/boot_progress_preload_start(  408): 19943

//Zygote 进程preload 结束时间32bit zygot

07-06 22:18:06.313 I/boot_progress_preload_end(  407): 21705

//Zygote 进程preload 结束时间64bit zygote

07-06 22:18:06.356 I/boot_progress_preload_end(  408): 21747

//System server 开始运行时间

07-06 22:18:06.462 I/boot_progress_system_run( 2182): 21853

//Package Scan 开始

07-06 22:18:06.784 I/boot_progress_pms_start( 2182): 22176

//System 目录开始scan

07-06 22:18:06.899 I/boot_progress_pms_system_scan_start(2182): 22290

//data 目录开始scan

07-06 22:18:38.644 I/boot_progress_pms_data_scan_start(2182): 54036

//package scan 结束时间

07-06 22:18:38.660 I/boot_progress_pms_scan_end( 2182):54052

//package manager ready

07-06 22:18:38.882 I/boot_progress_pms_ready( 2182): 54274

//Activity manager ready,这个事件之后便会启动home Activity。

07-06 22:21:40.221 I/boot_progress_ams_ready( 2182): 235613

//HomeActivity 启动完毕,系统将检查目前所有的window是否画完,如果所有的window(包括wallpaper, Keyguard 等)都已经画好,系统会设置属性service.bootanim.exit值为1.并且trigger下面的event。

07-06 22:21:52.740 I/boot_progress_enable_screen( 2182):248132

Code://

void enableScreenAfterBoot() {
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,SystemClock.uptimeMillis()); //sent  boot_progress_enable_screen

mWindowManager.enableScreenAfterBoot(); //结束 bootanimation

synchronized (this) {
            updateEventDispatchingLocked();
        }
    }

public void enableScreenAfterBoot() {
        synchronized(mWindowMap) {
            if (DEBUG_BOOT) {
                RuntimeException here = new RuntimeException("here");
                here.fillInStackTrace();
               ....
            }
            if (mSystemBooted) {
                return;
            }
            
            mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000);
        }

mPolicy.systemBooted();

performEnableScreen(); //here 设置bootanimation exit 
    }

public void performEnableScreen() {
        synchronized(mWindowMap) {
           ...
            if (mDisplayEnabled) {
                return;
            }
            if (!mSystemBooted && !mShowingBootMessages) {
                return;
            }

// Don't enable the screen until all existing windows have been drawn.
            if (!mForceDisplayEnabled && checkWaitingForWindowsLocked()) {
                return;
            }

if (!mBootAnimationStopped) {
                // Do this one time.
                try {
                    IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
                    if (surfaceFlinger != null) {
                       ...
                        Parcel data = Parcel.obtain();
                        data.writeInterfaceToken("android.ui.ISurfaceComposer");
                        surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
                                data, null, 0);
                        data.recycle();
                    }
                } catch (RemoteException ex) {
                    Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
                }
                mBootAnimationStopped = true;
            }

....
    }

status_t BnSurfaceComposer::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
       .....
        case BOOT_FINISHED: {
            CHECK_INTERFACE(ISurfaceComposer, data, reply);
            bootFinished();
            return NO_ERROR;
        }

void SurfaceFlinger::bootFinished()
{
    const nsecs_t now = systemTime();
    const nsecs_t duration = now - mBootTime;
    ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
    mBootFinished = true;

// wait patiently for the window manager death
    const String16 name("window");
    sp<IBinder> window(defaultServiceManager()->getService(name));
    if (window != 0) {
        window->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
    }

// stop boot animation
    // formerly we would just kill the process, but we now ask it to exit so it
    // can choose where to stop the animation.
    property_set("service.bootanim.exit", "1");
}

Bootanimation

在开机启动过程中,bootanimation在surfaceflinger实例化时启动,在其运行过程中会择机检查是否可以退出(service.bootanim.exit=1),如果可以退出则会根据bootanimation

的config退出。有时,当service.bootanim.exit=1时,bootanimation没有及时退出。我们就需要检查其原因。

http://qoofan.com/read/R84bR212ld.html

Android 开机时间慢问题debug相关推荐

  1. 【Android系统】Android开机时间分析

    参看博客: https://www.jianshu.com/p/30fdf86c3462?from=singlemessage                                      ...

  2. Android开机时间工具分析

    背景 android 上面有很多的方法可以分析开机时间 比如打log,通过log 分析.android 的官网上面提供了下面的两种图形化的方式来分析开机时间,一些异常很明显的拖长整个开机时间的活动 可 ...

  3. Android开机时间分析

    一. 关于本篇博文 该文档简单主要描述了如何找出开机各个阶段耗时情况,以及对开机各个阶段的分析方法和如何优化开机时间,减少耗时.便于读者可以通过此文档了解开机时间的各个阶段的耗时情况. 二.开机各阶段 ...

  4. Android开机时间统计,android 开机时间检测

    基于SPRD平台,根据关键字检查开机耗时 #coding=utf-8 __author__="ao.deng" import ctypes, sys,os import re ST ...

  5. Android开机时间慢问题调试小技巧

    adb shell cat /proc/bootprof 会把各部分用的时间打出来 然后根据时间看是慢在哪个地方,根据log逐步分析即可

  6. 安卓系统开机时间优化分析

    Android 开机时间分析工具-----perfboot 安卓10开机时间优化分析 Android开机阶段log分析

  7. 安卓10开机时间优化分析

    本文从以下六点分析开机时间 1.软件环境2.开机时间测试方法3.开机各阶段重要的时间节点4.bootchart工具使用说明5.Android开机时间日志信息6.开机时间优化方案 一.软件环境 平台:a ...

  8. android 性能优化---(2) MTK 平台开机时间优化

    一.在工程模式开启MTKLogger, 开机后取日志bootprof  adb pull /storage/emulated/0/mtklog/mobilelog/APLog_2018_0309_10 ...

  9. Android设备开机时间统计

    现在有一个需求:Android设备在开机的时候统计开机时间,然后上报至服务器.一般来说我们都是这样做的: 在开机广播里,调用System.currentTimeMillis()获取开机时的时间戳,然后 ...

  10. Android系统设置默认开机时间

    需求描述 Android设备开机时间默认为2020-01-01 解决方案 frameworks/base/services/java/com/android/server/SystemServer.j ...

最新文章

  1. 电大计算机应用基础上机考试1200,电大《计算机应用基础上机考试操作题
  2. 物理学在计算机领域的应用,物理学在计算机中的应用.doc
  3. 老男孩为网友工作疑难问题解答一例
  4. 学报格式和论文格式一样吗_学报投稿格式有哪些
  5. access是不是计算机编程,access编程简介之二:用宏还是VBA?
  6. pandas 更改单元格的值_懂Excel轻松入门Python数据分析包pandas(二十四):连续区域...
  7. OpenCV中的「透视变换 / 投影变换 / 单应性」—cv.warpPerspective、cv.findHomography
  8. 前端:JS/24/BOM和DOM简介,for...in循环遍历,window对象的属性和方法,延时器,定时器,screen屏幕对象,location地址栏对象,history历史记录对象
  9. 经典实战教程!java编译器eclipse
  10. GJB 软件定型测评大纲(模板)
  11. Real-Time Rendering——16.1 Sources of Three-Dimensional Data三维数据的来源
  12. R语言绘图--PCA图
  13. SQP验厂要怎么做?
  14. r语言中mpg数据_R语言数据分析系列之五
  15. matlab中 %d,%f,%c,%s代表的输出格式
  16. 普乐蛙大型5d动感影院4d影院设备价格4d动感影院座椅
  17. 安全威胁分类STRIDE
  18. 统计学的那些冷门思考(各种检验+中心极限)
  19. Linux多线程(线程互斥与线程锁)
  20. 短线王的盯盘宝怎么样_自用多年的很牛的多空指标、无敌短线王

热门文章

  1. 在WIN10中安装经典计算器
  2. java读取log4j配置文件路径_log4j配置文件位置详解
  3. 常犇_武汉大学管理学院2019年工商管理硕士(MBA)第三批复试通知
  4. 数据结构实验项目二:栈的基本操作及其应用
  5. 原生js自定义提示框
  6. proj4js 坐标转换
  7. 高德地图vs百度地图
  8. 影视剪辑,视频剪辑素材音效哪里找?超实用剪辑入门必备素材
  9. AI语音交互机器人,揭秘你不知道的隐藏功能
  10. Mac更换JDK版本