为什么写这篇文章呢?前段时间在研究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的应用。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

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对应的进程。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

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, truetrue);

    }

    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中有下面这个操作:

1

thread.attach(false);

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

1

final ApplicationThread mAppThread = new ApplicationThread();

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

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:

1

2

3

4

5

6

7

8

9

10

11

12

13

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, falsetrue);

    app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();

}

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

  你会发现在handleBindApplication函数中有这么一句:

1

mInstrumentation.callApplicationOnCreate(app);

  我们最终在绕了好大一圈之后,调用了app的onCreate函数来启动这个application。

android:persistent属性研究相关推荐

  1. android:persistent属性

    为什么写这篇文章呢?前段时间在研究telephony时,一直没有在framework下发现对telephony的初始化(PhoneFactory.java中的makeDefaultPhones函数)的 ...

  2. 说说Android应用的persistent属性

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

  3. Android Activity launchMode研究

    Android Activity launchMode研究 Activity的Launch mode一共有四种: standard, singleTop, singleTask, singleInst ...

  4. 再学一遍android:fitsSystemWindows属性

    本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 郭霖 即可关注,每个工作日都有文章更新. 对于android:fitsSystemWindows这个属性你是否感觉又熟悉又陌生呢? 熟 ...

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

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

  6. 关于Android应用本地拒绝服务漏洞和android:exported属性

    最近了项目中遇到一个Android应用本地拒绝服务漏洞的问题,第一眼看到这个玩意,我去,什么东东? 请教了下万能的度娘亲,才知道是应用本身组件对外性的一个问题.先简单说下这个漏洞. 下面漏洞介绍摘自阿 ...

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

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

  8. Android LinearLayout的android:layout_weight属性

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

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

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

  10. php worker类,Workerman进阶之Worker类-id属性研究

    Workerman进阶之Worker类->id属性研究 龙行    PHP    2019-5-20    1815    0评论 先来看看官方给的例子 如果id===0 设置定时器 use W ...

最新文章

  1. 机器学习中的方法技术与应用场景
  2. python绘制直方图-python plotly绘制直方图实例详解
  3. 如何学习Python数据爬虫?
  4. c语言计算pi后1000位,计算圆周率 Pi (π)值, 精确到小数点后 10000 位
  5. Anaconda 安装 ml_metrics package
  6. 【Python】AxisError: axis 0 is out of bounds for array of dimension 0
  7. 深度学习在NLP领域的发展之Transformer
  8. paip.远程服务器返回错误 (417) Expectation Failed 的解决办法
  9. 九个最佳ICON图标搜索引擎
  10. 无线通信蜂窝网络 的 覆盖范围
  11. iir滤波器的基本网络结构_DSP第五章数字滤波器基本结构
  12. VS2005 常见问题分析
  13. Javapython实现网页内容自动识别与提取技术实现
  14. 飞机大战游戏制作思路
  15. mysql优化——mycat数据库中间件
  16. 国培南通之行的感悟——(其二)
  17. 推荐几个牛逼的 iOSer 号
  18. qq魔法表情原理,解密及其他
  19. PGP应用——PGP软件的安装
  20. java Excel导入(兼容格式xls和xlsx)

热门文章

  1. PHP房贷计算器代码,等额本息,等额本金
  2. 网易云音乐前端性能监控实践
  3. 杂谈:微信推出赞赏码功能
  4. Game Master(思维 + 贪心)
  5. 利用ettercap进行简单的arp欺骗和mitm攻击
  6. taocat服务器的作用,随笔2_tww
  7. Python转义字符及用法
  8. node.js实现微信授权登陆
  9. 读《我怎样设计飞机》
  10. python大神的成长之路普通话三分钟_我的成长之路普通话考试讲话三分钟范文