Android系统源码分析之-ContentProvider

距离上一次写博客已经半年多了,这半年发生了很多事情,也有了很多感触,最主要是改变了忙碌了工作,更加重视身体的健康,为此也把工作地点从深圳这个一线城市换到了珠海,工作相对没有那么累,身体感觉也好了很多。所以在工作完成之余,也有了更多的时间来自我学习和提高,后续会用更多时间来写更多实用的东西,帮助我们理解安卓系统的原理,帮助我们快速、稳定的开发。
这一篇我们接着之前的计划,完成四大组件的最后一个ContentProvider的分析。ContentProvider是一个抽象类,用来提供访问数据的统一格式的接口。ContentProvider的作用是多应用间共享数据,如果用户需要直接使用则可以直接在里面使用数据库来保存数据,也可以通用ContentResolver使用URI来存储数据,使用URI用户不需要知道内部怎么存储只需要知道如何使用该存储方式。

ContentProvider

ContentProvider的描述及使用:

在之前我们分析过ContentProvider的启动比Application的启动早,所以使用时需要知道这种情况。在使用ContentResolver时是通过URI来访问的,URI的结构:content://cn.codemx.myprovider/item/123,我们划分一下:

1
2
[ 1 ][ 2 ][ 3 ][ 4 ]
[content://][cn.codemx.myprovider.settings][/item][/123]
  • 第一个组件:是一个协议名称,它的值固定为:“content://”,是Content Provider组件的专用访问协议
  • 第二个组件:是一个Content Provider组件的android:authority属性值。这个组件类似于URL中的域名,因此我们要保证它是全局唯一的,一般使用它所描述的ContentProvider组件的包名来命名。
  • 第三个组件:是一个资源相对路径,用来描述要访问的资源类型。如果一个ContentProvider只有一种资源,那么忽略这个组件,否则通过它来指定要访问的资源的类型。
  • 第四个组件:是一个资源ID,用来描述具体的资源。

举个例子:

1
2
3
4
5
6
<provider
android:name="com.android.launcher3.LauncherProvider"
android:authorities="cn.codemx.myprovider.settings"
android:exported="true"
android:readPermission="cn.codemx.myprovider.permission.READ_SETTINGS"
android:writePermission="cn.codemx.myprovider.permission.WRITE_SETTINGS"/>

我有个LauncherProvider继承ContentProvider,在AndroidManifest.xml中要像上面一样声明,其中authorities是位置认证,在使用时是这样使用的:

1
2
3
4
5
6
7
public static final String TABLE_NAME = "favorites";
/**
* The content:// style URL for this table
*/
public static final Uri CONTENT_URI = Uri.parse("content://" +
ProviderConfig.AUTHORITY + "/" + TABLE_NAME);

其中ProviderConfig.AUTHORITY为:

1
2
3
4
public class ProviderConfig {
public static final String AUTHORITY = "cn.codemx.myprovider.settings".intern();
}

这个就是上面AndroidManifest.xml中声明的那个authorities属性值。上面获取了Uri就可以通过Uri来获取或者保存数据了。

ContentProvider启动过程:

  • Activity通过MyContentProvider.CONTENT_URI来访问MyContentProvider组件,以便可以获得它的内容
  • Activity组件所运行在的应用程序进程发现它里面不存在一个用来访问MyContentProvider组件的代理对象,于是通过MyContentProvider.CONTENT_URI来请求AMS返回一个用来访问MyContentProvider组件的代理对象
  • AMS发现MyContentProvider还没有起来,于是先创建一个新的应用进程,然后在这个新创建的应用进程中启动MyContentProvider组件
  • MyContentProvider组件启动之后,就会将自己发布到AMS中,以便AMS可以将它的一个代理对象返回Activity组件。

ContentProvider方法:

1
2
3
4
5
6
onCreate() // 执行初始化工作;
insert(Uri, ContentValues) // 插入新数据;
delete(Uri, String, String[]) // 删除已有数据;
update(Uri, ContentValues, String, String[]) // 更新数据;
query(Uri, String[], String, String[], String) // 查询数据;
getType(Uri) // 获取数据MIME类型。

ContentProvider不像Activity一样有生命周期,只有一个onCreate方法用来创建。然后就是提供了增、删、改、查用来操作数据的接口,通过Uri来管理数据。

ContentResolver的获取:

上面我们提到ContentProvider主要是提供接口,并没有具体实现,如果需要具体实现,一种是通过操作数据库,一种是通过URI操作ContentResolver,数据库的这里不再介绍,只介绍一下ContentResolver。

通常我们获取ContentResolver的代码如下:

1
ContentResolver cr = context.getContentResolver(); //获取ContentResolver

前面Android系统源码分析–Context章节我们分析过Context的子类及继承关系,知道,Context的所有实现都是在ContextImp中,所以context.getContentResolver()方法的实现也是一样。

ContextImpl.getContentResolver():

1
2
3
4
@Override
public ContentResolver getContentResolver() {
return mContentResolver;
}

mContentResolver是定义在ContextImpl中类型为ApplicationContentResolver的变量:

1
private final ApplicationContentResolver mContentResolver;

这里我们可以知道我们获取到的ContentResolver实际上是ApplicationContentResolver,所以具体操作应该都是在ApplicationContentResolver中实现的。我们先看看这个mContentResolver是在哪里初始化的。

1
2
3
4
5
6
7
private ContextImpl(ContextImpl container, ActivityThread mainThread,
LoadedApk packageInfo, IBinder activityToken, UserHandle user, int flags,
Display display, Configuration overrideConfiguration, int createDisplayWithId) {
...
mContentResolver = new ApplicationContentResolver(this, mainThread, user);
}

上面代码可以知道这个是在ContextImpl构造函数中初始化的。而ContentResolver中的所有操作都在ApplicationContentResolver实现。

ContentResolver.query

先看时序图:

ContentProvider启动时序图

1.ContentResolver.query

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,
@Nullable String[] projection, @Nullable String selection,
@Nullable String[] selectionArgs, @Nullable String sortOrder,
@Nullable CancellationSignal cancellationSignal) {
Preconditions.checkNotNull(uri, "uri");
// 返回的是ContentProvider的中的mTransport(Transport)
IContentProvider unstableProvider = acquireUnstableProvider(uri);
if (unstableProvider == null) {
return null;
}
IContentProvider stableProvider = null;
Cursor qCursor = null;
try {
...
try {
qCursor = unstableProvider.query(mPackageName, uri, projection,
selection, selectionArgs, sortOrder, remoteCancellationSignal);
} catch (DeadObjectException e) {
// The remote process has died... but we only hold an unstable
// reference though, so we might recover!!! Let's try!!!!
// This is exciting!!1!!1!!!!1
unstableProviderDied(unstableProvider);
// 返回的是ContentProvider的中的mTransport(Transport)
stableProvider = acquireProvider(uri);
if (stableProvider == null) {
return null;
}
qCursor = stableProvider.query(mPackageName, uri, projection,
selection, selectionArgs, sortOrder, remoteCancellationSignal);
}
if (qCursor == null) {
return null;
}
...
// Wrap the cursor object into CursorWrapperInner object.
final IContentProvider provider = (stableProvider != null) ? stableProvider
: acquireProvider(uri);
final CursorWrapperInner wrapper = new CursorWrapperInner(qCursor, provider);
stableProvider = null;
qCursor = null;
return wrapper;
} catch (RemoteException e) {
...
return null;
} finally {
// 释放资源
...
}
}

首先是判断Uri是否是空,如果空抛出异常,如果不是获取unstableProvider,从名字看是不稳定的Provider,往下看还有个stableProvider(稳定的Provider),其实从代码看没有区别,只是第一次获取是不稳定的,出现异常就再次获取就是稳定的。所以我们只看一个即可。从注释可以知道unstableProvider其实是ContentProvider中的Transport对象mTransport,这个我们先提出来,后面通过代码看是不是对的。

2.ContentResolver.acquireUnstableProvider

1
2
3
4
5
6
7
8
9
10
11
12
13
public final IContentProvider acquireUnstableProvider(Uri uri) {
// uri以"content"开头
if (!SCHEME_CONTENT.equals(uri.getScheme())) {
return null;
}
// 获取Manifest文件中的authorities属性(例如:cn.codemx.myprovider.settings)
String auth = uri.getAuthority();
if (auth != null) {
// 具体实现ApplicationContentResolver中
return acquireUnstableProvider(mContext, uri.getAuthority());
}
return null;
}

这里主要是验证协议名是不是content,然后验证属性是不是存在,如果存在则开始获取实现IContentProvider接口的对象。

3.ApplicationContentResolver.acquireUnstableProvider

1
2
3
4
5
protected IContentProvider acquireUnstableProvider(Context c, String auth) {
return mMainThread.acquireProvider(c,
ContentProvider.getAuthorityWithoutUserId(auth),
resolveUserIdFromAuthority(auth), false);
}

这里调用的是ActivityThread.acquireProvider方法。

4.ActivityThread.acquireProvider

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public final IContentProvider acquireProvider(
Context c, String auth, int userId, boolean stable) {
// 返回的是ContentProvider的中的mTransport(Transport)
final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
if (provider != null) {// 如果不为空,说明访问过,如果是第一次访问,为空
return provider;
}
...
IActivityManager.ContentProviderHolder holder = null;
try {
// 核心部分
holder = ActivityManagerNative.getDefault().getContentProvider(
getApplicationThread(), auth, userId, stable);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
if (holder == null) {
Slog.e(TAG, "Failed to find provider info for " + auth);
return null;
}
// Install provider will increment the reference count for us, and break
// any ties in the race.
holder = installProvider(c, holder, holder.info,
true /*noisy*/, holder.noReleaseNeeded, stable);
return holder.provider;
}

先根据auth获取是否存在实现IContentProvider的类,如果存在直接返回,不存在则获取IActivityManager.ContentProviderHolder对象,然后获取实现IContentProvider接口的类。我们先看acquireExistingProvider方法。

5.ActivityThread.acquireExistingProvider

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public final IContentProvider acquireExistingProvider(
Context c, String auth, int userId, boolean stable) {
synchronized (mProviderMap) {
final ProviderKey key = new ProviderKey(auth, userId);
// mProviderMap保存当前应用程序进程访问过的ContentProvider组件代理对象
final ProviderClientRecord pr = mProviderMap.get(key);
if (pr == null) {// 如果不存在说明还没有访问过
return null;
}
// 返回的是ContentProvider的中的mTransport(Transport)
IContentProvider provider = pr.mProvider;
IBinder jBinder = provider.asBinder();
// 检查线程是否还存在
if (!jBinder.isBinderAlive()) {
...
return null;
}
// Only increment the ref count if we have one. If we don't then the
// provider is not reference counted and never needs to be released.
ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
if (prc != null) {
// 增加引用计数
incProviderRefLocked(prc, stable);
}
return provider;
}
}

首先是去缓存中获取,是否存在封装了ContentProvider对象的ProviderClientRecord对象,如果不存在则说明第一次启动,还没添加到缓存中,如果存在,那么说明已经启动过,则会有需要的实现IContentProvider接口的对象。再看第4步中如果返回对象不为空则直接返回,如果是空则要先获取IActivityManager.ContentProviderHolder。

6.ActivityManagerProxy.getContentProvider

1
2
3
4
5
6
7
8
public ContentProviderHolder getContentProvider(IApplicationThread caller,
String name, int userId, boolean stable) throws RemoteException {
...
// 通过Binder代理对象mRemote发送一个类型为GET_CONTENT_PROVIDER_TRANSACTION的进程间通信消息
mRemote.transact(GET_CONTENT_PROVIDER_TRANSACTION, data, reply, 0);
...
return cph;
}

这里我们在前面几章涉及到了很多次,就不再说了,主要是从这里调用AMS(ActivityManagerService)中的对应方法getContentProvider

7.AMS.getContentProvider

1
2
3
4
5
public final ContentProviderHolder getContentProvider(
IApplicationThread caller, String name, int userId, boolean stable) {
...
return getContentProviderImpl(caller, name, null, stable, userId);
}

这里比较简单,调用AMS.getContentProviderImpl方法。

8.AMS.getContentProviderImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
String name, IBinder token, boolean stable, int userId) {
ContentProviderRecord cpr;
ContentProviderConnection conn = null;
ProviderInfo cpi = null;
synchronized (this) {
// 描述进程信息的对象
ProcessRecord r = null;
if (caller != null) {// 如果调用者的线程存在,根据caller获取对应的进程
r = getRecordForAppLocked(caller);
// 如果找不到caller对应的进程抛出异常
...
}
...
// 根据名称和userId获取ContentProviderRecord对象,用来检测是不是ContentProvider已经发布了
cpr = mProviderMap.getProviderByName(name, userId);
// If that didn't work, check if it exists for user 0 and then
// verify that it's a singleton provider before using it.
if (cpr == null && userId != UserHandle.USER_SYSTEM) {// 如果不存在并且不是系统的userId
// 检测mProviderMap中是否存在系统的ContentProviderRecord对象,如果已经启动则存在
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.uid, cpi.applicationInfo.uid)) {
...
} else {
cpr = null;
cpi = null;
}
}
}
// 检查ContentProvider是否正在运行(第一次还没有运行)
boolean providerRunning = cpr != null && cpr.proc != null && !cpr.proc.killed;
if (providerRunning) {// ContentProvider已经运行
...
if (r != null && cpr.canRunHere(r)) {// 进程存在
ContentProviderHolder holder = cpr.newHolder(null);
holder.provider = null;
return holder;
}
...
// provider实例已经存在,因此我们直接返回
conn = incProviderCountLocked(r, cpr, token, stable);
// 如何stable和unstable的总引用计数为1,那么更新LruProcess列表
if (conn != null && (conn.stableCount + conn.unstableCount) == 1) {
if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
...
updateLruProcessLocked(cpr.proc, false, null);
}
}
final int verifiedAdj = cpr.proc.verifiedAdj;
// 更新provider进程的adj
boolean success = updateOomAdjLocked(cpr.proc);
...
if (!success) {// 如果更新不成功,那么减少引用计数并杀死provider进程
...
ppDiedLocked(cpr.proc);// 杀死进程
...
// 已经杀死了,所以要恢复初始状态
providerRunning = false;
conn = null;
} else {// 更新成功了
cpr.proc.verifiedAdj = cpr.proc.setAdj;
}
...
}
if (!providerRunning) {// 还没有运行,第一次启动
try {
// 根据ContentProvider的AUTHORITY来获取对应的配置信息(ProviderInfo)
cpi = AppGlobals.getPackageManager().
resolveContentProvider(name,
STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId);
} catch (RemoteException ex) {
}
// 没有找到对应的ProviderInfo,因此返回空
if (cpi == null) {
return null;
}
// Provider是否为单例
boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo,
cpi.name, cpi.flags)
&& isValidSingletonCall(r.uid, cpi.applicationInfo.uid);
...
// 通过ComponentName获取providerMap中的cpr
ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
// 先去缓存中找
cpr = mProviderMap.getProviderByClass(comp, userId);
// 是否是第一次启动
final boolean firstClass = cpr == null;
if (firstClass) {// 第一次启动
final long ident = Binder.clearCallingIdentity();
try {
// 获取应用信息
ApplicationInfo ai =
AppGlobals.getPackageManager().
getApplicationInfo(
cpi.applicationInfo.packageName,
STOCK_PM_FLAGS, userId);
...
// 创建一个cpr(ContentProviderRecord)
cpr = new ContentProviderRecord(this, cpi, ai, comp, singleton);
} catch (RemoteException ex) {
...
} finally {
...
}
}
...
if (r != null && cpr.canRunHere(r)) {// 进程存在且正在运行
return cpr.newHolder(null);
}
...
final int N = mLaunchingProviders.size();
int i;
for (i = 0; i < N; i++) {
if (mLaunchingProviders.get(i) == cpr) {
break;
}
}
// ContentProvider还没有被启动
if (i >= N) {
final long origId = Binder.clearCallingIdentity();
try {
...
// 获取运行ContentProvider的进程
ProcessRecord proc = getProcessRecordLocked(
cpi.processName, cpr.appInfo.uid, false);
// 如果进程已经存在并且没有被杀死
if (proc != null && proc.thread != null && !proc.killed) {
if (!proc.pubProviders.containsKey(cpi.name)) {
// 将描述ContentProvider的对象(ContentProviderRecord)以包名为键放到进程进行缓存
proc.pubProviders.put(cpi.name, cpr);
try {
// 安装ContentProvider
proc.thread.scheduleInstallProvider(cpi);
} catch (RemoteException e) {
}
}
} else {// 进程不存在
// 启动进程
proc = startProcessLocked(cpi.processName,
cpr.appInfo, false, 0, "content provider",
new ComponentName(cpi.applicationInfo.packageName,
cpi.name), false, false, false);
if (proc == null) {// 进程启动失败
return null;
}
}
cpr.launchingApp = proc;
mLaunchingProviders.add(cpr);
} finally {
...
}
}
if (firstClass) {// 第一次启动要保存ContentProvider
mProviderMap.putProviderByClass(comp, cpr);
}
// 保存
mProviderMap.putProviderByName(name, cpr);
conn = incProviderCountLocked(r, cpr, token, stable);
if (conn != null) {
conn.waiting = true;
}
}
}
...
return cpr != null ? cpr.newHolder(conn) : null;
}

这里代码比较多,但是思路比较清晰,首先是找对应的进程是否存在,因为我们正在启动ContentProvider,所以正常进程时存在的,然后根据进程找描述ContentProvider的描述对象ContentProviderRecord,如果第一次启动,这个描述对象是不存在的,如果不是第一次那么则存在该对象,其中providerRunning参数用来判断ContentProvider是否已经运行的,如果运行了直接返回,如果没有运行则创建ContentProvider的描述对象ContentProviderRecord,然后判断进程是否存在,存在则调用ApplicationThread.scheduleInstallProvider方法安装ContentProvider,不存在则直接启动进程。安装完成后缓存这些创建的ContentProvider相关的对象,方便下次使用直接从缓存获取。

9.ApplicationThread.scheduleInstallProvider

1
2
3
public void scheduleInstallProvider(ProviderInfo provider) {
sendMessage(H.INSTALL_PROVIDER, provider);
}

这里是发送消息到ApplicationThread中的H(继承Handler)中,然后调用ActivityThread.handleInstallProvider

10.ActivityThread.handleInstallProvider

1
2
3
4
5
6
7
8
public void handleInstallProvider(ProviderInfo info) {
final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
try {
installContentProviders(mInitialApplication, Lists.newArrayList(info));
} finally {
StrictMode.setThreadPolicy(oldPolicy);
}
}

调用installContentProviders方法。

11.ActivityThread.installContentProviders

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private void installContentProviders(
Context context, List<ProviderInfo> providers) {
final ArrayList<IActivityManager.ContentProviderHolder> results =
new ArrayList<IActivityManager.ContentProviderHolder>();
for (ProviderInfo cpi : providers) {
...
// 加载ContentProvider,然后调用ContentProvider的onCreate方法
IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
if (cph != null) {
cph.noReleaseNeeded = true;
results.add(cph);
}
}
try {
ActivityManagerNative.getDefault().publishContentProviders(
getApplicationThread(), results);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}

这里有两步,第一步:安装ContentProvider,然后调用ContentProvider.onCreate方法,第二步:调用AMP.publishContentProviders发布ContentProvider。我们先看第一步。

12.ActivityThread.installProvider

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
private IActivityManager.ContentProviderHolder installProvider(Context context,
IActivityManager.ContentProviderHolder holder, ProviderInfo info,
boolean noisy, boolean noReleaseNeeded, boolean stable) {
ContentProvider localProvider = null;
IContentProvider provider;
if (holder == null || holder.provider == null) {
...
try {
final java.lang.ClassLoader cl = c.getClassLoader();
// 根据名字通过类加载方式加载ContentProvider
localProvider = (ContentProvider) cl.
loadClass(info.name).newInstance();
// 获取provider,也就是ContentProvider中的mTransport(Transport),这个provider赋值给了retHolder,所以前面在获取的时候就是这个provider(Transport)
provider = localProvider.getIContentProvider();
...
// 添加ProviderInfo,然后调用ContentProvider的onCreate方法
localProvider.attachInfo(c, info);
} catch (java.lang.Exception e) {
...
return null;
}
} else {// localProvider == null
provider = holder.provider;
...
}
IActivityManager.ContentProviderHolder retHolder;
// 创建IActivityManager.ContentProviderHolder并且缓存ContentProvider相关信息
...
return retHolder;
}

这里通过反射获取ContentProvider,然后调用ContentProvider的onCreate方法。创建完成后会缓存到IActivityManager.ContentProviderHolder中,并且返回IActivityManager.ContentProviderHolder对象。在11步中我们提到两步,一个就是安装,一个是发布,下面我看发布的代码。

13.AMP.publishContentProviders

1
2
3
4
5
6
public void publishContentProviders(IApplicationThread caller,
List<ContentProviderHolder> providers) throws RemoteException {
...
mRemote.transact(PUBLISH_CONTENT_PROVIDERS_TRANSACTION, data, reply, 0);
...
}

通过这里调用AMS.publishContentProviders方法。

14.AMS.publishContentProviders

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public final void publishContentProviders(IApplicationThread caller,
List<ContentProviderHolder> providers) {
if (providers == null) {
return;
}
synchronized (this) {
// 获取进程描述对象
final ProcessRecord r = getRecordForAppLocked(caller);
...
final long origId = Binder.clearCallingIdentity();
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;
}
// 获取每个ContentProvider的描述对象ContentProviderRecord放到mProviderMap中
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);
}
int launchingCount = mLaunchingProviders.size();
...
synchronized (dst) {
dst.provider = src.provider;
dst.proc = r;
// 通知AMS provider已经"发布"成功
dst.notifyAll();
}
...
}
}
...
}
}

这里主要是从ContentProvider列表中获取对应的描述对象进行缓存,然后通知AMS中的ContentProvider发布完成。

15.ActivityThread.installProvider

这个方法我们上面12中分析了。只是一个是第一次启动,一个已经存在缓存了。

16.Transport.query

结合第1步和第12步我们知道IContentProvider unstableProvider返回的是ContentProvider中的mTransport,因此这里调用的是Transport.query方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public Cursor query(String callingPkg, Uri uri, String[] projection,
String selection, String[] selectionArgs, String sortOrder,
ICancellationSignal cancellationSignal) {
...
if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
...
// 回调目标ContentProvider所定义的query方法
Cursor cursor = ContentProvider.this.query(uri, projection, selection,
selectionArgs, sortOrder, CancellationSignal.fromTransport(
cancellationSignal));
if (cursor == null) {
return null;
}
// Return an empty cursor for all columns.
return new MatrixCursor(cursor.getColumnNames(), 0);
}
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.query(
uri, projection, selection, selectionArgs, sortOrder,
CancellationSignal.fromTransport(cancellationSignal));
} finally {
...
}
}

最终调用了ContentProvider.this.query方法。到此我们对于ContentProvider.this.query方法分析完成了。其实还有其他方法(insert,delete,update)逻辑也是差不多的,分析完一个其他也就很好分析。

到此Android系统四大组件都分析完了,可能感觉还是不够详细,其实还是要自己多看,多看几遍源码就熟悉了。后面开始分析View的绘制流程,因为这个相对来说非常复杂,如果一篇写完会写很长,看的话也很累,所以后面改用分章节去写,没章尽量分离开,尽量简短清晰,一看就能明白。

参考

从源码角度看ContentProvider
理解ContentProvider原理

代码地址:

直接拉取导入开发工具(Intellij idea或者Android studio)

由于coding与腾讯云合作,改变很多,所以后续代码切换到Gitlab。

https://gitlab.com/yuchuangu85/android-25

Android开发群:192508518

微信公众账号:Code-MX

注:本文原创,转载请注明出处,多谢。

×

纯属好玩

扫码支持
扫码打赏,多少你说算

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. ContentProvider
    1. 1.0.1. ContentProvider的描述及使用:
    2. 1.0.2. ContentProvider启动过程:
    3. 1.0.3. ContentProvider方法:
  • 2. ContentResolver的获取:
    1. 2.0.1. ContextImpl.getContentResolver():
  • 3. ContentResolver.query
    1. 3.0.1. 1.ContentResolver.query
    2. 3.0.2. 2.ContentResolver.acquireUnstableProvider
    3. 3.0.3. 3.ApplicationContentResolver.acquireUnstableProvider
    4. 3.0.4. 4.ActivityThread.acquireProvider
    5. 3.0.5. 5.ActivityThread.acquireExistingProvider
    6. 3.0.6. 6.ActivityManagerProxy.getContentProvider
    7. 3.0.7. 7.AMS.getContentProvider
    8. 3.0.8. 8.AMS.getContentProviderImpl
    9. 3.0.9. 9.ApplicationThread.scheduleInstallProvider
    10. 3.0.10. 10.ActivityThread.handleInstallProvider
    11. 3.0.11. 11.ActivityThread.installContentProviders
    12. 3.0.12. 12.ActivityThread.installProvider
    13. 3.0.13. 13.AMP.publishContentProviders
    14. 3.0.14. 14.AMS.publishContentProviders
    15. 3.0.15. 15.ActivityThread.installProvider
    16. 3.0.16. 16.Transport.query
  • 4. 参考
  • 5. 代码地址:
  • 6.
  • ,