第 2 页 应用进程的初始化 先看一下ActivityThread.main的实现,它创建了一个ActivityThread对象,初始化之后,进入消息循环。
view plaincopy to clipboardprint?
- public static final void main(String[] args) {
-
- ActivityThread thread = new ActivityThread();
- thread.attach(false);
-
- Looper.loop();
-
-
- }
public static final void main(String[] args) {
// ......
ActivityThread thread = new ActivityThread();
thread.attach(false);
Looper.loop();
// ......
}
attach函数中,回去调用ActivityManagerService.attachApplication方法。
view plaincopy to clipboardprint?
- mgr.attachApplication(mAppthread);
mgr.attachApplication(mAppThread);
此时,会进入ActivityManagerService的进程空间,进入方法attachApplicationLocked,它会去获取和当前客户端应用程序关联的Provider信息。
view plaincopy to clipboardprint?
- List providers = generateApplicationProvidersLocked(app);
List providers = generateApplicationProvidersLocked(app);
根据上面的信息,很容易知道此处是通过PackageManagerService获取Provider信息的。参数app表明,只是取运行在该app内的Provider。根据Android的
文档,content provider必须在对应的AndroidManifest.xml中定义。默认情况下,是运行在安装包名称命名的进程里面。你也可以在android:process属性中制定所属的进程名称。另一个重要的属性android:multiprocess则可以指定provider的初始化方式,是分散在调用端进程中,从而避免进程间通信;还是只初始化在某个进程内,各个调用端只保留provider的代理。
随后,通过下面的方法调用,返回到应用程序的进程空间,参数中包含了上面获得的providers。此处的thread实际上就是应用端的ApplicationThread对象。
view plaincopy to clipboardprint?
- thread.bindApplication(processName, app.instrumentationInfo != null
- ? app.instrumentationInfo : app.info, providers,
- app.instrumentationClass, app.instrumentationProfileFile,
- app.instrumentationArguments, app.instrumentationWatcher, testMode,
- isRestrictedBackupMode, mConfiguration, getCommonServicesLocked());
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中):
view plaincopy to clipboardprint?
- List<ProviderInfo> providers = data.providers;
- if (providers != null) {
- installContentProviders(app, providers);
- }
List<ProviderInfo> providers = data.providers;
if (providers != null) {
installContentProviders(app, providers);
}
获取ActivityManagerService传递过来的provider信息,并在本进程中初始化。具体的,installContentProviders方法中,会对每个provider调用installProvider方法:
view plaincopy to clipboardprint?
- IContentProvider cp = installProvider(context, null, cpi, false);
IContentProvider cp = installProvider(context, null, cpi, false);
installProvider方法中,主要是实例化Provider,并保存到mProviderMap中:
view plaincopy to clipboardprint?
- final java.lang.ClassLoader cl = c.getClassLoader();
- localProvider = (ContentProvider)cl.
- loadClass(info.name).newInstance();
- provider = localProvider.getIContentProvider();
-
-
- String names[] = PATTERN_SEMICOLON.split(info.authority);
- for (int i=0; i<names.length; i++) {
- ProviderRecord pr = new ProviderRecord(names[i], provider,
- localProvider);
- try {
- provider.asBinder().linkToDeath(pr, 0);
- mProviderMap.put(names[i], pr);
- } catch (RemoteException e) {
- return null;
- }
- }
final java.lang.ClassLoader cl = c.getClassLoader();
localProvider = (ContentProvider)cl.
loadClass(info.name).newInstance();
provider = localProvider.getIContentProvider();
// ......
// Cache the pointer for the remote provider.
String names[] = PATTERN_SEMICOLON.split(info.authority);
for (int i=0; i<names.length; i++) {
ProviderRecord pr = new ProviderRecord(names[i], provider,
localProvider);
try {
provider.asBinder().linkToDeath(pr, 0);
mProviderMap.put(names[i], pr);
} catch (RemoteException e) {
return null;
}
}
上面的installContentProviders方法执行完成之后,会调用ActivityManagerService.publishContentProviders方法,将provider注册到ActivityManagerService中,方便其它应用进程获取。这里面有两个参数,一个是ApplicationThread对象,另一个是provider实例信息。
view plaincopy to clipboardprint?
- try {
- ActivityManagerNative.getDefault().publishContentProviders(
- getApplicationThread(), results);
- } catch (RemoteException ex) {
- }
try {
ActivityManagerNative.getDefault().publishContentProviders(
getApplicationThread(), results);
} catch (RemoteException ex) {
}
ActivityManagerService.publishContentProviders的实现也很简单,主要是将provider信息保存到ActivityManagerService.mProvidersByName中。具体参见源码。
本文主要介绍了Android系统内provider的初始化,Android系统默认是会初始化一些provider的,比如:ContactsProvider。它们的初始化和本文介绍的流程应该差不多,主要是在应用进程初始化时获取provider的信息,然后实例化provider,最后将实例化的provider保存到ActivityManagerService中,供其它应用进程使用。需要说明的一点是,应用进程内可以运行多个apk中的组件。