ContentProvider相关学习(2)-服务端instal
下面主要针对第二种情况,install Provider和publish Provider
注意,从这里开始针对的是服务端了
ActivityThread#scheduleInstallProvider
服务端安装provider
1380 @Override
1381 public void scheduleInstallProvider(ProviderInfo provider) {
1382 sendMessage(H.INSTALL_PROVIDER, provider);
1383 }
1841 case INSTALL_PROVIDER:
1842 handleInstallProvider((ProviderInfo) msg.obj);
1843 break;
ActivityThread#handleInstallProvider
3159 public void handleInstallProvider(ProviderInfo info) {
3160 final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
3161 try {
3162 installContentProviders(mInitialApplication, Lists.newArrayList(info));
3163 } finally {
3164 StrictMode.setThreadPolicy(oldPolicy);
3165 }
3166 }
ActivityThread#installContentProviders
5937 private void installContentProviders(
5938 Context context, List<ProviderInfo> providers) {
5939 final ArrayList<ContentProviderHolder> results = new ArrayList<>();
5940
5941 for (ProviderInfo cpi : providers) {
5942 if (DEBUG_PROVIDER) {
5943 StringBuilder buf = new StringBuilder(128);
5944 buf.append("Pub ");
5945 buf.append(cpi.authority);
5946 buf.append(": ");
5947 buf.append(cpi.name);
5948 Log.i(TAG, buf.toString());
5949 }
//安装provider
5950 ContentProviderHolder cph = installProvider(context, null, cpi,
5951 false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
5952 if (cph != null) {
5953 cph.noReleaseNeeded = true;
5954 results.add(cph);
5955 }
5956 }
5957
5958 try {
//发布provider
5959 ActivityManager.getService().publishContentProviders(
5960 getApplicationThread(), results);
5961 } catch (RemoteException ex) {
5962 throw ex.rethrowFromSystemServer();
5963 }
5964 }
ActivityThread#installProvider
前半部分主要是针对服务端的,首次安装ContentProvider时创建实例,并调用onCreate
后半段主要针对客户端,创建客户端需要保存的ProviderRefCount,ContentProviderHolder,ProviderClientRecord等数据结构,并增加相应的引用计数
6367 * Installs the provider.
6368 *
6369 * Providers that are local to the process or that come from the system server
6370 * may be installed permanently which is indicated by setting noReleaseNeeded to true.
6371 * Other remote providers are reference counted. The initial reference count
6372 * for all reference counted providers is one. Providers that are not reference
6373 * counted do not have a reference count (at all).
6374 *
6375 * This method detects when a provider has already been installed. When this happens,
6376 * it increments the reference count of the existing provider (if appropriate)
6377 * and returns the existing provider. This can happen due to concurrent
6378 * attempts to acquire the same provider.
6379 */
6380 private ContentProviderHolder installProvider(Context context,
6381 ContentProviderHolder holder, ProviderInfo info,
6382 boolean noisy, boolean noReleaseNeeded, boolean stable) {
//当provider还没起来,用于安装provider时, ContentProviderHolder = null
6383 ContentProvider localProvider = null;
6384 IContentProvider provider;
//如果provider尚未实例化,则需要在这个宿主进程中进行”安装”
6385 if (holder == null || holder.provider == null) { //holder为null,holder中保存的IContentProvider为null,首次安装
6386 if (DEBUG_PROVIDER || noisy) {
6387 Slog.d(TAG, "Loading provider " + info.authority + ": "
6388 + info.name);
6389 }
6390 Context c = null;
6391 ApplicationInfo ai = info.applicationInfo;
6392 if (context.getPackageName().equals(ai.packageName)) {
6393 c = context;
6394 } else if (mInitialApplication != null &&
6395 mInitialApplication.getPackageName().equals(ai.packageName)) {
6396 c = mInitialApplication;
6397 } else {
6398 try {
6399 c = context.createPackageContext(ai.packageName,
6400 Context.CONTEXT_INCLUDE_CODE);
6401 } catch (PackageManager.NameNotFoundException e) {
6402 // Ignore
6403 }
6404 }
6405 if (c == null) {
//无法获取context对象则直接返回,用于通过反射创建ContentProvider对象实
6406 Slog.w(TAG, "Unable to get context for package " +
6407 ai.packageName +
6408 " while loading content provider " +
6409 info.name);
6410 return null;
6411 }
6412
6413 if (info.splitName != null) {
6414 try {
6415 c = c.createContextForSplit(info.splitName);
6416 } catch (NameNotFoundException e) {
6417 throw new RuntimeException(e);
6418 }
6419 }
6420
6421 try {
6422 final java.lang.ClassLoader cl = c.getClassLoader();
6423 localProvider = (ContentProvider)cl.
6424 loadClass(info.name).newInstance();
6425 provider = localProvider.getIContentProvider(); //创建ContentProvider实例,并得到其binder代理对象
6426 if (provider == null) {
6427 Slog.e(TAG, "Failed to instantiate class " +
6428 info.name + " from sourceDir " +
6429 info.applicationInfo.sourceDir);
6430 return null;
6431 }
6432 if (DEBUG_PROVIDER) Slog.v(
6433 TAG, "Instantiating local provider " + info.name);
6434 // XXX Need to create the correct context for this provider.
6435 localProvider.attachInfo(c, info);
//设置ContentProvider的成员变量,并调用其onCreate
6436 } catch (java.lang.Exception e) {
6438 UserManager userManager = (UserManager)c.getSystemService(Context.USER_SERVICE);
6439 if (!userManager.isUserUnlockingOrUnlocked(c.getUserId())
6440 && !info.directBootAware) {
6441 Slog.w(TAG, "Current user Id = " + c.getUserId() + " is stopped, "
6442 + "kill this process!");
//将ContentProvider的宿主进程杀掉
6443 Process.killProcess(Process.myPid());
6444 }
6446 if (!mInstrumentation.onException(null, e)) {
6447 throw new RuntimeException(
6448 "Unable to get provider " + info.name
6449 + ": " + e.toString(), e);
6450 }
6451 return null;
6452 }
6453 } else {
6454 provider = holder.provider;
6455 if (DEBUG_PROVIDER) Slog.v(TAG, "Installing external provider " + info.authority + ": "
6456 + info.name);
6457 }
6458
6459 ContentProviderHolder retHolder;
6460 //进行引用方面的操纵;在宿主进程进行provider的缓存
//在宿主进程中创建相关的数据结构,进行provider的相关缓存
6461 synchronized (mProviderMap) {
//前面是服务端创建ContentProvider实例及对应的IContentProvider操作
//下面是关于ProviderClientRecord对象,是用来存储访问过该ContentProvider的客户端的对象
//ContentProvider宿主进程(服务端进程)需要保存访问其的客户端进程,这是用于连带死亡时的逻辑
//类似于ServiceRecord中的final ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections
6462 if (DEBUG_PROVIDER) Slog.v(TAG, "Checking to add " + provider
6463 + " / " + info.name);
// 获取provider代理
6464 IBinder jBinder = provider.asBinder();
// 如果这个provider在上一个操作刚被创建
6465 if (localProvider != null) {
6466 ComponentName cname = new ComponentName(info.packageName, info.name);
6467 ProviderClientRecord pr = mLocalProvidersByName.get(cname);
// 本地缓存
6468 if (pr != null) {
6469 if (DEBUG_PROVIDER) {
6470 Slog.v(TAG, "installProvider: lost the race, "
6471 + "using existing local provider");
6472 }
6473 provider = pr.mProvider;
6474 } else {
6475 holder = new ContentProviderHolder(info);
6476 holder.provider = provider;
6477 holder.noReleaseNeeded = true;
// 根据Uri authority name进行分类缓存
6478 pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
6479 mLocalProviders.put(jBinder, pr);
6480 mLocalProvidersByName.put(cname, pr);
6481 }
6482 retHolder = pr.mHolder;
6483 } else {
6484 ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
6485 if (prc != null) {
6486 if (DEBUG_PROVIDER) {
6487 Slog.v(TAG, "installProvider: lost the race, updating ref count");
6488 }
6489 // We need to transfer our new reference to the existing
6490 // ref count, releasing the old one... but only if
6491 // release is needed (that is, it is not running in the
6492 // system process).
6493 if (!noReleaseNeeded) {
6494 incProviderRefLocked(prc, stable);
6495 try {
6496 ActivityManager.getService().removeContentProvider(
6497 holder.connection, stable);
6498 } catch (RemoteException e) {
6499 //do nothing content provider object is dead any way
6500 }
6501 }
6502 } else {
6503 ProviderClientRecord client = installProviderAuthoritiesLocked(
6504 provider, localProvider, holder);
6505 if (noReleaseNeeded) {
6506 prc = new ProviderRefCount(holder, client, 1000, 1000);
6507 } else {
6508 prc = stable
6509 ? new ProviderRefCount(holder, client, 1, 0)
6510 : new ProviderRefCount(holder, client, 0, 1);
6511 }
6512 mProviderRefCountMap.put(jBinder, prc);
6513 }
6514 retHolder = prc.holder;
6515 }
6516 }
6517 return retHolder;
6518 }
ActivityThread#installProviderAuthoritiesLocked
6329 private ProviderClientRecord installProviderAuthoritiesLocked(IContentProvider provider,
6330 ContentProvider localProvider, ContentProviderHolder holder) {
6331 final String auths[] = holder.info.authority.split(";");
6332 final int userId = UserHandle.getUserId(holder.info.applicationInfo.uid);
6333
6334 if (provider != null) {
6335 // If this provider is hosted by the core OS and cannot be upgraded,
6336 // then I guess we're okay doing blocking calls to it.
6337 for (String auth : auths) {
6338 switch (auth) {
6339 case ContactsContract.AUTHORITY:
6340 case CallLog.AUTHORITY:
6341 case CallLog.SHADOW_AUTHORITY:
6342 case BlockedNumberContract.AUTHORITY:
6343 case CalendarContract.AUTHORITY:
6344 case Downloads.Impl.AUTHORITY:
6345 case "telephony":
6346 Binder.allowBlocking(provider.asBinder());
6347 }
6348 }
6349 }
6350
6351 final ProviderClientRecord pcr = new ProviderClientRecord(
6352 auths, provider, localProvider, holder);
6353 for (String auth : auths) {
6354 final ProviderKey key = new ProviderKey(auth, userId);
6355 final ProviderClientRecord existing = mProviderMap.get(key);
6356 if (existing != null) {
6357 Slog.w(TAG, "Content provider " + pcr.mHolder.info.name
6358 + " already published as " + auth);
6359 } else {
6360 mProviderMap.put(key, pcr);
6361 }
6362 }
6363 return pcr;
6364 }
相当于客户端和服务端都有机会走到installProvider,服务端调用时,都保存了相关的数据结构ProviderClientRecord,ProviderRefCount
5950 ContentProviderHolder cph = installProvider(context, null, cpi,
5951 false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
客户端调用时(aquireProvider中)
//如果ContentProvider install过了,这个功能只是增加引用计数
5872 holder = installProvider(c, holder, holder.info,
5873 true /*noisy*/, holder.noReleaseNeeded, stable);
这样是为了使installProvider这个函数公用,客户端主要是用其来增加
引用计数,服务端是用来创建ContentProvider实例的
ActivityManagerService#publishContentProviders
将创建的ContentProviderRecord这种数据结构保存在AMS中的mProviderMap和ProcessRecord.pubProviders
12302 public final void publishContentProviders(IApplicationThread caller,
12303 List<ContentProviderHolder> providers) {
12304 if (providers == null) {
12305 return;
12306 }
12307
12308 enforceNotIsolatedCaller("publishContentProviders");
12309 synchronized (this) {
12310 final ProcessRecord r = getRecordForAppLocked(caller);
//获取provider宿主进程
12311 if (DEBUG_MU) Slog.v(TAG_MU, "ProcessRecord uid = " + r.uid);
12312 if (r == null) {
12313 throw new SecurityException(
12314 "Unable to find app for caller " + caller
12315 + " (pid=" + Binder.getCallingPid()
12316 + ") when publishing content providers");
12317 }
12318
12319 final long origId = Binder.clearCallingIdentity();
12320
12321 final int N = providers.size();
12322 for (int i = 0; i < N; i++) {
12323 ContentProviderHolder src = providers.get(i);
12324 if (src == null || src.info == null || src.provider == null) {
12325 continue;
12326 }
12327 ContentProviderRecord dst = r.pubProviders.get(src.info.name); //从服务端进程得到ContentProviderRecord
12328 if (DEBUG_MU) Slog.v(TAG_MU, "ContentProviderRecord uid = " + dst.uid);
12329 if (dst != null) {
12330 ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
//将ContentProviderRecord加入到mProviderMap中
12331 mProviderMap.putProviderByClass(comp, dst);
12332 String names[] = dst.info.authority.split(";");
12333 for (int j = 0; j < names.length; j++) {
12334 mProviderMap.putProviderByName(names[j], dst);
12335 }
12336 //将服务端创建的ContentProviderRecord结构添加到AMS中,相当于publish
12337 int launchingCount = mLaunchingProviders.size();
12338 int j;
12339 boolean wasInLaunchingProviders = false;
12340 for (j = 0; j < launchingCount; j++) {
12341 if (mLaunchingProviders.get(j) == dst) {
//正式publish之后,从mLaunchingProviders移除相关ContentProviderRecord
12342 mLaunchingProviders.remove(j);
12343 wasInLaunchingProviders = true;
12344 j--;
12345 launchingCount--;
12346 }
12347 }
12348 if (wasInLaunchingProviders) {
12349 mHandler.removeMessages(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r);
//对应发送的地方在attachApplicationLocked中,对应宿主进程启动的地方
12350 }
12351 synchronized (dst) {
12352 dst.provider = src.provider;
12353 dst.proc = r;
12354 dst.notifyAll(); //唤醒AMS中的wait方法,在getContentProviderImpl中等待
12355 }
12356 updateOomAdjLocked(r, true);
12357 maybeUpdateProviderUsageStatsLocked(r, src.info.packageName,
12358 src.info.authority);
12359 }
12360 }
12361
12362 Binder.restoreCallingIdentity(origId);
12363 }
12364 }
AMS缓存ContentProviderRecord后,客户端也会缓存ContentProviderRecord,在acquireExistingProvider中就已获得IContentProvider,后续无需通过AMS,而是直接通过IContentProvider binder proxy来调用ContentProvider实例的override函数,类似bindService中的onServiceConnected的IBinder,代表Service binder proxy
这里最后理一下ContentProvider客户端操作时的大致流程:
1.首先有一个进程A需要使用B进程的Provider,通过binder call到system_server查询;在system_server中进行判断要请求的provider是否已经正在运行,也就是要请求的provider是否由B进程已经publish过了
2.1 如果要请求的provider已经在运行,那么就建立A和B之间的链接,并返回一个ContentProviderHolder
2.2 如果要请求的provider不在运行,那么首先需要启动B进程,并把需要provider增加到mLaunchingProviders中
2.2.1 B进程在启动过程中attach到system_server的时候会设置一个10s的定时消息,然后在bindApplication中客户端执行installProvider
2.2.2 B进程installProvider成功之后,会publish provider到system_server,并移除上面的10s的定时消息
2.3 因为启动进程的过程是异步的,所以在等待对方进程启动并publish的时候,通过A进程binder call到system_server的线程一直会处在wait状态,直到等待的provider被publish或者由于进程被杀/启动超时等原因被remove掉
ContentProvider_query.png