Framework 学习(十)Content Provider 启动过程,android 快速开发
String table = cursor.getString(cursor.getColumnIndex("table_name"));
String name = cursor.getString(cursor.getColumnIndex("name"));
String detail = cursor.getString(cursor.getColumnIndex("detail"));
showlog("table_name:" + table);
showlog("name: " + name);
showlog("detail: " + detail);
cursor.moveToNext();
}
cursor.close();
}
要想调用 Content Provider,首先需要使用注释 1 处的 getContentResolver 方法,如下所示。
frameworks/base/core/Java/android/content/ContextWrapper.java
ContextWrapper#getContentResolver()
@Override
public ContentResolver getContentResolver() {
return mBase.getContentResolver();
}
[Framework 学习(八)Service 的启动/绑定过程](
)
这篇文章中我们已经分析了,mBase 具体指向就是 ContextImpl。
frameworks/base/core/java/android/app/ContextImpl.java
ContextImpl#getContentResolver()
private final ApplicationContentResolver mContentResolver;
...
@Override
public ContentResolver getContentResolver() {
return mContentResolver;
}
上面代码返回了 ApplicationContentResolver 类型的 mContentResolver 对象,ApplicationContentResolver 是 ContextImpl 中的静态内部类,继承自 ContentResolver,它在 ContextImpl 的构造方法中被创建。
当我们调用 ContentResolver 的 insert、query、update、delete 等方法时就会启动 Content Provider,这里拿 query 方法来进行举例。query 方法的实现在 ApplicationContentResolver 的父类 ContentResolver 中。
frameworks/base/core/java/android/content/ContentResolver.java
ContentResolver#query()
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");
IContentProvider unstableProvider = acquireUnstableProvider(uri); //1
...
try {
...
try {
qCursor = unstableProvider.query(mPackageName, uri, projection,
selection, selectionArgs, sortOrder, remoteCancellationSignal); //2
} catch (DeadObjectException e) {
...
}
...
}
注释 1 处通过 acquireUnstableProvider 方法返回 IContentProvider 类型的 unstableProvider 对象。
注释 2 处调用 unstableProvider 的 query 方法。
先看看注释 1 的方法吧。
ContentResolver#acquireUnstableProvider()
public final IContentProvider acquireUnstableProvider(Uri uri) {
if (!SCHEME_CONTENT.equals(uri.getScheme())) { //1
return null;
}
String auth = uri.getAuthority();
if (auth != null) {
return acquireUnstableProvider(mContext, uri.getAuthority()); //2
}
return null;
}
注释 1 处用来检查 Uri 的 scheme 是否等于”content”,如果不是则返回 null。
注释 2 处调用了 acquireUnstableProvider 方法,这是个抽象方法,它的实现在 ContentResolver 的子类 ApplicationContentResolver 中。
frameworks/base/core/java/android/app/ContextImpl.java
ApplicationContentResolver#acquireUnstableProvider()
@Override
protected IContentProvider acquireUnstableProvider(Context c, String auth) {
return mMainThread.acquireProvider(c,
ContentProvider.getAuthorityWithoutUserId(auth),
resolveUserIdFromAuthority(auth), false);
}
返回了 ActivityThread 类型的 mMainThread 对象的 acquireProvider 方法。
frameworks/base/core/java/android/app/ActivityThread.java
ActivityThread#acquireProvider()
public final IContentProvider acquireProvider(
Context c, String auth, int userId, boolean stable) {
final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable); //1
if (provider != null) {
return provider;
}
IActivityManager.ContentProviderHolder holder = null;
try {
holder = ActivityManagerNative.getDefault().getContentProvider(
getApplicationThread(), auth, userId, stable); //2
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
if (holder == null) {
Slog.e(TAG, "Failed to find provider info for " + auth);
return null;
}
holder = installProvider(c, holder, holder.info,
true /noisy/, holder.noReleaseNeeded, stable); //3
return holder.provider;
}
注释 1 处检查 ActivityThread 中的 ArrayMap 类型的 mProviderMap 中是否有目标 ContentProvider 存在,有则返回,没有就会在注释 2 处调用 AMP 的 getContentProvider 方法,最终会调用 AMS 的 getContentProvider 方法。
注释 3 处的 installProvider 方法用来将注释 2 处返回的 ContentProvider 相关的数据存储在 mProviderMap 中,起到缓存的作用,这样使用相同的 Content Provider 时,就不需要每次都要调用 AMS 的 getContentProvider 方法。
AMS 到 ActivityThread 的调用
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
ActivityManagerService#getContentProvider()
@Override
public final ContentProviderHolder getContentProvider(
IApplicationThread caller, String name, int userId, boolean stable) {
...
return getContentProviderImpl(caller, name, null, stable, userId);
}
ActivityManagerService#getContentProviderImpl()
private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
String name, IBinder token, boolean stable, int userId) {
...
ProcessRecord proc = getProcessRecordLocked(
cpi.processName, cpr.appInfo.uid, false); //1
if (proc != null && proc.thread != null && !proc.killed) {
...
if (!proc.pubProviders.containsKey(cpi.name)) {
checkTime(startTime, "getContentProviderImpl: scheduling install");
proc.pubProviders.put(cpi.name, cpr);
try {
proc.thread.scheduleInstallProvider(cpi); //2
} catch (RemoteException e) {
}
}
} else {
checkTime(startTime, "getContentProviderImpl: before start process");
proc = startProcessLocked(cpi.processName,
cpr.appInfo, false, 0, "content provider",
new ComponentName(cpi.applicationInfo.packageName,
cpi.name), false, false, false); //3
checkTime(startTime, "getContentProviderImpl: after start proces
s");
...
}
...
}
注释 1 处通过 getProcessRecordLocked 方法来获取目标 ContentProvider 的应用程序进程信息,这些信息用 ProcessRecord 类型的 proc 来表示,如果该应用进程已经启动就会调用注释 2 处的代码,否则就会调用注释 3 的 startProcessLocked 方法来启动进程。
应用程序进程启动过程请参考 Framework 学习(六)应用程序进程启动过程这篇文章。
ActivityThread 启动 Provider
frameworks/base/services/core/java/com/android/app/ActivityThread.java
ActivityThread#scheduleInstallProvider()
@Override
public void scheduleInstallProvider(ProviderInfo provider) {
sendMessage(H.INSTALL_PROVIDER, provider);
}
这里的 H 是 ActivityThread 的内部类并继承 Handler。
ActivityThread.H
private class H extends Handler {
public static final int INSTALL_PROVIDER = 145;
...
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case INSTALL_PROVIDER:
handleInstallProvider((ProviderInfo) msg.obj);
break;
评论