为什么写这篇文章呢?前段时间在研究telephony时,一直没有在framework下发现对telephony的初始化(PhoneFactory.java中的makeDefaultPhones函数)的调用。结果全局搜索之后发现在application PhoneApp(packages/apps/Phone)中调用了。但是application PhoneApp既没有被Broadcast唤醒,也没有被其他service调用,那么是android是通过什么方式来启动PhoneApp,所以就发现了属性android:persistent。

在AndroidManifest.xml定义中,application有这么一个属性android:persistent,根据字面意思来理解就是说该应用是可持久的,也即是常驻的应用。其实就是这么个理解,被android:persistent修饰的应用会在系统启动之后被AM启动。

AM首先去PM(PackageManagerService)中去查找设置了android:persistent的应用。

[c-sharp] view plaincopyprint?
  1. public void systemReady(final Runnable goingCallback) {
  2. if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
  3. try {
  4. List apps = AppGlobals.getPackageManager().
  5. getPersistentApplications(STOCK_PM_FLAGS);
  6. if (apps != null) {
  7. int N = apps.size();
  8. int i;
  9. for (i=0; i<N; i++) {
  10. ApplicationInfo info
  11. = (ApplicationInfo)apps.get(i);
  12. if (info != null &&
  13. !info.packageName.equals("android")) {
  14. addAppLocked(info);
  15. }
  16. }
  17. }
  18. } catch (RemoteException ex) {
  19. // pm is in same process, this will never happen.
  20. }
  21. }
  22. }

public void systemReady(final Runnable goingCallback) { if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { try { List apps = AppGlobals.getPackageManager(). getPersistentApplications(STOCK_PM_FLAGS); if (apps != null) { int N = apps.size(); int i; for (i=0; i<N; i++) { ApplicationInfo info = (ApplicationInfo)apps.get(i); if (info != null && !info.packageName.equals("android")) { addAppLocked(info); } } } } catch (RemoteException ex) { // pm is in same process, this will never happen. } } }

假如该被android:persistent修饰的应用此时并未运行的话,那么AM将调用startProcessLocked启动该app,关于startProcessLocked不再描述,另外一篇文章《How to start a new process for Android?》中做了详细的介绍。

app的启动过程就是启动app所在的package对应的进程。

[c-sharp] view plaincopyprint?
  1. final ProcessRecord addAppLocked(ApplicationInfo info) {
  2. ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
  3. if (app == null) {
  4. app = newProcessRecordLocked(null, info, null);
  5. mProcessNames.put(info.processName, info.uid, app);
  6. updateLruProcessLocked(app, true, true);
  7. }
  8. if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
  9. == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
  10. app.persistent = true;
  11. app.maxAdj = CORE_SERVER_ADJ;
  12. }
  13. if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
  14. mPersistentStartingProcesses.add(app);
  15. startProcessLocked(app, "added application", app.processName);
  16. }
  17. return app;
  18. }

final ProcessRecord addAppLocked(ApplicationInfo info) { ProcessRecord app = getProcessRecordLocked(info.processName, info.uid); if (app == null) { app = newProcessRecordLocked(null, info, null); mProcessNames.put(info.processName, info.uid, app); updateLruProcessLocked(app, true, true); } if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) { app.persistent = true; app.maxAdj = CORE_SERVER_ADJ; } if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) { mPersistentStartingProcesses.add(app); startProcessLocked(app, "added application", app.processName); } return app; }

下面介绍app所在的package对应的进程启动完成之后,app是如何被create的。

从文章《How to start a new process for Android?》中可知,zygote在创建新的进程均会启动它的mainThread android.app.ActivityThread,因此我们从ActivityThread的main函数中接着分析app的create过程。

在main中有下面这个操作

[c-sharp] view plaincopyprint?
  1. thread.attach(false);

thread.attach(false);

在attach过程中,ActivityThread会将对应的application attach到AM中去,交与AM去管理。这里需要注意一个变量

[c-sharp] view plaincopyprint?
  1. final ApplicationThread mAppThread = new ApplicationThread();

final ApplicationThread mAppThread = new ApplicationThread();

mAppThread是一个ApplicationThread对象,mAppThread可以看作是当前进程主线程的核心,它负责处理本进程与其他进程(主要是AM)之间的通信,同时通过attachApplication将mAppThread的代理Binder传递给AM。

[c-sharp] view plaincopyprint?
  1. private final void attach(boolean system) {
  2. sThreadLocal.set(this);
  3. mSystemThread = system;
  4. if (!system) {
  5. ViewRoot.addFirstDrawHandler(new Runnable() {
  6. public void run() {
  7. ensureJitEnabled();
  8. }
  9. });
  10. android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
  11. RuntimeInit.setApplicationObject(mAppThread.asBinder());
  12. IActivityManager mgr = ActivityManagerNative.getDefault();
  13. try {
  14. mgr.attachApplication(mAppThread);
  15. } catch (RemoteException ex) {
  16. }
  17. }
  18. }

private final void attach(boolean system) { sThreadLocal.set(this); mSystemThread = system; if (!system) { ViewRoot.addFirstDrawHandler(new Runnable() { public void run() { ensureJitEnabled(); } }); android.ddm.DdmHandleAppName.setAppName("<pre-initialized>"); RuntimeInit.setApplicationObject(mAppThread.asBinder()); IActivityManager mgr = ActivityManagerNative.getDefault(); try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { } } }

上面的attach代码中,我们顺着IPC调用AM的attachApplication过程再往下看。
    在该过程中,AM调用到了IPC通信调用mAppThread的bindApplication;

[c-sharp] view plaincopyprint?
  1. private final boolean attachApplicationLocked(IApplicationThread thread,
  2. int pid) {
  3. thread.bindApplication(processName, app.instrumentationInfo != null
  4. ? app.instrumentationInfo : app.info, providers,
  5. app.instrumentationClass, app.instrumentationProfileFile,
  6. app.instrumentationArguments, app.instrumentationWatcher, testMode,
  7. isRestrictedBackupMode || !normalMode,
  8. mConfiguration, getCommonServicesLocked());
  9. updateLruProcessLocked(app, false, true);
  10. app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
  11. }

private final boolean attachApplicationLocked(IApplicationThread thread, int pid) { thread.bindApplication(processName, app.instrumentationInfo != null ? app.instrumentationInfo : app.info, providers, app.instrumentationClass, app.instrumentationProfileFile, app.instrumentationArguments, app.instrumentationWatcher, testMode, isRestrictedBackupMode || !normalMode, mConfiguration, getCommonServicesLocked()); updateLruProcessLocked(app, false, true); app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis(); }

mAppThread的bindApplication再通过消息机制向ActivityThread自身维护的handler发送BIND_APPLICATION消息。下面看看ActivityThread自身维护的handler对消息BIND_APPLICATION的处理,最终会调用到handleBindApplication函数
    你会发现在handleBindApplication函数中有这么一句

[c-sharp] view plaincopyprint?
  1. mInstrumentation.callApplicationOnCreate(app);

mInstrumentation.callApplicationOnCreate(app);     
    我们最终在绕了好大一圈之后,调用了app的onCreate函数来启动这个application

android:persistent属性相关推荐

  1. 说说Android应用的persistent属性

    2019独角兽企业重金招聘Python工程师标准>>> 说说Android应用的persistent属性 侯 亮 1 启动persistent应用 在Android系统中,有一种永久 ...

  2. android preference属性,Android进阶——Preference详解之Preference系的基本应用和管理(二)...

    并非我们第一次打开相应界面之后就会自动创建对应的SharedPreferences文件,而是在我们改变了原有状态时候喎�"/kf/ware/vc/" target="_b ...

  3. android:layout_gravity和android:gravity属性的区别

    android:gravity / android:layout_gravity区别: android:gravity 是设置该view里面的内容相对于该view的位置,例如设置button里面的te ...

  4. Android LinearLayout的android:layout_weight属性

    本文主要介绍Android LinearLayout的android:layout_weight属性意义 android:layout_weight为大小权重,相当于在页面上显示的百分比,它的计算是根 ...

  5. 使用Java代码在应用层获取Android系统属性

    之前使用Native代码的property_get()/property_set()来获取Android系统属性,现在需要改写到Java上面, 但是System.getProperty() / Sys ...

  6. 【Android开发经验】android:windowSoftInputMode属性具体解释

    本文章来自CSDN博客:http://blog.csdn.net/zhaokaiqiang1992.转载请注明地址! 在前面的一篇文章中,简单的介绍了一下怎样实现软键盘不自己主动弹出,使用的方法是设置 ...

  7. Android --- allowBackup 属性的含义和危险性实例讲解

    一.前言 今天在开发的过程中遇到一个问题,就是关于AndroidManifest.xml中的allowBackup属性,也算是自己之前对这个属性的不了解,加上IDE的自动生成代码,没太注意这个属性,但 ...

  8. Android踩坑日记:Android字体属性及测量(FontMetrics)

    Android字体属性及测量(FontMetrics) 字体的几个参数,以Android API文档定义为尊,见下图 要点如下: 基准点是baseline Ascent是baseline之上至字符最高 ...

  9. android布局的属性大全,Android布局属性大全

    第一类:属性值为true或false android:layout_centerHrizontal 水平居中 android:layout_centerVertical 垂直居中 android:la ...

最新文章

  1. Centos7 Docker Compose部署mysql5.7
  2. 后端小白的VUE入门笔记, 进阶篇
  3. html引入latex,如何在html文件中使用MathJax或LaTex?
  4. 【目录】《剑指Offer》Java实现
  5. 关于scanf和的问题
  6. citrix 产品上线
  7. python和access哪个难_python和access的区别
  8. 开奖及送书|《Vue.js权威指南》
  9. linux epoll原理详解,Linux下selectpollepoll的实现原理(一)【转】
  10. python template languages_更换Django默认的模板引擎为jinja2的实现方法
  11. 金蝶K/3WISE V14.0安装包下载地址,金蝶K3 WISE V14.0安装包资源包下载链接
  12. 实习生去公司都干些啥
  13. c#winform单表生树
  14. 循环经济升级推动产业升级发展建议
  15. Linux系统之磁盘管理
  16. 老男孩28期学员卞勃森决心书
  17. GitHub设置代理 提升速度
  18. 【GDScript】保存/加载物品装备数据
  19. 1秒生成证件照——小米云证件照微信小程序
  20. 用Python的mutagen模块获取MP3音频文件的时长

热门文章

  1. WPF 之 线程使用
  2. 《梦断代码》读后感一
  3. NeuSoft(2)添加系统调用
  4. R语言 非中心化F分布
  5. 初步了解Linux创建文件系统命令
  6. 理解Java枚举类型
  7. 第二章 向量(d2)有序向量:二分查找
  8. 为什么使用hibernate
  9. [算法]——归并排序(Merge Sort)
  10. js动态添加,删除option及add的使用方法