android persistent属性研究

来源:互联网 发布:动物百科全书软件 编辑:程序博客网 时间:2024/04/29 18:14

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

 

    假如该被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, truetrue);  
  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.     }  

 

    下面介绍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);  

 

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

[c-sharp] view plaincopyprint?
  1. 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.     }  

 

 

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

 

 

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

 

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


[c-sharp] view plaincopyprint?
  1. mInstrumentation.callApplicationOnCreate(app);  
    
    我们最终在绕了好大一圈之后,调用了app的onCreate函数来启动这个application。

0 0
原创粉丝点击