360 Replugin Binder实现原理

作者: brycegao | 来源:发表于2018-09-13 14:00 被阅读26次

    在安卓日常app开发过程中一般自定义Service并实现Binder, 且常用的ActivityManager/WindowManager/TelephonyManager最终都是通过ServiceManager.getService取到IBinder对象。

    那么是不是离开Service, 就用不了Binder了呢? 在看Replugin源码前, 我是这么认为的。 但Replugin告诉我还有另一种使用方式。

    Replugin有一个核心类ServiceProvider, 实现了ServiceManager的getService功能。 原来Cursor还能传Binder对象。 我们知道Content Provider可以实现跨进程通讯, Replugin就是利用这个特性实现的跨进程拿到IBinder(或本地代理)。

    image.png
    打开replugin-host-gradle工程, 可以看到是在宿主编译时将ServiceProvider的注册语句添加到AndroidManifest.xml。 代码在ComponentsGenerator.groovy。
     // ServiceManager 服务框架
                provider(
                        "${name}":"com.qihoo360.mobilesafe.svcmanager.ServiceProvider",
                        "${authorities}":"${applicationID}.svcmanager",
                        "${exp}":"false",
                        "${multiprocess}":"false",
                        "${process}":"${pluginMgrProcessName}")
    

    打开replugin-host-lib工程里的ServiceProvider.java,只有query函数返回了一个单例的sServiceChannelCursor对象。

    public class ServiceProvider extends ContentProvider {
        private static final boolean DEBUG = BuildConfig.DEBUG;
     
        private static final String TAG = "ServerProvider";
     
        public static final String AUTHORITY = IPC.getPackageName() + ".svcmanager";
     
        public static final String PATH_SERVER_CHANNEL = "severchannel";
     
        @Override
        public boolean onCreate() {
            if (DEBUG) {
                Log.d(TAG, "[onCreate]" + " App = " + getContext().getApplicationContext());
            }
     
            return true;
        }
     
        @Override
        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
            if (DEBUG) {
                Log.d(TAG, "[query] uri = " + (uri == null ? "null" : uri.toString()));
            }
     
            return ServiceChannelImpl.sServiceChannelCursor;
        }
     
        @Override
        public String getType(Uri uri) {
            return null;
        }
     
        @Override
        public Uri insert(Uri uri, ContentValues values) {
            return null;
        }
     
        @Override
        public int delete(Uri uri, String selection, String[] selectionArgs) {
            return 0;
        }
     
        @Override
        public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
            return 0;
        }
    }
    

    在ServiceChannelImpl.java实现了IServiceChannel.Stub, 将引用赋值到sServiceChannelImpl。 Replugin里的所有Binder的get/add都最终走到这里, 这个sServiceChannel运行在UI进程或者:GuardService, 依赖于配置ServiceProvider的android:process参数。

        static MatrixCursor sServiceChannelCursor = ServiceChannelCursor.makeCursor(sServiceChannelImpl);
    

    ServiceProvider的query函数返回的是ServiceChannelCursor对象, 其实就是对sServiceChannelImpl的封装。

    我们看看ServiceChannelCursor做了什么事情。

    class ServiceChannelCursor extends MatrixCursor {
     
        public static final String SERVER_CHANNEL_BUNDLE_KEY = "servicechannel";
     
        /* PACKAGE */static final String[] DEFAULT_COLUMNS = {
            "s"
        };
     
        static final ServiceChannelCursor makeCursor(IBinder binder) {
            return new ServiceChannelCursor(DEFAULT_COLUMNS, binder);
        }
     
        static final IBinder getBinder(Cursor cursor) {
            Bundle bundle = cursor.getExtras(); //Java多态,执行当前类的getExtra函数体
            bundle.setClassLoader(ParcelBinder.class.getClassLoader());
            ParcelBinder parcelBinder = bundle.getParcelable(SERVER_CHANNEL_BUNDLE_KEY);
            return parcelBinder.getIbinder();
        }
     
        Bundle mBinderExtra = new Bundle();
     
        public ServiceChannelCursor(String[] columnNames, IBinder binder) {
            super(columnNames);
     
            mBinderExtra.putParcelable(SERVER_CHANNEL_BUNDLE_KEY, new ParcelBinder(binder)); //利用cursor可以传递Bundle对象的特性,将binder保存到Bundle中
        }
     
        @Override
        public Bundle getExtras() {
            return mBinderExtra;
        }
    }
    

    IBinder的序列化/反序列化是通过自定义类ParcelBinder实现的。

    class ParcelBinder implements Parcelable {
     
        private final IBinder mBinder;
     
        private ParcelBinder(Parcel source) {
            mBinder = source.readStrongBinder();
        }
     
        public ParcelBinder(IBinder binder) {
            this.mBinder = binder;
        }
     
        public IBinder getIbinder() {
            return mBinder;
        }
     
        @Override
        public int describeContents() {
            return 0;
        }
     
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeStrongBinder(mBinder);
        }
     
        public static final Parcelable.Creator<ParcelBinder> CREATOR = new Parcelable.Creator<ParcelBinder>() {
     
            @Override
            public ParcelBinder createFromParcel(Parcel source) {
                return new ParcelBinder(source);
            }
     
            @Override
            public ParcelBinder[] newArray(int size) {
                return new ParcelBinder[size];
            }
     
        };
     
    }
    

    最后, Replugin的QihooServiceManager的作用等同于android.os.ServiceManager, 区别是ServiceManager使用的Binder方式, 而Replugin使用了Content Provider方式实现跨进程通讯。

    相关文章

      网友评论

        本文标题:360 Replugin Binder实现原理

        本文链接:https://www.haomeiwen.com/subject/ehywgftx.html