到这里,我们可以看到,PackageManagerService真的是用来管理手机的应用包的。通过它可以知道所有的系统可用资源。当然这些资源只是一些静态信息。通过这些信息,可以创建应用进程、初始化相关的Android组件。
应用进程的初始化 先看一下ActivityThread.main的实现,它创建了一个ActivityThread对象,初始化之后,进入消息循环。public static final void main(String[] args) { // ...... ActivityThread thread = new ActivityThread(); thread.attach(false); Looper.loop(); // ...... }
attach函数中,回去调用ActivityManagerService.attachApplication方法。mgr.attachApplication(mAppThread);
此时,会进入ActivityManagerService的进程空间,进入方法attachApplicationLocked,它会去获取和当前客户端应用程序关联的Provider信息。List providers = generateApplicationProvidersLocked(app);
根据上面的信息,很容易知道此处是通过PackageManagerService获取Provider信息的。参数app表明,只是取运行在该app内的Provider。根据Android的文档,content provider必须在对应的AndroidManifest.xml中定义。默认情况下,是运行在安装包名称命名的进程里面。你也可以在android:process属性中制定所属的进程名称。另一个重要的属性android:multiprocess则可以指定provider的初始化方式,是分散在调用端进程中,从而避免进程间通信;还是只初始化在某个进程内,各个调用端只保留provider的代理。随后,通过下面的方法调用,返回到应用程序的进程空间,参数中包含了上面获得的providers。此处的thread实际上就是应用端的ApplicationThread对象。
thread.bindApplication(processName, app.instrumentationInfo != null ? app.instrumentationInfo : app.info, providers, app.instrumentationClass, app.instrumentationProfileFile, app.instrumentationArguments, app.instrumentationWatcher, testMode, isRestrictedBackupMode, mConfiguration, getCommonServicesLocked());
ApplicationThread.bindApplication会发送BIND_APPLICATION消息给主线程。主线程会调用ActivityThread.handleBindApplication方法。这个函数里面主要分两步:一是根据需要创建Application、ApplicationContext和ApplicationContentResolver对象。因为,有可能多个apk���行在一个进程中,那么它们内部的组件(Component)执行的上下文(context)是不一样的。这几个对象实际上就是provider执行的上下文。二是根据传递过来的provider信息,创建provider实例,并保存在ActivityThread.mProviderMap中。具体的实例化provider过程如下(下面的代码位于ActivityThread.handleBindApplication中):List<ProviderInfo> providers = data.providers; if (providers != null) { installContentProviders(app, providers); }
获取ActivityManagerService传递过来的provider信息,并在本进程中初始化。具体的,installContentProviders方法中,会对每个provider调用installProvider方法: