作为四大组件之一的ContentProvider,信任大多数开发者往常都很少用到。就像咱们这种toB的公司,面向Android整机开发,多个应之间的交互,也是经过播送。经过对ContentProvider的学习,整体的逻辑和播送是相似的。但播送更多理解成为是一种观察者模式,而ContentProvider是一种数据库结构类型。但它们共同的任务之一,便是经过IPC对外供给数据。

ContentProvider的装置

运用进程的创立进程中,最终一步经过反射创立运用程序的主线程ActivityThread,调用其main函数中,并经过ActivityThreadattach函数,attach函数又调用了AMSattachApplicationLocked函数。attachApplicationLocked函数会涉及到运用程序ContentProviderinstall逻辑。

Android的CotentProvider的启动流程

AMS.attachApplicationLocked

AMS的attachApplicationLocked函数中,咱们只关怀和ContentProvider相关的部分,如下所示,调用了generateApplicationProvidersLocked函数生成了List<ProviderInfo>类型的providersProviderInfo目标对应运用程序的一个ContentProvider,也便是ContentProviderFramework层的描绘。并将providers转换成ProviderInfoList目标传递给thread.bindApplication函数。

 private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
		...
		//经过PMS过滤和匹配当时运用的ProviderInfo列表
       	boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
        List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;
		...
        //封装成ProviderInfoList
        final ProviderInfoList providerList = ProviderInfoList.fromList(providers);
        thread.bindApplication(processName, appInfo, providerList,
                instr2.mClass,
                profilerInfo, instr2.mArguments,
                instr2.mWatcher,
                instr2.mUiAutomationConnection, testMode,
                mBinderTransactionTrackingEnabled, enableTrackAllocation,
                isRestrictedBackupMode || !normalMode, app.isPersistent(),
                new Configuration(app.getWindowProcessController().getConfiguration()),
                app.compat, getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked(),
                buildSerial, autofillOptions, contentCaptureOptions,
                app.mDisabledCompatChanges);
            ...
        return true;
    }

ProviderInfo列表的生成

这儿咱们先看下ProviderInfo列表的生成,generateApplicationProvidersLocked函数。

剖析一:调用了PMS查询当时运用的一切ProviderInfo,并扫除其他进程调起本运用程序独立的contentProvider。其中ppGlobals.getPackageManager()是经过ActivityThread调用了PMS的AIDL引证。

剖析二:将ProviderInfo封装成ContentProviderRecord,缓存在ProviderMap类型的mProviderMap中。

    private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
        List<ProviderInfo> providers = null;
        try {
        	//剖析一
            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();
            app.pubProviders.ensureCapacity(N + app.pubProviders.size());
            for (int i=0; i<N; i++) {
				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) {
                    providers.remove(i);
                    N--;
                    i--;
                    continue;
                }
                ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
                ContentProviderRecord cpr = mProviderMap.getProviderByClass(comp, userId);
				//剖析二
				//假如mProviderMap中没有缓存,则封装成ContentProviderRecor缓存到mProviderMap
				if (cpr == null) {
                    cpr = new ContentProviderRecord(this, cpi, app.info, comp, singleton);
                    mProviderMap.putProviderByClass(comp, cpr);
                }
                app.pubProviders.put(cpi.name, cpr);
                if (!cpi.multiprocess || !"android".equals(cpi.packageName)) {
                    app.addPackage(cpi.applicationInfo.packageName,
                            cpi.applicationInfo.longVersionCode, mProcessStats);
                }
                notifyPackageUse(cpi.applicationInfo.packageName,
                                 PackageManager.NOTIFY_PACKAGE_USE_CONTENT_PROVIDER);
            }
        }
        return providers;
    }

经过AIDL调用了PackageMangerServicequeryContentProviders函数。

剖析一:

经过ComponentResolver类型的mComponentResolverqueryProviders获取一切配的ProviderInfo,查看合法性。ComponentResolver是四大组件解析器,从运用程序的AndroidManifest中解析四大组件的信息。

    public @NonNull ParceledListSlice<ProviderInfo> queryContentProviders(String processName,
            int uid, int flags, String metaDataKey) {
        ...
        ArrayList<ProviderInfo> finalList = null;
        //剖析一
        final List<ProviderInfo> matchList =
                mComponentResolver.queryProviders(processName, metaDataKey, uid, flags, userId);
        final int listSize = (matchList == null ? 0 : matchList.size());
        synchronized (mLock) { 
            for (int i = 0; i < listSize; i++) {
                final ProviderInfo providerInfo = matchList.get(i);
                if (!mSettings.isEnabledAndMatchLPr(providerInfo, flags, userId)) {
                    continue;
                }
                final PackageSetting ps = mSettings.mPackages.get(providerInfo.packageName);
                final ComponentName component =
                        new ComponentName(providerInfo.packageName, providerInfo.name);
                if (shouldFilterApplicationLocked(
                        ps, callingUid, component, TYPE_PROVIDER, userId)) {
                    continue;
                }
                if (finalList == null) {
                    finalList = new ArrayList<>(listSize - i);
                }
                finalList.add(providerInfo);
            }
        }
        if (finalList != null) {
            finalList.sort(sProviderInitOrderSorter);
            return new ParceledListSlice<>(finalList);
        }
        return ParceledListSlice.emptyList();
    }

ComponentResolver类型的mComponentResolverqueryProviders函数查询属于当时进程的一切ContentProvider的解析类ParsedProvider,然后依据ParsedProvider生成对应的ProviderInfo

剖析一:ProviderIntentResolver类型的mProviders用于描绘解析一切运用的一切ContentProvider信息。其内部持有的ArrayMap<ComponentName, ParsedProvider>类型的mProviders,则是持有的一切ContentProvider,经过组件名CompnoneName进行查找对应ContentProvider解析类ParsedProvider

    List<ProviderInfo> queryProviders(String processName, String metaDataKey, int uid, int flags,
            int userId) {
        if (!sUserManager.exists(userId)) {
            return null;
        }
        List<ProviderInfo> providerList = null;
        CachedApplicationInfoGenerator appInfoGenerator = null;
        synchronized (mLock) {
        	//剖析一:ProviderIntentResolver
            for (int i = mProviders.mProviders.size() - 1; i >= 0; --i) {
            	//一个Provider对应ParsedProvider解析
                final ParsedProvider p = mProviders.mProviders.valueAt(i);
                ...
                //对p的合法性进行查看
                ...
              	//依据ParsedProvider解析器生成当时运用的ProviderInfo
                final ProviderInfo info = PackageInfoUtils.generateProviderInfo(
                        pkg, p, flags, state, appInfo, userId, ps);
                if (info == null) {
                    continue;
                }
                if (providerList == null) {
                    providerList = new ArrayList<>(i + 1);
                }
                //找到添加
                providerList.add(info);
            }
        }
        return providerList;
    }

至于界说在AndroidManifestProvider什么时分被添加到ProviderIntentResolver类型的mProviders。就得另外剖析了。

ApplicationThread.bindApplication

attachApplicationLocked的后续逻辑调用了thread.bindApplication函数,并将providerList作为参数传递进去。

public final void bindApplication(String processName, ApplicationInfo appInfo,
        ProviderInfoList providerList, ComponentName instrumentationName,
        ProfilerInfo profilerInfo, Bundle instrumentationArgs,
        IInstrumentationWatcher instrumentationWatcher,
        IUiAutomationConnection instrumentationUiConnection, int debugMode,
        boolean enableBinderTracking, boolean trackAllocation,
        boolean isRestrictedBackupMode, boolean persistent, Configuration config,
        CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
        String buildSerial, AutofillOptions autofillOptions,
        ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges) {
	...
    AppBindData data = new AppBindData();
 	...
    data.providers = providerList.getList();
 	...
    sendMessage(H.BIND_APPLICATION, data);
}

从这儿也能够看出为什么要封装成providerList目标,以整个目标序列化Parcel便利传递,而不是以ArrayList的形式。运用程序段ApplicationThread接纳到来自AMS.bindApplication函数调用,将provider列表获取并设置给AppBindData类型的data目标,经过H发送音讯BIND_APPLICATION切换到运用程序主线程。

而在H的handleMessage函数中BIND_APPLICATION分支又调用了:

case BIND_APPLICATION:
    AppBindData data = (AppBindData)msg.obj;
    handleBindApplication(data);
    break;

handleBindApplication函数,这些函数处理的逻辑都很长,咱们只摘取和ContentProvider有关的内容。

if (!data.restrictedBackupMode) {
    if (!ArrayUtils.isEmpty(data.providers)) {
        installContentProviders(app, data.providers);
    }
}

installContentProviders

调用了installContentProviders函数,传递了Application类型的app和一切的ProviderInfoinstallContentProviders函数遍历一切的ProviderInfo,经过installProvider函数,将一个个ProviderInfo封装成ContentProviderHolder目标,并添加到results集合中。将results传递给AMS的publishContentProviders函数。

private void installContentProviders(
        Context context, List<ProviderInfo> providers) {
    final ArrayList<ContentProviderHolder> results = new ArrayList<>();
    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);
        }
    }
    try {
    	//剖析二
        ActivityManager.getService().publishContentProviders(
            getApplicationThread(), results);
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
}

installProvider函数。

剖析一:经过LoadedApk获取ProviderInfo对应的ContentProvider目标localProvider,这儿是经过反射创立ProviderInfo对应的ContentProvider实例,也便是咱们界说ContentProvider的子类。并经过localProvider获取IContentProvider类型的provider,这儿实践回来的是Transport类型的mTransport目标。Transport继承自ContentProviderNative,也便是IContentProvider的本地署理的完成。

剖析二:调用了localProviderattachInfo函数。该函数会调用ContentProvider本身的onCreate函数。这时分ContentProvider能够理解为已经创立结束。

剖析三:将localProviderproviderholderauths封装成ProviderClientRecord,缓存到ArrayMap<ProviderKey, ProviderClientRecord>类型的mProviderMap中。

    private ContentProviderHolder installProvider(Context context,
            ContentProviderHolder holder, ProviderInfo info,
            boolean noisy, boolean noReleaseNeeded, boolean stable) {
        ContentProvider localProvider = null;
        IContentProvider provider;
        if (holder == null || holder.provider == null) {
            if (DEBUG_PROVIDER || noisy) {
                Slog.d(TAG, "Loading provider " + info.authority + ": "
                        + info.name);
            }
            Context c = null;
            ...
            //获取info的地点运用的正确context
            ...
            try {
                final java.lang.ClassLoader cl = c.getClassLoader();
                LoadedApk packageInfo = peekPackageInfo(ai.packageName, true);
                if (packageInfo == null) {
                    // System startup case.
                    packageInfo = getSystemContext().mPackageInfo;
                }
                //剖析一:经过反射创立ContentProvider
                localProvider = packageInfo.getAppFactory()
                        .instantiateProvider(cl, info.name);
               	//ContentProvider本地署理的完成
                provider = localProvider.getIContentProvider();
                ...
                剖析二:会调用onCreate函数
                localProvider.attachInfo(c, info);
            } catch (java.lang.Exception e) {
              	...
                return null;
            }
        } else {
            provider = holder.provider;
        }
        ContentProviderHolder retHolder;
        synchronized (mProviderMap) {
            IBinder jBinder = provider.asBinder();
            //封装localProvider并缓存到mLocalProvidersByName中
            if (localProvider != null) {
                ComponentName cname = new ComponentName(info.packageName, info.name);
                ProviderClientRecord pr = mLocalProvidersByName.get(cname);
                if (pr != null) {
                    provider = pr.mProvider;
                } else {
                    holder = new ContentProviderHolder(info);
                    holder.provider = provider;
                    holder.noReleaseNeeded = true;
                    //剖析三:将三参数以及权限auths封装成ProviderClientRecord,缓存到mProviderMap中
                    pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
                    //缓存
                    mLocalProviders.put(jBinder, pr);
                    mLocalProvidersByName.put(cname, pr);
                }
                retHolder = pr.mHolder;
            } else {
                ...
                //经过mProviderRefCountMap获取
                ...
            }
        }
        return retHolder;
    }

那么整个installProvider函数,便是创立ContentProvider实例,并将相关信息缓存到mProviderMapmLocalProvidersmLocalProvidersByName集合。后续运用直接经过集合来查询。

在运用进程创立好一切ContentProvider实例后,调用AMS的publishContentProviders函数。

AMS.publishContentProviders

首要效果是将传递过来的providers依据auth缓存到mProviderMap中。

public final void publishContentProviders(IApplicationThread caller,
        List<ContentProviderHolder> providers) {
	...
    synchronized (this) {
        final ProcessRecord r = getRecordForAppLocked(caller);
		...
        final int N = providers.size();
        for (int i = 0; i < N; i++) {
            ContentProviderHolder src = providers.get(i);
            if (src == null || src.info == null || src.provider == null) {
                continue;
            }
            ContentProviderRecord dst = r.pubProviders.get(src.info.name);
            if (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);
                }
                ...
                r.addPackage(dst.info.applicationInfo.packageName,
                        dst.info.applicationInfo.longVersionCode, mProcessStats);
                synchronized (dst) {
                    dst.provider = src.provider;
                    dst.setProcess(r);
                    dst.notifyAll();
                }
                dst.mRestartCount = 0;
                updateOomAdjLocked(r, true, OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER);
                maybeUpdateProviderUsageStatsLocked(r, src.info.packageName,
                        src.info.authority);
            }
        }
        Binder.restoreCallingIdentity(origId);
    }
}

也便是说,ContentProvider的装置进程,是在创立运用进程,调用ActivityThreadmain函数开端,在attach函数后经过AMS去PMS中取得运用界说在AndroidManifestContentProvider的描绘信息ProviderInfo,最终切回到运用程序创立ContentProvider实例,将相关信息别离缓存到运用程序和AMS中mProviderMap,便利后续运用,防止每次都要创立ContentProvider

ContentProvider的运用

咱们经常经过下面的方法去获取ContentResover目标,并调用其insertquerydeleteupdate函数。

val uri=Uri.parse("content://com.xxm.content.auth.share.data")
contentResolver.query(uri, arrayOf("id","name"),null,null )

而这儿的getContentResolver函数其实是ContextWrapper的方法。这样ApplciationServiceActivity都能够经过这种方法调用。

public ContentResolver getContentResolver() {
    return mBase.getContentResolver();
}

Context类型的mBase,实践类型是ContextImpl

public ContentResolver getContentResolver() {
    return mContentResolver;
}

ApplicationContentResolver类型的mContentResolverContextImpl创立的时分被实例化。

Cursor的获取

query函数来自ApplicationContentResolver父类ContentResolverquery函数一共有三个重载函数。最终调用如下函数。

query函数会获取两个IContentProvider类型实例,一个称为unstableProvider,一个称为stableProvider。先经过不安稳去获取Cursor类型的qCursor,可能因为地点进程已死从而抛出反常。在这种情况下,再去获取stableProvider,然后获取qCursorIContentProviderAMSContentProvider在本地的跨进程引证。

最终将查询到的ProviderCursor实例封装成CursorWrapperInner目标,并回来CursorWrapperInner实例。

public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,
        @Nullable String[] projection, @Nullable Bundle queryArgs,
        @Nullable CancellationSignal cancellationSignal) {
    ...
    //剖析一:不安稳的Provider
    IContentProvider unstableProvider = acquireUnstableProvider(uri);
    if (unstableProvider == null) {
        return null;
    }
    IContentProvider stableProvider = null;
    Cursor qCursor = null;
    try {
        ...
        try {
        	//调用query函数
            qCursor = unstableProvider.query(mPackageName, mAttributionTag, uri, projection,
                    queryArgs, remoteCancellationSignal);
        } catch (DeadObjectException e) {
            unstableProviderDied(unstableProvider);
            //产生反常,调用安稳的provider
            stableProvider = acquireProvider(uri);
            if (stableProvider == null) {
                return null;
            }
            //查询
            qCursor = stableProvider.query(mPackageName, mAttributionTag, uri, projection,
                    queryArgs, remoteCancellationSignal);
        }
        ...
        qCursor.getCount();
        ...
        final IContentProvider provider = (stableProvider != null) ? stableProvider
                : acquireProvider(uri);
        //包装cursor和provider
        final CursorWrapperInner wrapper = new CursorWrapperInner(qCursor, provider);
        stableProvider = null;
        qCursor = null;
        return wrapper;
    } catch (RemoteException e) {
        ...
    } finally {
        ...
    }
}

贴下时序图:

Android的CotentProvider的启动流程

1、acquireUnstableProvider

query函数在剖析一,调用了acquireUnstableProvider函数,其在ContentResolver是一个笼统方法,在ApplicationCotnentResolver完成。与acquireProvider的区别是最终一个参数为false.

protected IContentProvider acquireUnstableProvider(Context c, String auth) {
    return mMainThread.acquireProvider(c,
            ContentProvider.getAuthorityWithoutUserId(auth),
            resolveUserIdFromAuthority(auth), false);
}

2、ActivityThread.acquireProvider

acquireProvider函数先在自己的ContentProvider列表中查询有没有对应ContentProivder实例,有的话,意味本次交互式在同个运用内,非跨进程通讯。否则 需要经过跨进程通讯到AMS中的mProviderMap进行查询。

public final IContentProvider acquireProvider(
        Context c, String auth, int userId, boolean stable) {
    //剖析一
    //从缓存中获取,前面讲ContentProvider注册,每个运用都会加载自己的ContentProvider到mProviderMap中。
    final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
    if (provider != null) {
        return provider;
    }
    ContentProviderHolder holder = null;
    try {
        synchronized (getGetProviderLock(auth, userId)) {
        	//剖析二:
        	//在ContentProvider注册中,ContentProvider会以ContentProviderHolder
        	//实例缓存在AMS的mProviderMap中
            holder = ActivityManager.getService().getContentProvider(
                    getApplicationThread(), c.getOpPackageName(), auth, userId, stable);
        }
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
    if (holder == null) {
        return null;
    }
    //为当时进程装置ContentProvider,也是为什么运用装置ContentProvider的进程中,查看合法性时
    //需要扫除非运用实例化的的ContentProvider
    holder = installProvider(c, holder, holder.info,
            true /*noisy*/, holder.noReleaseNeeded, stable);
    return holder.provider;
}

剖析一的代码acquireExistingProvider函数比较简单,从运用程序的ActivityThreadmProviderMap中查询,假如有,且进程还存活,则增加引证计数,并回来provider;假如有,但进程已死,从缓存中进行移除。假如有没有,则回来null,需要在剖析二,同个AMS查询。

3、AMS.getContentProvider

内部又调用了getContentProviderImpl函数。该函数涵盖了ContentProvider获取的整个流程。首要分为两个大逻辑:

剖析一:从mProviderMap获取,是运用程序发动后,装置好一切ContentProvider,然后告诉AMS进行缓存。假如在mProviderMap查询不到,可能该ContentProvider地点的进程没有发动过。

剖析二:providerRunningtrue,需要对其合法性进行查看,判别是否符合当时所需的ContentProvider

剖析三:providerRunningfalse, 经过发动ContentProvider地点的进程,然后等待运用程序的告诉。参考第一节最终AMS.publishContentProvider函数。

  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;
        synchronized(this) {
           	...
            //剖析一:先从mProviderMap获取缓存,这一步首要运用程序本身发动装置的ContentProvider
            //推到AMS记载的。或者本函数加载的ContentProvider
            cpr = mProviderMap.getProviderByName(name, userId);
            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;
                    }
                }
            }
            ProcessRecord dyingProc = null;
            if (cpr != null && cpr.proc != null) {
            	//判别进程是否发动
                providerRunning = !cpr.proc.killed;
                //为了清空已死进程的相关信息
                if (cpr.proc.killed && cpr.proc.killedByAm) 
                    dyingProc = cpr.proc;
                }
            }
			//大分支,provider处于运转状况,即地点进程活着
            if (providerRunning) {
                cpi = cpr.info;
                String msg;
                if (r != null && cpr.canRunHere(r)) {
                    ...
                    holder.provider = null;
                    return holder;
                }
				...
				//查看权限
                ...
                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) {
                        mProcessList.updateLruProcessLocked(cpr.proc, false, null);
                    }
                }
				...
            }
			//大分支,provider处于未运转状况,即地点进程未发动
            if (!providerRunning) {
				...                
                //经过PMS去解析
                cpi = AppGlobals.getPackageManager().
                    resolveContentProvider(name,
                        STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId);
                ...
                if (cpi == null) {
                    return null;
                }
                ...
                //对一些状况的查看
                ...
                ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
                cpr = mProviderMap.getProviderByClass(comp, userId);
                boolean firstClass = cpr == null;
                if (firstClass) {
                   	...
                    ApplicationInfo ai =
                        AppGlobals.getPackageManager().
                            getApplicationInfo(
                                    cpi.applicationInfo.packageName,
                                    STOCK_PM_FLAGS, userId);
                    if (ai == null) {
                        return null;
                    }
                    ai = getAppInfoForUser(ai, userId);
                    cpr = new ContentProviderRecord(this, cpi, ai, comp, singleton);
                   ...
                } else if (dyingProc == cpr.proc && dyingProc != null) {
                    cpr = new ContentProviderRecord(cpr);
                    firstClass = true;
                }
                if (r != null && cpr.canRunHere(r)) {
                    return cpr.newHolder(null);
                }
                //判别正在发动的Provider是否有当时ContentProvider
                final int N = mLaunchingProviders.size();
                int i;
                for (i = 0; i < N; i++) {
                    if (mLaunchingProviders.get(i) == cpr) {
                        break;
                    }
                }
				//未发动
                if (i >= N) {
                    final long origId = Binder.clearCallingIdentity();
                    try {
                      	...
                        ProcessRecord proc = getProcessRecordLocked(
                                cpi.processName, cpr.appInfo.uid, false);
                        if (proc != null && proc.thread != null && !proc.killed) {
                          	//进程已发动,未发动ContentProvider
                            if (!proc.pubProviders.containsKey(cpi.name)) {
                                proc.pubProviders.put(cpi.name, cpr);
                                try {
                                    proc.thread.scheduleInstallProvider(cpi);
                                } catch (RemoteException e) {
                                }
                            }
                        } else {
                            //发动进程,在bindApplication会装置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);
                        }
                        cpr.launchingApp = proc;
                        mLaunchingProviders.add(cpr);
                    } finally {
                        Binder.restoreCallingIdentity(origId);
                    }
                }
				//缓存
                if (firstClass) {
                    mProviderMap.putProviderByClass(comp, cpr);
                }
                mProviderMap.putProviderByName(name, cpr);
                //引证,创立衔接
                conn = incProviderCountLocked(r, cpr, token, callingUid, callingPackage, callingTag,
                        stable);
                if (conn != null) {
                    conn.waiting = true;
                }
            }
        }
        // Wait for the provider to be published...
 		...
 		//等待进程发动后装置一切ContentProvider,调用AMS.pushContentProviders来告诉
		...
        return cpr.newHolder(conn);
    }

AMS.incProviderCountLocked

经过incProviderCountLocked函数来创立ContentProviderConnection类型的conn,以便创立ContentProviderHolder实例回来给客户端。ContentProviderConnection代表了客户端和当时ContentProvider的衔接。该函数先经过遍历ProcessRecordconProviders列表,判别是有已存在已有当时ContentProviderContentProviderConnection。没有的话,则新建。

ContentProviderConnection incProviderCountLocked(ProcessRecord r,
        final ContentProviderRecord cpr, IBinder externalProcessToken, int callingUid,
        String callingPackage, String callingTag, 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++;
                }
                //回来已存在匹配的ContentProviderConnection实例
                return conn;
            }
        }
        //没有历史,则新建
        ContentProviderConnection conn = new ContentProviderConnection(cpr, r, callingPackage);
        conn.startAssociationIfNeeded();
        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.getCurProcState(),
                cpr.uid, cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName);
        return conn;
    }
    cpr.addExternalProcessHandleLocked(externalProcessToken, callingUid, callingTag);
    return null;
}

这样一路回来到最开端query函数。在取得IContentProvider实例之后,调用其query函数。

qCursor = unstableProvider.query(mPackageName, mAttributionTag, uri, projection,queryArgs, remoteCancellationSignal);

ContentProviderdeleteupdateinsert函数也如此。

总结

经过对ContentProvider源码的剖析,了解到一切运用程序在创立运用进程的时分,会装置一切在AndroidManifestContentProvider,假如没有声明,则不会被装置。所谓的装置,便是依据事务逻辑,查看合法性和权限,然后调用每个ContentProvideronCreate函数,触发第一个生命周期。并缓存到本身的mProviderMap中,以后要用能够直接查询,而不是又经过PMS去解析。在装置好一切ContentProvider之后,要告诉AMS,让AMS有记载,以便利其他进程运用本身的ContentProvier。毕竟ContentProvider的首要效果 是对其他运用分享数据。假如一个运用所要查询的ContentProvider在其他运用B,恰巧运用B还没有发动,那么AMS还要负责发动运用B,以便供给ContentProvider的才能。