通过不同的key,来存储,然后构建不同的map对象,分别是以authority为key、IBinder文key、ComponentName为key.
代码后面还按照其它方式保存到内存
mLocalProviders.put(jBinder, pr); mLocalProvidersByName.put(cname, pr);
按照不同的存储类型分别保存不同的ContentProvider集合中。
然后我们在第8步开始的installContentProviders方法里面还有这个函数没有分析,publishContentProviders函数,代码实现如下
public final void publishContentProviders(IApplicationThread caller, List<ContentProviderHolder> providers) { if (providers == null) { return; } enforceNotIsolatedCaller("publishContentProviders"); synchronized (this) { final ProcessRecord r = getRecordForAppLocked(caller); if (DEBUG_MU) Slog.v(TAG_MU, "ProcessRecord uid = " + r.uid); if (r == null) { throw new SecurityException( "Unable to find app for caller " + caller + " (pid=" + Binder.getCallingPid() + ") when publishing content providers"); } final long origId = Binder.clearCallingIdentity(); final int N = providers.size(); for (int i=0; i<N; i++) { ContentProviderHolder src = providers.get(i); if (src == null || src.info == null || src.provider == null) { continue; } ContentProviderRecord dst = r.pubProviders.get(src.info.name); if (DEBUG_MU) Slog.v(TAG_MU, "ContentProviderRecord uid = " + dst.uid); if (dst != null) { ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name); mProviderMap.putProviderByClass(comp, dst); String names[] = dst.info.authority.split(";"); for (int j = 0; j < names.length; j++) { mProviderMap.putProviderByName(names[j], dst); } int NL = mLaunchingProviders.size(); int j; for (j=0; j<NL; j++) { if (mLaunchingProviders.get(j) == dst) { mLaunchingProviders.remove(j); j--; NL--; } } synchronized (dst) { dst.provider = src.provider; dst.proc = r; dst.notifyAll(); } updateOomAdjLocked(r); maybeUpdateProviderUsageStatsLocked(r, src.info.packageName, src.info.authority); } } Binder.restoreCallingIdentity(origId); } }
为每一个ContentProvider信息创建了一个ContentProviderRecord对象,保存到了ProviderMap集合中,启动的ContentProvider按照authority为key保存到ProviderMap中,这里工作主要就是将ContentProvider的信息保存到AMS服务中去。
AMS服务保存ContentProvider的信息主要是在类ProviderMap中,它里边有两种保存的Provider信息的集合
1. ProviderByClass
以ComponentName为key保存了ContentProviderRecord的信息
2. ProviderByName
以authority为key保存了ContentProviderRecord的信息
最后我们不是看到这个函数,
notifyAll()
不同进程间调用ContentProvider的时候,先会判断该ContentProvider所在的进程是否已经启动,如果有启动需要首先启动该进程,在该进程启动完成后这个ContentProvider也就启动起来了,比如在我们项目中,我们有2个进程,然后一个ContentProvider在一个进程里面,我们在自己app通过下面的方法拉起ContentProvider
getContentResolver().insert
如果没有启动的时候,AMS就会首先启动个进程及ContentProvider,并把这个ContentProviderRecord添加到等待队列mLaunchingProviders中去,如下声明
final ArrayList<ContentProviderRecord> mLaunchingProviders = new ArrayList<ContentProviderRecord>();
然后等他它启动完成,此处代码就是新的进程及ContentProvider启动完成后,首先判断是否在等待进程中,如果有,就将该ContentProvider信息从等待队列中移除,并调用notifyAll来唤醒等待的工作。
9、最后分析handleBindApplication函数的最后一步
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites(); try { // If the app is being launched for full backup or restore, bring it up in // a restricted environment with the base application class. Application app = data.info.makeApplication(data.restrictedBackupMode, null); mInitialApplication = app; // don't bring up providers in restricted mode; they may depend on the // app's custom Application class if (!data.restrictedBackupMode) { List<ProviderInfo> providers = data.providers; if (providers != null) { installContentProviders(app, providers); // For process that contains content providers, we want to // ensure that the JIT is enabled "at some point". mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000); } } // Do this after providers, since instrumentation tests generally start their // test thread at this point, and we don't want that racing. try { mInstrumentation.onCreate(data.instrumentationArgs); } catch (Exception e) { throw new RuntimeException( "Exception thrown in onCreate() of " + data.instrumentationName + ": " + e.toString(), e); } try { mInstrumentation.callApplicationOnCreate(app); } catch (Exception e) { if (!mInstrumentation.onException(app, e)) { throw new RuntimeException( "Unable to create application " + app.getClass().getName() + ": " + e.toString(), e); } } } finally { StrictMode.setThreadPolicy(savedPolicy); }
当有触发ContentProvider启动完成的时候,我们可以看到才去执行
mInstrumentation.callApplicationOnCreate(app);
这里跟踪进去也就是Application的onCreate方法,所以它是在ContentProvider的onCreate后面(前提是同时启动Appliation和ContentProvider)
3、总结
AMS服务保存ContentProvider的信息主要是在类ProviderMap中,它里边有两种保存的Provider信息的集合
1. ProviderByClass
以ComponentName为key保存了ContentProviderRecord的信息
2. ProviderByName
以authority为key保存了ContentProviderRecord的信息
3、如果Applicaton和ContentProvider都会起来,确保ContentProvider在本进程里面,不能单独开辟一个进程放ContentProvider,那么部分函数执行顺序如下
Application继承类的的attachBaseContext方法----->ContentProvider继承类的onCreate方法---->pplication继承类的onCreate函数
4、如果是Applicaton和ContentProvider不在同进程,不管是否在一个app里面的不同进程还是在另外一个app的进程,那么会先启动Application继承类的的attachBaseContext方法----->Application继承类的onCreate函数,如果有另外一个进程或者一个app触发ContentProvider,那么依然部分函数执行顺序如下
Application继承类的的attachBaseContext方法----->ContentProvider继承类的onCreate方法---->pplication继承类的onCreate函数,因为每个进程都有一个Application,所以会在ContentProvider里面再次启动一次Application