写点什么

Framework 学习(十)Content Provider 启动过程,android 快速开发

用户头像
Android架构
关注
发布于: 27 分钟前

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


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


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;

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Framework学习(十)Content Provider启动过程,android快速开发