ActivityManagerService之ContentProvider原理篇2数据传输流程

ContentProvider通过Binder进程间通信机制来突破应用程序边界的权限控制(IBulkCursor和IContentProvider),同时以共享内存作为数据载体(CursorWindow),ContentProviderProxy所对应的进程通过IBulkCursor和CursorWindow来操作数据集合

ContentProvider数据传输流程的时序图如下:
在这里插入图片描述

类的简单说明
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
数据操作的抽象接口

ContentProvider数据传输流程的简单类图如下:
在这里插入图片描述

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);
            }
        }
} 

猜你喜欢

转载自blog.csdn.net/he980725866/article/details/106750860