ContentProvider详解

本文基于android 12.0
主要讲解的是A进程访问B进程的ContentProvider的流程, 主要涉及到的代码路径:

frameworks/base/core/java/android/content/ContentResolver.java
frameworks/base/core/java/android/app/ContextImpl$ApplicationContentResolver.java
frameworks/base/core/java/android/app/ActivityThread.java
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
frameworks/base/services/core/java/com/android/server/am/ContentProviderHelper.java
frameworks/base/services/core/java/com/android/server/am/ContentProviderRecord.java
frameworks/base/services/core/java/com/android/server/am/ContentProviderConnection.java

查询和发布流程

进程A查询ContentProvider

运行在A进程中,即客户端进程。这里需要注意发生anr时若堆栈卡在acquireProvider则是跟system server端通信;若是访问IContentProvider的接口,则是跟B进程(provider的server端)通信。

stable 和 unstable连接

代表client端和server端的连接,query方式若失败,还会重新创建stable连接。只有query和其他操作同时进行时,ContentProviderConnection的unstableCount和stableCount才会同时为1。

  1. stable : call/insert/delete/update等方式建立的都是stable连接;对端挂掉,client会被级联查杀。
  2. unstable :query建立的是unstable连接;对端挂掉,client端没事。
    ContentProvider详解_第1张图片

ContentResolver#call

@Override
    public final @Nullable Bundle call(@NonNull String authority, @NonNull String method,
            @Nullable String arg, @Nullable Bundle extras) {
        Objects.requireNonNull(authority, "authority");
        Objects.requireNonNull(method, "method");

        try {
            if (mWrapped != null) return mWrapped.call(authority, method, arg, extras);
        } catch (RemoteException e) {
            return null;
        }
		// call方法默认去获取stable的provider
        IContentProvider provider = acquireProvider(authority);
		// 获取不到provider,抛出如下log的异常
        if (provider == null) {
            throw new IllegalArgumentException("Unknown authority " + authority);
        }
        try {
			// call流程,binder对端是B进程,非system server
            final Bundle res = provider.call(mPackageName, mAttributionTag, authority, method, arg,
                    extras);
            Bundle.setDefusable(res, true);
            return res;
        } catch (RemoteException e) {
            return null;
        } finally {
			// 访问完后都会释放provider
            releaseProvider(provider);
        }
    }

ActivityThread#acquireProvider

  1. 本地存在对应的IConetntProvider实例则直接获取
  2. 不存在则向AMS查询
    a. 对应的server端provider已发布,则直接执行本地的install操作。
    b. server端provider未发布,则本地先wait,等待对方发布成功被唤醒,超时时间为20s。
    @UnsupportedAppUsage
    public final IContentProvider acquireProvider(
            Context c, String auth, int userId, boolean stable) {
		// 先在本地查询是否有保存这个auth对应的IContentProvider,有则直接返回
		// 1.运行在自己进程的provider
        // 2. 已经访问过的其他进程的provider
        final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
        if (provider != null) {
            return provider;
        }
		// 根据auth,userId封装获取provider key
        ContentProviderHolder holder = null;
        final ProviderKey key = getGetProviderKey(auth, userId);
        try {
            synchronized (key) {
				// 不存在通过AMS查询 , 直接返回一个ContentProviderHolder的实例
                holder = ActivityManager.getService().getContentProvider(
                        getApplicationThread(), c.getOpPackageName(), auth, userId, stable);
            	// 如果对端进程不存在或进程存在provider未发布,则需要等待对端provider发布成功
                if (holder != null && holder.provider == null && !holder.mLocal) {
                    synchronized (key.mLock) {
						// 等待provider进程发布provider完成,超时时间为20s
						// 会在ContentProviderRecord的notifyContentProviderPublishStatus方法回调时notify
                        key.mLock.wait(ContentResolver.CONTENT_PROVIDER_READY_TIMEOUT_MILLIS);
						// notify后,将key中的holder赋值给holder
                        holder = key.mHolder;
                    }
					// 如果超时仍未收到notify,holder会为null
                    if (holder != null && holder.provider == null) {
                        // probably timed out
                        holder = null;
                    }
                }
            }
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        } catch (InterruptedException e) {
            holder = null;
        } finally {
            // Clear the holder from the key since the key itself is never cleared.
            synchronized (key.mLock) {
                key.mHolder = null;
            }
        }
		// 打印失败log,user未解锁情况大部分不允许访问provider
        if (holder == null) {
            if (UserManager.get(c).isUserUnlocked(userId)) {
                Slog.e(TAG, "Failed to find provider info for " + auth);
            } else {
                Slog.w(TAG, "Failed to find provider info for " + auth + " (user not unlocked)");
            }
            return null;
        }
		// 在本进程中installProvider,增加引用计数
        holder = installProvider(c, holder, holder.info,
                true /*noisy*/, holder.noReleaseNeeded, stable);
        return holder.provider;
    }

ActivityThread#acquireExistingProvider

获取本地存在的IContentProvider对象

    @UnsupportedAppUsage
    public final IContentProvider acquireExistingProvider(
            Context c, String auth, int userId, boolean stable) {
        synchronized (mProviderMap) {
			// 通过key获取provider clent 对象,如果不为null,说明当前进程已经install该provider
            final ProviderKey key = new ProviderKey(auth, userId);
            final ProviderClientRecord pr = mProviderMap.get(key);
            if (pr == null) {
                return null;
            }

            IContentProvider provider = pr.mProvider;
			// 对端进程挂掉了, 返回null,在acquireProvider重新向ams获取
            IBinder jBinder = provider.asBinder();
            if (!jBinder.isBinderAlive()) {
                Log.i(TAG, "Acquiring provider " + auth + " for user " + userId
                        + ": existing object's process dead");
                handleUnstableProviderDiedLocked(jBinder, true);
                return null;
            }
            // 查看是否是自己进程的provider
            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
			// 增加访问其他进程ContentProvider的引用计数
            // 否则引用计数从来不需要被释放
            if (prc != null) {
                incProviderRefLocked(prc,stable);
            }
            return provider;
        }
    }

Ams查询provider

运行在system server进程,android 12.0后ContentProvider相关的逻辑都从AMS.java中拆出到ContentProviderHelper.java中了。
ContentProvider详解_第2张图片

ContentProviderHelper#getContentProviderImpl

代码过于庞大,去除一些浅显易懂的判断代码

查询过程中有如下三种场景:
  1. B进程存在且对应的provider已经发布,直接创建连接
  2. B进程存在,provider尚未发布,通知B进程去发布provider
  3. B进程不存在,去创建B进程
返回null的情况
  1. 对端进程死亡,且不是最后一次引用
  2. provider不在运行,且pms解析provider信息失败
  3. provider所在user不在运行中
  4. 是否需要权限review 页面,一般为false
  5. pms解析provider所在app的application信息失败
  6. provider所在进程不存在&短时间crash多次拉起进程失败
  7. 经历过上面场景2.3后,launchingApp为null
  private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
            String name, IBinder token, int callingUid, String callingPackage, String callingTag,
            boolean stable, int userId) {
        ContentProviderRecord cpr;
        ContentProviderConnection conn = null;
        ProviderInfo cpi = null;
        boolean providerRunning = false;
        final int expectedUserId = userId;
        synchronized (mService) {
            long startTime = SystemClock.uptimeMillis();
			// 对caller判断
			..........
            boolean checkCrossUser = true;

            checkTime(startTime, "getContentProviderImpl: getProviderByName");

            // 检查mProviderMap中该provider是不是已经发布了
            cpr = mProviderMap.getProviderByName(name, userId);
            // 如果当前查询的user不是system,且要查找的provider是只能存在system的单例
     		..........

            ProcessRecord dyingProc = null;
            if (cpr != null && cpr.proc != null) {
				// 判断当前provider是不是已经在运行了
                providerRunning = !cpr.proc.isKilled();

                // 如果provider所在进程被AMS查杀了,但是没有回调appDiedLocked方法,标记为dyingProc
              ..............
			// 1. 当前provider正在运行
            if (providerRunning) {
                cpi = cpr.info;
				// canRunHere主要针对自己请求的provider运行在自己进程中的情况
                if (r != null && cpr.canRunHere(r)) {
                    checkAssociationAndPermissionLocked(r, cpi, callingUid, userId, checkCrossUser,
                            cpr.name.flattenToShortString(), startTime);

                   //1.1 这种情况,无须制造一个connection,且local为true
                    ContentProviderHolder holder = cpr.newHolder(null, true);
                    // 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
         ..........
				// 清除caling相关信息,以免校验callingUid等问题
                final long origId = Binder.clearCallingIdentity();
                try {
                    checkTime(startTime, "getContentProviderImpl: incProviderCountLocked");

                    // 1.2 建立provider之间的链接.
                    conn = incProviderCountLocked(r, cpr, token, callingUid, callingPackage,
                            callingTag, stable, true, startTime, mService.mProcessList,
                            expectedUserId);

                    checkTime(startTime, "getContentProviderImpl: before updateOomAdj");
                    final int verifiedAdj = cpr.proc.mState.getVerifiedAdj();
					// 更新进程优先级
                    boolean success = mService.updateOomAdjLocked(cpr.proc,
                            OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER);
                    // 如果verify adj和计算后的adj不相等且provider的持有进程死亡
                    if (success && verifiedAdj != cpr.proc.mState.getSetAdj()
                            && !isProcessAliveLocked(cpr.proc)) {
                        success = false;
                    }
                    maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name);
                    checkTime(startTime, "getContentProviderImpl: after updateOomAdj");
                    // 如果更新adj失败(持有provider的进程死亡等)
                    if (!success) {
                       //打印异常log
                        Slog.wtf(TAG, "Existing provider " + cpr.name.flattenToShortString()
                                + " is crashing; detaching " + r);
                        boolean lastRef = decProviderCountLocked(conn, cpr, token, stable,
                                false, false);
                        if (!lastRef) {
                            // This wasn't the last ref our process had on
                            // the provider...  we will be killed during cleaning up, bail.
                            return null;
                        }
                        // We'll just start a new process to host the content provider
                        providerRunning = false;
                        conn = null;
                        dyingProc = cpr.proc;
                    } else {
						// provider对应进程存在,设置当前adj为erify adj
                        cpr.proc.mState.setVerifiedAdj(cpr.proc.mState.getSetAdj());
                    }
                } finally {
					// 恢复calling相关信息
                    Binder.restoreCallingIdentity(origId);
                }
            }
			// provider未发布
            if (!providerRunning) {
                try {
					// 获取provider的info信息
                    checkTime(startTime, "getContentProviderImpl: before resolveContentProvider");
                    cpi = AppGlobals.getPackageManager().resolveContentProvider(name,
                            ActivityManagerService.STOCK_PM_FLAGS
                                    | PackageManager.GET_URI_PERMISSION_PATTERNS,
                            userId);
                    checkTime(startTime, "getContentProviderImpl: after resolveContentProvider");
                } catch (RemoteException ex) {
                }
				// 获取失败,直接返回null
                if (cpi == null) {
                    return null;
                }
                // 跟上面一次的判读一样
                boolean singleton = mService.isSingleton(
                        cpi.processName, cpi.applicationInfo, cpi.name, cpi.flags)
                            && mService.isValidSingletonCall(
                                    r == null ? callingUid : r.uid, cpi.applicationInfo.uid);
                // 一样
                if (singleton) {
                    userId = UserHandle.USER_SYSTEM;
                }
                cpi.applicationInfo = mService.getAppInfoForUser(cpi.applicationInfo, userId);
                checkTime(startTime, "getContentProviderImpl: got app info for user");

                checkAssociationAndPermissionLocked(r, cpi, callingUid, userId, !singleton,
                        name, startTime);
				// 系统还没ready,抛出异常
            ........
                // user未运行,返回null
                if (!mService.mUserController.isUserRunning(userId, 0)) {
                    Slog.w(TAG, "Unable to launch app "
                            + cpi.applicationInfo.packageName + "/" + cpi.applicationInfo.uid
                            + " for provider " + name + ": user " + userId + " is stopped");
                    return null;
                }
				// 构造component
                ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
                checkTime(startTime, "getContentProviderImpl: before getProviderByClass");
				// 检查AMS这边是否有保存该provider
                cpr = mProviderMap.getProviderByClass(comp, userId);
                checkTime(startTime, "getContentProviderImpl: after getProviderByClass");
                boolean firstClass = cpr == null;
				// 第一次创建
                if (firstClass) {
                    final long ident = Binder.clearCallingIdentity();

                    // If permissions need a review before any of the app components can run,
                    // we return no provider and launch a review activity if the calling app
                    // is in the foreground.
                    if (!requestTargetProviderPermissionsReviewIfNeededLocked(
                            cpi, r, userId, mService.mContext)) {
                        return null;
                    }

                    try {
                        checkTime(startTime, "getContentProviderImpl: before getApplicationInfo");
						// 获取provider相关的application信息
                        ApplicationInfo ai = AppGlobals.getPackageManager().getApplicationInfo(
                                cpi.applicationInfo.packageName,
                                ActivityManagerService.STOCK_PM_FLAGS, userId);
                        checkTime(startTime, "getContentProviderImpl: after getApplicationInfo");
                        if (ai == null) {
                            Slog.w(TAG, "No package info for content provider " + cpi.name);
                            return null;
                        }
						// 构造新的content provider对象
                        ai = mService.getAppInfoForUser(ai, userId);
                        cpr = new ContentProviderRecord(mService, cpi, ai, comp, singleton);
                    } catch (RemoteException ex) {
                        // pm is in same process, this will never happen.
                    } finally {
                        Binder.restoreCallingIdentity(ident);
                    }
                } else if (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.
                    cpr = new ContentProviderRecord(cpr);
                    // This is sort of "firstClass"
                    firstClass = true;
                }

                checkTime(startTime, "getContentProviderImpl: now have ContentProviderRecord");

                if (r != null && cpr.canRunHere(r)) {
                    // 上面一样的逻辑
                    return cpr.newHolder(null, true);
                }

                // 看看当前请求的provider是不是在mLaunchingProviders
				// 如果一个 provider被请求过,但是因为对方进程没有启动没有publishProvider
				// 则会加入mLaunchingProviders中
                final int numLaunchingProviders = mLaunchingProviders.size();
                int i;
                for (i = 0; i < numLaunchingProviders; i++) {
                    if (mLaunchingProviders.get(i) == cpr) {
                        break;
                    }
                }

                // 没有正在启动该provider进程
                if (i >= numLaunchingProviders) {
                    final long origId = Binder.clearCallingIdentity();

                    try {
                      .....
                        // Content provider is now in use, its package can't be stopped.
                        try {
                            checkTime(startTime,
                                    "getContentProviderImpl: before set stopped state");
                            AppGlobals.getPackageManager().setPackageStoppedState(
                                    cpr.appInfo.packageName, false, userId);
                            checkTime(startTime, "getContentProviderImpl: after set stopped state");
                        } catch (RemoteException e) {
                        } catch (IllegalArgumentException e) {
                            Slog.w(TAG, "Failed trying to unstop package "
                                    + cpr.appInfo.packageName + ": " + e);
                        }

                        // Use existing process if already started
                        checkTime(startTime, "getContentProviderImpl: looking for process record");
						//进程已经存在
                        ProcessRecord proc = mService.getProcessRecordLocked(
                                cpi.processName, cpr.appInfo.uid);
                        IApplicationThread thread;
                        if (proc != null && (thread = proc.getThread()) != null
                                && !proc.isKilled()) {
                           // 2. 进程存在,但是没有对应的provider,则通知app端install provider
                            final ProcessProviderRecord pr = proc.mProviders;
                            if (!pr.hasProvider(cpi.name)) {
                                checkTime(startTime, "getContentProviderImpl: scheduling install");
                                pr.installProvider(cpi.name, cpr);
                                try {
                                    thread.scheduleInstallProvider(cpi);
                                } catch (RemoteException e) {
                                }
                            }
                        } else {
							// 3. 进程不存在,启动进程
                            checkTime(startTime, "getContentProviderImpl: before start process");
                            proc = mService.startProcessLocked(
                                    cpi.processName, cpr.appInfo, false, 0,
                                    new HostingRecord("content provider",
                                        new ComponentName(
                                                cpi.applicationInfo.packageName, cpi.name)),
                                    Process.ZYGOTE_POLICY_FLAG_EMPTY, false, false);
                            checkTime(startTime, "getContentProviderImpl: after start process");
							// 短时间内crash多次,启动失败,打印异常log
                            if (proc == null) {
                                Slog.w(TAG, "Unable to launch app "
                                        + cpi.applicationInfo.packageName + "/"
                                        + cpi.applicationInfo.uid + " for provider " + name
                                        + ": process is bad");
                                return null;
                            }
                        }
                        cpr.launchingApp = proc;
						// 将当前provider加到laucnhing列表,避免二次创建进程
                        mLaunchingProviders.add(cpr);
                    } finally {
                        Binder.restoreCallingIdentity(origId);
                    }
                }

                checkTime(startTime, "getContentProviderImpl: updating data structures");

               	// 第一次创建,将当前provider加入mProviderMap map中
                if (firstClass) {
                    mProviderMap.putProviderByClass(comp, cpr);
                }
				// 根据name加入map中
                mProviderMap.putProviderByName(name, cpr);
				// 创建连接
                conn = incProviderCountLocked(r, cpr, token, callingUid, callingPackage, callingTag,
                        stable, false, startTime, mService.mProcessList, expectedUserId);
				// 等待对端publish provider
                if (conn != null) {
                    conn.waiting = true;
                }
            }
            checkTime(startTime, "getContentProviderImpl: done!");

            mService.grantImplicitAccess(userId, null, callingUid,
                    UserHandle.getAppId(cpi.applicationInfo.uid));

            if (caller != null) {
                // The client will be waiting, and we'll notify it when the provider is ready.
                synchronized (cpr) {
                    if (cpr.provider == null) {
                        if (cpr.launchingApp == null) {
                            Slog.w(TAG, "Unable to launch app "
                                    + cpi.applicationInfo.packageName + "/"
                                    + cpi.applicationInfo.uid + " for provider "
                                    + name + ": launching app became null");
                            EventLogTags.writeAmProviderLostProcess(
                                    UserHandle.getUserId(cpi.applicationInfo.uid),
                                    cpi.applicationInfo.packageName,
                                    cpi.applicationInfo.uid, name);
                            return null;
                        }

                        if (conn != null) {
                            conn.waiting = true;
                        }
                        Message msg = mService.mHandler.obtainMessage(
                                ActivityManagerService.WAIT_FOR_CONTENT_PROVIDER_TIMEOUT_MSG);
                        msg.obj = cpr;
                        mService.mHandler.sendMessageDelayed(msg,
                                ContentResolver.CONTENT_PROVIDER_READY_TIMEOUT_MILLIS);
                    }
                }
                // Return a holder instance even if we are waiting for the publishing of the
                // provider, client will check for the holder.provider to see if it needs to wait
                // for it.
				// 返回holder
                return cpr.newHolder(conn, false);
            }
        }

        // 以下这些逻辑在S上基本不会走到,超时逻辑移到app端
        final long timeout =
                SystemClock.uptimeMillis() + ContentResolver.CONTENT_PROVIDER_READY_TIMEOUT_MILLIS;
        boolean timedOut = false;
        synchronized (cpr) {
            while (cpr.provider == null) {
                if (cpr.launchingApp == null) {
                    Slog.w(TAG, "Unable to launch app 中间B进程的创建&app的初始化过程省略
"
                            + cpi.applicationInfo.packageName + "/" + cpi.applicationInfo.uid
                            + " for provider " + name + ": launching app became null");
                    EventLogTags.writeAmProviderLostProcess(
                            UserHandle.getUserId(cpi.applicationInfo.uid),
                            cpi.applicationInfo.packageName, cpi.applicationInfo.uid, name);
                    return null;
                }
                try {
                    final long wait = Math.max(0L, timeout - SystemClock.uptimeMillis());
                    if (DEBUG_MU) {
                        Slog.v(TAG_MU, "Waiting to start provider " + cpr
                                + " launchingApp=" + cpr.launchingApp + " for " + wait + " ms");
                    }
                    if (conn != null) {
                        conn.waiting = true;
                    }
                    cpr.wait(wait);
                    if (cpr.provider == null) {
                        timedOut = true;
                        break;
                    }
                } catch (InterruptedException ex) {
                } finally {
                    if (conn != null) {
                        conn.waiting = false;
                    }
                }
            }
        }
        if (timedOut) {
            // Note we do it after releasing the lock.
            String callerName = "unknown";
            if (caller != null) {
                synchronized (mService.mProcLock) {
                    final ProcessRecord record =
                            mService.mProcessList.getLRURecordForAppLOSP(caller);
                    if (record != null) {
                        callerName = record.processName;
                    }
                }
            }

            Slog.wtf(TAG, "Timeout waiting for provider "
                    + cpi.applicationInfo.packageName + "/" + cpi.applicationInfo.uid
                    + " for provider " + name + " providerRunning=" + providerRunning
                    + " caller=" + callerName + "/" + Binder.getCallingUid());
            return null;
        }
        return cpr.newHolder(conn, false);
    }

中间B进程的创建&app的初始化过程省略

B进程install Provider

主要运行在B进程,app端install完成后binder ams去publish该provider
ContentProvider详解_第3张图片
install场景有两种,对应上面查询过程中的2 3场景

  1. B进程bind application过程中install
  2. B进程收到ams的回调直接install

ActivityThread#handleBindApplication

ApplicationThread的binder线程发送消息到ActivityThread的主线程中去执行。

  @UnsupportedAppUsage
    private void handleBindApplication(AppBindData data) {
        ......
        try { 
			.......
			// 先安装providers(严格备份模式下不会拉起providers)
            // don't bring up providers in restricted mode; they may depend on the
            // app's custom Application class
            if (!data.restrictedBackupMode) {
                if (!ArrayUtils.isEmpty(data.providers)) {
                    installContentProviders(app, data.providers);
                }
            }
            .......
			// 再执行application的onCreate逻辑
            try {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "app.onCreate");
                mInstrumentation.callApplicationOnCreate(app);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            } catch (Exception e) {
                if (!mInstrumentation.onException(app, e)) {
                    throw new RuntimeException(
                      "Unable to create application " + app.getClass().getName()
                      + ": " + e.toString(), e);
                }
            }
        } ......

ActivityThread#installContentProviders

@UnsupportedAppUsage
    private void installContentProviders(
            Context context, List<ProviderInfo> providers) {
        final ArrayList<ContentProviderHolder> results = new ArrayList<>();
        // 遍历providers去安装
        for (ProviderInfo cpi : providers) {
            ContentProviderHolder cph = installProvider(context, null, cpi,
                    false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
            if (cph != null) {
                cph.noReleaseNeeded = true;
                results.add(cph);
            }
        }
		// 告知system server 发布完成
        try {
            ActivityManager.getService().publishContentProviders(
                getApplicationThread(), results);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }

ActivityThread.java#installProvider

@UnsupportedAppUsage
    private ContentProviderHolder installProvider(Context context,
            ContentProviderHolder holder, ProviderInfo info,
            boolean noisy, boolean noReleaseNeeded, boolean stable) {
        ContentProvider localProvider = null;
        IContentProvider provider;
		// 这里holder为null
        if (holder == null || holder.provider == null) {
			// 打印provider的debug log
      .....
            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 {
                    c = context.createPackageContext(ai.packageName,
                            Context.CONTEXT_INCLUDE_CODE);
                } catch (PackageManager.NameNotFoundException e) {
                    // Ignore
                }
            }
      ........

            try {
                final java.lang.ClassLoader cl = c.getClassLoader();
                LoadedApk packageInfo = peekPackageInfo(ai.packageName, true);
                if (packageInfo == null) {
                    // System startup case.
                    packageInfo = getSystemContext().mPackageInfo;
                }
				//如果是本地自己app的provider
                localProvider = packageInfo.getAppFactory()
                        .instantiateProvider(cl, info.name);
                provider = localProvider.getIContentProvider();
                if (provider == null) {
                    Slog.e(TAG, "Failed to instantiate class " +
                          info.name + " from sourceDir " +
                          info.applicationInfo.sourceDir);
                    return null;
                }
				// 打印contentprovider的初始化的debug log
                if (DEBUG_PROVIDER) Slog.v(
                    TAG, "Instantiating local provider " + info.name);
                // XXX Need to create the correct context for this provider.
                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;
            if (DEBUG_PROVIDER) Slog.v(TAG, "Installing external provider " + info.authority + ": "
                    + info.name);
        }

        ContentProviderHolder retHolder;

        synchronized (mProviderMap) {
            // 增加引用计数的debug log
            if (DEBUG_PROVIDER) Slog.v(TAG, "Checking to add " + provider
                    + " / " + info.name);
            IBinder jBinder = provider.asBinder();
            // 如果是本地自己app的provider
            if (localProvider != null) {
                ComponentName cname = new ComponentName(info.packageName, info.name);
                ProviderClientRecord pr = mLocalProvidersByName.get(cname);
                if (pr != null) {
                    if (DEBUG_PROVIDER) {
                        Slog.v(TAG, "installProvider: lost the race, "
                                + "using existing local provider");
                    }
                    provider = pr.mProvider;
                } else {
					// 第一次创建
                    holder = new ContentProviderHolder(info);
                    holder.provider = provider;
                    holder.noReleaseNeeded = true;
					// 初始化客户端provider实例,通过providerkey将当前的ProviderClientRecord保存到mroviderMap中
                    pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
					// 通过IBinder和component保存到对应的map中
                    mLocalProviders.put(jBinder, pr);
                    mLocalProvidersByName.put(cname, pr);
                }
                retHolder = pr.mHolder;
            } else {
				// 其他app的provider
                ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
                if (prc != null) {
                    if (DEBUG_PROVIDER) {
                        Slog.v(TAG, "installProvider: lost the race, updating ref count");
                    }
                    // 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).
					// 增加新的引用计数,移除旧的引用计数
                    if (!noReleaseNeeded) {
                        incProviderRefLocked(prc, stable);
                        try {
                            ActivityManager.getService().removeContentProvider(
                                    holder.connection, stable);
                        } catch (RemoteException e) {
                            //do nothing content provider object is dead any way
                        }
                    }
                } else {
					// 首次访问会走到这
                    ProviderClientRecord client = installProviderAuthoritiesLocked(
                            provider, localProvider, holder);
                    if (noReleaseNeeded) {
                        prc = new ProviderRefCount(holder, client, 1000, 1000);
                    } else {
                        prc = stable
                                ? new ProviderRefCount(holder, client, 1, 0)
                                : new ProviderRefCount(holder, client, 0, 1);
                    }
                    mProviderRefCountMap.put(jBinder, prc);
                }
                retHolder = prc.holder;
            }
        }
        return retHolder;
    }

ActivityThread#installProviderAuthoritiesLocked

install 安装的时候会将key添加到mProviderMap中去,这样下次查询就可以查到

 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) {
            // If this provider is hosted by the core OS and cannot be upgraded,
            // then I guess we're okay doing blocking calls to it.
            for (String auth : auths) {
                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());
                }
            }
        }

        final ProviderClientRecord pcr = new ProviderClientRecord(
                auths, provider, localProvider, holder);
        for (String auth : auths) {
            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;
    }

Ams 发布B进程的provider

发布成功后通知A进程
ContentProvider详解_第4张图片
超时20s没有发布成功也会通知A进程client端
ContentProvider详解_第5张图片
进程死亡也会通知到A进程client端
ContentProvider详解_第6张图片

ContentProviderHelper#publishContentProviders

 void publishContentProviders(IApplicationThread caller, List<ContentProviderHolder> providers) {
        if (providers == null) {
            return;
        }

        mService.enforceNotIsolatedCaller("publishContentProviders");
		// 需要拿AMS 锁
        synchronized (mService) {
			// 通过app端的binder对象获取system server端对应的进程实例
            final ProcessRecord r = mService.getRecordForAppLOSP(caller);
			// app端发布时,传入的caller对应的进程实例得存在
            if (r == null) {
                throw new SecurityException("Unable to find app for caller " + caller
                        + " (pid=" + Binder.getCallingPid()
                        + ") when publishing content providers");
            }
			// 清除calling 标识
            final long origId = Binder.clearCallingIdentity();
            boolean providersPublished = false;
			// 遍历providers
            for (int i = 0, size = providers.size(); i < size; i++) {
                ContentProviderHolder src = providers.get(i);
				// holder未被初始化赋值,跳出当前循环
                if (src == null || src.info == null || src.provider == null) {
                    continue;
                }
				// 从进程的ProcessProviderRecord中通过provider的name获取ContentProviderRecord实例
				// ProcessProviderRecord中mPubProviders列表在CPH的generateApplicationProvidersLocked中初始化
                ContentProviderRecord dst = r.mProviders.getProvider(src.info.name);
                if (dst == null) {
                    continue;
                }
                if (DEBUG_MU) {
                    Slog.v(TAG_MU, "ContentProviderRecord uid = " + dst.uid);
                }
                providersPublished = true;
				// 按照Component和name添加provider实例到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);
                }
				// 查看当前provider是否是需要等待拉起的provider,是的话从mLaunchingProviders中移除
                boolean wasInLaunchingProviders = false;
                for (int j = 0, numLaunching = mLaunchingProviders.size(); j < numLaunching; j++) {
                    if (mLaunchingProviders.get(j) == dst) {
                        mLaunchingProviders.remove(j);
                        wasInLaunchingProviders = true;
                        j--;
                        numLaunching--;
                    }
                }
				// 移除content provider的超时消息
                if (wasInLaunchingProviders) {
                    mService.mHandler.removeMessages(
                            ActivityManagerService.WAIT_FOR_CONTENT_PROVIDER_TIMEOUT_MSG, dst);
                    mService.mHandler.removeMessages(
                            ActivityManagerService.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, mService.mProcessStats);
                synchronized (dst) {
                    dst.provider = src.provider;
                    dst.setProcess(r);
					// 唤醒,告知app端可以获取holder了
                    dst.notifyAll();
                    dst.onProviderPublishStatusLocked(true);
                }
                dst.mRestartCount = 0;
            }

            // update the app's oom adj value and each provider's usage stats
            if (providersPublished) {
                mService.updateOomAdjLocked(r, OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER);
                for (int i = 0, size = providers.size(); i < size; i++) {
                    ContentProviderHolder src = providers.get(i);
                    if (src == null || src.info == null || src.provider == null) {
                        continue;
                    }
                    maybeUpdateProviderUsageStatsLocked(r,
                            src.info.packageName, src.info.authority);
                }
            }

            Binder.restoreCallingIdentity(origId);
        }
    }

ContentProviderRecord#onProviderPublishStatusLocked

   /**
     * Notify all clients that the provider has been published and ready to use,
     * or timed out.
     *
     * @param status true: successfully published; false: timed out
     */
    void onProviderPublishStatusLocked(boolean status) {
        final int numOfConns = connections.size();
        for (int i = 0; i < numOfConns; i++) {
            final ContentProviderConnection conn = connections.get(i);
            if (conn.waiting && conn.client != null) {
                final ProcessRecord client = conn.client;
                if (!status) {
                    if (launchingApp == null) {
                        Slog.w(TAG_AM, "Unable to launch app "
                                + appInfo.packageName + "/"
                                + appInfo.uid + " for provider "
                                + info.authority + ": launching app became null");
                        EventLogTags.writeAmProviderLostProcess(
                                UserHandle.getUserId(appInfo.uid),
                                appInfo.packageName,
                                appInfo.uid, info.authority);
                    } else {
                        Slog.wtf(TAG_AM, "Timeout waiting for provider "
                                + appInfo.packageName + "/"
                                + appInfo.uid + " for provider "
                                + info.authority
                                + " caller=" + client);
                    }
                }
                final IApplicationThread thread = client.getThread();
                if (thread != null) {
                    try {
						// 告知app端发布成功,可以去获取holder
                        thread.notifyContentProviderPublishStatus(
                                newHolder(status ? conn : null, false),
                                info.authority, conn.mExpectedUserId, status);
                    } catch (RemoteException e) {
                    }
                }
            }
            conn.waiting = false;
        }
    }

A进程成功获取到IContentProvider

A进程收到binder回调,并notify 告知acquireProvider不再wait
ContentProvider详解_第7张图片

ApplicationThread#notifyContentProviderPublishStatus

        @Override
        public void notifyContentProviderPublishStatus(@NonNull ContentProviderHolder holder,
                @NonNull String authorities, int userId, boolean published) {
            final String auths[] = authorities.split(";");
            for (String auth: auths) {
                final ProviderKey key = getGetProviderKey(auth, userId);
                synchronized (key.mLock) {
                    key.mHolder = holder;
                    key.mLock.notifyAll();
                }
            }
        }

引用计数添加和减少

A获取到B进程的IContentProvider后会创建一个连接,具体表现为ContentProviderConnection。

    @GuardedBy("mLock")
    private int mStableCount;
    @GuardedBy("mLock")
    private int mUnstableCount;

引用计数增加

A进程app端流程同上面查询流程,不做赘述。
system server端如下:
ContentProvider详解_第8张图片

ContentProviderHelper#incProviderCountLocked

 @GuardedBy("mService")
    private ContentProviderConnection incProviderCountLocked(ProcessRecord r,
            final ContentProviderRecord cpr, IBinder externalProcessToken, int callingUid,
            String callingPackage, String callingTag, boolean stable, boolean updateLru,
            long startTime, ProcessList processList, @UserIdInt int expectedUserId) {
        if (r == null) {
            cpr.addExternalProcessHandleLocked(externalProcessToken, callingUid, callingTag);
            return null;
        }

		// 获取caller进程的ProcessProviderRecord
        final ProcessProviderRecord pr = r.mProviders;
        for (int i = 0, size = pr.numberOfProviderConnections(); i < size; i++) {
            ContentProviderConnection conn = pr.getProviderConnectionAt(i);
			// 如果当前要获取的provider在该caller进程中已有相关连接,则计数+1
            if (conn.provider == cpr) {
                conn.incrementCount(stable);
				// 获取链接直接返回
                return conn;
            }
        }

        //否则 新建一个content provider的连接
        ContentProviderConnection conn = new ContentProviderConnection(cpr, r, callingPackage,
                expectedUserId);
        conn.startAssociationIfNeeded();
		// 初始化count为1
        conn.initializeCount(stable);
		// 将当前连接添加到content provider的连接列表里
        cpr.connections.add(conn);
		// 将当前链接保存到进程provider列表里
        pr.addProviderConnection(conn);
        mService.startAssociationLocked(r.uid, r.processName, r.mState.getCurProcState(),
                cpr.uid, cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName);
        if (updateLru && cpr.proc != null
                && r.mState.getSetAdj() <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
            // caller的adj <= 250,更新持有provider进程的adj
            checkTime(startTime, "getContentProviderImpl: before updateLruProcess");
            processList.updateLruProcessLocked(cpr.proc, false, null);
            checkTime(startTime, "getContentProviderImpl: after updateLruProcess");
        }
        return conn;
    }

引用计数减少

app端
ContentProvider详解_第9张图片

ActivityThread#releaseProvider

 @UnsupportedAppUsage
    public final boolean releaseProvider(IContentProvider provider, boolean stable) {
        if (provider == null) {
            return false;
        }

        IBinder jBinder = provider.asBinder();
        synchronized (mProviderMap) {
			// 其他进程的provider
            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
			// 自己进程的provider,没有引用计数,无需release
            if (prc == null) {
                // The provider has no ref count, no release is needed.
                return false;
            }

            boolean lastRef = false;
			// call 方式调用
            if (stable) {
                if (prc.stableCount == 0) {
                    return false;
                }
                prc.stableCount -= 1;
                // 是否是其他进程provider
                if (prc.stableCount == 0) {
                    // stable 和unstable 引用计数均为0,则此次是最后一个引用
                    lastRef = prc.unstableCount == 0;
                    try {
                        // 告知ams
                        ActivityManager.getService().refContentProvider(
                                prc.holder.connection, -1, lastRef ? 1 : 0);
                    } catch (RemoteException e) {
                        //do nothing content provider object is dead any way
                    }
                }
            } else {
                if (prc.unstableCount == 0) {
                    return false;
                }
                prc.unstableCount -= 1;
                if (prc.unstableCount == 0) {
                    // 当前是最后一个引用
                    lastRef = prc.stableCount == 0;
                    if (!lastRef) {
                        try {
                            // 还有stable引用的话告知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) {
                    // 延时1s后从本地移除
                    prc.removePending = true;
                    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);
                }
            }
            return true;
        }
    }

ActivityThread#completeRemoveProvider

    final void completeRemoveProvider(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.
                if (DEBUG_PROVIDER) Slog.v(TAG, "completeRemoveProvider: lost the race, "
                        + "provider still in use");
                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);
            }

            for (int i=mProviderMap.size()-1; i>=0; i--) {
                ProviderClientRecord pr = mProviderMap.valueAt(i);
                IBinder myBinder = pr.mProvider.asBinder();
				// 从mProviderMap中移除,这样下次acquire时,acquireExistingProvider就返回null
                if (myBinder == jBinder) {
                    mProviderMap.removeAt(i);
                }
            }
        }

        try {
            if (DEBUG_PROVIDER) {
                Slog.v(TAG, "removeProvider: Invoking ActivityManagerService."
                        + "removeContentProvider(" + prc.holder.info.name + ")");
            }
            ActivityManager.getService().removeContentProvider(
                    prc.holder.connection, false);
        } catch (RemoteException e) {
            //do nothing content provider object is dead any way
        }
    }
```这样下次acquire时,acquireExistingProvider就返回null
                if (myBinder == jBinder) {
                    mProviderMap.removeAt(i);
                }
            }
        }

        try {
            if (DEBUG_PROVIDER) {
                Slog.v(TAG, "removeProvider: Invoking ActivityManagerService."
                        + "removeContentProvider(" + prc.holder.info.name + ")");
            }
            ActivityManager.getService().removeContentProvider(
                    prc.holder.connection, false);
        } catch (RemoteException e) {
            //do nothing content provider object is dead any way
        }
    }

system server端
ContentProvider详解_第10张图片

ContentProviderHelper#removeContentProvider

  /**
     * Drop a content provider from a ProcessRecord's bookkeeping
     */
    void removeContentProvider(IBinder connection, boolean stable) {
        mService.enforceNotIsolatedCaller("removeContentProvider");
        final long ident = Binder.clearCallingIdentity();
        try {
            ContentProviderConnection conn;
            try {
                conn = (ContentProviderConnection) connection;
            } catch (ClassCastException e) {
                String msg = "removeContentProvider: " + connection
                        + " not a ContentProviderConnection";
                Slog.w(TAG, msg);
                throw new IllegalArgumentException(msg);
            }
            if (conn == null) {
                throw new NullPointerException("connection is null");
            }
            ActivityManagerService.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                    "removeContentProvider: ",
                    (conn.provider != null && conn.provider.info != null如果在acquireExistingProvider发现对端进程binder died了,则也会执行handleUnstableProviderDiedLocked


                    ? conn.provider.info.authority : ""));
            try {
                synchronized (mService) {
                    decProviderCountLocked(conn, null, null, stable, true, true);
                }
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }

ContentProviderHelper#decProviderCountLocked

  @GuardedBy("mService")
    private boolean decProviderCountLocked(ContentProviderConnection conn,
            ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable,
            boolean enforceDelay, boolean updateOomAdj) {
        if (conn == null) {
            cpr.removeExternalProcessHandleLocked(externalProcessToken);
            return false;
        }

        if (conn.totalRefCount() > 1) {
            conn.decrementCount(stable);
            return false;
        }
        if (enforceDelay) {
            // delay the removal of the provider for 5 seconds - this optimizes for those cases
            // where providers are released and then quickly re-acquired, causing lots of churn.
            BackgroundThread.getHandler().postDelayed(() -> {
                handleProviderRemoval(conn, stable, updateOomAdj);
            }, 5 * 1000);
        } else {
            handleProviderRemoval(conn, stable, updateOomAdj);
        }
        return true;
    }

ContentProviderHelper#handleProviderRemoval

 private void handleProviderRemoval(ContentProviderConnection conn, boolean stable,
            boolean updateOomAdj) {
        synchronized (mService) {
            // if the proc was already killed or this is not the last reference, simply exit.
            if (conn == null || conn.provider == null || conn.decrementCount(stable) != 0) {
                return;
            }

            final ContentProviderRecord cpr = conn.provider;
            conn.stopAssociation();
            cpr.connections.remove(conn);
            conn.client.mProviders.removeProviderConnection(conn);
            if (conn.client.mState.getSetProcState()
                    < ActivityManager.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.mProviders.setLastProviderTime(SystemClock.uptimeMillis());
                }
            }
            mService.stopAssociationLocked(conn.client.uid, conn.client.processName, cpr.uid,
                    cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName);
            if (updateOomAdj) {
                mService.updateOomAdjLocked(conn.provider.proc,
                        OomAdjuster.OOM_ADJ_REASON_REMOVE_PROVIDER);
            }
        }
    }

调整引用计数
ContentProvider详解_第11张图片

ContentProviderHelper#refContentProvider

 boolean refContentProvider(IBinder connection, int stable, int unstable) {
        ContentProviderConnection conn;
        try {
            conn = (ContentProviderConnection) connection;
        } catch (ClassCastException e) {
            String msg = "refContentProvider: " + connection + " not a ContentProviderConnection";
            Slog.w(TAG, msg);
            throw new IllegalArgumentException(msg);
        }
        if (conn == null) {
            throw new NullPointerException("connection is null");
        }

        ActivityManagerService.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "refContentProvider: ",
                (conn.provider != null && conn.provider.info != null
                ? conn.provider.info.authority : ""));
        try {
            conn.adjustCounts(stable, unstable);
            return !conn.dead;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }

ContentProviderHelper#adjustCounts

 /**
     * Adjusts the reference counts up or down (the inputs may be positive,
     * zero, or negative.  This method does not return a total count because
     * a return is not needed for the current use case.
    */
    public void adjustCounts(int stableIncrement, int unstableIncrement) {
        synchronized (mLock) {
            if (stableIncrement > 0) {
                mNumStableIncs += stableIncrement;
            }
            final int stable = mStableCount + stableIncrement;
            if (stable < 0) {
                throw new IllegalStateException("stableCount < 0: " + stable);
            }
            if (unstableIncrement > 0) {
                mNumUnstableIncs += unstableIncrement;
            }
            final int unstable = mUnstableCount + unstableIncrement;
            if (unstable < 0) {
                throw new IllegalStateException("unstableCount < 0: " + unstable);
            }
            if ((stable + unstable) <= 0) {
                throw new IllegalStateException("ref counts can't go to zero here: stable="
                                                + stable + " unstable=" + unstable);
            }
            mStableCount = stable;
            mUnstableCount = unstable;
        }
    }

进程死亡移除

在目标CP进程死后,AMS会去调用removeDyingProviderLocked,其中会根据ContentProviderConnection的stableCount和unstableCount处理引用该CP的进程。如果stableCount不为0,则杀死该客户进程。如果stableCount为0,而unstableCount不为0,则通过ApplicationThread#unstableProviderDied通知客户进程,并从ContentProviderRecord中移除该ContentProviderConnection。

如果在acquireExistingProvider发现对端进程binder died了,则也会执行handleUnstableProviderDiedLocked

ActivityThread#handleUnstableProviderDiedLocked

    final void handleUnstableProviderDiedLocked(IBinder provider, boolean fromClient) {
        ProviderRefCount prc = mProviderRefCountMap.get(provider);
        if (prc != null) {
            if (DEBUG_PROVIDER) Slog.v(TAG, "Cleaning up dead provider "
                    + provider + " " + prc.holder.info.name);
			// 引用计数移除
            mProviderRefCountMap.remove(provider);
            for (int i=mProviderMap.size()-1; i>=0; i--) {
                ProviderClientRecord pr = mProviderMap.valueAt(i);
                if (pr != null && pr.mProvider.asBinder() == provider) {
                    Slog.i(TAG, "Removing dead content provider:" + pr.mProvider.toString());
					// 从map中移除
                    mProviderMap.removeAt(i);
                }
            }

            if (fromClient) {
                // We found out about this due to execution in our client
                // code.  Tell the activity manager about it now, to ensure
                // that the next time we go to do anything with the provider
                // it knows it is dead (so we don't race with its death
                // notification).
                try {
                    ActivityManager.getService().unstableProviderDied(
                            prc.holder.connection);
                } catch (RemoteException e) {
                    //do nothing content provider object is dead any way
                }
            }
        }
    }

你可能感兴趣的:(AMS,android)