publicfinal IContentProvider acquireProvider( Context c, String auth, int userId, boolean stable){ //尝试从本地缓存中获取ContentProvider对象 final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable); if (provider != null) { return provider; }
// There is a possible race here. Another thread may try to acquire // the same provider at the same time. When this happens, we want to ensure // that the first one wins. // Note that we cannot hold the lock while acquiring and installing the // provider since it might take a long time to run and it could also potentially // be re-entrant in the case where the provider is in the same process. ContentProviderHolder holder = null; try { synchronized (getGetProviderLock(auth, userId)) { //使用AMS获取ContentProvider对象 holder = ActivityManager.getService().getContentProvider( getApplicationThread(), c.getOpPackageName(), auth, userId, stable); } } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } if (holder == null) { ... returnnull; }
// Install provider will increment the reference count for us, and break // any ties in the race. //安装ContentProvider holder = installProvider(c, holder, holder.info, true/*noisy*/, holder.noReleaseNeeded, stable); return holder.provider; }
publicfinal IContentProvider acquireExistingProvider( Context c, String auth, int userId, boolean stable){ synchronized (mProviderMap) { //从缓存Map中查找 final ProviderKey key = new ProviderKey(auth, userId); final ProviderClientRecord pr = mProviderMap.get(key); if (pr == null) { returnnull; }
IContentProvider provider = pr.mProvider; IBinder jBinder = provider.asBinder(); //判断远端进程是否已被杀死 if (!jBinder.isBinderAlive()) { // The hosting process of the provider has died; we can't // use this one. //清理ContentProvider handleUnstableProviderDiedLocked(jBinder, true); returnnull; }
// Only increment the ref count if we have one. If we don't then the // provider is not reference counted and never needs to be released. ProviderRefCount prc = mProviderRefCountMap.get(jBinder); if (prc != null) { //更新引用计数 incProviderRefLocked(prc, stable); } return provider; } }
synchronized(this) { //获取调用方所在进程记录 ProcessRecord r = null; if (caller != null) { r = getRecordForAppLocked(caller); if (r == null) { thrownew SecurityException( "Unable to find app for caller " + caller + " (pid=" + Binder.getCallingPid() + ") when getting content provider " + name); } }
boolean checkCrossUser = true;
// First check if this content provider has been published... //检查需要的ContentProvider是否已被发布 cpr = mProviderMap.getProviderByName(name, userId); // If that didn't work, check if it exists for user 0 and then // verify that it's a singleton provider before using it. //如果没找到,尝试从系统用户中查找已发布的ContentProvider //并确保它是可用的单例组件,条件如下: //是用户级应用程序且组件设置了单例flag且拥有INTERACT_ACROSS_USERS权限 或 App运行在system进程中 或 组件设置了单例flag且是同一个App if (cpr == null && userId != UserHandle.USER_SYSTEM) { cpr = mProviderMap.getProviderByName(name, UserHandle.USER_SYSTEM); if (cpr != null) { cpi = cpr.info; if (isSingleton(cpi.processName, cpi.applicationInfo, cpi.name, cpi.flags) && isValidSingletonCall(r == null ? callingUid : r.uid, cpi.applicationInfo.uid)) { userId = UserHandle.USER_SYSTEM; checkCrossUser = false; } else { cpr = null; cpi = null; } } }
// Note if killedByAm is also set, this means the provider process has just been // killed by AM (in ProcessRecord.kill()), but appDiedLocked() hasn't been called // yet. So we need to call appDiedLocked() here and let it clean up. // (See the commit message on I2c4ba1e87c2d47f2013befff10c49b3dc337a9a7 to see // how to test this case.) if (cpr.proc.killed && cpr.proc.killedByAm) { Slog.wtf(TAG, cpr.proc.toString() + " was killed by AM but isn't really dead"); // Now we are going to wait for the death before starting the new process. dyingProc = cpr.proc; } } ... } ... }
// This provider has been published or is in the process // of being published... but it is also allowed to run // in the caller's process, so don't make a connection // and just let the caller instantiate its own instance. ContentProviderHolder holder = cpr.newHolder(null); // don't give caller the provider object, it needs // to make its own. holder.provider = null; return holder; }
// Don't expose providers between normal apps and instant apps try { if (AppGlobals.getPackageManager() .resolveContentProvider(name, 0/*flags*/, userId) == null) { returnnull; } } catch (RemoteException e) { }
... //权限检查
finallong origId = Binder.clearCallingIdentity();
// In this case the provider instance already exists, so we can // return it right away. //获取连接并更新引用计数 conn = incProviderCountLocked(r, cpr, token, callingUid, callingPackage, callingTag, stable); if (conn != null && (conn.stableCount+conn.unstableCount) == 1) { if (cpr.proc != null && r != null && r.setAdj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) { // If this is a perceptible app accessing the provider, // make sure to count it as being accessed and thus // back up on the LRU list. This is good because // content providers are often expensive to start. //更新进程优先级 mProcessList.updateLruProcessLocked(cpr.proc, false, null); } }
finalint verifiedAdj = cpr.proc.verifiedAdj; //更新进程adj boolean success = updateOomAdjLocked(cpr.proc, true, OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER); // XXX things have changed so updateOomAdjLocked doesn't actually tell us // if the process has been successfully adjusted. So to reduce races with // it, we will check whether the process still exists. Note that this doesn't // completely get rid of races with LMK killing the process, but should make // them much smaller. if (success && verifiedAdj != cpr.proc.setAdj && !isProcessAliveLocked(cpr.proc)) { success = false; } maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name); // NOTE: there is still a race here where a signal could be // pending on the process even though we managed to update its // adj level. Not sure what to do about this, but at least // the race is now smaller. if (!success) { // Uh oh... it looks like the provider's process // has been killed on us. We need to wait for a new // process to be started, and make sure its death // doesn't kill our process. Slog.wtf(TAG, "Existing provider " + cpr.name.flattenToShortString() + " is crashing; detaching " + r); //ContentProvider所在进程被杀了,更新引用计数 boolean lastRef = decProviderCountLocked(conn, cpr, token, stable); //仍有别的地方对这个ContentProvider有引用,直接返回null(需要等待进程清理干净才能重启) if (!lastRef) { // This wasn't the last ref our process had on // the provider... we will be killed during cleaning up, bail. returnnull; } // We'll just start a new process to host the content provider //将运行状态标为false,使得重新启动ContentProvider所在进程 providerRunning = false; conn = null; dyingProc = cpr.proc; } else { cpr.proc.verifiedAdj = cpr.proc.setAdj; }
synchronized(this) { ... //ContentProvider未在运行 if (!providerRunning) { //通过PMS获取ContentProvider信息 try { cpi = AppGlobals.getPackageManager(). resolveContentProvider(name, STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId); } catch (RemoteException ex) { } if (cpi == null) { returnnull; } // If the provider is a singleton AND // (it's a call within the same user || the provider is a // privileged app) // Then allow connecting to the singleton provider boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo, cpi.name, cpi.flags) && isValidSingletonCall(r == null ? callingUid : r.uid, cpi.applicationInfo.uid); if (singleton) { userId = UserHandle.USER_SYSTEM; } cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo, userId);
try { //获取应用信息 ApplicationInfo ai = AppGlobals.getPackageManager(). getApplicationInfo( cpi.applicationInfo.packageName, STOCK_PM_FLAGS, userId); if (ai == null) { Slog.w(TAG, "No package info for content provider " + cpi.name); returnnull; } ai = getAppInfoForUser(ai, userId); //新建ContentProvider记录 cpr = new ContentProviderRecord(this, cpi, ai, comp, singleton); } catch (RemoteException ex) { // pm is in same process, this will never happen. } finally { Binder.restoreCallingIdentity(ident); } } elseif (dyingProc == cpr.proc && dyingProc != null) { // The old stable connection's client should be killed during proc cleaning up, // so do not re-use the old ContentProviderRecord, otherwise the new clients // could get killed unexpectedly. //旧的ContentProvider进程在死亡过程中,不要复用旧的ContentProviderRecord,避免出现预期之外的问题 cpr = new ContentProviderRecord(cpr); // This is sort of "firstClass" firstClass = true; }
//如果此ContentProvider可以在调用者进程中直接运行(同一个App的同进程 或 同一个App且Provider组件支持多进程) //直接返回一个新的ContentProviderHolder让调用者进程自己启动ContentProvider if (r != null && cpr.canRunHere(r)) { // If this is a multiprocess provider, then just return its // info and allow the caller to instantiate it. Only do // this if the provider is the same user as the caller's // process, or can run as root (so can be in any process). return cpr.newHolder(null); }
// This is single process, and our app is now connecting to it. // See if we are already in the process of launching this // provider. //查找正在启动中的ContentProvider finalint N = mLaunchingProviders.size(); int i; for (i = 0; i < N; i++) { if (mLaunchingProviders.get(i) == cpr) { break; } }
// If the provider is not already being launched, then get it // started. //目标ContentProvider不在启动中 if (i >= N) { finallong origId = Binder.clearCallingIdentity();
try { // Content provider is now in use, its package can't be stopped. //将App状态置为unstopped,设置休眠状态为false try { AppGlobals.getPackageManager().setPackageStoppedState( cpr.appInfo.packageName, false, userId); } catch (RemoteException e) { } catch (IllegalArgumentException e) { Slog.w(TAG, "Failed trying to unstop package " + cpr.appInfo.packageName + ": " + e); }
// Use existing process if already started //获取目标ContentProvider所在进程记录 ProcessRecord proc = getProcessRecordLocked( cpi.processName, cpr.appInfo.uid, false); if (proc != null && proc.thread != null && !proc.killed) { //进程存活 if (!proc.pubProviders.containsKey(cpi.name)) { //将ContentProviderRecord保存到进程已发布ContentProvider列表中 proc.pubProviders.put(cpi.name, cpr); try { //调度ActivityThread直接安装ContentProvider proc.thread.scheduleInstallProvider(cpi); } catch (RemoteException e) { } } } else { //进程死亡 //启动App(App启动过程中会自动启动ContentProvider) proc = startProcessLocked(cpi.processName, cpr.appInfo, false, 0, new HostingRecord("content provider", new ComponentName(cpi.applicationInfo.packageName, cpi.name)), ZYGOTE_POLICY_FLAG_EMPTY, false, false, false); if (proc == null) { ... returnnull; } } cpr.launchingApp = proc; //将目标ContentProvider添加到启动中列表 mLaunchingProviders.add(cpr); } finally { Binder.restoreCallingIdentity(origId); } }
// Make sure the provider is published (the same provider class // may be published under multiple names). if (firstClass) { mProviderMap.putProviderByClass(comp, cpr); }
privatebooleanattachApplicationLocked(@NonNull IApplicationThread thread, int pid, int callingUid, long startSeq){ ... //normalMode一般情况下均为true List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null; ... }
privatefinal List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app){ List<ProviderInfo> providers = null; try { //通过PMS获取App中同一个进程内的所有的ContentProvider组件信息 providers = AppGlobals.getPackageManager() .queryContentProviders(app.processName, app.uid, STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS | MATCH_DEBUG_TRIAGED_MISSING, /*metadastaKey=*/null) .getList(); } catch (RemoteException ex) { } int userId = app.userId; if (providers != null) { int N = providers.size(); //有必要的情况下进行Map扩容 app.pubProviders.ensureCapacity(N + app.pubProviders.size()); for (int i=0; i<N; i++) { // TODO: keep logic in sync with installEncryptionUnawareProviders ProviderInfo cpi = (ProviderInfo)providers.get(i); //对于单例ContentProvider,需要在默认用户中启动,如果不是默认用户的话则直接将其丢弃掉,不启动 boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo, cpi.name, cpi.flags); if (singleton && UserHandle.getUserId(app.uid) != UserHandle.USER_SYSTEM) { // This is a singleton provider, but a user besides the // default user is asking to initialize a process it runs // in... well, no, it doesn't actually run in this process, // it runs in the process of the default user. Get rid of it. providers.remove(i); N--; i--; continue; }
ComponentName comp = new ComponentName(cpi.packageName, cpi.name); ContentProviderRecord cpr = mProviderMap.getProviderByClass(comp, userId); if (cpr == null) { //新建ContentProviderRecord并将其加入到缓存中 cpr = new ContentProviderRecord(this, cpi, app.info, comp, singleton); mProviderMap.putProviderByClass(comp, cpr); } //将ContentProviderRecord保存到进程已发布ContentProvider列表中 app.pubProviders.put(cpi.name, cpr); if (!cpi.multiprocess || !"android".equals(cpi.packageName)) { // Don't add this if it is a platform component that is marked // to run in multiple processes, because this is actually // part of the framework so doesn't make sense to track as a // separate apk in the process. //将App添加至进程中运行的包列表中 app.addPackage(cpi.applicationInfo.packageName, cpi.applicationInfo.longVersionCode, mProcessStats); } notifyPackageUse(cpi.applicationInfo.packageName, PackageManager.NOTIFY_PACKAGE_USE_CONTENT_PROVIDER); } } return providers; }
privatevoidhandleBindApplication(AppBindData data){ ... 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 //在非受限模式下启动ContentProvider if (!data.restrictedBackupMode) { if (!ArrayUtils.isEmpty(data.providers)) { installContentProviders(app, data.providers); } }
...
//执行Application的onCreate方法 try { mInstrumentation.callApplicationOnCreate(app); } catch (Exception e) { ... } } finally { // If the app targets < O-MR1, or doesn't change the thread policy // during startup, clobber the policy to maintain behavior of b/36951662 if (data.appInfo.targetSdkVersion < Build.VERSION_CODES.O_MR1 || StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) { StrictMode.setThreadPolicy(savedPolicy); } } ... }
synchronized (mProviderMap) { //对于外部ContentProvider来说,这里的实际类型是BinderProxy IBinder jBinder = provider.asBinder(); if (localProvider != null) { //本地启动ContentProvider的情况 ... } else { //获取远程ContentProvider的情况 ProviderRefCount prc = mProviderRefCountMap.get(jBinder); if (prc != null) { //如果ContentProvider引用已存在 // We need to transfer our new reference to the existing // ref count, releasing the old one... but only if // release is needed (that is, it is not running in the // system process). //对于远程ContentProvider来说,如果目标App为system应用(UID为ROOT_UID或SYSTEM_UID) //并且目标App不为设置(包名不为com.android.settings),则noReleaseNeeded为true if (!noReleaseNeeded) { //增加已存在的ContentProvider引用的引用计数 incProviderRefLocked(prc, stable); try { //释放传入的引用,移除ContentProviderConnection相关信息,更新引用计数 ActivityManager.getService().removeContentProvider( holder.connection, stable); } catch (RemoteException e) { //do nothing content provider object is dead any way } } } else { //创建ProviderClientRecord并将其保存到mProviderMap本地缓存中 ProviderClientRecord client = installProviderAuthoritiesLocked( provider, localProvider, holder); if (noReleaseNeeded) { //同上,目标App为system应用,不需要释放引用 //新建一个ProviderRefCount,但引用计数初始化为一个较大的数值 //这样后续无论调用方进程的ContentProvider引用计数如何变动都不会影响到AMS prc = new ProviderRefCount(holder, client, 1000, 1000); } else { //需要释放引用的情况下 //正常的新建初始化一个ProviderRefCount prc = stable ? new ProviderRefCount(holder, client, 1, 0) : new ProviderRefCount(holder, client, 0, 1); } //保存至缓存 mProviderRefCountMap.put(jBinder, prc); } retHolder = prc.holder; } } return retHolder; }
synchronized (this) { final ProcessRecord r = getRecordForAppLocked(caller); if (r == null) { thrownew SecurityException( "Unable to find app for caller " + caller + " (pid=" + Binder.getCallingPid() + ") when publishing content providers"); }
finallong origId = Binder.clearCallingIdentity();
finalint 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; } //App进程启动时或AMS.getContentProvider中已经将相应ContentProviderRecord添加到了pubProviders中 ContentProviderRecord dst = r.pubProviders.get(src.info.name); 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); }
//ContentProvider已经启动完毕,将其从正在启动的ContentProvider列表中移除 int launchingCount = mLaunchingProviders.size(); int j; boolean wasInLaunchingProviders = false; for (j = 0; j < launchingCount; j++) { if (mLaunchingProviders.get(j) == dst) { mLaunchingProviders.remove(j); wasInLaunchingProviders = true; j--; launchingCount--; } } //移除ContentProvider启动超时监听 if (wasInLaunchingProviders) { mHandler.removeMessages(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r); } // Make sure the package is associated with the process. // XXX We shouldn't need to do this, since we have added the package // when we generated the providers in generateApplicationProvidersLocked(). // But for some reason in some cases we get here with the package no longer // added... for now just patch it in to make things happy. r.addPackage(dst.info.applicationInfo.packageName, dst.info.applicationInfo.longVersionCode, mProcessStats); synchronized (dst) { dst.provider = src.provider; dst.setProcess(r); //让出锁,通知其他wait的地方 //对应着AMS.getContentProvider的第四部分:等待ContentProvider启动完成 dst.notifyAll(); } dst.mRestartCount = 0; updateOomAdjLocked(r, true, OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER); maybeUpdateProviderUsageStatsLocked(r, src.info.packageName, src.info.authority); } }
privatefinalvoidincProviderRefLocked(ProviderRefCount prc, boolean stable){ if (stable) { //增加ActivityThread的stable引用计数 prc.stableCount += 1; //本进程对目标ContentProvider产生了stable引用关系 if (prc.stableCount == 1) { // We are acquiring a new stable reference on the provider. int unstableDelta; //正在移除ContentProvider引用中(释放ContentProvider后发现stable和unstable引用计数均为0) if (prc.removePending) { // We have a pending remove operation, which is holding the // last unstable reference. At this point we are converting // that unstable reference to our new stable reference. //当ActivityThread释放一个stable的ContentProvider时,如果释放完后, //发现stable和unstable引用计数均为0,则会暂时保留一个unstable引用 //所以这里需要为 -1 ,将这个unstable引用移除 unstableDelta = -1; // Cancel the removal of the provider. prc.removePending = false; // There is a race! It fails to remove the message, which // will be handled in completeRemoveProvider(). //取消移除ContentProvider引用 mH.removeMessages(H.REMOVE_PROVIDER, prc); } else { //对于正常情况,只需要增加stable引用计数,不需要动unstable引用计数 unstableDelta = 0; } try { //AMS层修改引用计数 ActivityManager.getService().refContentProvider( prc.holder.connection, 1, unstableDelta); } catch (RemoteException e) { //do nothing content provider object is dead any way } } } else { //增加ActivityThread的unstable引用计数 prc.unstableCount += 1; //本进程对目标ContentProvider产生了unstable引用关系 if (prc.unstableCount == 1) { // We are acquiring a new unstable reference on the provider. //正在移除ContentProvider引用中(释放ContentProvider后发现stable和unstable引用计数均为0) if (prc.removePending) { // Oh look, we actually have a remove pending for the // provider, which is still holding the last unstable // reference. We just need to cancel that to take new // ownership of the reference. //取消移除ContentProvider引用 prc.removePending = false; mH.removeMessages(H.REMOVE_PROVIDER, prc); } else { // First unstable ref, increment our count in the // activity manager. try { //增加AMS层的unstable引用计数 ActivityManager.getService().refContentProvider( prc.holder.connection, 0, 1); } catch (RemoteException e) { //do nothing content provider object is dead any way } } } } }
IBinder jBinder = provider.asBinder(); synchronized (mProviderMap) { ProviderRefCount prc = mProviderRefCountMap.get(jBinder); if (prc == null) { // The provider has no ref count, no release is needed. returnfalse; }
boolean lastRef = false; if (stable) { //引用计数已经为0,无法再减了 if (prc.stableCount == 0) { returnfalse; } //减少ActivityThread的stable引用计数 prc.stableCount -= 1; if (prc.stableCount == 0) { // What we do at this point depends on whether there are // any unstable refs left: if there are, we just tell the // activity manager to decrement its stable count; if there // aren't, we need to enqueue this provider to be removed, // and convert to holding a single unstable ref while // doing so. lastRef = prc.unstableCount == 0; try { //如果是最后的引用,则暂时保留一个unstable引用 ActivityManager.getService().refContentProvider( prc.holder.connection, -1, lastRef ? 1 : 0); } catch (RemoteException e) { //do nothing content provider object is dead any way } } } else { //引用计数已经为0,无法再减了 if (prc.unstableCount == 0) { returnfalse; } //减少ActivityThread的unstable引用计数 prc.unstableCount -= 1; if (prc.unstableCount == 0) { // If this is the last reference, we need to enqueue // this provider to be removed instead of telling the // activity manager to remove it at this point. lastRef = prc.stableCount == 0; //如果是最后的引用,则不进入到这里,暂时保留一个unstable引用 if (!lastRef) { try { //减少AMS引用计数 ActivityManager.getService().refContentProvider( prc.holder.connection, 0, -1); } catch (RemoteException e) { //do nothing content provider object is dead any way } } } }
if (lastRef) { if (!prc.removePending) { // Schedule the actual remove asynchronously, since we don't know the context // this will be called in. //表面此ContentProvider正在移除中 prc.removePending = true; //发送延时消息,等待一定时间后移除ContentProvider Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, prc); mH.sendMessageDelayed(msg, CONTENT_PROVIDER_RETAIN_TIME); } else { Slog.w(TAG, "Duplicate remove pending of provider " + prc.holder.info.name); } } returntrue; } }
finalvoidcompleteRemoveProvider(ProviderRefCount prc){ synchronized (mProviderMap) { if (!prc.removePending) { // There was a race! Some other client managed to acquire // the provider before the removal was completed. // Abort the removal. We will do it later. return; }
// More complicated race!! Some client managed to acquire the // provider and release it before the removal was completed. // Continue the removal, and abort the next remove message. prc.removePending = false;
//移除缓存 final IBinder jBinder = prc.holder.provider.asBinder(); ProviderRefCount existingPrc = mProviderRefCountMap.get(jBinder); if (existingPrc == prc) { mProviderRefCountMap.remove(jBinder); }
booleandecProviderCountLocked(ContentProviderConnection conn, ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable){ if (conn != null) { cpr = conn.provider; //减少引用计数值 if (stable) { conn.stableCount--; } else { conn.unstableCount--; } if (conn.stableCount == 0 && conn.unstableCount == 0) { //停止关联 conn.stopAssociation(); //移除连接 cpr.connections.remove(conn); conn.client.conProviders.remove(conn); if (conn.client.setProcState < PROCESS_STATE_LAST_ACTIVITY) { // The client is more important than last activity -- note the time this // is happening, so we keep the old provider process around a bit as last // activity to avoid thrashing it. if (cpr.proc != null) { cpr.proc.lastProviderTime = SystemClock.uptimeMillis(); } } //停止关联 stopAssociationLocked(conn.client.uid, conn.client.processName, cpr.uid, cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName); returntrue; } returnfalse; } cpr.removeExternalProcessHandleLocked(externalProcessToken); returnfalse; }
// Remove published content providers. //清除已发布的ContentProvider for (int i = app.pubProviders.size() - 1; i >= 0; i--) { ContentProviderRecord cpr = app.pubProviders.valueAt(i); if (cpr.proc != app) { // If the hosting process record isn't really us, bail out continue; } finalboolean alwaysRemove = app.bad || !allowRestart; finalboolean inLaunching = removeDyingProviderLocked(app, cpr, alwaysRemove); if (!alwaysRemove && inLaunching && cpr.hasConnectionOrHandle()) { // We left the provider in the launching list, need to // restart it. restart = true; }
// Take care of any launching providers waiting for this process. //清除正在启动中的ContentProvider if (cleanupAppInLaunchingProvidersLocked(app, false)) { mProcessList.noteProcessDiedLocked(app); restart = true; }
// Unregister from connected content providers. //清除已连接的ContentProvider if (!app.conProviders.isEmpty()) { for (int i = app.conProviders.size() - 1; i >= 0; i--) { ContentProviderConnection conn = app.conProviders.get(i); conn.provider.connections.remove(conn); stopAssociationLocked(app.uid, app.processName, conn.provider.uid, conn.provider.appInfo.longVersionCode, conn.provider.name, conn.provider.info.processName); } app.conProviders.clear(); } ... }
privatefinalbooleanremoveDyingProviderLocked(ProcessRecord proc, ContentProviderRecord cpr, boolean always){ boolean inLaunching = mLaunchingProviders.contains(cpr); if (inLaunching && !always && ++cpr.mRestartCount > ContentProviderRecord.MAX_RETRY_COUNT) { // It's being launched but we've reached maximum attempts, force the removal always = true; }
if (!inLaunching || always) { synchronized (cpr) { cpr.launchingApp = null; cpr.notifyAll(); } finalint userId = UserHandle.getUserId(cpr.uid); // Don't remove from provider map if it doesn't match // could be a new content provider is starting //移除缓存 if (mProviderMap.getProviderByClass(cpr.name, userId) == cpr) { mProviderMap.removeProviderByClass(cpr.name, userId); } String names[] = cpr.info.authority.split(";"); for (int j = 0; j < names.length; j++) { // Don't remove from provider map if it doesn't match // could be a new content provider is starting //移除缓存 if (mProviderMap.getProviderByName(names[j], userId) == cpr) { mProviderMap.removeProviderByName(names[j], userId); } } }
for (int i = cpr.connections.size() - 1; i >= 0; i--) { ContentProviderConnection conn = cpr.connections.get(i); if (conn.waiting) { // If this connection is waiting for the provider, then we don't // need to mess with its process unless we are always removing // or for some reason the provider is not currently launching. if (inLaunching && !always) { continue; } } ProcessRecord capp = conn.client; conn.dead = true; if (conn.stableCount > 0) { if (!capp.isPersistent() && capp.thread != null && capp.pid != 0 && capp.pid != MY_PID) { //当调用方与被杀死的目标ContentProvider进程间有stable连接 //并且调用方App进程非persistent进程并且非system_server进程中的情况下 //杀死调用方进程 capp.kill("depends on provider " + cpr.name.flattenToShortString() + " in dying proc " + (proc != null ? proc.processName : "??") + " (adj " + (proc != null ? proc.setAdj : "??") + ")", ApplicationExitInfo.REASON_DEPENDENCY_DIED, ApplicationExitInfo.SUBREASON_UNKNOWN, true); } } elseif (capp.thread != null && conn.provider.provider != null) { try { //通知调用方移除ContentProvider capp.thread.unstableProviderDied(conn.provider.provider.asBinder()); } catch (RemoteException e) { } // In the protocol here, we don't expect the client to correctly // clean up this connection, we'll just remove it. //移除连接 cpr.connections.remove(i); if (conn.client.conProviders.remove(conn)) { stopAssociationLocked(capp.uid, capp.processName, cpr.uid, cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName); } } }