Android 系统ContentProvider流程
先从pms获取ContentProvider基本信息创建 ContentProvider实现类对象,然后将ContentProvider 的 Binder 接口对象封装到 ProcessRecord.pubProviders供应客户端aidl调用。
一、ContentProvider初始化注册流程
源码查看路径:http://xrefandroid.com/android-11.0.0_r48/
涉及到源码文件:
/frameworks/base/core/java/android/content/ContentProvider.java
自定义ContentProvider需要继承该类,内部类Transport继承关系如下,实现了aidl 接口 IContentProvider,提供增删改查注册监听操作
ContentProvider.Transport -> ContentProviderNative -> IContentProvider
这里的ContentProviderNative(同自定义Ixx.aidl文件生成的Ixx.Stub类对象)继承Binder类同时实现 IInterface接口。
即ContentProvider.Transport 为binder对象。
客户端通过获取aidl binder对象,调用注册的ContentProvider接口
ContentProvider.getIContentProvider 返回创建的aidl 实现Transport对象
/frameworks/base/core/java/android/app/ContentProviderHolder.java
ContentProviderHolder继承Parcelable 通过序列化支持跨进程传输.
ContentProviderHolder.provider 存储 ContentProvider 的 Binder 接口(IContentProvider)
ContentProviderHolder.info 存储当前ContentProvider的组件信息ProviderInfo
/frameworks/base/services/core/java/com/android/server/content/ContentService.java
作为系统级观察者模型的核心组件,允许应用通过注册 ContentObserver 监听指定 URI 的数据变更(如联系人、短信、设置等),并在数据更新时异步通知所有订阅者,实现跨进程数据同步。
/frameworks/base/core/java/android/database/ContentObserver.java
ContentObserver.Transport 继承 IContentObserver.Stub ContentProvider服务端通过此 binder 对象通知客户端用户数据发生变化
/frameworks/base/services/core/java/com/android/server/am/ContentProviderRecord.java
存储 ContentProvider 的 Binder 对象(如 IContentProvider)、所属进程(ProcessRecord)及权限配置(如 readPermission)
记录 ContentProvider 的启动状态(如已绑定、已发布)ContentProviderRecord.provider 存储 ContentProvider 的 Binder 接口(IContentProvider),
系统会为每个 Provider 创建独立的 ContentProviderRecord,通过 ProviderInfo 中的 authority 字段区分,
应用创建多个Provider时候配置的AndroidManifest.xml中的authorities不能相同。
/frameworks/base/core/java/android/content/pm/ProviderInfo.java
继承自 ComponentInfo,定义 ContentProvider 的组件信息,包括包名、类名、权限(如 readPermission/writePermission)、路径匹配规则(pathPattern)等。
在 AndroidManifest.xml 中通过 <provider> 标签声明,由 PMS(PackageManagerService)解析后生成内存对象。
/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
/frameworks/base/services/core/java/com/android/server/pm/ComponentResolver.java
解析所有Android组件类型activities, services, providers 和 receivers
由Android系统启动流程可知SystemServer进程启动时,会调用SystemServer.startBootstrapServices 启动系统Boot级别服务,该方法会启动ams。
还会调用SystemServer.startOtherServices 该方法会mActivityManagerService.installSystemProviders()来解析所有注册的ContentProvider
ActivityManagerService.installSystemProviders() 中调用如下2步,
1.从pms中获取ContentProvider列表
从AMS的processList中找到进程为"system"且uid="SYSTEM_UID"的ProcessRecord,
然后从系统进程中获取所有ContentProvider ,具体是调用
ActivityManagerService.generateApplicationProvidersLocked(ProcessRecord app) 执行2步
1.1 调用 List<ProviderInfo> providers = ppGlobals.getPackageManager().queryContentProviders(app.processName,...) 获取ProviderInfo列表
ApplicationPackageManager.queryContentProviders(String processName,int uid, int flags,null) 调用 slice = mPM.queryContentProviders(processName, ...) 通过aidl调用pms接口
PackageManagerService.queryContentProviders(String processName,...) 调用matchList =mComponentResolver.queryProviders(processName,...)
ComponentResolver.queryProviders(String processName,...) 遍历 mProviders.mProviders 中的ParsedProvider 如果进程和当前请求进程一致添加到providerList然后返回
ps:mProviders.mProviders 是开机PackageManagerService(PMS)扫描应用安装包(APK)后,将解析出的应用信息添加到mProviders中的。
1.2 将 ProviderInfo列表 封装到 ContentProviderRecord 然后添加到 ProcessRecord.pubProviders 。
2.调用mSystemThread.installSystemProviders(providers) 发布系统应用的providers
ActivityThread.installSystemProviders(List<ProviderInfo> providers) 调用 installContentProviders(mInitialApplication, providers)
或者
非系统应用会在进程启动后,调用installContentProviders发布providers。
ActivityThread.handleBindApplication
→ installContentProviders
ActivityThread.installContentProviders(Context context, List<ProviderInfo> providers) 主要执行如下两步
2.1 遍历providers列表对象ProviderInfo.
生成 ContentProviderHolder 对象(包含 ContentProvider 的 Binder 接口 IContentProvider) 列表,用于跨进程通信时传递数据提供实例,
具体是调用:
cph = installProvider(context, null, cpi,false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/)
ActivityThread.installProvider(.., ProviderInfo info,...) 创建当前应用注册的 ContentProvider 实例,并完成其初始化操作
基于ContentProvider名称创建ContentProvider实现类对象, localProvider = packageInfo.getAppFactory().instantiateProvider(cl, info.name)
然后获取ContentProvider中的binder对象赋值给 holder.provider = provider, 调用 provider = localProvider.getIContentProvider() 返回binder 对象 ContentProvider.mTransport.
installProvider方法最后返回ContentProviderHolder对象 holder.
然后将 获取的ContentProviderHolder添加到ContentProviderHolder列表对象results,调用 results.add(cph)
2.2 将ContentProviderHolder列表发布到ams
具体是调用:ActivityManager.getService().publishContentProviders(getApplicationThread(), results)
ActivityManagerService.publishContentProviders(IApplicationThread caller,List<ContentProviderHolder> providers)
遍历ContentProviderHolder列表providers 中 ContentProviderHolder对象src
基于ContentProviderHolder 从ProcessRecord.pubProviders 获取ContentProviderRecord对象dst,然后添加到ActivityManagerService.mProviderMap,
调用mProviderMap.putProviderByClass(comp, dst),mProviderMap.putProviderByName(names[j], dst)
初始化 ContentProviderRecord.provider 调用dst.provider = src.provider.ContentProviderRecord.provider为ContentProvider 的 Binder 接口。
总结: 先从pms获取ContentProvider基本信息创建 ContentProvider实现类对象,然后将 ContentProvider 的 Binder 接口对象(ContentProvider.Transport) 存储到ActivityManagerService.mProviderMap中ContentProviderRecord.provider对象中,
供应客户端aidl调用
二、ContentResolver调用ContentProvider接口流程
1.查询接口
1.1 获取ContentResolver对象
(ContextImpl.ApplicationContentResolver对象)
调用 ContentResolver cr = getContentResolver() 获取ContentResolver为ApplicationContentResolver对象
ContextWrapper.getContentResolver() 调用 mBase.getContentResolver()
ContextImpl.getContentResolver() 返回mContentResolver
mContentResolver是 ContextImpl.ContextImpl构造方法中调用mContentResolver = new ApplicationContentResolver(this, mainThread)
ContextImpl.ApplicationContentResolver继承ContentResolver
1.2 查询uri
cr.query(uri, null, null, null, null) 从上可知cr为ContextImpl.ApplicationContentResolver
ContentResolver.query(Uri uri,...) 调用 如下3步:
#1.获取服务端的ContentProvider 的 Binder 接口对象(ContentProvider.Transport)
调用IContentProvider unstableProvider = acquireUnstableProvider(uri) ,基于uri获取对应ContentProvider的aidl 接口实现的binder。
ContentResolver.acquireUnstableProvider(Uri uri) 调用acquireUnstableProvider(mContext, uri.getAuthority()
ContextImpl.ApplicationContentResolver.acquireUnstableProvider(Context c, String auth) 调用 mMainThread.acquireProvider(c,ContentProvider.getAuthorityWithoutUserId(auth),resolveUserIdFromAuthority(auth), false)
ActivityThread.acquireProvider(Context c, String auth, int userId, boolean stable) 获取holder.provider,holder获取流程如下:
#1.1 调用holder = ActivityManager.getService().getContentProvider(getApplicationThread(), c.getOpPackageName(), auth, userId, stable)
ActivityManagerService.getContentProvider(....) 调用getContentProviderImpl(caller, name,...)
ActivityManagerService.getContentProviderImpl(...) 该方法返回ContentProviderHolder对象
根据调用方请求的 ContentProvider 的 authority(如 com.example.provider),遍历系统已注册的 ProviderInfo 列表,匹配到对应的组件信息。将ActivityManagerService.mProviderMap中ContentProviderRecord.provider对象封装到ContentProviderHolder.provider中.
若目标 ContentProvider 尚未启动(未绑定到宿主进程),则触发其宿主进程的启动流程(如通过 startProcessLocked 方法),并等待其初始化完成。
#1.2 返回 ContentProviderHolder.provider即 ContentProvider 的 Binder 接口对象(ContentProvider.Transport) 给调用方(如 ContentResolver),作为后续数据操作(query、insert 等)的通道。
ContentProviderHolder.provider初始化流程:
ContentProviderHolder.ContentProviderHolder(Parcel source) 调用provider = ContentProviderNative.asInterface(source.readStrongBinder())
ContentProviderNative.asInterface(IBinder obj) 返回new ContentProviderProxy(obj) 即 ContentProviderHolder.provider 为ContentProviderNative.ContentProviderProxy。
#2.获取服务端数据到BulkCursorToCursorAdaptor,调用qCursor = unstableProvider.query(mPackageName, mAttributionTag, uri, projection,queryArgs, remoteCancellationSignal)
因为 unstableProvider是基于uri获取对应ContentProvider的aidl 接口实现的binder。即通过aidl 调用服务端创建的 ContentProvider.query 方法.应用层返回的Cursor接口实际是BulkCursorToCursorAdaptor类对象。
unstableProvider.query流程如下:
相关文件接口
AbstractCursor.java
AbstractCursor.SelfContentObserver 继承 ContentObserver
ContentObserver.java
ContentObserver.getContentObserver() 返回ContentObserver.Transport 对象mTransport, mTransport = new Transport(this)
BulkCursorToCursorAdaptor.java
BulkCursorToCursorAdaptor -> AbstractWindowedCursor -> AbstractCursor -> CrossProcessCursor -> Cursor
BulkCursorToCursorAdaptor.getContentObserver() 返回mObserverBridge.getContentObserver()
BulkCursorToCursorAdaptor.mObserverBridge为 mObserverBridge = new AbstractCursor.SelfContentObserver
CursorToBulkCursorAdaptor.java
CursorToBulkCursorAdaptor -> BulkCursorNative -> Binder
是Android中实现跨进程Cursor数据传输的核心适配器类,
在服务端(ContentProvider进程)创建实例,通过Binder将接口对象传递给客户端进程
CrossProcessCursorWrapper.java
CrossProcessCursorWrapper -> CursorWrapper -> Cursor
CrossProcessCursorWrapper -> CrossProcessCursor -> Cursor
CursorWrapper 封装服务端query返回的Cursor(例如MatrixCursor等)
CrossProcessCursor 接口定义用于支持跨进程访问数据库查询结果
#2.1.客户端:
ContentProviderNative.ContentProviderProxy.query(...)
从上可知adaptor.getObserver().asBinder()为ContentObserver.Transport 的binder对象,用来监听服务端数据变化,通过CursorWindow的匿名共享内存(ashmem)传递数据变更通知,当Cursor关闭时自动解注册观察者,防止内存泄漏。
这里会最终aidl传递BulkCursorToCursorAdaptor封装的ContentObserver.Transport 对象。
BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor()
data.writeStrongBinder(adaptor.getObserver().asBinder())
mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0)
#2.2.服务端:
#2.2.1.服务端将客户监听ContentObserver.Transport 的binder对象,以及服务端query的cursor封装到CursorToBulkCursorAdaptor。
调用如下:
ContentProviderNative.onTransact(...) case QUERY_TRANSACTION:
IContentObserver observer = IContentObserver.Stub.asInterface(data.readStrongBinder());
Cursor cursor = query(callingPkg, callingFeatureId, url, projection, queryArgs,cancellationSignal);
adaptor = new CursorToBulkCursorAdaptor(cursor, observer,getProviderName());
#2.2.2.通过CursorToBulkCursorAdaptor中创建Parcelabl对象BulkCursorDescriptor返回cursor,window等数据给客户端。
调用如下:
BulkCursorDescriptor d = adaptor.getBulkCursorDescriptor() 该方法创建 BulkCursorDescriptor(继承Parcelable) 对象
d.cursor = this; 保存CursorToBulkCursorAdaptor对象。
d.columnNames = mCursor.getColumnNames(); 保存列名称数据。
d.count = mCursor.getCount();
d.window = mCursor.getWindow(); 保存CursorWindow
..
d.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE) BulkCursorDescriptor.writeToParcel(Parcel out, int flags) 最终调用如下,
public void writeToParcel(Parcel out, int flags) {
out.writeStrongBinder(cursor.asBinder());
out.writeStringArray(columnNames);
out.writeInt(wantsAllOnMoveCalls ? 1 : 0);
out.writeInt(count);
if (window != null) {
out.writeInt(1);
window.writeToParcel(out, flags);
} else {
out.writeInt(0);
}
}
通过aidl传递服务端的 CursorToBulkCursorAdaptor 的binder对象,columnNames,CursorWindow对象window(如果是MatrixCursor则window为null) 数据给客户端。
因为aidl传输限制是1MB,这里需要考虑columnNames数组数据大小限制。
参考 Android 的 Java 中,字符串(String 类)默认使用 UTF-16 编码,
比如平均单个columnName字符串占用 24个字符占用 24 * 2 = 48字节(UTF-16 编码每个char占2字节),
一次请求query可以传递 1MB / 48B ≈ 21,845个 columnName。
ps:mCursor为CursorToBulkCursorAdaptor构造方法初始化的CrossProcessCursorWrapper或者 (CrossProcessCursor)cursor对象,
例如 服务端query返回的Cursor是MatrixCursor对象则
CursorToBulkCursorAdaptor.mCursor 存储服务端query返回的MatrixCursor,上面
mCursor.getColumnNames() 调用的是MatrixCursor.getColumnNames()方法。
mCursor.getCount()调用的是MatrixCursor.getCount()方法。
mCursor.getWindow()调用的是MatrixCursor父类getWindow方法返回null,应用调用cursor.moveToNext()时候会创建CursorWindow并从MatrixCursor获取数据填充CursorWindow。
#2.3.客户端:
获取服务端返回的BulkCursorToCursorAdaptor对象。
BulkCursorDescriptor d = BulkCursorDescriptor.CREATOR.createFromParcel(reply); 从服务端获取 Parcelabl对象BulkCursorDescriptor.
adaptor.initialize(d); 将数据设置到到BulkCursorToCursorAdaptor中。
至此cr.query 获取的Cursor接口对象BulkCursorToCursorAdaptor。其中:
BulkCursorToCursorAdaptor.mWindow 为服务端传递的CursorWindow对象,CursorWindow.mWindowPtr字段(JNI层指针)实际关联着底层的共享内存区域.
BulkCursorToCursorAdaptor.mColumns
BulkCursorToCursorAdaptor.mBulkCursor 存储服务端CursorToBulkCursorAdaptor的binder引用。
#3.封装数据到CursorWrapperInner返回, 调用CursorWrapperInner wrapper = new CursorWrapperInner(qCursor, provider)
将BulkCursorToCursorAdaptor对象 qCursor和 ContentProvider 的 Binder 接口对象(ContentProvider.Transport) provider封装到CursorWrapperInner中并返回。
客户端数据操作实际操作的BulkCursorToCursorAdaptor对象。
1.3 查询cursor数据
1.3.1 cursor.moveToNext() 将游标从当前位置移动到下一行,如果第一次服务端返回的是 MatrixCursor(CursorWindow为空)还会创建CursorWindow并填充该行数据。这里的cursor为CursorWrapperInner,
CursorWrapper.moveToNext() 调用mCursor.moveToNext(),mCursor为BulkCursorToCursorAdaptor,即调用父类
AbstractCursor.moveToNext() 调用moveToPosition(mPos + 1) ,这里 mPos 默认是-1
AbstractCursor.moveToPosition(int position) 调用 result = onMove(mPos, position)
BulkCursorToCursorAdaptor.onMove(int oldPosition, int newPosition) 判断 mWindow为空(如果服务端返回的是MatrixCursor 则第一次mWindow为空)
调用setWindow(mBulkCursor.getWindow(newPosition)) 从服务端获取CursorWindow并填充数据到CursorWindow,然后将CursorWindow设置到BulkCursorToCursorAdaptor.mWindow,
这里 mBulkCursor为服务端返回的CursorToBulkCursorAdaptor的binder引用,
从服务端获取CursorWindow并填充数据流程:
CursorToBulkCursorAdaptor.getWindow(int position) 先调用window = mCursor.getWindow() 例如存储服务端query返回的是MatrixCursor
,则mCursor为MatrixCursor 返回window为空,调用mFilledWindow = new CursorWindow(mProviderName) 创建CursorWindow,
然后调用 mCursor.fillWindow(position, window) 将 MatrixCursor的数据填充到新创建的CursorWindow中.调用MatrixCursor父类方法
AbstractCursor.fillWindow(int position, CursorWindow window) 调用 DatabaseUtils.cursorFillWindow(this, position, window)
DatabaseUtils.cursorFillWindow(Cursor cursor,int position, CursorWindow window) 这里主要做几件事
window.setStartPosition(position) //为CursorWindow设置position
window.setNumColumns(cursor.getColumnCount()) //为CursorWindow设置列数(数据来源MatrixCursor的列数)
然后遍历 MatrixCursor的每一列填充数据到CursorWindow。
例如:window.putLong(cursor.getLong(i), position, i)
CursorWindow.putLong(long value,int row, int column) 调用nativePutLong(mWindowPtr, value, row - mStartPos, column)结果集按行拷贝至共享内存.
ps:CursorWindow中按照列顺序存储服务端返回的Cursor数据,不存储列名columnNames信息。
1.3.2 cursor.getColumnIndex(columnName) 获取columnName的索引。
AbstractCursor.getColumnIndex(String columnName) 调用
String columnNames[] = getColumnNames() 返回返回当前columnName的index
BulkCursorToCursorAdaptor.getColumnNames() 返回mColumns ,此mColumns为从服务端返回的BulkCursorDescriptor中 d.columnNames赋值。
返回columnNames[]中包含columnName的索引。
1.3.3 cursor.getInt(columnIndex) 获取对应索引的数据。
cursor为BulkCursorToCursorAdaptor对象,调用父类方法。
AbstractWindowedCursor.getInt(int columnIndex) 调用mWindow.getInt(mPos, columnIndex)
CursorWindow.getInt(int row, int column) 调用(int) getLong(row, column)
CursorWindow.getLong(int row, int column) 调用nativeGetLong(mWindowPtr, row - mStartPos, column) 客户端通过映射的共享内存直接读取数据。
2.更新接口
ContentResolver.update(Uri uri,...)
2.1调用IContentProvider provider = acquireProvider(uri) ,基于uri获取对应ContentProvider的aidl 接口实现的binder。
ContentResolver.acquireProvider(Uri uri) 调用 acquireProvider(mContext, auth) 会调用ContextImpl类中方法
ContextImpl.ApplicationContentResolver.acquireProvider(Context context, String auth) 调用
mMainThread.acquireProvider(context,ContentProvider.getAuthorityWithoutUserId(auth),resolveUserIdFromAuthority(auth), true)
后面流程同 1.2 查询uri 获取ContentProviderHolder.provider即 ContentProvider 的 Binder 接口对象(ContentProvider.Transport) 给调用方。
2.2调用服务端update接口更新数据。 rowsUpdated = provider.update(mContext.getAttributionSource(),uri, values, extras) 调用
IContentProvider.update(String callingPkg, Uri url...) 调用update(callingPkg, null, url,...)最终调用到子类ContentProviderNative.java
ContentProviderProxy.update(String callingPkg, String featureId, Uri url,...) 调用 url.writeToParcel(data, 0) mRemote.transact(IContentProvider.UPDATE_TRANSACTION, data, reply, 0)
ContentProviderNative.onTransact(...) case UPDATE_TRANSACTION:调用count = update(callingPkg, featureId, url, values, extras) 这里直接服务端ContentProvider.update方法。
即update是直接调用aidl 接口更新。insert和delete同update也是直接调用aidl 接口添加删除。
3.监听接口
3.1注册监听
cr.registerContentObserver(uri, true, ContentObserver类对象)
ContentResolver.registerContentObserver(Uri uri, boolean notifyForDescendents,ContentObserver observer, int userHandle) 该方法
调用getContentService().registerContentObserver(uri, notifyForDescendents,observer.getContentObserver(), userHandle, mTargetSdkVersion)
observer.getContentObserver方法返回 ContentObserver的Binder 接口对象(ContentObserver.Transport)
getContentService方法返回 ContentService 对象的binder IContentService,即调用
ContentService.registerContentObserver(Uri uri, ...) 调用 mRootNode.addObserverLocked(uri, ...)
ContentService.addObserverLocked(Uri uri, ...)
例如uri为content://com.android.mycontentprovider/contact
最终我们得到ObserverNode的树形结构如下所示:
mRootNode("")
-- ObserverNode("com.android.mycontentprovider")
--ObserverNode("contact") ,在叶子节点 mObservers 添加ContentObserver的Binder 接口对象(ContentObserver.Transport) ,
调用 mObservers.add(new ObserverEntry(observer, notifyForDescendants, observersLock,uid, pid, userHandle, uri))
3.2. 监听回调
例如uri为 content://com.android.mycontentprovider/contact/d
getContext().getContentResolver().notifyChange(uri, null) 调用notifyChange(uri, observer, true /* sync to network */);
ContentResolver.notifyChange(Uri uri, ContentObserver observer,boolean syncToNetwork) 调用notifyChange(uri, observer, syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0)
ContentResolver.notifyChange(Uri uri, ContentObserver observer,int flags) 调用notifyChange(ContentProvider.getUriWithoutUserId(uri),observer,flags,ContentProvider.getUserIdFromUri(uri, mContext.getUserId()))
ContentResolver.notifyChange(Uri uri, ContentObserver observer, int flags,int userHandle) 调用notifyChange(new Uri[] { uri }, observer, flags, userHandle)
ContentResolver.notifyChange(Uri[] uris, ContentObserver observer, int flags,int userHandle) 调用getContentService().notifyChange(uris, observer == null ? null : observer.getContentObserver(),...)
ContentService.notifyChange(Uri[] uris, IContentObserver observer,...)
#1.调用ContentService的成员变量mRootNode的collectObserversLocked()函数来收集那些注册了监控"content://com.android.mycontentprovider/contact/d"这个URI的ContentObserver,
mRootNode.collectObserversLocked(uri, segmentCount, 0, observer,observerWantsSelfNotifications, flags, resolvedUserId, collector)
ContentService.ObserverNode.collectObserversLocked(Uri uri, int segmentCount, int index,IContentObserver observer,...) 本Uri的 segmentCount 为 3
从如下index开始逐层遍历ObserverNode的树形结构:
index 0:mRootNode 为 ObserverNode(""), getUriSegment(uri, 0) 为 com.android.mycontentprovider,mObservers为空
index 1:ObserverNode("com.android.mycontentprovider"),getUriSegment(uri, 1) 为 contact,mObservers为空
index 2:ObserverNode("contact"), getUriSegment(uri, 2) 为 d ObserverNode("contact").mChildren为空无子ObserverNode需要处理,mObservers不为空,
此处的mObservers为上面registerContentObserver注册的uri:content://com.android.mycontentprovider/contact ,会调用 collectMyObserversLocked(uri, false...)
ContentService.ObserverNode.collectMyObserversLocked 判断当前 mObservers不为空
调用collector.collect(entry.observer, entry.uid, selfChange, uri, flags,targetUserHandle);
将IContentObserver的key和uri列表的value添加到 ContentService.ObserverCollector.collected
#2.调用了这些ContentObserver的onChange()函数来通知它们监控的数据发生变化了具体是调用
collector.dispatch()
ContentService.ObserverCollector.dispatch() 该方法遍历ContentService.ObserverCollector.collected的key,value
调用key.observer.onChangeEtc(key.selfChange,value.toArray(new Uri[value.size()]), key.flags, key.userId)
ContentObserver.Transport.onChangeEtc(boolean selfChange, Uri[] uris, int flags, int userId) 调用mContentObserver.dispatchChange(selfChange, Arrays.asList(uris), flags, userId)
ContentObserver.dispatchChange(boolean selfChange, Collection<Uri> uris, int flags, @UserIdInt int userId) 调用onChange(selfChange, uris, flags)
ContentObserver.onChange(boolean selfChange, @NonNull Collection<Uri> uris,int flags) 遍历uris调用onChange(selfChange, uri, flags)
ContentObserver.onChange(boolean selfChange, @Nullable Uri uri, @NotifyFlags int flags) 调用onChange(selfChange, uri) 这里调用注册uri监听的子类重载方法
ContentObserver子类对象.onChange(selfChange, uri) 即客户端调用 cr.registerContentObserver(uri, true, ContentObserver类对象)可以监听到变化
总结:
1.ContentProvider发布:应用进程启动时系统将 ContentProvider 的 Binder 接口对象(ContentProvider.Transport) 存储到ActivityManagerService.mProviderMap中ContentProviderRecord.provider对象中。
2.服务端注册uri UriMatcher.addURI:将uri信息注册到 ObserverNode的树形结构节点中。
3.客户端查询ContentResolver.query: 应用端通过ams接口获取ActivityManagerService.mProviderMap中ContentProviderRecord.provider对象,即ContentProvider 的 Binder 接口对象(ContentProvider.Transport) ,通过该 Binder 接口对象即可调用服务端ContentProvider.query方法。
客户端调用cursor.moveToNext时,服务端将数据ContentProvider.query的数据封装到CursorWindow的共享内存中,客户端通过CursorWindow共享内存读取数据。
4.客户端注册监听ContentResolver.registerContentObserver:系统基于uri将ContentObserver的Binder 接口对象(ContentObserver.Transport)添加到ObserverNode的树形结构节点中,
5.服务端通知uri变化getContentResolver().notifyChange:系统基于uri找到ObserverNode的树形结构节点中的ContentObserver.Transport列表,然遍历调用客户端的ContentObserver.Transport接口通知客户端。
更多推荐


所有评论(0)