讲完了 dumpsys
,这节我们看下 am
命令,这个不同于 dumpsys
的可执行文件, am
是个脚本文件。
具体来看,先从android.mk来阅读下。很多时候,我不做太多强调,重复的去写一些流程,一些跟踪逻辑,这个是要掌握的关键,比如这里的android.mk
从这个文件,可以看到,编译出来的主要有两个文件,一个am.jar(BUILD_JAVA_LIBRARY指定编译结果),同时还有一个am脚本(BUILD_PREBUILT 指定此文件已经是最终文件),最终放置在/system/bin目录,打开这个文件,可以看到:
从第一行的#!/system/bin/sh可以看到,是个sh脚本,具体含义等会讲解。 am.jar是将当前目录下的src目录和proto目录,编译成am.jar包,放置在system/framework下面。 然后我们使用的时候,命令如下:(举个例子,更详细的直接am -h) am start -n com.android.camera/com.android.camera.Camera 我们知道,这个am命令,系统是在system/bin目录,关于在adb shell环境下,系统如何找的文件,可以通过查看PATH看到系统搜索的路径: echo $PATH 输出结果:
/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin
那么我们现在看下这里的am文件:
我们直接看else的这部分,
base=/system
export CLASSPATH=$base/framework/am.jar
exec app_process $base/bin com.android.commands.am.Am "$@"
这里可以看到就是几条 shell
命令,第一行定义一个变量,第二行导出一个类的搜索路径
第三行使用exec创建一个app_process进程,然后找到里面的com.android.commands.am.Am类,调用里面的main方法
$@ 是我们传入的参数。
比如这里am start -n com.android.camera/com.android.camera.Camera $@就是start -n com.android.camera/com.android.camera.Camera
关于 exec
可执行文件,我们当前不讲,因为牵扯了进程切换,可以百度linux exec找到答案。同时 app_process
也不详细讲解,今天主要顺下am的执行过程。
am
运行使用 exec
创建一个 app_process
进程,然后找到里面的com.android.commands.am.Am类,调用里面的main方法 $@ 是我们传入的参数,
我们这里就来看下app_process 如何加载这个类,同时执行Am.java里面的main方法。
app_process
可执行文件,是 app_main.cpp
编译而成的,于是我们找下这个文件,看下里面的main方法。
new 一个 runtime
实例,将参数设置进来。
这里参数是shell脚本里面带来的,即/system/bin 和 com.android.commands.am.Am,以及我们代入的其他参数
(比如:am start -n com.android.camera/com.android.camera.Camera 这里的start -n com.android.camera/com.android.camera.Camera 也会作为参数带入)
当找到 className
的时候,就会跳出循环,不解析后面的参数,然后将 className
以及后面的参数,通过runtime.setClassNameAndArgs设置到 runtime
里面,然后启动 runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
继续运行。
关于start方法的执行过程,下节继续讲解。