Binder机制在Android系统中地位毋庸置疑,system_server就经过Binder来实现进程间的通讯,从而达到管理、调用一系列系统服务的能力。本文就AIDL来解读一下Binder机制的。 先了解一下以下几个概念:java
还有一点须要说明一下:当一个Service向AMS进行注册时,传递的过去的以及保存在AMS中的是一个Binder对象。当Client须要跟Service进行通讯,经过AMS查询到实际上是一个BinderProxy,由于能够有多个Client同时跟Service进行通讯。固然若是Service和Client在同一进程,AMS返回的仍是一个Binder对象,毕竟没有必要进行IPC。在进行IPC时,Binder Drivder会在中间帮忙转换Binder和BinderProxy。android
仍是按照Android Service详解(二)的例子来解释app
如今咱们来看一下系统自动生成的aidl文件具体有些什么:ide
/* * This file is auto-generated. DO NOT MODIFY. * Original file: /Users/lebens/Development/WorkSpace/jxx_workspace/Server/app/src/main/aidl/jxx/com/server/aidl/IServerServiceInfo.aidl */
package jxx.com.server.aidl;
public interface IServerServiceInfo extends android.os.IInterface {
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements jxx.com.server.aidl.IServerServiceInfo {
private static final java.lang.String DESCRIPTOR = "jxx.com.server.aidl.IServerServiceInfo";
/** Construct the stub at attach it to the interface. */
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/** * Cast an IBinder object into an jxx.com.server.aidl.IServerServiceInfo interface, * generating a proxy if needed. */
public static jxx.com.server.aidl.IServerServiceInfo asInterface(android.os.IBinder obj) {
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof jxx.com.server.aidl.IServerServiceInfo))) {
return ((jxx.com.server.aidl.IServerServiceInfo)iin);
}
return new jxx.com.server.aidl.IServerServiceInfo.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder() {
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
java.lang.String descriptor = DESCRIPTOR;
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
case TRANSACTION_getServerInfo:
{
data.enforceInterface(descriptor);
jxx.com.server.aidl.ServerInfo _result = this.getServerInfo();
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
case TRANSACTION_setServerInfo:
{
data.enforceInterface(descriptor);
jxx.com.server.aidl.ServerInfo _arg0;
if ((0!=data.readInt())) {
_arg0 = jxx.com.server.aidl.ServerInfo.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
this.setServerInfo(_arg0);
reply.writeNoException();
if ((_arg0!=null)) {
reply.writeInt(1);
_arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements jxx.com.server.aidl.IServerServiceInfo {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override public jxx.com.server.aidl.ServerInfo getServerInfo() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
jxx.com.server.aidl.ServerInfo _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getServerInfo, _data, _reply, 0);
_reply.readException();
if ((0!=_reply.readInt())) {
_result = jxx.com.server.aidl.ServerInfo.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public void setServerInfo(jxx.com.server.aidl.ServerInfo serverinfo) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((serverinfo!=null)) {
_data.writeInt(1);
serverinfo.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_setServerInfo, _data, _reply, 0);
_reply.readException();
if ((0!=_reply.readInt())) {
serverinfo.readFromParcel(_reply);
}
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_getServerInfo = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_setServerInfo = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public jxx.com.server.aidl.ServerInfo getServerInfo() throws android.os.RemoteException;
public void setServerInfo(jxx.com.server.aidl.ServerInfo serverinfo) throws android.os.RemoteException;
}
复制代码
关于Stub再来看几点:post
以getServerInfo()为例来分析一下onTransact传递过程。 首先咱们在Proxy的实现是这样的this
@Override public jxx.com.server.aidl.ServerInfo getServerInfo() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
jxx.com.server.aidl.ServerInfo _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(IServerServiceInfo.Stub.TRANSACTION_getServerInfo, _data, _reply, 0);
_reply.readException();
if ((0!=_reply.readInt())) {
_result = jxx.com.server.aidl.ServerInfo.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
复制代码
从上面的分析能够知道,这里的mRemote实际上是一个BinderProxy对象,咱们去看一下这个方法spa
/** * Default implementation rewinds the parcels and calls onTransact. On * the remote side, transact calls into the binder to do the IPC. */
public final boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
if (false) Log.v("Binder", "Transact: " + code + " to " + this);
if (data != null) {
data.setDataPosition(0);
}
boolean r = onTransact(code, data, reply, flags);
if (reply != null) {
reply.setDataPosition(0);
}
return r;
}
复制代码
最终调用的是Binder内的onTransact(),也就是Stub的onTransact(),咱们来看一下线程
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
java.lang.String descriptor = DESCRIPTOR;
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
case TRANSACTION_getServerInfo:
{
data.enforceInterface(descriptor);
jxx.com.server.aidl.ServerInfo _result = this.getServerInfo();
reply.writeNoException();
if ((_result!=null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
case TRANSACTION_setServerInfo:
{
data.enforceInterface(descriptor);
jxx.com.server.aidl.ServerInfo _arg0;
if ((0!=data.readInt())) {
_arg0 = jxx.com.server.aidl.ServerInfo.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
this.setServerInfo(_arg0);
reply.writeNoException();
if ((_arg0!=null)) {
reply.writeInt(1);
_arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
复制代码
在内部能够看到case TRANSACTION_getServerInfo 下的操做其实也是很简单,就是把Client须要的结果经过reply传递回Client代理
经过上面的代码分析,AIDL咱们能够快速实现IPC,咱们来总结一下:code
经过这个例子的分析,其实系统的AMS管理各类系统服务也是一样的套路,经过2个Binder创建通讯。
还有一点须要注意: Binder或者BinderProxy都是运行在他们本身的Binder池中的,也就是直接经过Binder通讯的话,须要注意线程切换