Android App 启动过程分析

原文链接:http://harttle.com/2014/05/27/android-appstartup.html

通过分析和修改Android 源码,分析 Android App 启动过程的时间消耗及性能瓶颈。

本文包括源码编译与运行、源码修改与调试、数据收集与分析。分析了 App 启动过程中, Activity Manager ServiceBinderLauncherMainActivity扮演的角色以及消耗的时间。

源码编译与运行

环境配置

环境要求可以在从 文档 查询得到。以下在Arch Linux中进行Android Source Building的环境配置。

安装依赖

# x86
yaourt -S --needed gcc git gnupg flex bison gperf sdl wxgtk squashfs-tools curl ncurses zlib schedtool perl-switch zip unzip libxslt

# x64
yaourt -S --needed gcc-multilib lib32-zlib lib32-ncurses lib32-readline

# Android 工具
yaourt -S android-sdk android-sdk-platform-tools android-sdk-build-tools android-studio

增加交换空间,加 RAM 应达到 16G (另外,还需要 30G 的大小写敏感文件系统可用空间)

su
swapoff /swapfile && rm /swapfile
dd if=/dev/zero of=/swapfile bs=512M count=8
mkswap /swapfile && swapon /swapfile

环境降级

# make 3.81-3.82
yaourt -S make-3.81 

# python2
cd /usr/bin && sudo ln -sf python python2

# java SE 1.6
yaourt -S jdk6-compat

环境配置

#!/bin/bash
# file: env.sh

# cache
export USE_CCACHE=1
export CCACHE_DIR=~/.ccache

# output
export OUT_DIR_COMMON_BASE=~/code/androidcore/output

# alias
alias make='make-3.81'

# java6
export JAVA_HOME=/opt/java6
export PATH=/opt/java6/bin:$PATH

配置USB访问权限:

# file: /etc/udev/rules.d/51-android.rules

# adb protocol on passion (Nexus One)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e12", MODE="0600", OWNER="<username>"
# fastboot protocol on passion (Nexus One)
SUBSYSTEM=="usb", ATTR{idVendor}=="0bb4", ATTR{idProduct}=="0fff", MODE="0600", OWNER="<username>"
# ...

最终环境

Linux acer 3.13.7-1-ARCH #1 SMP PREEMPT Mon Mar 24 20:06:08 CET 2014 x86_64 GNU/Linux
Python 2.7.6 (default, Feb 26 2014, 12:07:17)
gcc 版本 4.9.0 20140507 (prerelease) (GCC)
GNU Make 3.81
java SE 1.6

编译Android Source

参照 文档 ,下载Android4.2源码。

# 导入环境
. ../env.sh
. build/envsetup.sh

# 设置缓存大小
prebuilts/misc/linux-x86/ccache/ccache -M 50G

# 选择目标
lunch

# 并行编译
make -j4

启动Emulator

# 加载环境
lunch 

# 启动
emulator

启动成功,Android版本为4.2.1:

snapscreen

源码修改与调试

考虑从Launcher启动应用程序时,ActivityManagerServiceLauncherMainActivity之间的执行与通信序列如下图。在源码中相应的过程调用或进程通信处加入日志信息,用于分析启动时各部分的耗时。

Android源码修改

以下列出所有需要更改的源码。注释中给出了文件路径、类名、函数名,与添加的语句。添加日志输出(Level为Info,Tag为”PKU”)。

说明:文件ApplicationThreadNative没有引入Log类。添加import andriod.util.Log会发生运行时错误,可能是因为该文件的在类层次中的特殊性。所以我们将在try catch语句中指明命名空间并进行调用。我们关心的是整个系统启动后的 App启动过程,所以直接吞掉这个在早期才会产生的异常。

/////////////////////////////////////////////////////////////////////////
// file: packages/apps/Launcher2/src/com/android/launcher2/Launcher.java

// 0 Launcher.onClick
Log.i("PKU", "0 shortcut clicked");


/////////////////////////////////////////////////////////////////////////
// file: frameworks/base/core/java/android/app/ActivityManagerNative.java

// 1 ActivityManagerProxy.startActivity 
Log.i("PKU","1 START_ACTIVITY_TRANSACTION begin");
Log.i("PKU","1 START_ACTIVITY_TRANSACTION end");

// 5 ActivityManagerProxy.activityPaused
Log.i("PKU","5 ACTIVITY_PAUSED_TRANSACTION begin");
Log.i("PKU","5 ACTIVITY_PAUSED_TRANSACTION end");

// 9 ActivityManagerProxy.attachApplication
Log.i("PKU","9 ATTACH_APPLICATION_TRANSACTION begin");
Log.i("PKU","9 ATTACH_APPLICATION_TRANSACTION end");


/////////////////////////////////////////////////////////////////////////
// file: frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

// 2 ActivityManagerService.startActivity
Log.i("PKU","2 on START_ACTIVITY_TRANSACTION");

// 6 ActivityManagerService.activityPaused
Log.i("PKU","6 on ACTIVITY_PAUSED_TRANSACTION");

// 7 ActivityManagerService.startProcessLocked
Log.i("PKU"<
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值