为什么写这篇文章呢?前段时间在研究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 plain copy print ?
  1. publicvoidsystemReady(finalRunnablegoingCallback){
  2. if(mFactoryTest!=SystemServer.FACTORY_TEST_LOW_LEVEL){
  3. try{
  4. Listapps=AppGlobals.getPackageManager().
  5. getPersistentApplications(STOCK_PM_FLAGS);
  6. if(apps!=null){
  7. intN=apps.size();
  8. inti;
  9. for(i=0;i<N;i++){
  10. ApplicationInfoinfo
  11. =(ApplicationInfo)apps.get(i);
  12. if(info!=null&&
  13. !info.packageName.equals("android")){
  14. addAppLocked(info);
  15. }
  16. }
  17. }
  18. }catch(RemoteExceptionex){
  19. //pmisinsameprocess,thiswillneverhappen.
  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 plain copy print ?
  1. finalProcessRecordaddAppLocked(ApplicationInfoinfo){
  2. ProcessRecordapp=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,"addedapplication",app.processName);
  16. }
  17. returnapp;
  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 plain copy print ?
  1. thread.attach(false);

thread.attach(false);

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

[c-sharp] view plain copy print ?
  1. finalApplicationThreadmAppThread=newApplicationThread();

final ApplicationThread mAppThread = new ApplicationThread();

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

[c-sharp] view plain copy print ?
  1. privatefinalvoidattach(booleansystem){
  2. sThreadLocal.set(this);
  3. mSystemThread=system;
  4. if(!system){
  5. ViewRoot.addFirstDrawHandler(newRunnable(){
  6. publicvoidrun(){
  7. ensureJitEnabled();
  8. }
  9. });
  10. android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
  11. RuntimeInit.setApplicationObject(mAppThread.asBinder());
  12. IActivityManagermgr=ActivityManagerNative.getDefault();
  13. try{
  14. mgr.attachApplication(mAppThread);
  15. }catch(RemoteExceptionex){
  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 plain copy print ?
  1. privatefinalbooleanattachApplicationLocked(IApplicationThreadthread,
  2. intpid){
  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 plain copy print ?
  1. mInstrumentation.callApplicationOnCreate(app);

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

更多相关文章

  1. Android-隐藏app图标以及隐式启动
  2. Android(安卓)WebView 全面干货指南
  3. Android面试题(数据存储、view篇)
  4. android实现数据库和UI同步更新
  5. android内从泄漏
  6. Android(安卓)通过网页打开自己的APP(scheme)
  7. Android(安卓)Service 介绍
  8. SEAndroid安全机制框架分析
  9. android_8.1 hdmi设备热插拔事件

随机推荐

  1. 【北亚数据恢复】IBM服务器raid5硬盘离线
  2. ClickHouse镜像在阿里云镜像站首发上线
  3. C++实现飞机订票系统
  4. C语言中const和define的区别你了解嘛
  5. SpringBoot项目实战之数据交互篇
  6. @RequestBody,@RequestParam和@Param的区
  7. 原画如何入门?原画学习技巧
  8. Laravel6接入谷歌验证器
  9. 手部怎么画?漫画初学者手部绘画教程
  10. SpringBoot实战教程之新手入门篇