Android应用程序组件Content Provider的启动过程源代码分析(5)

 Step 13. ActivityManagerService.attachApplicationLocked
         这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:

  1. public final class ActivityManagerService extends ActivityManagerNative   
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {   
  3.     ......   
  4.    
  5.     private final boolean attachApplicationLocked(IApplicationThread thread,   
  6.             int pid) {   
  7.         // Find the application record that is being attached...  either via   
  8.         // the pid if we are running in multiple processes, or just pull the   
  9.         // next app record if we are emulating process with anonymous threads.   
  10.         ProcessRecord app;   
  11.         if (pid != MY_PID && pid >= 0) {   
  12.             synchronized (mPidsSelfLocked) {   
  13.                 app = mPidsSelfLocked.get(pid);   
  14.             }   
  15.         } else if (mStartingProcesses.size() > 0) {   
  16.             ......   
  17.         } else {   
  18.             ......   
  19.         }   
  20.    
  21.         ......   
  22.    
  23.         app.thread = thread;   
  24.         app.curAdj = app.setAdj = -100;   
  25.         app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;   
  26.         app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;   
  27.         app.forcingToForeground = null;   
  28.         app.foregroundServices = false;   
  29.         app.debugging = false;   
  30.    
  31.         ......   
  32.    
  33.         boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);   
  34.         List providers = normalMode ? generateApplicationProvidersLocked(app) : null;   
  35.    
  36.         try {   
  37.             ......   
  38.    
  39.             thread.bindApplication(processName, app.instrumentationInfo != null   
  40.                 ? app.instrumentationInfo : app.info, providers,   
  41.                 app.instrumentationClass, app.instrumentationProfileFile,   
  42.                 app.instrumentationArguments, app.instrumentationWatcher, testMode,   
  43.                 isRestrictedBackupMode || !normalMode,   
  44.                 mConfiguration, getCommonServicesLocked());   
  45.    
  46.             ......   
  47.         } catch (Exception e) {   
  48.             ......   
  49.         }   
  50.    
  51.         ......   
  52.            
  53.         return true;   
  54.     }   
  55.    
  56.     ......   
  57.    
  58.     private final List generateApplicationProvidersLocked(ProcessRecord app) {   
  59.         List providers = null;   
  60.         try {   
  61.             providers = AppGlobals.getPackageManager().   
  62.                 queryContentProviders(app.processName, app.info.uid,   
  63.                 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);   
  64.         } catch (RemoteException ex) {   
  65.         }   
  66.         if (providers != null) {   
  67.             final int N = providers.size();   
  68.             for (int i=0; i<N; i++) {   
  69.                 ProviderInfo cpi =   
  70.                     (ProviderInfo)providers.get(i);   
  71.                 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);   
  72.                 if (cpr == null) {   
  73.                     cpr = new ContentProviderRecord(cpi, app.info);   
  74.                     mProvidersByClass.put(cpi.name, cpr);   
  75.                 }   
  76.                 app.pubProviders.put(cpi.name, cpr);   
  77.                 app.addPackage(cpi.applicationInfo.packageName);   
  78.                 ensurePackageDexOpt(cpi.applicationInfo.packageName);   
  79.             }   
  80.         }   
  81.         return providers;   
  82.     }   
  83.    
  84.     ......   
  85. }   
  这个函数首先是根据传进来的进程ID找到相应的进程记录块,注意,这个进程ID是应用程序ArticlesProvider的ID,然后对这个进程记录块做一些初倾始化的工作。再接下来通过调用generateApplicationProvidersLocked获得需要在这个过程中加载的Content Provider列表,在我们这个情景中,就只有ArticlesProvider这个Content Provider了。最后调用从参数传进来的IApplicationThread对象thread的bindApplication函数来执行一些应用程序初始化工作。从Android应用程序启动过程源代码分析一文中我们知道,在Android系统中,每一个应用程序进程都加载了一个ActivityThread实例,在这个ActivityThread实例里面,有一个成员变量mAppThread,它是一个Binder对象,类型为ApplicationThread,实现了IApplicationThread接口,它是专门用来和ActivityManagerService服务进行通信的。因此,调用下面语句:
  1. thread.bindApplication(processName, app.instrumentationInfo != null  
  2.     ? app.instrumentationInfo : app.info, providers,  
  3.     app.instrumentationClass, app.instrumentationProfileFile,  
  4.     app.instrumentationArguments, app.instrumentationWatcher, testMode,  
  5.     isRestrictedBackupMode || !normalMode,  
  6.     mConfiguration, getCommonServicesLocked());  
        就会进入到应用程序ArticlesProvider进程中的ApplicationThread对象的bindApplication函数中去。在我们这个情景场,这个函数调用中最重要的参数便是第三个参数providers了,它是我们要处理的对象。
 
        Step 14. ApplicationThread.bindApplication
        这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:

  1. public final class ActivityThread {   
  2.     ......   
  3.    
  4.     private final class ApplicationThread extends ApplicationThreadNative {   
  5.         ......   
  6.    
  7.         public final void bindApplication(String processName,   
  8.                 ApplicationInfo appInfo, List<ProviderInfo> providers,   
  9.                 ComponentName instrumentationName, String profileFile,   
  10.                 Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,   
  11.                 int debugMode, boolean isRestrictedBackupMode, Configuration config,   
  12.                 Map<String, IBinder> services) {   
  13.             if (services != null) {   
  14.                 // Setup the service cache in the ServiceManager   
  15.                 ServiceManager.initServiceCache(services);   
  16.             }   
  17.    
  18.             AppBindData data = new AppBindData();   
  19.             data.processName = processName;   
  20.             data.appInfo = appInfo;   
  21.             data.providers = providers;   
  22.             data.instrumentationName = instrumentationName;   
  23.             data.profileFile = profileFile;   
  24.             data.instrumentationArgs = instrumentationArgs;   
  25.             data.instrumentationWatcher = instrumentationWatcher;   
  26.             data.debugMode = debugMode;   
  27.             data.restrictedBackupMode = isRestrictedBackupMode;   
  28.             data.config = config;   
  29.             queueOrSendMessage(H.BIND_APPLICATION, data);   
  30.         }   
  31.    
  32.         ......   
  33.     }   
  34.    
  35.     ......   
  36. }   
这个函数把相关的信息都封装成一个AppBindData对象,然后以一个消息的形式发送到主线程的消息队列中去等等待处理。这个消息最终是是在ActivityThread类的handleBindApplication函数中进行处理的。

 
         Step 15. ActivityThread.handleBindApplication
         这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:
  1. public final class ActivityThread {  
  2.     ......  
  3.       
  4.     private final void handleBindApplication(AppBindData data) {  
  5.         ......  
  6.   
  7.         List<ProviderInfo> providers = data.providers;  
  8.         if (providers != null) {  
  9.             installContentProviders(app, providers);  
  10.             ......  
  11.         }  
  12.   
  13.         ......  
  14.     }  
  15.   
  16.     ......  
  17. }  

         这个函数的内容比较多,我们忽略了其它无关的部分,只关注和Content Provider有关的逻辑,这里主要就是调用installContentProviders函数来在本地安装Content Providers信息。

 
         Step 16. ActivityThread.installContentProviders
         这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:

  1. public final class ActivityThread {   
  2.     ......   
  3.        
  4.     private final void installContentProviders(   
  5.             Context context, List<ProviderInfo> providers) {   
  6.         final ArrayList<IActivityManager.ContentProviderHolder> results =   
  7.             new ArrayList<IActivityManager.ContentProviderHolder>();   
  8.    
  9.         Iterator<ProviderInfo> i = providers.iterator();   
  10.         while (i.hasNext()) {   
  11.             ProviderInfo cpi = i.next();   
  12.             StringBuilder buf = new StringBuilder(128);   
  13.             buf.append("Pub ");   
  14.             buf.append(cpi.authority);   
  15.             buf.append(": ");   
  16.             buf.append(cpi.name);   
  17.             Log.i(TAG, buf.toString());   
  18.             IContentProvider cp = installProvider(context, null, cpi, false);   
  19.             if (cp != null) {   
  20.                 IActivityManager.ContentProviderHolder cph =   
  21.                     new IActivityManager.ContentProviderHolder(cpi);   
  22.                 cph.provider = cp;   
  23.                 results.add(cph);   
  24.                 // Don't ever unload this provider from the process.   
  25.                 synchronized(mProviderMap) {   
  26.                     mProviderRefCountMap.put(cp.asBinder(), new ProviderRefCount(10000));   
  27.                 }   
  28.             }   
  29.         }   
  30.    
  31.         try {   
  32.             ActivityManagerNative.getDefault().publishContentProviders(   
  33.                 getApplicationThread(), results);   
  34.         } catch (RemoteException ex) {   
  35.         }   
  36.     }   
  37.    
  38.     ......   
  39. }   

    这个函数主要是做了两件事情,一是调用installProvider来在本地安装每一个Content Proivder的信息,并且为每一个Content Provider创建一个ContentProviderHolder对象来保存相关的信息。ContentProviderHolder对象是一个Binder对象,是用来把Content Provider的信息传递给ActivityManagerService服务的。当这些Content Provider都处理好了以后,还要调用ActivityManagerService服务的publishContentProviders函数来通知ActivityManagerService服务,这个进程中所要加载的Content Provider,都已经准备完毕了,而ActivityManagerService服务的publishContentProviders函数的作用就是用来唤醒在前面Step 7等待的线程的了。我们先来看installProvider的实现,然后再来看ActivityManagerService服务的publishContentProviders函数的实现。




本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966988,如需转载请自行联系原作者
上一篇:阿里巴巴代码平台架构的演进之路


下一篇:容器镜像服务 - Webhook使用说明