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") ,
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的collectObserverLocked()函数来收集那些注册了监控"content://com.android.mycontentprovider/contact/d"这个URI的ContentObserver,
2.调用了这些ContentObserver的onChange()函数来通知它们监控的数据发生变化了
相关文章:
Android 系统ContentProvider流程
一、ContentProvider初始化注册流程 源码查看路径:http://xrefandroid.com/android-11.0.0_r48/ 涉及到源码文件: /frameworks/base/core/java/android/content/ContentProvider.java 自定义ContentProvider需要继承该类,内部类Transport继承关系如下,实…...
SpringBean模块(一)定义如何创建生命周期
一、介绍 1、简介 在 Spring 框架中,Bean 是指由 Spring 容器 管理的 Java 对象。Spring 负责创建、配置和管理这些对象,并在应用程序运行时对它们进行依赖注入(Dependency Injection,DI)。 通俗地讲,Sp…...
k8s存储介绍(六)StorangeClass
一、Kubernetes 存储类(StorageClass)详解 1. 什么是 StorageClass? 在 Kubernetes 中,StorageClass(存储类)是一种用于动态创建 PersistentVolume(PV)的资源对象。它允许管理员根…...
Redis-04.Redis常用命令-字符串常用命令
一.字符串操作命令 set name jack 点击左侧name,显示出值。 get name get abc:null setex key seconds value:设置过期时间,过期后该键值对将会被删除。 然后再get,在过期时间内可以get到,过期get不到。…...
golang接口-interface
interface接口 概述 接口(interface)是 Go 语言中的一种类型,用于定义行为的集合,它通过描述类型必须实现的方法,规定了类型的行为契约。 它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这…...
Epub转PDF软件Calibre电子书管理软件
Epub转PDF软件:Calibre电子书管理软件 https://download.csdn.net/download/hu5566798/90549599 一款好用的电子书管理软件,可快速导入电脑里的电子书并进行管理,支持多种格式,阅读起来非常方便。同时也有电子书格式转换功能。 …...
【自学笔记】PHP语言基础知识点总览-持续更新
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1. PHP 简介2. PHP 环境搭建3. 基本语法变量与常量数据类型运算符 4. 控制结构条件语句循环语句 5. 函数函数定义与调用作用域 6. 数组7. 字符串8. 表单处理9. 会话…...
FAST-LIVO2 Fast, Direct LiDAR-Inertial-Visual Odometry论文阅读
FAST-LIVO2 Fast, Direct LiDAR-Inertial-Visual Odometry论文阅读 论文下载论文翻译FAST-LIVO2: 快速、直接的LiDAR-惯性-视觉里程计摘要I 引言II 相关工作_直接方法__LiDAR-视觉(-惯性)SLAM_ III 系统概述IV 具有顺序状态更新的误差状态迭代卡尔曼滤波…...
【Git】--- Git远程操作 标签管理
Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏: Git 前面我们学习的操作都是在本地仓库进行了,如果团队内多人协作都在本地仓库操作是不行的,此时需要新的解决方案 --- 远程仓库。…...
Docker学习之服务编排(day9)
文章目录 前言一、问题描述二、解决方案1.安装Docker Compose1.1 [github下载相应版本](https://github.com/docker/compose/releases)1.2 将下载的文件移动到 /usr/local/bin 目录,确保它能够被系统识别为可执行文件1.3 赋予执行权限1.4 验证安装1.5 创建软链 2. 使…...
前后端常见模型以及相关环境配置介绍
一、前端常见框架 Vue.js 特点:采用数据驱动的响应式编程,组件化的开发模式使得代码结构清晰,易于维护,且学习成本相对较低,适合初学者和快速迭代的项目。应用场景:广泛应用于各类 Web 应用开发ÿ…...
职能型组织、项目型组织、矩阵型组织的介绍及优缺点比较
PMP考试中,经常会涉及到职能型组织、项目型组织、矩阵型组织的比较,下面简单介绍下职能型组织、项目型组织、矩阵型组织及其优缺点: 一、职能型组织 定义:以专业职能划分部门(如财务、技术、市场等)&…...
Java基本类型深度解析:从内存模型到高效编程实践
Java基本类型深度解析:从内存模型到高效编程实践 一、Java基本类型概述 Java作为强类型语言,定义了8种基本数据类型(Primitive Types),这些类型直接存储数据值而非对象引用,是构建Java程序的基础。它们的…...
论文阅读笔记——ST-4DGS,WideRange4D
ST-4DGS ST-4DGS 论文 在 4DGS 中,变形场 F \mathcal{F} F 与运动参数 X 和形状参数 ( S , R ) (S,R) (S,R) 高度耦合,导致训练时高斯表示紧凑型退化,影响动态渲染质量。由此,本文提出两种方法解耦运动与形状参数,保…...
[python]基于yolov8实现热力图可视化支持图像视频和摄像头检测
YOLOv8 Grad-CAM 可视化工具 本工具基于YOLOv8模型,结合Grad-CAM技术实现目标检测的可视化分析,支持图像、视频和实时摄像头处理。 功能特性 支持多种Grad-CAM方法实时摄像头处理视频文件处理图像文件处理调用简单 环境要求 Python 3.8需要电脑带有…...
五.ubuntu20.04 - ffmpeg推拉流以及Nginx、SRS本地部署
一.本地部署nginx 1.编译ffmpeg,参考这位博主的,编译选项有的enable找不到的不需要的可以直接删除,但是像sdl(包含ffplay)、h264、h265这些需要提前下载好,里面都有下载指令。 Ubuntu20.04 编译安装 FFmp…...
深度神经网络全解析:原理、结构与方法对比
深度神经网络全解析:原理、结构与方法对比 1. 引言 随着人工智能的发展,深度神经网络(Deep Neural Network,DNN)已经成为图像识别、自然语言处理、语音识别、自动驾驶等领域的核心技术。相比传统机器学习方法&#x…...
豪越科技消防一体化平台:打通消防管理“任督二脉”
在城市的车水马龙间,火灾隐患如潜藏的暗礁,威胁着人们的生命财产安全。传统消防管理模式在现代社会的复杂环境下,逐渐显露出诸多弊端。内部管理分散混乱,人员、装备、物资管理缺乏统一标准和高效流程;外部监管困难重重…...
【Matlab】-- 基于MATLAB的美赛常用多种算法
文章目录 文章目录 01 内容概要02 各种算法基本原理03 部分代码04 代码下载 01 内容概要 本资料集合了多种数学建模和优化算法的常用代码资源,旨在为参与美国大学生数学建模竞赛(MCM/ICM,简称美赛)的参赛者提供实用的编程工具和…...
机器学习课程
前言 课程代码和数据文件: 一、机器学习概述 1.1.人工智能概述 机器学习和人工智能,深度学习的关系 机器学习是人工智能的一个实现途径深度学习是机器学习的一个方法发展而来 达特茅斯会议-人工智能的起点 1956年8月,在美国汉诺斯小镇宁静…...
AIGC(生成式AI)试用 28 -- 跟着清华教程学习 - AIGC发展研究 3.0
目标:继续学习 - 信息不对称、不平等、隐私泄露和数据滥用 - 问、改、创、优 - “概率预测(快速反应)”模型和“链式推理(慢速思考)”模型 - 思维滞环现象解决思路:1.调整提问:改变问题方式&…...
问题:md文档转换word,html,图片,excel,csv
文章目录 问题:md文档转换word,html,图片,excel,csv,ppt**主要职责****技能要求****发展方向****学习建议****薪资水平** 方案一:AI Markdown内容转换工具打开网站md文档转换wordmd文档转换pdfm…...
【Java】面向对象之static
用static关键字修饰成员变量 有static修饰成员变量,说明这个成员变量是属于类的,这个成员变量称为类变量或者静态成员变量。 直接用 类名访问即可。因为类只有一个,所以静态成员变量在内存区域中也只存在一份。所有的对象都可以共享这个变量…...
解决:在运行 plt.show()`时,程序会等待你手动关闭图片窗口才能继续往下执行
你这个问题本质是: 在运行 plt.show() 时,程序会等待你手动关闭图片窗口才能继续往下执行。 这其实是 matplotlib 的默认行为 —— 它会弹出一个交互式窗口让你“看完图再走”。 ✅ 为什么会这样? 你在程序中使用了: import mat…...
Anaconda安装-Ubuntu-Linux
1、进入Anaconda官网,以下载最新版本,根据自己的操作系统选择适配的版本。 2、跳过注册: 3、选择适配的版本: 4、cd ~/anaconda_download 5、bash Anaconda3-2024.10-1-Linux-x86_64.sh 6、按Enter或PgDn键滚动查看协议&…...
Linux 配置NFS服务器
1. 开放/nfs/shared目录,供所有用户查阅资料 服务端 (1)安装nfs服务,nfs-utils包中包含rpcbind(rpc守护进程) [rootnode1-server ~]# yum install -y nfs-utils # nfs-utils包中包含rpcbind [rootnode…...
css100个问题
一、基础概念 CSS的全称及作用是什么?行内样式、内部样式表、外部样式表的优先级?解释CSS的层叠性(Cascading)CSS选择器优先级计算规则伪类与伪元素的区别?举例说明!important的作用及使用注意事项如何继承父元素字体…...
塔能科技:用精准节能撬动社会效益的行业杠杆
在全球积极践行可持续发展理念的当下,能源高效利用与节能减排,已然成为各行各业实现高质量发展绕不开的关键命题。对企业来说,节能早已不是一道可做可不做的选择题,而是关乎生存与发展、社会责任与竞争力的必答题。塔能科技推出的…...
Java 大视界 -- Java 大数据在自动驾驶高精度地图数据更新与优化中的技术应用(157)
💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...
Conda配置Python环境
1. 安装 Conda 选择发行版: Anaconda:适合需要预装大量科学计算包的用户(体积较大)。 Miniconda:轻量版,仅包含 Conda 和 Python(推荐自行安装所需包)。 验证安装: co…...
