首先,new一个女儿,
var mDdaughter = new 女儿(“6岁”,“漂亮可爱”,“健康乖巧”,“最喜欢玩小天才电话手表和她的爸爸”)
好了,女儿有了,有一天,女儿问我:
“爸爸爸爸,你说我玩的这个小天才电话手表怎么这么厉害,随便点一下这个小图片,这个应用就冒出来了,就可以听儿歌了。好神奇啊。”
我心里一惊:
小天才电话手表的系统就是Android,所以这不就是。。面试官常考的应用启动流程嘛!女儿也要来面试我了吗!好了,既然女儿问了,那就答吧。但是,对付这个小小的0经验面试官,我该咋说呢?
解答小小面试官
女儿,你可以把手表里面想象成一个幼儿园,里面有一个老师,一个班长,一个班干部,以及一大堆小朋友。
一个老师:Z老师(Zygote进程)
一个班长:小A(ActivityManagerService)
一个班干部:小L(Launcher桌面应用)
一大堆小朋友:所有应用,包括音乐小朋友,聊天小朋友,日历小朋友等等。
应用启动过程就像一个小朋友被叫醒一样,开机之后呢,Z老师会依次叫醒班长和班干部(SystemServer#ActivityManagerService,Launcher),小L醒了之后就会去了解手表里有哪些小朋友,长什么样(icon,name),家庭信息(包名,androidmanifest)等等,然后一个个把小朋友的照片(icon)贴到自己的身上。比如有音乐小朋友,聊天小朋友,日历小朋友,其实也就是你手表上这个桌面啦。
这时候你要点开一个音乐小朋友呢(startActivity),小L就会通知班长小A(Binder),小A知道了之后,让小L自己休息下(Paused),然后就去找Z老师了。Z老师就负责叫音乐小朋友起床了(fork进程,启动ActivityThread),音乐小朋友起来后就又找小A带她去洗脸刷牙(启动ApplicationThread,Activity),都弄完了就可以进行各种表演了,唱歌啊,跳舞啊。
女儿似懂非懂的给我点了一个赞,爸爸你真棒。
十五年后
mDdaughter.grow(15)
mDdaughter.study(“Android”)
复制代码
过了十五年,女儿已经21岁了,正在学习Android,考虑要不要女从父业。
这天,她一脸疑惑的来找我: “爸,这个app启动到底是怎么个流程啊,我看了好久还是不大明白,要不你再跟我详细讲一遍吧?” “好嘞,别担心,我这次详细跟你说说”
解答Android程序媛
还记得我小时候跟你说过的故事吗,Android系统就像一个幼儿园,有一个大朋友叫Launcher,身上会贴很多其他小朋友的名片。这个Launcher就是我们的桌面了,它通过PackageManagerService获知了系统里所有应用的信息,并展示了出来,当然它本身也是一个应用。
通过点击一个应用图标,也就是触发了点击事件,最后会执行到startActivity方法。这里也就和启动Activity步骤重合上了。
那么这个startActivity干了啥?是怎么通过重重关卡唤醒这个应用的?
首先,介绍下系统中那些重要的成员,他们在app启动流程中都担任了重要的角色.
系统成员介绍
init进程,Android系统启动后,Zygote并不是第一个进程,而是linux的根进程init进程,然后init进程才会启动Zygote进程。
Zygote进程,所有android进程的父进程,当然也包括SystemServer进程
SystemServer进程,正如名字一样,系统服务进程,负责系统中大大小小的事物,为此也是启动了三员大将(ActivityManagerService,PackageManagerService,WindowManagerService)以及binder线程池。
ActivityManagerService,主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,对于一些进程的启动,都会通过Binder通信机制传递给AMS,再处理给Zygote。
PackageManagerService,主要负责应用包的一些操作,比如安装,卸载,解析AndroidManifest.xml,扫描文件信息等等。
WindowManagerService,主要负责窗口相关的一些服务,比如窗口的启动,添加,删除等。
Launcher,桌面应用,也是属于应用,也有自己的Activity,一开机就会默认启动,通过设置Intent.CATEGORY_HOME的Category隐式启动。
搞清楚这些成员,就跟随我一起看看怎么过五关斩六将,最终启动了一个App。
第一关:跨进程通信,告诉系统我的需求
首先,要告诉系统,我Launcher要启动一个应用了,调用Activity.startActivityForResult方法,最终会转到mInstrumentation.execStartActivity方法。 由于Launcher自己处在一个单独的进程,所以它需要跨进程告诉系统服务我要启动App的需求。 找到要通知的Service,名叫ActivityTaskManagerService,然后使用AIDL,通过Binder与他进行通信。
这里的简单说下ActivityTaskManagerService(简称ATMS)。原来这些通信工作都是属于ActivityManagerService,现在分了一部分工作给到ATMS,主要包括四大组件的调度工作。也是由SystemServer进程直接启动的,相关源码可见ActivityManagerService.Lifecycle.startService方法,感兴趣朋友可以自己看看。
接着说跨进程通信,相关代码如下:
//Instrumentation.java
int result = ActivityTaskManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
//ActivityTaskManager.java
public static IActivityTaskManager getService() {
return IActivityTaskManagerSingleton.get();
}
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
new Singleton<IActivityTaskManager>() {
@Override
protected IActivityTaskManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
return IActivityTaskManager.Stub.asInterface(b);
}
};
//ActivityTaskManagerService.java
public class ActivityTaskManagerService extends IActivityTaskManager.Stub
public static final class Lifecycle extends SystemService {
private final ActivityTaskManagerService mService;
public Lifecycle(Context context) {
super(context);
mService = new ActivityTaskManagerServ