当前位置: 首页 > news >正文

Android 系统ContentProvider流程

一、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
客户端通过获取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)

/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)
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 接口对象封装到 ProcessRecord.pubProviders
供应客户端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 查询
cr.query(uri, null, null, null, null) 从上可知cr为ContextImpl.ApplicationContentResolver
ContentResolver.query(Uri uri,...)  调用 如下2几步:
#1.获取对应的IContentProvider
调用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获取流程如下:
调用holder = ActivityManager.getService().getContentProvider(getApplicationThread(), c.getOpPackageName(), auth, userId, stable)
ActivityManagerService.getContentProvider(....) 调用getContentProviderImpl(caller, name,...)
ActivityManagerService.getContentProviderImpl(...) 该方法返回ContentProviderHolder对象
根据调用方请求的 ContentProvider 的 authority(如 com.example.provider),遍历系统已注册的 ProviderInfo 列表,匹配到对应的组件信息。
若目标 ContentProvider 尚未启动(未绑定到宿主进程),则触发其宿主进程的启动流程(如通过 startProcessLocked 方法),并等待其初始化完成。
通过 IContentProvider 接口封装 ContentProvider 的 Binder 通信句柄,返回 ContentProviderHolder 对象给调用方(如 ContentResolver),作为后续数据操作(query、insert 等)的通道

#2.调用qCursor = unstableProvider.query(mPackageName, mAttributionTag, uri, projection,queryArgs, remoteCancellationSignal)
因为 unstableProvider是基于uri获取对应ContentProvider的aidl 接口实现的binder。
即通过aidl 调用服务端创建的 ContentProvider.query 方法.

其他增删改流程同上。

2.监听接口
2.1注册监听
cr.registerContentObserver(uri, true, ContentObserver类对象)
ContentResolver.registerContentObserver(Uri uri, boolean notifyForDescendents,ContentObserver observer, int userHandle) 该方法
调用getContentService().registerContentObserver(uri, notifyForDescendents,observer.getContentObserver(), userHandle, mTargetSdkVersion)
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 添加 IContentObserver监听binder对象,
                调用 mObservers.add(new ObserverEntry(observer, notifyForDescendants, observersLock,uid, pid, userHandle, uri))
2.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类对象)可以监听到变化


http://www.mrgr.cn/news/96935.html

相关文章:

  • Docker in Docker(Dind)
  • 解决Centos7集成IDEA报git版本太低问题
  • [leetcode]回溯法
  • 总结面试中可能会涉及到简历的问题
  • 合并有序链表
  • Windows系统服务器安装Office Online Server
  • leetcode 62. Unique Paths
  • DeepSeek-R1 模型现已在亚马逊云科技上提供
  • 【大模型系列篇】大模型基建工程:基于 FastAPI 自动构建 SSE MCP 服务器
  • 关于依赖注入框架VContainer DIIOC 的学习记录
  • el-select+el-tree、el-select+vl-tree实现下拉树形选择
  • VS+Qt配置QtXlsx库实现execl文件导入导出(全教程)
  • 论文阅读9——更严格的汽车排放标准对气候、健康、农业和经济的影响
  • 酶动力学预测工具CataPro安装教程
  • LeetCode Hot100 刷题笔记(4)—— 二叉树、图论
  • 详解相机的内参和外参,以及内外参的标定方法
  • 论文阅读10——解开碳排放与碳足迹之间的关系:文献回顾和可持续交通框架
  • 国产系统服务器识别不到SATA盘
  • 洛谷题单3-P5720 【深基4.例4】一尺之棰-python-流程图重构
  • SQL语句(一)—— DDL