360 Replugin Binder实现原理
在安卓日常app开发过程中一般自定义Service并实现Binder, 且常用的ActivityManager/WindowManager/TelephonyManager最终都是通过ServiceManager.getService取到IBinder对象。
那么是不是离开Service, 就用不了Binder了呢? 在看Replugin源码前, 我是这么认为的。 但Replugin告诉我还有另一种使用方式。
Replugin有一个核心类ServiceProvider, 实现了ServiceManager的getService功能。 原来Cursor还能传Binder对象。 我们知道Content Provider可以实现跨进程通讯, Replugin就是利用这个特性实现的跨进程拿到IBinder(或本地代理)。
打开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参数。
ServiceProvider的query函数返回的是ServiceChannelCursor对象, 其实就是对sServiceChannelImpl的封装。
static MatrixCursor sServiceChannelCursor = ServiceChannelCursor.makeCursor(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方式实现跨进程通讯。