ContentProvider通过Binder进程间通信机制来突破应用程序边界的权限控制(IBulkCursor和IContentProvider),同时以共享内存作为数据载体(CursorWindow),ContentProviderProxy所对应的进程通过IBulkCursor和CursorWindow来操作数据集合
类的简单说明
BulkCursorToCursorAdaptor
将BulkCursor代理对象转成Cursor的适配器类
BulkCursorNative
IBulkCursor Binder本地对象
BulkCursorProxy
IBulkCursor Binder代理对象
ContentProviderNative
IContentProvider Binder本地对象
ContentProviderProxy
IContentProvider Binder代理对象
CursorToBulkCursorAdaptor
将ContentPrivade中查询得到的Cursor对象适配成IBulkCursor对象
BulkCursorDescriptor
Binder进程间通信传递IBulkCursor和CursorWindow对象
CursorWindow
匿名共享内存的封装类
Cursor
数据操作的抽象接口
ContentResolver.java (d:\source\android\android8.0\android-8.0.0_r1\frameworks\base\core\java\android\content)
unstableProvider是通过AMS获取得到的IContentProvider Binder代理对象,IContentProvider Binder代理对象对应的类为ContentProviderProxy,接下来分析ContentProviderProxy的query函数
public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,
@Nullable String[] projection, @Nullable Bundle queryArgs,
@Nullable CancellationSignal cancellationSignal) {
IContentProvider unstableProvider = acquireUnstableProvider(uri);
try {
// unstableProvider为IContentProvider代理对象,对应ContentProviderProxy的query函数
qCursor = unstableProvider.query(mPackageName, uri, projection,
queryArgs, remoteCancellationSignal);
} catch (DeadObjectException e) {
}
qCursor.getCount();
long durationMillis = SystemClock.uptimeMillis() - startTime;
maybeLogQueryToEventLog(durationMillis, uri, projection, queryArgs);
// 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;
// 将CursorWrapperInner返回给调用者
return wrapper;
} catch (RemoteException e) {
return null;
} finally {
}
}
ContentProviderNative.java (d:\source\android\android8.0\android-8.0.0_r1\frameworks\base\core\java\android\content)
ContentProviderProxy的query函数首先创建一个BulkCursorToCursorAdaptor对象,BulkCursorToCursorAdaptor对象从名字上来看是将IBulkCursor对象适配成Cursor操作的接口类,封装IBulkCursor的细节.接下来将数据查询的信息写入Pracel,然后将数据通过Binder驱动发送给IContentProvider的Binder本地对象ContentProviderNative,Binder通信返回后,如果有数据,从Binder对象中读取对应的BulkCursorDescriptor信息,BulkCursorDescriptor中有两个重要的信息,IBulkCursor和CursorWindow代理对象,将BulkCursorDescriptor保存在BulkCursorToCursorAdaptor中,以提供给对应的客服端程序对具体的数据操作
ContentProviderProxy
public Cursor query(String callingPkg, Uri url, @Nullable String[] projection,
@Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal)
throws RemoteException {
// 创建BulkCursorToCursorAdaptor对象,将BulkCursorDescriptor注入,方便调用放通过Cursor层的接口既可获取对应的数据
BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor();
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
data.writeString(callingPkg);
url.writeToParcel(data, 0);
int length = 0;
if (projection != null) {
length = projection.length;
}
data.writeInt(length);
for (int i = 0; i < length; i++) {
data.writeString(projection[i]);
}
data.writeBundle(queryArgs);
data.writeStrongBinder(adaptor.getObserver().asBinder());
data.writeStrongBinder(
cancellationSignal != null ? cancellationSignal.asBinder() : null);
// 向Binder发送QUERY_TRANSACTION命令
mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);
DatabaseUtils.readExceptionFromParcel(reply);
if (reply.readInt() != 0) {
// 通过Binder驱动将IBulkCursor和CursorWindow代理对象读取出来
BulkCursorDescriptor d = BulkCursorDescriptor.CREATOR.createFromParcel(reply);
Binder.copyAllowBlocking(mRemote, (d.cursor != null) ? d.cursor.asBinder() : null);
// 把BulkCursorDescriptor保存在BulkCursorToCursorAdaptor中
adaptor.initialize(d);
} else {
adaptor.close();
adaptor = null;
}
return adaptor;
} catch (RemoteException ex) {
adaptor.close();
throw ex;
} catch (RuntimeException ex) {
adaptor.close();
throw ex;
} finally {
data.recycle();
reply.recycle();
}
}
接下来分析IContentProvider的Binder本地对象,IContentProvider代理对象最终会调用到ContentProviderNative的nTransact函数,query函数对应的cmd为QUERY_TRANSACTION,首先调用query函数,ContentProviderNative没有实现query函数。 ContentProvider有个成员变量mTransport类型为Transport,Transport为ContentProvider的内部类。继承ContentProviderNative,ContentProvider在向AMS提交时,会把mTransport的Binder对象传递给AMS。query函数最终调用的是Transport的query函数,query查询得到的Cursor对象将其封装成可以跨Binder进程的BulkCursorDescriptor对象,将BulkCursorDescriptor对象返回给ContentProviderProxy代理端。CursorToBulkCursorAdaptor对象作为适配器类,方便Cursor转成BulkCursorDescriptor对象
ContentProviderNative
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
try {
switch (code) {
case QUERY_TRANSACTION:
{
// query函数最终调用的是ContentProvider的query函数
Cursor cursor = query(callingPkg, url, projection, queryArgs, cancellationSignal);
if (cursor != null) {
// 将ContentProvider中查询到的信息封装成CursorToBulkCursorAdaptor
CursorToBulkCursorAdaptor adaptor = null;
try {
adaptor = new CursorToBulkCursorAdaptor(cursor, observer,
getProviderName());
cursor = null;
BulkCursorDescriptor d = adaptor.getBulkCursorDescriptor();
adaptor = null;
reply.writeNoException();
reply.writeInt(1);
// 通过Binder驱动把BulkCursorDescriptor对象传递给调用的APP进程
d.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} finally {
// Close cursor if an exception was thrown while constructing the adaptor.
if (adaptor != null) {
adaptor.close();
}
if (cursor != null) {
cursor.close();
}
}
} else {
reply.writeNoException();
reply.writeInt(0);
}
}
return true;
}
}
ContentProvider.java (d:\source\android\android8.0\android-8.0.0_r1\frameworks\base\core\java\android\content)
Transport的query函数,最终调用的是子类的query函数的具体实现,将查询得到的Cursor对象返回
class Transport extends ContentProviderNative {
@Override
public Cursor query(String callingPkg, Uri uri, @Nullable String[] projection,
@Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal) {
validateIncomingUri(uri);
try {
// 调用子类的query函数
return ContentProvider.this.query(
uri, projection, queryArgs,
CancellationSignal.fromTransport(cancellationSignal));
} finally {
setCallingPackage(original);
}
}
}