转载请标明出处:【顾林海的博客】


前言

AMS(ActivityManagerService)的启动是在SystemServer进程中启动的,它的职责是用于和所有APP的四大组件进行通信,Activity的启动过程就是APP端与AMS端进行通信,首先理解的一点是APP端与AMS是在两个不同的进程中,因此APP端与AMS是通过跨进程通信的。

从Launcher启动APP

Launcher就是指手机的屏幕,同时它也是一个APP,只不过这是由制造商开发的,手指点击屏幕的某个APP,这时APP启动并打开首页的界面,这一系列操作需要和AMS进行通信才能完成,APP安装(启动)时,PackageManagerService从APK包的AndroidManifest文件中读取四大组件的信息并保存下来。

下图是Launcher与AMS的通信时序图:

Launcher与APP是在两个不同的进程中,他们之间的通信是通过Binder完成的,点击Launcher上的某个APP,这时会调用Launcher的startActivitySafely方法。

public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {...intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//1...startActivity(intent, optsBundle);//2...
}

上面代码我省略了一些不太重要的,重点看上面两行代码,第一行给intent设置Flag为Intent.FLAG_ACTIVITY_NEW_TASK,Activity会在新的任务栈中启动,第二行代码调用startActivity方法,很简单,就是启动APP中的Activity。

最终会调用Activity的startActivity方法,Intent中携带的就是需要启动的APP的Activity信息。startActivity方法最终会调用startActivityForResult方法,代码如下:

@Override
public void startActivity(Intent intent) {this.startActivity(intent, null);
}@Override
public void startActivity(Intent intent, @Nullable Bundle options) {if (options != null) {startActivityForResult(intent, -1, options);} else {// Note we want to go through this call for compatibility with// applications that may have overridden the method.startActivityForResult(intent, -1);}
}public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,@Nullable Bundle options) {...Instrumentation.ActivityResult ar =mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options);...
}

Activity内部会保持一个对Instrumentation的引用,Instrumentation主要用来监控应用程序和系统的交互,在startActivityForResult方法中会调用Instrumentation的execStartActivity方法,在execStartActivity方法的第二个参数中,可以看到一个mMainThread的变量,这是一个ActivityThread类型的变量,ActivityThread就是主线程,也就是我们平常所说的UI线程,它是在APP启动时创建的,代表APP应用程序,ActivityThread里面有个main函数,是APP启动时的入口。

execStartActivity方法传递了两个很重要的参数,mMainThread.getApplicationThread(Binder对象)将Launcher所在的进程传递了过去,这样AMS知道是哪个进程;还有一个比较重要的是mToken,它是Binder对象,代表Launcher这个Activity也通过Instrumentation传给AMS,AMS查询时,就知道谁向AMS发起了请求。

Instrumentation的execStartActivity代码如下:

public Instrumentation.ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {...try {...int result = ActivityManager.getService().startActivity(whoThread, who.getBasePackageName(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()),token, target != null ? target.mEmbeddedID : null,requestCode, 0, null, options);...} catch (RemoteException e) {throw new RuntimeException("Failure from system", e);}return null;
}

这里通过ActivityManager的getService方法来获取AMS的代理对象(Android 7.0是通过ActivityManagerNative的getDefault来获取AMS的代理对象),返回一个类型为IActivityManager,IActivityManager是一个接口,内部定义了四大组件的生命周期,

public static IActivityManager getService() {return IActivityManagerSingleton.get();
}private static final Singleton<IActivityManager> IActivityManagerSingleton =new Singleton<IActivityManager>() {@Overrideprotected IActivityManager create() {final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);final IActivityManager am = IActivityManager.Stub.asInterface(b);return am;}};

Singleton是一个单例类,内部通过ServiceManager取出一个activity的对象,通过IActivityManager.Stub.asInterface将它包装成一个ActivityManagerProxy对象(AMP),IActivityManager.Stub.asInterface这段代码是不是很熟悉,就是AIDL远程代理,这里获取到的是AMS的代理对象。

AMP告诉AMS启动哪个APP,并且启动的是哪个Activity,AMS会检查APP中的AndroidManifest文件,看看是否存在要启动的Activity,如果不存在,就会抛出一个Activity not found的错误。AMS检查到启动的Activity存在,这时会告诉Launcher:“我要启动Activity了”,Launcher会将它所在的进程传给AMS,AMS会将它保存为一个ActivityRecord对象,这个对象里面有一个ApplicationThreadProxy,是一个Binder代理,AMS想要发送消息给Launcher,可以通过ApplicationThreadProxy(ATP)来发送消息,ATP是APP端ApplicationThread(APT)的代理对象,用于AMS与APP端的通信。

既然AMS知道了启动的Activity,接下来就应该启动Activity,在启动Activity之前,AMS需要告诉Launcher“我要启动了,你可以暂停了“,时序图如下:

中间通过ApplicationThreadProxy向APP端的ApplicationThread发送消息,ApplicationThread接受到AMS的消息后,调用ActivityThread的sendMessage方法,向Launcher的主线程消息队列发送一个PAUSE_ACTIVITY消息。

@Override
public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,int configChanges, PendingTransactionActions pendingActions, String reason) {//获取Launcher的ActivityActivityClientRecord r = mActivities.get(token);if (r != null) {if (userLeaving) {performUserLeavingActivity(r);}r.activity.mConfigChangeFlags |= configChanges;performPauseActivity(r, finished, reason, pendingActions);// Make sure any pending writes are now committed.if (r.isPreHoneycomb()) {QueuedWork.waitToFinish();}mSomeActivitiesChanged = true;}
}

handlePauseActivity方法中从mActivities集合中,获取Launcher的Activity并让他休眠。

到这里Launcher与AMS之间的通信就结束了,接下来的事情就是启动APP中的Activity,因为是首次启动,APP的进程不存在,需要创建一个新的进程,需要调用Process.start方法,并且指定了ActivityThread的main函数为入口函数:

int pid=Process.start("android.app.ActivityThread",mSimpleProcessManagement ? app.processName:gid,debugFlags,null);

为新进程创建ActivityThread对象,也就是UI线程,同时执行入口函数main,其中创建一个主线程Looper,也就是MainLooper。

另外创建Application,主线程序会收到BIND_APPLICATION消息:

public void handleMessage(Message msg) {...switch (msg.what) {case BIND_APPLICATION:Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");AppBindData data = (AppBindData)msg.obj;handleBindApplication(data);Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);break;...}...
}

根据传递过来的ApplicationInfo创建一个对应的LoadedApk对象,然后创建ContextImpl对象,接着通过反射创建目标Application,并调用attach方法,将ContextImpl对象设置为目标Application的上下文环境,最后调用Application的onCreate函数。

创建完APP后,APP端通知AMS创建完毕同时把ActivityThread对象发送给AMS,同时AMS端把ActivityThread对象转换成一个ActivityThreadProxy对象,之后AMS可以向APP端发送消息,通过ActivityThreadProxy这个代理对象。

public void callActivityOnCreate(Activity activity, Bundle icicle) {prePerformCreate(activity);activity.performCreate(icicle);postPerformCreate(activity);
}

ActivityThread接受到AMS的消息,在H中发送LAUNCH_ACTIVITY消息,调用handleLaunchActivity方法,在该方法中通过Instrumentation的newActivity方法,创建要启动的Activity实例,为这个Activity创建一个上下文Context对象,并与Activity关联,通过Instrumentation的callActivityOnCreate方法,执行Activity的onCreate方法,从而启动Activity,至此APP启动完毕。

Android之ActivityManagerService详解(APP启动过程)相关推荐

  1. Android Studio 安装详解及安装过程中出现的问题解决方案

    Android Studio 安装详解及安装过程中出现的问题解决方案 一,Android Studio安装包下载, 首先到官网下载,就是去Android Studio中文社区官网下载你的平台需要的安装 ...

  2. Android系统(116)---APP启动过程

    APP启动过程 上图就可以很好的说明App启动的过程 ActivityManagerService组织回退栈时以ActivityRecord为基本单位,所有的ActivityRecord放在同一个Ar ...

  3. Android复习10【Service与Thread的区别、Service的生命周期、Service生命周期解析(相关方法详解、启动方式的不同、绑定)、音乐播放器+服务】

    音乐播放器Android代码下载:https://wws.lanzous.com/ifqzihaxvij 目   录 Service与Thread的区别 Service的生命周期 Service生命周 ...

  4. android apk安装过程,Android安装apk文件并适配Android 7.0详解

    Android安装apk文件并适配Android 7.0详解 首先在AndroidManifest.xml文件,activity同级节点注册provider: android:name="a ...

  5. Android SystemUI 架构详解

    Android SystemUI 架构详解 本文描述Android系统中一个核心应用SystemUI,详细赘述SystemUI中几大模块功能的实现过程.由于作者水平有限,如发现本文中错误的地方,欢迎指 ...

  6. Android学习笔记——Android 签名机制详解

    Android 签名机制详解 近期由于工作需要在学习 Android 的签名机制,因为没有现成资料,只能通过开发者文档和阅读博客的方式对 Android 签名机制进行大致了解.过程中查阅到的资料相对零 ...

  7. 【Android签名机制详解】二:Android V1、V2、V3、V4签名方案

    前言 书接上回[Android签名机制详解]一:密码学入门,在了解了消息摘要.非对称加密.数字签名.数字证书的基本概念后,我们趁热打铁.直奔主题,讲解签名在Android中的实际应用. 基础知识 An ...

  8. [Android]多进程知识点详解

    作者:Android开发_Hua 链接:https://www.jianshu.com/p/e0f833151f66 多进程知识点汇总: 一:了解多进程 二:项目中多进程的实现 三:多进程的优缺点与使 ...

  9. JMessage Android 端开发详解

    JMessage Android 端开发详解 目前越来越多的应用会需要集成即时通讯功能,这里就为大家详细讲一下如何通过集成 JMessage 来为你的 App 增加即时通讯功能. 首先,一个最基础的 ...

最新文章

  1. hive常用参数配置设置
  2. Spoken English(021)
  3. Java交流|面试最后一问:你有什么问题想问我吗?
  4. 路径规划之基于优化的规划算法
  5. 课设——C语言学生成绩管理系统
  6. java计算ipv6前缀位数
  7. js动态添加HTML css失效,JS动态添加元素和设置其样式问题
  8. 程序分析技术栈-测试/辅助证明/模型检验/保守静态分析/bug-finding
  9. 如何申请邮件安全证书(S/MIME)实现邮件加密和数字签名
  10. PS怎么用3D功能怎么用?如何用PS做立体字
  11. linux 临时文件夹设置,Linux 系统 tmp 目录的安全设置
  12. Tensorflow训练的模型,如何保存与载入?
  13. 没有躲过的坑--C++函数的默认参数(重新定义默认参数)
  14. IDEA Wrong tag '**' add [**] to custom tags 移除自定义的javadoc tags
  15. PS填充、仿制图章和修补工具
  16. 视频教程-内功修炼之数据结构与算法-Java
  17. 用python实现植物大战僵尸(游戏截图+动态演示+源码分享)
  18. 使用TestFlight安装ios APP的测试版本
  19. 如何用u盘做系统盘?
  20. 设计模式之备忘录模式

热门文章

  1. 串口调试助手c语言程序,串口调试助手C语言源程序
  2. 脚本大全_抖音文案大全2020励志:抖音最火励志搞笑句子,直接套用上热门
  3. Office 365和SFB更新
  4. Machine Learning:如何选择机器学习算法?
  5. Java冒泡排序【简】
  6. Web测试实践-任务进度-Day02
  7. DOM_05之DOM、BOM常用对象
  8. 实习日记7.13-7.14
  9. PHP严重致命错误处理:php Fatal error: Cannot redeclare clas
  10. linux shell之cut用法