aosp原生Service快捷扩展接口¶
背景¶
想在 aosp 原生 Service 提供新的功能给 APP 使用,但又不想改动 aidl 文件以及 manager 文件。 也就是说想尽量少改代码的方式实现新功能。基于这样的大前提下可以通过 onTransact() 接口去实现。 对 binder 了解的都知道,每个 binder 对象里的 Stub 会有一个 onTransact() 接口用来 ipc 的;并且区分每个接口是通过 transact code 来区分。
我们以 WindowManagerService 为例。
Service¶
在 WindowManagerService 中:
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
try {
if (code == 100001) {
Log.d(TAG, "onTransact(solo-debug) called with: code = [" + code + "], data = [" + data + "], reply = [" + reply + "], flags = [" + flags + "]");
return true;
}
return super.onTransact(code, data, reply, flags);
} catch (RuntimeException e) {
// The window manager only throws security exceptions, so let's
// log all others. if (!(e instanceof SecurityException)) {
ProtoLog.wtf(WM_ERROR, "Window Manager Crash %s", e);
}
throw e;
}
}
APP¶
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
IBinder binder = ServiceManager.getService(Context.WINDOW_SERVICE);
if (binder != null) {
data.writeInterfaceToken("android.view.IWindowManager");
data.writeInt(11);
data.writeInt(22);
data.writeString("test");
binder.transact(100001, data, reply, 0);
}
} catch (Exception e) {
Log.e(TAG, "solo-debug transact failed = "+ e);
} finally {
data.recycle();
reply.recycle();
}
执行后输出的log如下,说明这个方案是可行的。
11-29 08:27:07.139 2414 4145 D WindowManager: onTransact(solo-debug) called with: code = [100001], data = [android.os.Parcel@cc9491b], reply = [android.os.Parcel@bdc8ab8], flags = [0]
这个方案在 SurfaceFlinger 中经常用到。