
本文共 40214 字,大约阅读时间需要 134 分钟。
一 概述
ContentProvider 用于提供数据的统一访问格式,封装底层的具体实现。对于数据的使用者来说,无需知晓数据的来源是数据库、文件,或者网络,只需简单地使用 ContentProvider 提供的数据操作接口:增(insert)、删(delete)、改(update)、查(query) 即可,非常方便。在 Android 系统中通讯录或者短信的数据,都是以 ContentProvider 的形式提供的,ContentProvider 本质上就是是把数据存储在 SQLite 数据库中,另外 ContentProvider 读取数据时使用了匿名共享内存(ASM),ASM 实质上也是通过 Binder 通信的。
ContentProvider 的 onCreate 先于 Application 的 onCreate 启动,在应用启动的时候,会通过 ActivityThread 的 attach 方法,通过远程调用 AMS 的 attachApplication 来将 ApplicationThread 传递给 AMS,同时在该方法中会调用 ApplicationThread 的 bindApplication 方法,同样也是跨进程的。该方法最终跳转到 ActivityThread 中运行,具体为 handleBindApplication,进而调用 installContentProviders 完成 ContentProvider 的加载。
外界无法直接访问 ContentProvider,只能通过 AMS 根据 URI 来获取对应的 ContentProvider 的 Binder 接口 IContentProvider,然后再访问相应数据。
ContentProvider 可以做成多实例,通过属性控制,但是现实中很少采用因为浪费开销。外界访问其增删改查的任何一个方法都会导致 ContentProvider 的创建,并且拉起进程。
比如通过 query 方法启动 ContentProvider:
- 通过 acquireProvider 来获取 IContentProvider 对象
- 先检查本端 ActivityThread 中是否存在 ContentProvider,如果存在就直接返回(返回的是 IContentProvider 客户端接口对象)。如果没有,就通过远程 AMS.getContentProvider 方法
- ContentProvider 的启动伴随着进程的启动,启动进程靠的是 AMS 的 startProcessLocked,新进程启动后其入口方法为 ActivityThread.main() 方法,然后在 attach 方法中通过 attachApplication方法将ApplicationThread作为参数传递给AMS
- AMS 的方法中又调用了ApplicationThread.bindApplication
- ActivityThread 的 bindApplication 发送 BIND_APPLICATION 消息给 mH 使得 ActivityThread 完成一系列工作,包括(按步骤顺序):
- 创建 ContextImpl 和 instrumrent
- 创建 Application 对象
- 启动当前进程的 ContentProvider 并调用其 onCreate 方法,将创建好的 Contentprovider 保存在 AMS 中的 providerMap 中,这样外部调用者就能直接从 AMS 中获取 ContentProvider 了,然后调用其onCreate 方法
- 调用 Application 的 onCreate 方法
上述四个步骤之后,外部就能在 AMS 中拿到 ContentProvider 访问其接口了,但拿到的其实是 Binder 类型对象 IContentProvider。其具体实现是 ContentProvider.Transport,所以外界调用 query 方法时候,是通过调用 ContentProvider.Transport 中的 query 方法,其远程调用 ContentProvider.query 方法,结果通过 Binder 返回给调用者,其它方法调用类似。
涉及代码:
frameworks/base/core/java/android/app/ContextImpl.javaframeworks/base/core/java/android/app/ActivityThread.javaframeworks/base/core/java/android/content/ContentProvider.javaframeworks/base/core/java/android/content/ContentProviderNative.javaframeworks/base/core/java/android/app/ContentProviderHolder.javaframeworks/base/core/java/android/content/ContentResolver.javaframeworks/base/core/java/android/app/IActivityManager.aidlframeworks/base/core/java/android/os/ICancellationSignal.aidlframeworks/base/core/java/android/database/BulkCursorToCursorAdaptor.javaframeworks/base/core/java/android/database/AbstractWindowedCursor.javaframeworks/base/core/java/android/database/AbstractCursor.javaframeworks/base/core/java/android/database/CursorWindow.javaframeworks/base/core/jni/android_database_CursorWindow.cppframeworks/base/services/core/java/com/android/server/am/ActivityManagerService.javaframeworks/base/services/core/java/com/android/server/pm/PackageManagerService.javaframeworks/base/services/core/java/com/android/server/pm/ComponentResolver.javapackages/providers/ContactsProvider/src/com/android/providers/contacts/ContactsProvider2.java
二 分析流程
通过 ContentProvider 操作手机通信录的 demo 示例:
// 查询联系人信息public void getContactInfo() { ContentResolver contentResolver = getContext().getContentResolver(); Uri uri = Uri.parse("content://com.android.contacts/contacts"); Cursor cursor = contentResolver.query(uri, null, null, null, null); while(cursor.moveToNext()){ // 获取联系人姓名 String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); // 获取联系人手机号码 Cursor phones = contentResolver.query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ contactId, null, null); while (phones.moveToNext()) { String phone = phones.getString(phones.getColumnIndex("data1")); } // 获取联系人Email Cursor emails = contentResolver.query( ContactsContract.CommonDataKinds.Email.CONTENT_URI, null, ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = " + contactId, null, null); while (emails.moveToNext()) { String email = emails.getString(emails.getColumnIndex("data1")); } }}// 添加联系人信息public void addContactInfo() { ContentValues values = new ContentValues(); // 首先向RawContacts.CONTENT_URI执行一个空值插入,目的是获取系统返回的rawContactId Uri rawContactUri = getContext().getContentResolver().insert(RawContacts.CONTENT_URI, values); long rawContactId = ContentUris.parseId(rawContactUri); // 往data表中插入联系人信息 values.clear(); values.put(Data.RAW_CONTACT_ID, rawContactId); values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); // 名字 values.put(StructuredName.GIVEN_NAME, "zhangsan"); // 手机号码 values.put(Phone.NUMBER, "5554"); values.put(Phone.TYPE, Phone.TYPE_MOBILE); // Email values.put(Email.DATA, "ljq218@126.com"); values.put(Email.TYPE, Email.TYPE_WORK); getContext().getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);}
本文以获取联系人姓名(即 query 操作) 为例进行分析。
2.1 ContextImpl.getContentResolver
frameworks/base/core/java/android/app/ContextImpl.java
private final ApplicationContentResolver mContentResolver;private ContextImpl(@Nullable ContextImpl container, @NonNull ActivityThread mainThread, @NonNull LoadedApk packageInfo, @Nullable String splitName, @Nullable IBinder activityToken, ......) { ... mContentResolver = new ApplicationContentResolver(this, mainThread);} @Overridepublic ContentResolver getContentResolver() { return mContentResolver;}
2.2 ApplicationContentResolver
frameworks/base/core/java/android/app/ContextImpl.java
private static final class ApplicationContentResolver extends ContentResolver { private final ActivityThread mMainThread; public ApplicationContentResolver(Context context, ActivityThread mainThread) { super(context); mMainThread = Preconditions.checkNotNull(mainThread); } @Override protected IContentProvider acquireProvider(Context context, String auth) { return mMainThread.acquireProvider(context, ContentProvider.getAuthorityWithoutUserId(auth), resolveUserIdFromAuthority(auth), true); } @Override protected IContentProvider acquireExistingProvider(Context context, String auth) { return mMainThread.acquireExistingProvider(context, ContentProvider.getAuthorityWithoutUserId(auth), resolveUserIdFromAuthority(auth), true); } @Override protected IContentProvider acquireUnstableProvider(Context c, String auth) { return mMainThread.acquireProvider(c, ContentProvider.getAuthorityWithoutUserId(auth), resolveUserIdFromAuthority(auth), false); } protected int resolveUserIdFromAuthority(String auth) { return ContentProvider.getUserIdFromAuthority(auth, getUserId()); } ......}
而 ApplicationContentResolver 继承 ContentResolver,我们看下父类的实现:
frameworks/base/core/java/android/content/ContentResolver.javapublic abstract class ContentResolver implements ContentInterface { ...... public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { return query(uri, projection, selection, selectionArgs, sortOrder, null); } public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder, @Nullable CancellationSignal cancellationSignal) { // 将查询条件封装到Bundle. 参考【第4.1节】 Bundle queryArgs = createSqlQueryBundle(selection, selectionArgs, sortOrder); // 查询操作. 参考【第4.2节】 return query(uri, projection, queryArgs, cancellationSignal); } ......}
其中 ContentResolver.query(…) 各参数含义如下:
- uri:URI 类型, 以 content:// 开头, 如 content://com.android.contacts/contacts
- projection:String[] 类型, 表示返回哪些列, null 表示返回所有列
- selection:String 类型, SQL WHERE 后面语句(可以用?占位), 表示返回哪行, null 表示返回所有行
- selectionArgs:String[] 类型, 表示 selection 中?占位符的值
- sortOrder:返回行的排序方式, ORDER BY 后面语句, null 表示默认方式(即无序)
- cancellationSignal:CancellationSignal 类型, 取消某操作(ContentResolver 增删改查操作)的信号, 当操作取消时会抛出OperationCanceledException 异常, null 表示不取消
- 返回值:Cursor 类型, 指向第一项的前面, 可能返回 null (如果没有返回内容)
2.3 ContentResolver.createSqlQueryBundle
public static @Nullable Bundle createSqlQueryBundle( @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { if (selection == null && selectionArgs == null && sortOrder == null) { return null; } Bundle queryArgs = new Bundle(); if (selection != null) { queryArgs.putString(QUERY_ARG_SQL_SELECTION, selection); } if (selectionArgs != null) { queryArgs.putStringArray(QUERY_ARG_SQL_SELECTION_ARGS, selectionArgs); } if (sortOrder != null) { queryArgs.putString(QUERY_ARG_SQL_SORT_ORDER, sortOrder); } return queryArgs;}
2.3 ContentResolver.query
@Overridepublic final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri, @Nullable String[] projection, @Nullable Bundle queryArgs, @Nullable CancellationSignal cancellationSignal) { // 此处mWrapped为空, 调不到 if (mWrapped != null) { return mWrapped.query(uri, projection, queryArgs, cancellationSignal); } // 获取ContentProviderProxy对象(stable为false). IContentProvider unstableProvider = acquireUnstableProvider(uri); if (unstableProvider == null) { return null; } IContentProvider stableProvider = null; Cursor qCursor = null; try { long startTime = SystemClock.uptimeMillis(); ICancellationSignal remoteCancellationSignal = null; if (cancellationSignal != null) { cancellationSignal.throwIfCanceled(); // 拿到ICancellationSignal.Stub.Proxy remoteCancellationSignal = unstableProvider.createCancellationSignal(); // 设置远程代理 cancellationSignal.setRemote(remoteCancellationSignal); } try { // ContentProviderProxy#query. qCursor = unstableProvider.query(mPackageName, uri, projection, queryArgs, remoteCancellationSignal); } catch (DeadObjectException e) { unstableProviderDied(unstableProvider); // 获取ContentProviderProxy对象(stable为true) stableProvider = acquireProvider(uri); if (stableProvider == null) { return null; } // ContentProviderProxy#query qCursor = stableProvider.query(mPackageName, uri, projection, queryArgs, remoteCancellationSignal); } if (qCursor == null) { return null; } // 获取查到的行数, 当qCursor被关闭时会抛出异常 qCursor.getCount(); // CursorWrapperInner封装qCursor和provder并返回 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 { // 资源释放 if (qCursor != null) { qCursor.close(); } if (cancellationSignal != null) { cancellationSignal.setRemote(null); } if (unstableProvider != null) { releaseUnstableProvider(unstableProvider); } if (stableProvider != null) { releaseProvider(stableProvider); } }}
ContentResolver#query 分为2个主要步骤:获取 Provider 和 query 查询。
2.4 ContentResolver.acquireUnstableProvider
// 根据Uri查询ContentProviderpublic final IContentProvider acquireUnstableProvider(Uri uri) { // uri必须以content开头 if (!SCHEME_CONTENT.equals(uri.getScheme())) { return null; } // 获取authority(全格式为host:port) String auth = uri.getAuthority(); if (auth != null) { // 走到实现类ApplicationContentResolver#acquireUnstableProvider // 最终走到ActivityThread.acquireProvider return acquireUnstableProvider(mContext, uri.getAuthority()); } return null;}private static final class ApplicationContentResolver extends ContentResolver { @UnsupportedAppUsage private final ActivityThread mMainThread; public ApplicationContentResolver(Context context, ActivityThread mainThread) { super(context); mMainThread = Preconditions.checkNotNull(mainThread); } ...... @Override protected IContentProvider acquireUnstableProvider(Context c, String auth) { return mMainThread.acquireProvider(c, ContentProvider.getAuthorityWithoutUserId(auth), resolveUserIdFromAuthority(auth), false); } ...... }
2.5 ActivityThread.acquireProvider
public final IContentProvider acquireProvider(Context c, String auth, ......) { // 先从map缓存中查询本地ContentProvider. final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable); if (provider != null) { return provider; } // IActivity.Stub.Proxy#getContentProvider获取ContentProviderHolder. ContentProviderHolder holder = null; synchronized (getGetProviderLock(auth, userId)) { holder = ActivityManager.getService().getContentProvider( getApplicationThread(), c.getOpPackageName(), auth, userId, stable); } if (holder == null) { return null; } // 增加引用计数, 同时删除老的provider holder = installProvider(c, holder, holder.info, true /*noisy*/, holder.noReleaseNeeded, stable); // ContentProviderProxy return holder.provider;}
获取 ContentProvider 过程:
1.先根据 ProviderKey 从本地缓存中查询, 若查询到则直接返回 2.若本地缓存没有, 则通过 Binder 通信找 AMS 获取其中 ProviderKey 由 authority 和 userId 组成,它们的获取逻辑为:
frameworks/base/core/java/android/content/ContentProvider.java
/ 例如userId@some.authority, 返回值为some.authority public static String getAuthorityWithoutUserId(String auth) { if (auth == null) return null; int end = auth.lastIndexOf('@'); return auth.substring(end+1);} // 例如userId@some.authority, 返回值为userIdpublic static int getUserIdFromAuthority(String auth, int defaultUserId) { if (auth == null) return defaultUserId; int end = auth.lastIndexOf('@'); if (end == -1) return defaultUserId; String userIdString = auth.substring(0, end); try { return Integer.parseInt(userIdString); } catch (NumberFormatException e) { return UserHandle.USER_NULL; }}
2.5.1 ActivityThread.acquireExistingProvider
// 从缓存查询ContentProviderpublic final IContentProvider acquireExistingProvider(Context c, String auth, int userId, boolean stable) { synchronized (mProviderMap) { // 根据authority和userId封装ProviderKey对象 final ProviderKey key = new ProviderKey(auth, userId); // 根据ProviderKey查询ProviderClientRecord final ProviderClientRecord pr = mProviderMap.get(key); if (pr == null) { return null; } // 拿到ContentProviderProxy IContentProvider provider = pr.mProvider; // 拿到mRemote-Transport(即ContentProviderNative实现类) IBinder jBinder = provider.asBinder(); if (!jBinder.isBinderAlive()) { // 若mRemote所在进程已经死掉, 则从mProviderMap和mProviderRefCountMap // 中移除该provider及引用计数, 并告诉AMS该provider不可用 handleUnstableProviderDiedLocked(jBinder, true); return null; } // 获取provider引用计数, 引用计数+1 ProviderRefCount prc = mProviderRefCountMap.get(jBinder); if (prc != null) { incProviderRefLocked(prc, stable); } return provider; }}
2.5.2 ActivityThread.incProviderRefLocked
private final void incProviderRefLocked(ProviderRefCount prc, boolean stable) { if (stable) { prc.stableCount += 1; if (prc.stableCount == 1) { int unstableDelta; if (prc.removePending) { unstableDelta = -1; prc.removePending = false; mH.removeMessages(H.REMOVE_PROVIDER, prc); } else { unstableDelta = 0; } ActivityManager.getService().refContentProvider(prc.holder.connection, 1, unstableDelta); } } else { prc.unstableCount += 1; if (prc.unstableCount == 1) { if (prc.removePending) { prc.removePending = false; mH.removeMessages(H.REMOVE_PROVIDER, prc); } else { ActivityManager.getService().refContentProvider(prc.holder.connection, 0, 1); } } }}
若本地缓存没有查找到, 则通过 Binder 通信找 AMS 获取。
下面主要分析 ActivityManager.getService().getContentProvider(…) 过程。是 AMP 向 AMS 发送获取 ContentProvider 对象的请求, AMS 会向 AMP 返回 ContentProvider。那么通过 AMP.getContentProvider(…) 获取到的 provider 究竟是什么呢? 我们通过下面的分析会知道是 ContentProviderProxy.2.6 AMP.getContentProvider
2.6.1 IActivityManager.aidl
interface IActivityManager { ...... ContentProviderHolder getContentProvider(in IApplicationThread caller, in String callingPackage, in String name, int userId, boolean stable); ......}
IActivityManager.aidl 文件编译后的 Java 文件为:
public interface IActivityManager extends android.os.IInterface{ /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements android.app.IActivityManager { private static final java.lang.String DESCRIPTOR = "android.app.IActivityManager"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } // Cast an IBinder object into an android.app.IActivityManager interface, // generating a proxy if needed. public static android.app.IActivityManager asInterface(android.os.IBinder obj) { if ((obj==null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin!=null)&&(iin instanceof android.app.IActivityManager))) { return ((android.app.IActivityManager)iin); } return new android.app.IActivityManager.Stub.Proxy(obj); } @Override public android.os.IBinder asBinder() { return this; } @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { java.lang.String descriptor = DESCRIPTOR; switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(descriptor); return true; } case TRANSACTION_getContentProvider: { data.enforceInterface(descriptor); IApplicationThread _arg0 = (IApplicationThread) data.readStrongBinder(); java.lang.String _arg1 = (java.lang.String) data.readString(); java.lang.String _arg2 = data.readString(); int _arg3 = data.readInt(); boolean _arg4 = data.readBoolean(); android.app.ContentProviderHolder _result = this.getContentProvider(_arg0, _arg1, _arg2, _arg3, _arg4); reply.writeNoException(); if ((_result!=null)) { reply.writeInt(1); // 会走到ContentProviderHolder.writeToParcel // reply中写进的provider是Transport _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { reply.writeInt(0); } return true; } default: { return super.onTransact(code, data, reply, flags); } } } private static class Proxy implements android.app.IActivityManager { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } @Override public android.app.ContentProviderHolder getContentProvider( in IApplicationThread caller, java.lang.String callingPackage, java.lang.String name, int userId, boolean stable) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); android.app.ContentProviderHolder _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeStrongBinder(caller); _data.writeString(callingPackage); _data.writeString(name); _data.writeInt(userId); _data.writeBoolean(stable); mRemote.transact(Stub.TRANSACTION_getContentProvider, _data, _reply, 0); _reply.readException(); if ((0!=_reply.readInt())) { // 最终ContentProviderHolder中读取出来的 // provider是ContentProviderProxy _result = android.app.ContentProviderHolder.CREATOR.createFromParcel(_reply); } else { _result = null; } } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_getContentProvider = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); } public android.app.ContentProviderHolder getContentProvider( in IApplicationThread caller, java.lang.String callingPackage, java.lang.String name, int userId, boolean stable) throws android.os.RemoteException;}
IActivityManager.aidl 的调用逻辑
IActivityManager.Stub.Proxy#getContentProvider -> mRemote.transact ->IActivityManager.Stub#onTransact -> IActivityManager#getContentProvider(AMS端) ->ContentViewHolder.writeToParcel(AMS端) -> ContentProviderHolder.CREATOR.createFromParcel(AMP端)
我们再看 AMS.getContentProvider 过程, 那么它返回的 provider 是什么呢?
2.6.2 AMS.getContentProvider
@Overridepublic final ContentProviderHolder getContentProvider( IApplicationThread caller, ......) { // 不允许isolate进程调用 enforceNotIsolatedCaller("getContentProvider"); ... final int callingUid = Binder.getCallingUid(); return getContentProviderImpl(caller, name, null, ......);}private ContentProviderHolder getContentProviderImpl(IApplicationThread caller, String name, IBinder token, int callingUid, String callingPackage, String callingTag, boolean stable, int userId) { ContentProviderRecord cpr; ContentProviderConnection conn = null; ProviderInfo cpi = null; boolean providerRunning = false; synchronized(this) { long startTime = SystemClock.uptimeMillis(); ProcessRecord r = null; if (caller != null) { r = getRecordForAppLocked(caller); } boolean checkCrossUser = true; //根据name获取ContentProviderRecord对象, 若普通用户未获取到, 则从系统用户获取 cpr = mProviderMap.getProviderByName(name, userId); if (cpr == null && userId != UserHandle.USER_SYSTEM) { 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)) { userId = UserHandle.USER_SYSTEM; checkCrossUser = false; } else { cpr = null; cpi = null; } } } // 检查ContentProviderRecord所在进程是否被杀, 若进程被杀, 执行数据清理操作 if (cpr != null && cpr.proc != null) { // 检查provider是否正在运行 providerRunning = !cpr.proc.killed; if (cpr.proc.killed && cpr.proc.killedByAm) { appDiedLocked(cpr.proc); } } // 若provider正在运行 if (providerRunning) { cpi = cpr.info; String msg; if (r != null && cpr.canRunHere(r)) { // 权限检查 ... ContentProviderHolder holder = cpr.newHolder(null); holder.provider = null; return holder; } // IPackageManager.Stub.Proxy#resolveContentProvider. //Binder通信PMP请求PMS解析出ContentProvider, 即PMS.resolveContentProvider // 而PMS又通过ComponentResolver组件解析器解析出ProviderInfo. // 对于联系人ProviderInfo中provider名称是ContactsProvider2 if (AppGlobals.getPackageManager().resolveContentProvider(name, 0 /*flags*/, userId) == null) { return null; } final long origId = Binder.clearCallingIdentity(); // ContentProviderRecord计数+1 conn = incProviderCountLocked(r, cpr, token, ......); if (conn != null && (conn.stableCount+conn.unstableCount) == 1) { if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) { // 更新lru进程信息 mProcessList.updateLruProcessLocked(cpr.proc, false, null); } } final int verifiedAdj = cpr.proc.verifiedAdj; boolean success = updateOomAdjLocked(cpr.proc, true, OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER); if (success && verifiedAdj != cpr.proc.setAdj && !isProcessAliveLocked(cpr.proc)) { success = false; } if (!success) { boolean lastRef = decProviderCountLocked(conn, cpr, token, stable); appDiedLocked(cpr.proc); if (!lastRef) { return null; } providerRunning = false; conn = null; } else { cpr.proc.verifiedAdj = cpr.proc.setAdj; } Binder.restoreCallingIdentity(origId); } // 若provider不在运行 if (!providerRunning) { // IPackageManager.Stub.Proxy#resolveContentProvider. // Binder通信PMP请求PMS解析出ContentProvider, 即PMS.resolveContentProvider // 而PMS又通过ComponentResolver组件解析器解析出ProviderInfo. // 对于联系人ProviderInfo中provider名称是ContactsProvider2 cpi = AppGlobals.getPackageManager().resolveContentProvider(name, STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId); if (cpi == null) { return null; } boolean singleton = isSingleton(cpi.processName, ......) && isValidSingletonCall(r.uid, cpi.applicationInfo.uid); if (singleton) { userId = UserHandle.USER_SYSTEM; } cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo, userId); // 各种有效性检查, 包括:系统是否ready ... // 根据ComponentName从mProviderMap中查找, 若没找到则新建 ComponentName comp = new ComponentName(cpi.packageName, cpi.name); cpr = mProviderMap.getProviderByClass(comp, userId); final boolean firstClass = cpr == null; if (firstClass) { try { ApplicationInfo ai = AppGlobals.getPackageManager().getApplicationInfo( cpi.applicationInfo.packageName, STOCK_PM_FLAGS, userId); ai = getAppInfoForUser(ai, userId); cpr = new ContentProviderRecord(this, cpi, ai, comp, singleton); } catch (RemoteException ex) { // pm is in same process, this will never happen. } finally { Binder.restoreCallingIdentity(ident); } } // 如果是单进程, 或provider允许多进程多个实例 if (r != null && cpr.canRunHere(r)) { return cpr.newHolder(null); } // 检查当前ContentProviderRecord是否已启动 final int N = mLaunchingProviders.size(); int i; for (i = 0; i < N; i++) { if (mLaunchingProviders.get(i) == cpr) { break; } } // 若当前ContentProviderRecord未启动 if (i >= N) { final long origId = Binder.clearCallingIdentity(); try { // Content provider is now in use, its package can't be stopped. AppGlobals.getPackageManager().setPackageStoppedState( cpr.appInfo.packageName, false, userId); // 获取当前ContentProvider所在进程 ProcessRecord proc = getProcessRecordLocked( cpi.processName, cpr.appInfo.uid, false); if (proc != null && proc.thread != null && !proc.killed) { // 若进程正在运行中, 且cpi还未发布, 则将其加到map中并发布Provider if (!proc.pubProviders.containsKey(cpi.name)) { proc.pubProviders.put(cpi.name, cpr); // 安装和发布provider proc.thread.scheduleInstallProvider(cpi); } } else { // 否则启动新进程 proc = startProcessLocked(cpi.processName, cpr.appInfo, false, 0, new HostingRecord("content provider", new ComponentName(cpi.applicationInfo.packageName, cpi.name)), false, false, false); } // cpr添加到mLaunchingProviders列表 cpr.launchingApp = proc; mLaunchingProviders.add(cpr); } finally { Binder.restoreCallingIdentity(origId); } } // ContentProviderRecord对象存到mProviderMap if (firstClass) { mProviderMap.putProviderByClass(comp, cpr); } mProviderMap.putProviderByName(name, cpr); // provider引用+1 conn = incProviderCountLocked(r, cpr, token, callingUid, ......); if (conn != null) { conn.waiting = true; } } } // 等待provider被发布, 超时时间20秒 final long timeout = SystemClock.uptimeMillis() + CONTENT_PROVIDER_WAIT_TIMEOUT; boolean timedOut = false; synchronized (cpr) { while (cpr.provider == null) { try { final long wait = Math.max(0L, timeout - SystemClock.uptimeMillis()); if (conn != null) { conn.waiting = true; } cpr.wait(wait); if (cpr.provider == null) { timedOut = true; break; } } catch (InterruptedException ex) { } finally { if (conn != null) { conn.waiting = false; } } } } // 超时返空 if (timedOut) { return null; } // 返回ContentProviderHolder. 持有的provider是 // ContactsProvider2(可理解为Transport) return cpr.newHolder(conn);}
AMS.getContentProvider(String name, int userId) 总结:
1.根据 name 从 mProviderMap 中查找 ContentProviderRecord 对象 cpr, 若普通用户未获取到, 则从系统用户获取 2.如果 cpr 非空, 则检查 cpr 所在进程是否被杀, 若进程被杀, 执行数据清理操作. 检查 provider 是否正在运行 3.若 provider 正在运行:通过 IPackageManger.Stub.Proxy#resolveContentProvider 解析出 ProviderInfo, 且 cpr 引用计数 +1, 并更新 lru 进程信息 4.若 provider 不在运行:- 通过 IPackageManger.Stub.Proxy#resolveContentProvider 解析出 ProviderInfo
- 根据 ProviderInfo 封装 ComponentName, 并从 mProviderMap 中查找 cpr, 若没找到则新建一个
- 如果当前是单进程, 或 provider 允许多进程多个实例, 则直接返回
- 检查 cpr 是否在 mLaunchingProviders 列表, 若不在, 则检查 cpr 所在进程是否正在运行.
- 若 cpr 所在进程正在运行, 但 ProviderInfo 对应的 provider 还未发布, 则将 ProviderInfo 加到 map 中, 执行 ApplicationThread#scheduleInstallProvider 发布 Provider
- 若 cpr 所在进程不在运行, 则启动新进程. cpr 添加到 mLaunchingProviders 和 mProviderMap, cpr 引用计数+1, 等待 provider 被发布, 超时时间20秒, 若超时返空
5.返回 ContentProviderHolder. 此时持有的 provider 是 ContactsProvider2 (可理解为 Transport)
2.6.3 PMS.resolveContentProvider
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
@Overridepublic ProviderInfo resolveContentProvider(String name, int flags, int userId) { return resolveContentProviderInternal(name, flags, userId);} private ProviderInfo resolveContentProviderInternal(String name, ......) { if (!sUserManager.exists(userId)) return null; flags = updateFlagsForComponent(flags, userId, name); final int callingUid = Binder.getCallingUid(); // 组件解析器解析ComponentResolver.queryProvider. final ProviderInfo providerInfo = mComponentResolver.queryProvider(name, flags, userId); if (providerInfo == null) { return null; } if (!mSettings.isEnabledAndMatchLPr(providerInfo, flags, userId)) { return null; } synchronized (mPackages) { final PackageSetting ps = mSettings.mPackages.get(providerInfo.packageName); final ComponentName component = new ComponentName(providerInfo.packageName, providerInfo.name); if (filterAppAccessLPr(ps, callingUid, component, TYPE_PROVIDER, userId)) { return null; } return providerInfo; }}
我们知道 PMS.resolveContentProvider 最终会拿到 ContactsProvider2. 那么它是怎么拿到的呢? 我们继续往下看这个过程.
2.6.4 ComponentResolver.queryProvider
frameworks/base/services/core/java/com/android/server/pm/ComponentResolver.java
ProviderInfo queryProvider(String authority, int flags, int userId) { synchronized (mLock) { final PackageParser.Provider p = mProvidersByAuthority.get(authority); if (p == null) { return null; } final PackageSetting ps = (PackageSetting) p.owner.mExtras; if (ps == null) { return null; } return PackageParser.generateProviderInfo(p, flags, ......); }}
现在分析下 mProvidersByAuthority 的取值.
根据赋值的地方反查可得出如下调用链:PMS: PackageHandler.INIT_COPY -> startCopy -> handleReturnCode -> processPendingInstall -> processInstallRequestsAsync -> installPackagesLI -> commitPackagesLocked -> commitReconciledScanResultLocked -> commitPackageSettingsComponentResolver: addAllComponents -> addProvidersLocked
我们再看下 ComponentResolver#addProvidersLocked 实现。
private void addProvidersLocked(PackageParser.Package pkg, boolean chatty) { final int providersSize = pkg.providers.size(); StringBuilder r = null; for (int i = 0; i < providersSize; i++) { PackageParser.Provider p = pkg.providers.get(i); p.info.processName = fixProcessName(pkg.applicationInfo.processName, p.info.processName); mProviders.addProvider(p); p.syncable = p.info.isSyncable; if (p.info.authority != null) { String[] names = p.info.authority.split(";"); p.info.authority = null; for (int j = 0; j < names.length; j++) { if (j == 1 && p.syncable) { p = new PackageParser.Provider(p); p.syncable = false; } if (!mProvidersByAuthority.containsKey(names[j])) { mProvidersByAuthority.put(names[j], p); if (p.info.authority == null) { p.info.authority = names[j]; } else { p.info.authority = p.info.authority + ";" + names[j]; } } else { final PackageParser.Provider other = mProvidersByAuthority.get(names[j]); final ComponentName component = (other != null && other.getComponentName() != null) ? other.getComponentName() : null; final String packageName = component != null ? component.getPackageName() : "?"; } } } }}
其中有个很重要的角色:包解析器 PackageParser, 它会在 App 安装过程中解析各种文件包括 AndroidManifest.xml
解析出来的信息会封装在 PackageParser.Package 对象中.我们再看下 Contacts 应用程序的 providers 包下的 AndroidManifest.xml 文件.
packages/providers/ContactsProvider/AndroidManifest.xml............ ......
mProvidersByAuthority 最终会存储 key 为 contacts 和 com.android.contacts, value 为 ContactsProvider2 的信息. 因此我们得出结论, PMS.resolveContentProvider 拿到的是 ContactsProvider2 对应的 ProviderInfo.
那么经过 AIDL Binder 通信, AMP.getContentProvider 拿到的究竟是什么呢?
我们再看下 ContentProviderHolder 的实现:2.6.5 ContentProviderHolder
frameworks/base/core/java/android/app/ContentProviderHolder.java
public class ContentProviderHolder implements Parcelable { public final ProviderInfo info; public IContentProvider provider; public IBinder connection; public boolean noReleaseNeeded; public ContentProviderHolder(ProviderInfo _info) { info = _info; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { info.writeToParcel(dest, 0); if (provider != null) { // 写入的是Transport dest.writeStrongBinder(provider.asBinder()); } else { dest.writeStrongBinder(null); } dest.writeStrongBinder(connection); dest.writeInt(noReleaseNeeded ? 1 : 0); } public static final Parcelable.CreatorCREATOR = new Parcelable.Creator () { @Override public ContentProviderHolder createFromParcel(Parcel source) { return new ContentProviderHolder(source); } @Override public ContentProviderHolder[] newArray(int size) { return new ContentProviderHolder[size]; } }; private ContentProviderHolder(Parcel source) { info = ProviderInfo.CREATOR.createFromParcel(source); // 拿到的provider是ContentProviderProxy provider = ContentProviderNative.asInterface(source.readStrongBinder()); connection = source.readStrongBinder(); noReleaseNeeded = source.readInt() != 0; }}
结合上面的 IActivityManager.aidl 分析过程中的调用链:
IActivityManager.Stub.Proxy#getContentProvider -> mRemote.transact ->IActivityManager.Stub#onTransact -> IActivityManager#getContentProvider(AMS端) ->ContentViewHolder.writeToParcel(AMS端) -> ContentProviderHolder.CREATOR.createFromParcel(AMP端)
我们已经知道了AMS.getContentProvider 拿到的是 ContactsProvider2 (可理解为 Transport 和 ContentProviderNative)
结合 ContentProviderHolder 源码可知, ContentViewHolder.writeToParcel (AMS 端)写入的是 Transport, ContentProviderHolder.CREATOR.createFromParcel(AMP 端) 拿到的是 ContentProviderProxy.最终 ActivityManager.getService().getContentProvider(…) 拿到的是 ContentProviderProxy
同时只有 provider 先发布, 才能获取到 provider. 发布逻辑主要在 ApplicationThread.scheduleInstallProvider
发表评论
最新留言
关于作者
