赞
踩
ContentProvider作为Android四大组件之一,重要性肯定是不言而喻的,顾名思义,内容提供者,其最重要的作用就在于提供了一种跨进程获取数据的方式,provider组件不仅可以自己的进程使用,还可以提供给其他的进程使用,大大方便了不同进程之间的数据交换,本文将详细介绍provider运行的原理。
注:本文基于Android 8.1
看起来涉及到的类非常多,一下有种不知道从何看起的感觉,所以这里对于其中的重点关注部分加上了颜色:
白色:provider运行过程中涉及到的内部类或私有类,一般APP开发过程中不太会涉及
蓝色:APP开发过程中经常会接触到的类
紫色:在system server进程中provider相关的类
其中白色部分:发起获取provider的client进程
红色部分:systemserver进程
蓝色部分:提供provider的server进程
时序图解读:
installProvider,顾名思义就是安装provider,说的通俗一点就是把APP进程中的provider组件封装成对象保存起来,方便使用
在APP的进程启动的时候,handleBindApplication中会触发installProvider:
- private void installContentProviders(
- Context context, List<ProviderInfo> providers) {
- // 此处的provider信息是在AMS启动进程时
- // 从manifest收集到的需要install的provider信息
- final ArrayList<ContentProviderHolder> results = new ArrayList<>();
-
- for (ProviderInfo cpi : providers) {
- // 执行installProvider,注意此处的stable参数默认为true
- ContentProviderHolder cph = installProvider(context, null, cpi,
- false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
- if (cph != null) {
- cph.noReleaseNeeded = true;
- results.add(cph);
- }
- }
- try {
- // install完成之后,要告诉AMS
- ActivityManager.getService().publishContentProviders(
- getApplicationThread(), results);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- }
进一步看一下ActivityThread.installProvider的具体实现
- private ContentProviderHolder installProvider(Context context,
- ContentProviderHolder holder, ProviderInfo info,
- boolean noisy, boolean noReleaseNeeded, boolean stable) {
- ContentProvider localProvider = null;
- IContentProvider provider;
- // holder为null表示还没有install过
- if (holder == null || holder.provider == null) {
- Context c = null;
- ApplicationInfo ai = info.applicationInfo;
- if (context.getPackageName().equals(ai.packageName)) {
- c = context;
- } else if (mInitialApplication != null &&
- mInitialApplication.getPackageName().equals(ai.packageName)) {
- c = mInitialApplication;
- } else {
- try {
- // 创建context
- c = context.createPackageContext(ai.packageName,
- Context.CONTEXT_INCLUDE_CODE);
- } catch (PackageManager.NameNotFoundException e) {
- // Ignore
- }
- }
- ...
- try {
- final java.lang.ClassLoader cl = c.getClassLoader();
- // 通过反射创建provider对象
- localProvider = (ContentProvider)cl.
- loadClass(info.name).newInstance();
- // 获取IContentProvider对象,用于跨进程binder call
- provider = localProvider.getIContentProvider();
- if (provider == null) {
- Slog.e(TAG, "Failed to instantiate class " +
- info.name + " from sourceDir " +
- info.applicationInfo.sourceDir);
- return null;
- }
- // provider的attach,其中最重要的是会执行provider的onCreate
- localProvider.attachInfo(c, info);
- } catch (java.lang.Exception e) {
- if (!mInstrumentation.onException(null, e)) {
- throw new RuntimeException(
- "Unable to get provider " + info.name
- + ": " + e.toString(), e);
- }
- return null;
- }
- } else {
- provider = holder.provider;
- }
-
- // 到这里,provider的对象创建好了,那么接下来需要做的就是数据结构的封装
- // 把provider相关信息保存起来
- ContentProviderHolder retHolder;
- // mProviderMap的key时providerKey,value是ProviderClientReocrd
- // 这两个类主要是封装了一些provider的基本信息,可以到上面看一下类图
- synchronized (mProviderMap) {
- IBinder jBinder = provider.asBinder();
- if (localProvider != null) {
- ComponentName cname = new ComponentName(info.packageName, info.name);
- // mLocalProvidersByName的key是component信息,value是对应的ProviderClientReocrd
- ProviderClientRecord pr = mLocalProvidersByName.get(cname);
- if (pr != null) {
- // 不为空代表install过
- provider = pr.mProvider;
- } else {
- // 对于新创建的provider,创建其对应的ContentProviderHolder对象
- holder = new ContentProviderHolder(info);
- holder.provider = provider;
- holder.noReleaseNeeded = true;
- // install Authorities
- pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
- // mLocalProviders的key是IContentProvider的binder对象,value是ProviderClientRecord
- // 将封装好的provider放入map中
- mLocalProviders.put(jBinder, pr);
- mLocalProvidersByName.put(cname, pr);
- }
- retHolder = pr.mHolder;
- } else {
- // mProviderRefCountMap的key是binder对象,value是ProviderRefCount
- // ProviderRefCount中记录了这个provider的stable和unstable的数量
- ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
- if (prc != null) {
- if (!noReleaseNeeded) {
- incProviderRefLocked(prc, stable);
- try {
- ActivityManager.getService().removeContentProvider(
- holder.connection, stable);
- } catch (RemoteException e) {
- }
- }
- } else {
- ProviderClientRecord client = installProviderAuthoritiesLocked(
- provider, localProvider, holder);
- if (noReleaseNeeded) {
- // 创建ProviderRefCount
- prc = new ProviderRefCount(holder, client, 1000, 1000);
- } else {
- // 根据参数中的stable和unstable创建对象
- prc = stable
- ? new ProviderRefCount(holder, client, 1, 0)
- : new ProviderRefCount(holder, client, 0, 1);
- }
- // 放入map
- mProviderRefCountMap.put(jBinder, prc);
- }
- retHolder = prc.holder;
- }
- }
- return retHolder;
- }
这里需要提一下其中的getIContentProvider:
返回的是一个Transport对象,而这又是ContentProviderNative的子类,主要作用就是用来binder通信的
它的创建:在ContentProvider类中
private Transport mTransport = new Transport();
也就是说在对象创建的时候就默认创建了
然后是ActivityThread.installProviderAuthoritiesLocked
- private ProviderClientRecord installProviderAuthoritiesLocked(IContentProvider provider,
- ContentProvider localProvider, ContentProviderHolder holder) {
- final String auths[] = holder.info.authority.split(";");
- final int userId = UserHandle.getUserId(holder.info.applicationInfo.uid);
-
- if (provider != null) {
- for (String auth : auths) {
- // 对于一些特殊的auth,允许跨进程binder call
- // Binder.allowBlocking代表允许执行同步的binder call
- switch (auth) {
- case ContactsContract.AUTHORITY:
- case CallLog.AUTHORITY:
- case CallLog.SHADOW_AUTHORITY:
- case BlockedNumberContract.AUTHORITY:
- case CalendarContract.AUTHORITY:
- case Downloads.Impl.AUTHORITY:
- case "telephony":
- Binder.allowBlocking(provider.asBinder());
- }
- }
- }
- // 创建ProviderClientRecord
- final ProviderClientRecord pcr = new ProviderClientRecord(
- auths, provider, localProvider, holder);
- for (String auth : auths) {
- // 根据auth和userId创建ProviderKey,放入mProviderMap
- final ProviderKey key = new ProviderKey(auth, userId);
- final ProviderClientRecord existing = mProviderMap.get(key);
- if (existing != null) {
- Slog.w(TAG, "Content provider " + pcr.mHolder.info.name
- + " already published as " + auth);
- } else {
- mProviderMap.put(key, pcr);
- }
- }
- return pcr;
- }
小结:
这里先说一下stable和unstable:
代表的是client和server的链接,主要取决于获取provider的传参,默认情况下,insert/update/delete建立的链接都是stable,而query则是unstable,不过在query的时候如果失败,还会重新创建stable
stable和unstable最重大的差别在于unstable的情况下,即使对端挂掉了,client也没关系,但是stable的话,如果对端进程挂掉了,client也会被跟着级联kill掉。(后面会介绍)
- public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,
- @Nullable ContentValues values) {
- Preconditions.checkNotNull(url, "url");
- // 请求provider,经过调用之后,最终传参获取的是stable类型provider
- IContentProvider provider = acquireProvider(url);
- if (provider == null) {
- throw new IllegalArgumentException("Unknown URL " + url);
- }
- try {
- long startTime = SystemClock.uptimeMillis();
- // 执行通过IContentProvider执行insert,其实是发起了binder call到了provider所在进程执行
- Uri createdRow = provider.insert(mPackageName, url, values);
- long durationMillis = SystemClock.uptimeMillis() - startTime;
- maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */);
- return createdRow;
- } catch (RemoteException e) {
- return null;
- } finally {
- releaseProvider(provider);
- }
- }
ContentResolver.delete:执行provider的delete
ContentResolver.update:执行provider的update
ContentResolver.call:执行provider的call,这个比较灵活,传递的参数比较多,不固定于某一个
这三个方法的实现都跟instert基本类似,此处不再罗列
下面需要重点说一下query
:
4.2.2 query
- public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,
- @Nullable String[] projection, @Nullable Bundle queryArgs,
- @Nullable CancellationSignal cancellationSignal) {
- Preconditions.checkNotNull(uri, "uri");
- // 这里执行的方法是acquireUnstableProvider
- // 也就是说建立的链接是unstable类型
- IContentProvider unstableProvider = acquireUnstableProvider(uri);
- if (unstableProvider == null) {
- return null;
- }
- IContentProvider stableProvider = null;
- Cursor qCursor = null;
- try {
- long startTime = SystemClock.uptimeMillis();
- ICancellationSignal remoteCancellationSignal = null;
- if (cancellationSignal != null) {
- cancellationSignal.throwIfCanceled();
- remoteCancellationSignal = unstableProvider.createCancellationSignal();
- cancellationSignal.setRemote(remoteCancellationSignal);
- }
- try {
- // 执行query
- qCursor = unstableProvider.query(mPackageName, uri, projection,
- queryArgs, remoteCancellationSignal);
- } catch (DeadObjectException e) {
- // 如果query失败
- // 因为unstable类型,失败代表对端挂掉了,那么重新请求stable类型链接
- unstableProviderDied(unstableProvider);
- stableProvider = acquireProvider(uri);
- if (stableProvider == null) {
- return null;
- }
- // 再次query
- qCursor = stableProvider.query(
- mPackageName, uri, projection, queryArgs, remoteCancellationSignal);
- }
- if (qCursor == null) {
- return null;
- }
- qCursor.getCount();
- long durationMillis = SystemClock.uptimeMillis() - startTime;
- final IContentProvider provider = (stableProvider != null) ? stableProvider
- : acquireProvider(uri);
- final CursorWrapperInner wrapper = new CursorWrapperInner(qCursor, provider);
- stableProvider = null;
- qCursor = null;
- return wrapper;
- } catch (RemoteException e) {
- ...
- }
- }
- public final IContentProvider acquireProvider(
- Context c, String auth, int userId, boolean stable) {
- // 如果已经存在则直接返回
- final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
- if (provider != null) {
- return provider;
- }
- ContentProviderHolder holder = null;
- // 如果不存在则需要向AMS查询
- try {
- holder = ActivityManager.getService().getContentProvider(
- getApplicationThread(), auth, userId, stable);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- if (holder == null) {
- Slog.e(TAG, "Failed to find provider info for " + auth);
- return null;
- }
- // 在本进程中installProvider
- holder = installProvider(c, holder, holder.info,
- true /*noisy*/, holder.noReleaseNeeded, stable);
- return holder.provider;
- }
到这里可能有有一些迷糊,前面已经installProvider过了,为什么acquireProvider的时候需要再install一次呢?
答案是因为这是两个不同的进程
4.3.1 ActivityThread.acquireExistingProvider
- public final IContentProvider acquireExistingProvider(
- Context c, String auth, int userId, boolean stable) {
- synchronized (mProviderMap) {
- final ProviderKey key = new ProviderKey(auth, userId);
- final ProviderClientRecord pr = mProviderMap.get(key);
- if (pr == null) {
- return null;
- }
- IContentProvider provider = pr.mProvider;
- IBinder jBinder = provider.asBinder();
- if (!jBinder.isBinderAlive()) {
- // 对端进程挂掉了
- handleUnstableProviderDiedLocked(jBinder, true);
- return null;
- }
- ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
- if (prc != null) {
- // 增加引用计数
- incProviderRefLocked(prc, stable);
- }
- return provider;
- }
- }
- public final ContentProviderHolder getContentProvider(
- IApplicationThread caller, String name, int userId, boolean stable) {
- enforceNotIsolatedCaller("getContentProvider");
- if (caller == null) {
- String msg = "null IApplicationThread when getting content provider "
- + name;
- Slog.w(TAG, msg);
- throw new SecurityException(msg);
- }
- return getContentProviderImpl(caller, name, null, stable, userId);
- }
简单对caller进行了判断,重点在getContentProviderImpl
方法比较长,删除了其中一些无用的log以及checkTime
- private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
- String name, IBinder token, boolean stable, int userId) {
- ContentProviderRecord cpr;
- ContentProviderConnection conn = null;
- ProviderInfo cpi = null;
- synchronized(this) {
- // 对caller判断
-
- boolean checkCrossUser = true;
- // 在AMS的providermap中先看看是不是已经存在了
- cpr = mProviderMap.getProviderByName(name, userId);
- // 如果不存在且system,校验Singleton,也就是只能有一个
- 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.uid, cpi.applicationInfo.uid)) {
- userId = UserHandle.USER_SYSTEM;
- checkCrossUser = false;
- } else {
- cpr = null;
- cpi = null;
- }
- }
- }
- // 看看这个provider当前是不是已经在运行了
- boolean providerRunning = cpr != null && cpr.proc != null && !cpr.proc.killed;
- // 如果已经在运行了,也就说明各个数据结构都已经添加过了,进程也都已经存在了
- if (providerRunning) {
- cpi = cpr.info;
- if (r != null && cpr.canRunHere(r)) {
- // canRunHere主要针对自己请求的provider在自己进程中的情况,一般不会遇到
- ContentProviderHolder holder = cpr.newHolder(null);
- holder.provider = null;
- return holder;
- }
- ...
-
- final long origId = Binder.clearCallingIdentity();
- // 建立provider之间的链接
- conn = incProviderCountLocked(r, cpr, token, stable);
- // 需要更新lru队列
- if (conn != null && (conn.stableCount+conn.unstableCount) == 1) {
- if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
- updateLruProcessLocked(cpr.proc, false, null);
- }
- }
- final int verifiedAdj = cpr.proc.verifiedAdj;
- // 更新进程优先级
- boolean success = updateOomAdjLocked(cpr.proc, true);
- if (success && verifiedAdj != cpr.proc.setAdj && !isProcessAliveLocked(cpr.proc)) {
- success = false;
- }
- // 记录usageStates
- maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name);
- if (!success) {
- // 更新lru失败代表那个进程挂掉了
- boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
- // 需要处理进程挂掉的流程
- // 并且标志provider当前不在运行状态,这样会走进下面的provider不在运行的流程中
- appDiedLocked(cpr.proc);
- if (!lastRef) {
- return null;
- }
- providerRunning = false;
- conn = null;
- } else {
- cpr.proc.verifiedAdj = cpr.proc.setAdj;
- }
- Binder.restoreCallingIdentity(origId);
- }
- // 如果provider当前不在运行
- if (!providerRunning) {
- try {
- // 先从packageManager那边查询到相关的信息
- cpi = AppGlobals.getPackageManager().
- resolveContentProvider(name,
- STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId);
- } catch (RemoteException ex) {
- }
- // 没查到的话那就说明这个是一个无效的provider
- if (cpi == null) {
- return null;
- }
- boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo,
- cpi.name, cpi.flags)
- && isValidSingletonCall(r.uid, cpi.applicationInfo.uid);
- if (singleton) {
- userId = UserHandle.USER_SYSTEM;
- }
- // 获取applicationInfo
- cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo, userId);
-
- String msg;
- if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, !singleton))
- != null) {
- throw new SecurityException(msg);
- }
- // 在system启动之前不允许非system的进程获取provider
- if (!mProcessesReady
- && !cpi.processName.equals("system")) {
- throw new IllegalArgumentException(
- "Attempt to launch content provider before system ready");
- }
- // 校验user是否正在运行中
- if (!mUserController.isUserRunningLocked(userId, 0)) {
- Slog.w(TAG, "Unable to launch app "
- + cpi.applicationInfo.packageName + "/"
- + cpi.applicationInfo.uid + " for provider "
- + name + ": user " + userId + " is stopped");
- return null;
- }
-
- ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
- // 从getProviderByClass中获取,看看这个provider是不是AMS这边已经有保存了
- // 如果没有,代表这个provider从来没有向AMS注册过
- // 此时需要创建一个新的ContentProviderRecord
- cpr = mProviderMap.getProviderByClass(comp, userId);
- final boolean firstClass = cpr == null;
- if (firstClass) {
- final long ident = Binder.clearCallingIdentity();
- if (mPermissionReviewRequired) {
- if (!requestTargetProviderPermissionsReviewIfNeededLocked(cpi, r, userId)) {
- return null;
- }
- }
-
- 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);
- return null;
- }
- ai = getAppInfoForUser(ai, userId);
- cpr = new ContentProviderRecord(this, cpi, ai, comp, singleton);
- } catch (RemoteException ex) {
- // pm is in same process, this will never happen.
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
- ...
- // 看看当前请求的provider是不是在mLaunchingProviders
- // 如果一个 provider被请求过,但是因为对方进程没有启动没有publishProvider
- // 则会加入mLaunchingProviders中
- final int N = mLaunchingProviders.size();
- int i;
- for (i = 0; i < N; i++) {
- if (mLaunchingProviders.get(i) == cpr) {
- break;
- }
- }
- // launching中没有
- if (i >= N) {
- final long origId = Binder.clearCallingIdentity();
-
- try {
- 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);
- }
- // 看看这个进程是不是存在
- ProcessRecord proc = getProcessRecordLocked(
- cpi.processName, cpr.appInfo.uid, false);
- if (proc != null && proc.thread != null && !proc.killed) {
- // 如果进程已经存在,那么就让这个进程去installProvider即可
- if (!proc.pubProviders.containsKey(cpi.name)) {
- proc.pubProviders.put(cpi.name, cpr);
- try {
- proc.thread.scheduleInstallProvider(cpi);
- } catch (RemoteException e) {
- }
- }
- } else {
- // 如果进程不存在,那就得先启动进程
- // 因为provider必然运行在某一个进程中,对端进程不在肯定无法获取provider
- proc = startProcessLocked(cpi.processName,
- cpr.appInfo, false, 0, "content provider",
- new ComponentName(cpi.applicationInfo.packageName,
- cpi.name), false, false, false);
- if (proc == null) {
- Slog.w(TAG, "Unable to launch app "
- + cpi.applicationInfo.packageName + "/"
- + cpi.applicationInfo.uid + " for provider "
- + name + ": process is bad");
- return null;
- }
- }
- // 因为需要启动进程,记录这个provider的launchingApp
- // 并把这个provider加入到mLaunchingProviders中,等待对方publish之后
- // 再从mLaunchingProviders中移除
- cpr.launchingApp = proc;
- mLaunchingProviders.add(cpr);
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
- // 如果是第一次创建的provider,还需要放入mProviderMap
- if (firstClass) {
- mProviderMap.putProviderByClass(comp, cpr);
- }
- mProviderMap.putProviderByName(name, cpr);
- // 建立privier之间的链接
- conn = incProviderCountLocked(r, cpr, token, stable);
- if (conn != null) {
- conn.waiting = true;
- }
- }
- grantEphemeralAccessLocked(userId, null /*intent*/,
- cpi.applicationInfo.uid, UserHandle.getAppId(Binder.getCallingUid()));
- }
-
- // 代码执行到这里就说明当前的provider不存在,需要等待对端publish
- synchronized (cpr) {
- while (cpr.provider == null) {
- ...
- try {
- if (conn != null) {
- conn.waiting = true;
- }
- // 在需要获取的provider上wait
- // 直到对端provider被publish之后,方可notify
- cpr.wait();
- } catch (InterruptedException ex) {
- } finally {
- if (conn != null) {
- conn.waiting = false;
- }
- }
- }
- }
- return cpr != null ? cpr.newHolder(conn) : null;
- }
这段逻辑比较长,总结来说流程如下:
4.4.2 incProviderCountLocked
- ContentProviderConnection incProviderCountLocked(ProcessRecord r,
- final ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable) {
- if (r != null) {
- for (int i=0; i<r.conProviders.size(); i++) {
- ContentProviderConnection conn = r.conProviders.get(i);
- if (conn.provider == cpr) {
- if (stable) {
- conn.stableCount++;
- conn.numStableIncs++;
- } else {
- conn.unstableCount++;
- conn.numUnstableIncs++;
- }
- return conn;
- }
- }
- ContentProviderConnection conn = new ContentProviderConnection(cpr, r);
- if (stable) {
- conn.stableCount = 1;
- conn.numStableIncs = 1;
- } else {
- conn.unstableCount = 1;
- conn.numUnstableIncs = 1;
- }
- cpr.connections.add(conn);
- r.conProviders.add(conn);
- startAssociationLocked(r.uid, r.processName, r.curProcState,
- cpr.uid, cpr.name, cpr.info.processName);
- return conn;
- }
- cpr.addExternalProcessHandleLocked(externalProcessToken);
- return null;
- }
这个方法相对简单,所以没有写太多注释,就是根绝provider是否存在以及是否stable,记录stable和unstable的数量
上面的流程中多次提到进程启动的时候会installProvider以及publishContentProviders,接下来就来看一下到底是怎么回事,在前面4.1节中也有提到,在installProvider之后,会通过binder call告诉AMS,publishContentProvider:
- public final void publishContentProviders(IApplicationThread caller,
- List<ContentProviderHolder> providers) {
- if (providers == null) {
- return;
- }
- enforceNotIsolatedCaller("publishContentProviders");
- synchronized (this) {
- final ProcessRecord r = getRecordForAppLocked(caller);
- 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();
- // 遍历所有已经安装的provider
- 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 (dst != null) {
- // 将这个providerRecord放入到mProviderMap中
- 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 launchingCount = mLaunchingProviders.size();
- int j;
- // 从mLaunchingProviders中移除
- boolean wasInLaunchingProviders = false;
- for (j = 0; j < launchingCount; j++) {
- if (mLaunchingProviders.get(j) == dst) {
- mLaunchingProviders.remove(j);
- wasInLaunchingProviders = true;
- j--;
- launchingCount--;
- }
- }
- if (wasInLaunchingProviders) {
- mHandler.removeMessages(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r);
- }
- // notify当前正在等待这个provider呗publish的所有的binder线程
- synchronized (dst) {
- dst.provider = src.provider;
- dst.proc = r;
- dst.notifyAll();
- }
- // 更新进程优先级
- updateOomAdjLocked(r, true);
- maybeUpdateProviderUsageStatsLocked(r, src.info.packageName,
- src.info.authority);
- }
- }
- Binder.restoreCallingIdentity(origId);
- }
- }
前面多次说了stable与unstable,而且前面基本都是在操作计数,那么到底什么时候会用到这个计数呢?
重点就在这个removeDyingProviderLocked
,这个方法作用是当一个进程死亡之后,把其中的所有的provider也remove掉:
- private final boolean removeDyingProviderLocked(ProcessRecord proc,
- ContentProviderRecord cpr, boolean always) {
- final boolean inLaunching = mLaunchingProviders.contains(cpr);
- // 如果这个provider还在等待launching就被remove了
- // 需要把当前等待这个provider的线程都notifyAll,否则就再也没有机会notify了
- if (!inLaunching || always) {
- synchronized (cpr) {
- cpr.launchingApp = null;
- cpr.notifyAll();
- }
- // 从mProviderMap中移除
- mProviderMap.removeProviderByClass(cpr.name, UserHandle.getUserId(cpr.uid));
- String names[] = cpr.info.authority.split(";");
- for (int j = 0; j < names.length; j++) {
- mProviderMap.removeProviderByName(names[j], UserHandle.getUserId(cpr.uid));
- }
- }
- // 判断这个provider上的所有链接
- for (int i = cpr.connections.size() - 1; i >= 0; i--) {
- ContentProviderConnection conn = cpr.connections.get(i);
- if (conn.waiting) {
- if (inLaunching && !always) {
- continue;
- }
- }
- ProcessRecord capp = conn.client;
- conn.dead = true;
- // 如果stableCount大于0,也就是说存在stable的链接
- // server挂掉了,那么就会把client也给kill掉
- // 这正是我们前面提到的stable和unstable的重大区别
- if (conn.stableCount > 0) {
- if (!capp.persistent && capp.thread != null
- && capp.pid != 0
- && capp.pid != MY_PID) {
- capp.kill("depends on provider "
- + cpr.name.flattenToShortString()
- + " in dying proc " + (proc != null ? proc.processName : "??")
- + " (adj " + (proc != null ? proc.setAdj : "??") + ")", true);
- }
- } else if (capp.thread != null && conn.provider.provider != null) {
- try {
- capp.thread.unstableProviderDied(conn.provider.provider.asBinder());
- } catch (RemoteException e) {
- }
- cpr.connections.remove(i);
- if (conn.client.conProviders.remove(conn)) {
- stopAssociationLocked(capp.uid, capp.processName, cpr.uid, cpr.name);
- }
- }
- }
- if (inLaunching && always) {
- mLaunchingProviders.remove(cpr);
- }
- return inLaunching;
- }
经过上面的解读,主要需要了解到的有以下几点:
来自:https://blog.csdn.net/u011733869/article/details/83958712
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。