作为四大组件之一的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
的才能。