作为四大组件之一的ContentProvider,相信大多数开发者平常都很少用到。就像我们这种toB的公司,面向Android整机开发,多个应之间的交互,也是通过广播。通过对ContentProvider的学习,整体的逻辑和广播是相似的。但广播更多理解成为是一种观察者模式,而ContentProvider是一种数据库结构类型。但它们共同的使命之一,就是通过IPC对外提供数据。
ContentProvider的安装
应用进程的创建过程中,最后一步通过反射创建应用程序的主线程ActivityThread,调用其main函数中,并通过ActivityThread的attach函数,attach函数又调用了AMS的attachApplicationLocked函数。attachApplicationLocked函数会涉及到应用程序ContentProvider的install逻辑。

AMS.attachApplicationLocked
AMS的attachApplicationLocked函数中,我们只关心和ContentProvider相关的部分,如下所示,调用了generateApplicationProvidersLocked函数生成了List<ProviderInfo>类型的providers。ProviderInfo对象对应应用程序的一个ContentProvider,也就是ContentProvider在Framework层的描述。并将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调用了PackageMangerService的queryContentProviders函数。
分析一:
通过ComponentResolver类型的mComponentResolver的queryProviders获取所有配的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类型的mComponentResolver的queryProviders函数查询属于当前进程的所有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;
}
至于定义在AndroidManifest的Provider什么时候被添加到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和所有的ProviderInfo。installContentProviders函数遍历所有的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的本地代理的实现。
分析二:调用了localProvider的attachInfo函数。该函数会调用ContentProvider自身的onCreate函数。这时候ContentProvider可以理解为已经创建完毕。
分析三:将localProvider、provider、holder、auths封装成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实例,并将相关信息缓存到mProviderMap、mLocalProviders、mLocalProvidersByName集合。后续使用直接通过集合来查询。
在应用进程创建好所有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的安装过程,是在创建应用进程,调用ActivityThread的main函数开始,在attach函数后通过AMS去PMS中获得应用定义在AndroidManifest的ContentProvider的描述信息ProviderInfo,最后切回到应用程序创建ContentProvider实例,将相关信息分别缓存到应用程序和AMS中mProviderMap,方便后续使用,避免每次都要创建ContentProvider。
ContentProvider的使用
我们经常通过下面的方式去获取ContentResover对象,并调用其insert、query、delete、update函数。
val uri=Uri.parse("content://com.xxm.content.auth.share.data")
contentResolver.query(uri, arrayOf("id","name"),null,null )
而这里的getContentResolver函数其实是ContextWrapper的方法。这样Applciation、Service、Activity都可以通过这种方式调用。
public ContentResolver getContentResolver() {
return mBase.getContentResolver();
}
Context类型的mBase,实际类型是ContextImpl。
public ContentResolver getContentResolver() {
return mContentResolver;
}
ApplicationContentResolver类型的mContentResolver在ContextImpl创建的时候被实例化。
Cursor的获取
query函数来自ApplicationContentResolver父类ContentResolver。query函数一共有三个重载函数。最终调用如下函数。
query函数会获取两个IContentProvider类型实例,一个称为unstableProvider,一个称为stableProvider。先通过不稳定去获取Cursor类型的qCursor,可能由于所在进程已死从而抛出异常。在这种情况下,再去获取stableProvider,然后获取qCursor。IContentProvider是AMS端ContentProvider在本地的跨进程引用。
最终将查询到的Provider和Cursor实例封装成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 {
...
}
}
贴下时序图:

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函数比较简单,从应用程序的ActivityThread的mProviderMap中查询,如果有,且进程还存活,则增加引用计数,并返回provider;如果有,但进程已死,从缓存中进行移除。如果有没有,则返回null,需要在分析二,同个AMS查询。
3、AMS.getContentProvider
内部又调用了getContentProviderImpl函数。该函数涵盖了ContentProvider获取的整个流程。主要分为两个大逻辑:
分析一:从mProviderMap获取,是应用程序启动后,安装好所有ContentProvider,然后通知AMS进行缓存。如果在mProviderMap查询不到,可能该ContentProvider所在的进程没有启动过。
分析二:providerRunning为true,需要对其合法性进行检查,判断是否符合当前所需的ContentProvider。
分析三:providerRunning为false, 通过启动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的连接。该函数先通过遍历ProcessRecord的conProviders列表,判断是有已存在已有当前ContentProvider的ContentProviderConnection。没有的话,则新建。
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);
ContentProvider的delete、update、insert函数也如此。
总结
通过对ContentProvider源码的分析,了解到所有应用程序在创建应用进程的时候,会安装所有在AndroidManifest的ContentProvider,如果没有声明,则不会被安装。所谓的安装,就是根据业务逻辑,检查合法性和权限,然后调用每个ContentProvider的onCreate函数,触发第一个生命周期。并缓存到自身的mProviderMap中,以后要用可以直接查询,而不是又通过PMS去解析。在安装好所有ContentProvider之后,要通知AMS,让AMS有记录,以方便其他进程使用自身的ContentProvier。毕竟ContentProvider的主要作用 是对其他应用分享数据。如果一个应用所要查询的ContentProvider在其他应用B,恰巧应用B还没有启动,那么AMS还要负责启动应用B,以便提供ContentProvider的能力。