[Android5.1]ContentProvider的Binder通信分析

Posted 迷途小书童Eric

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Android5.1]ContentProvider的Binder通信分析相关的知识,希望对你有一定的参考价值。

这篇文章大体介绍一下ContentProvider提供方和使用方之间如何通过binder机制进行通信的。
下面是ContentProvider相关的类图关系:

IContentProvider

ContentProvider接口类,继承于IInterface类。该类有两个很重要的子类:ContentProviderNative和ContentProviderProxy,分别为本地服务端和客户端的接口。

ContentProviderProxy

PATH:frameworks/base/core/java/android/content/ContentProviderNative.java
为Content客户端接口。Content使用方获得该接口后,就可以调用接口里的query/insert/delete/update函数进行内容的查询、插入、删除和更新。里面有个IBinder类型的变量mRemote,使用mRemote的transact方法就可以将具体的请求发给binder驱动,binder驱动会进一步将该请求转发给Content提供方。下面以ContentProviderProxy.query为例,看一下具体实现:

public Cursor query(String callingPkg, Uri url, String[] projection, String selection, String[] selectionArgs,
       String sortOrder, ICancellationSignal cancellationSignal) throws RemoteException     
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    try 
        // 将请求打包到Parceldata.writeInterfaceToken(IContentProvider.descriptor);
        data.writeString(callingPkg);      
        data.writeInt(length);
        ...
        // 将请求包发送给binder驱动。注意这里的请求类型为:IContentProvider.QUERY_TRANSACTION
        mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);   

        // 将返回结果转化为Cursor类型
        if (reply.readInt() != 0) 
            BulkCursorDescriptor d = BulkCursorDescriptor.CREATOR.createFromParcel(reply);
            adaptor.initialize(d);
         else 
            adaptor.close();
            adaptor = null;
        
        return adaptor; //返回结果
     

ContentProviderNative

PATH:frameworks/base/core/java/android/content/ContentProviderNative.java
为Content本地服务端接口,里面有个方法为onTransact,该方法主要是处理来自Content客户端的请求,然后调用其子类Transport来具体实现query/insert/delete/update等具体的操作。下面看一下具体代码:

public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException 
    try 
        switch (code) 
            case QUERY_TRANSACTION:
            
                ... //解析请求包data

                // 调用子类的query具体实现,即ContentProvider.Transport类。
                Cursor cursor = query(callingPkg, url, projection, selection, selectionArgs,
                        sortOrder, cancellationSignal);

                ... //将处理结果放入返回包reply中

                return true;
            

            case GET_TYPE_TRANSACTION:  //getType操作
            
                ...
            

            case INSERT_TRANSACTION:   //insert操作
            
                ...
            

            case DELETE_TRANSACTION:   //delete操作
            
                ...
            

            case UPDATE_TRANSACTION:   //update操作
            
                ...
            

            ...
        
     
    ...

ContentProvider

PATH:frameworks/base/core/java/android/content/ContentProvider.java
该类是一个抽象类,所有的Provider都继承于该类。ContentProvider定义了query/insert/delete/update的接口形式,具体实现由其子类完成。

public abstract class ContentProvider implements ComponentCallbacks2 
    public abstract Cursor query(Uri uri, String[] projection,
            String selection, String[] selectionArgs, String sortOrder);
    public abstract Uri insert(Uri uri, ContentValues values);
    public abstract int delete(Uri uri, String selection, String[] selectionArgs);
    public abstract int update(Uri uri, ContentValues values, String selection, String[] selectionArgs);
    ...

ContentProvider中还有一个内部类:Transport,其继承于ContentProviderNative,该类里面实现了query/insert/delete/update方法,由ContentProviderNative.onTransact调用。但这些方法仍然不是最终的实现,还需要进一步调用具体的ContentProvider实现。
下面以Transport.query()为例,看一下具体代码:

class Transport extends ContentProviderNative 
    public Cursor query(String callingPkg, Uri uri, String[] projection,
            String selection, String[] selectionArgs, String sortOrder,
            ICancellationSignal cancellationSignal) 
        ...
        try 
            // 由于ContentProvider是抽象类,因此进一步调用ContentProvider的子类的query方法。
            return ContentProvider.this.query(
                    uri, projection, selection, selectionArgs, sortOrder,
                    CancellationSignal.fromTransport(cancellationSignal));
         finally 
            setCallingPackage(original);
        
    
    ...

XXXProvider

这里就是系统中某一个ContentProvider的具体实现了,比如MediaProvider、SettingsProvider等。
这些类继承于ContentProvider类,因此必须要实现ContentProvider类中定义的query/insert/delete/update抽象方法。

以上是关于[Android5.1]ContentProvider的Binder通信分析的主要内容,如果未能解决你的问题,请参考以下文章

[Android5.1]开机动画显示工作流程分析

android5.1 ????????????????????????????????????

Android5.1源码分析系列Settings源码分析

Android5.1和Android6.0定时编译项目方法 (转)

Android5.1开机LOGO与开机动画

android5.1 隐藏状态栏