IPC学习---AIDL简单概念

251 阅读2分钟

Replugin源码阅读---框架初始化

在阅读Replugin源码时, RePlugin初始化涉及到进程间通信的问题, 常驻进程通过PmHostSvc统筹插件的使用, 其他进程获取常驻进程的代理对象, 然后对插件进行操作.阅读Replugin时对这一块进程间通信的流程并没有深入进行分析, 这里单独拿出来进行分析

进程间通信

多进程通信不管是Android的binder还是linux的channel最终都是通过共享内存的读写来实现的, 两个或多个进程都能读取内存中的某一个文件, 一个进程负责写, 一个进程负责读, 这样就实现了进程间通信.

Android使用AIDL的方式实现IPC
IPC通信过程

1、首先客户端要连接服务端

2、然后服务端会返回一个客户端的对象(代理对象)

3、然后客户端使用这个代理对象其中的方法时, 系统会先调用服务端的方法, 然后将运算的结果返回给客户端(其实并不是用了这个对象的方法, 而是去服务端里运算, 然后再返回给客户端)

1.创建AIDL文件
interface AidlBean {
    void setData(int data);
    int getData();
}
2.build自动生成AidlBean.java文件
public interface AidlBean extends android.os.IInterface {
	public void setData(int data) throws android.os.RemoteException;
	public int getData() throws android.os.RemoteException;
}

AidlBean的结构:

1、创建的类AidlBean继承IInterface接口

2、内部类Stub继承Binder

3、asInterface方法, 判断如果不是同一个进程会返回代理类

4、每个方法对应一个id, 用于在跨进程访问时确定访问的是哪个方法, 通过transact方法再调用服务端的onTransact方法

3.Stub.asInterface
public static com.hb.test.AidlBean asInterface(android.os.IBinder obj)
	{
		if ((obj==null)) {
			return null;
      	}
     	android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
      	if (((iin!=null)&&(iin instanceof com.hb.test.AidlBean))) {
        	return ((com.hb.test.AidlBean)iin);
      	}
      	return new com.hb.test.AidlBean.Stub.Proxy(obj);
	}
}
4.Client端transact方法
@Override 
public void setData(int data) throws android.os.RemoteException {
	android.os.Parcel _data = android.os.Parcel.obtain();
	android.os.Parcel _reply = android.os.Parcel.obtain();
	try {
		_data.writeInterfaceToken(DESCRIPTOR);
        _data.writeInt(data);
        boolean _status = mRemote.transact(Stub.TRANSACTION_setData, _data, _reply, 0);
        if (!_status && getDefaultImpl() != null) {
        	getDefaultImpl().setData(data);
            return;
        }
        _reply.readException();
    }
    finally {
    	_reply.recycle();
        _data.recycle();
    }
}

1、创建输出类型data

2、创建接收类型reply

3、创建需要的参数

4、将参数写入data中

5、发起远程调用, 当前线程挂起调用mRemote.transact()方法, 这个方法的实现在Binder中, 他会调用服务端的onTransact方法, 直到有返回结果

6、从_result中取出返回结果

5.Server端onTransact方法
@Override 
public boolean onTransact(int code, android.os.Parcel data, Parcel reply, int flags) {
	data.enforceInterface(descriptor);
    int _arg0;
    _arg0 = data.readInt();
    this.setData(_arg0);
    reply.writeNoException();
    return true;
}

服务端接到请求会走到onTransact方法, 这个方法运行在服务端的Binder线程池中

1、通过id确定访问哪个方法

2、从目标参数data取出需要的参数

3、调用请求的相应方法

4、将返回值写入reply

5、返回true成功, false客户端访问失败, 实际当中可根据这个特性来做远程校验