Server端:
// Person.class 需要实现Parcelable序列化
public class Person implements Parcelable {
private String name;
private int age;
......
}
//MyService.class
public class MyService extends Service {
private List<Person> list = new ArrayList<>();
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return myBinder;
}
private final IMyAidlInterface.Stub myBinder = new IMyAidlInterface.Stub() {
@Override
public void add(Person person) throws RemoteException {
list.add(person);
}
@Override
public List<Person> getAll() throws RemoteException {
return list;
}
};
}
// IMyAidlInterface.aidl
//需要手动导入Person类
import com.example.server.Person;
interface IMyAidlInterface {
void add(in Person person);
List<Person> getAll();
}
// Person.aidl
parcelable Person;
最终Server端的包结构应该是这样的
Server端包结构
Client端:
把Server端整个aidl的包复制到Client项目下。Person类也需要复制过来,但是要保证和Server端的路径一致。结构如下:
Client端包结构
//MainActivity.class
private IMyAidlInterface myAidlInterface;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.example.server",
"com.example.server.MyService"));
bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
private final ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("----->", "onServiceConnected: ");
myAidlInterface = IMyAidlInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
int count = 0;
// 按钮点击
public void test(View view) {
if (myAidlInterface != null) {
try {
count++;
myAidlInterface.add(new Person("echo" + count, 1 + count));
List<Person> list = myAidlInterface.getAll();
Log.d("----->", "test: " + list.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
复制过来之后最好先编译一下。接下来分别运行到手机上,点击Client端的按钮,输出结果如下:
运行结果
好了,基本使用到此结束。接下来就是分析AIDL如何实现的跨进程通信。
在Android Studio中按照/app/build/generated/aidl_source_output_dir/debug/compileDebugAidl/out此路径打开,可以找到系统自动生成的文件,内容如下:
// 自定义的Aidl接口 继承了 IInterface
public interface IMyAidlInterface extends android.os.IInterface{
// 抽象内部类 继承了Binder 同样实现了自己定义的IMyAidlInterface
public static abstract class Stub extends android.os.Binder implements com.example.server.IMyAidlInterface
{
// 描述符 用于标识身份
private static final java.lang.String DESCRIPTOR = "com.example.server.IMyAidlInterface";
public Stub()
{
// 父类Binder的方法 传入自身和标识符 Server端会调用构造方法 Client则不会
this.attachInterface(this, DESCRIPTOR);
}
// 这个方法就是在client端MainActivity中调用的myAidlInterface = IMyAidlInterface.Stub.asInterface(service);
public static com.example.server.IMyAidlInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
//也是在父类Binder中调用 根据构造方法中attachInterface()传入的参数比较来确认是不是同一个进程
//queryLocalInterface()方法内部逻辑
// if (mDescriptor != null && mDescriptor.equals(descriptor)) {
// return mOwner;
// }
// return null;
// 由于在Client端是调用上面的静态方法,不会走Stub的构造,也就是说传入的是null 所以返回的也是null
// 而在Server端当MyService启动的时候Stub就被初始化了,会传入自己的标识符
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
// 这一个if成立 意味着在同一个进程 就不需要通过binder来通信了
if (((iin!=null)&&(iin instanceof com.example.server.IMyAidlInterface))) {
return ((com.example.server.IMyAidlInterface)iin);
}
// 直接返回Proxy 其实传入的是就是ServiceConnection的onServiceConnected()方法中的第二个参数
// 也就是说Client就拿到了proxy的实例,那么自然就可以调用proxy里的方法了
return new com.example.server.IMyAidlInterface.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;
}
// 最终Proxy的tansact会调到onTransact(),并根据TRANSACTION_add找到这里
case TRANSACTION_add:
{
// 校验
data.enforceInterface(descriptor);
com.example.server.Person _arg0;
if ((0!=data.readInt())) {
// 拿到person对象
_arg0 = com.example.server.Person.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
// this.add()其实就是调用MyServer中new出来的Stub中的add()方法
this.add(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_getAll:
{
data.enforceInterface(descriptor);
java.util.List<com.example.server.Person> _result = this.getAll();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
// Stub的内部类 同样实现了自己写的IMyAidlInterface接口
private static class Proxy implements com.example.server.IMyAidlInterface
{
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 void add(com.example.server.Person person) 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 ((person!=null)) {
_data.writeInt(1);
person.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
// 调用IBinder的transact()方法 记住 传入的是TRANSACTION_add 这是一个int值
// 同时会把客户端的线程挂起 直到服务端返回
boolean _status = mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().add(person);
return;
}
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
..... // 省略getAll()方法 和add()方法类似
public static com.example.server.IMyAidlInterface sDefaultImpl;
}
// 由于Client的aidl是直接从Server端复制过来的,所以方法的顺序也是一样的
// 那么调用时就可以通过数字编号来找到方法
static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getAll = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
public static boolean setDefaultImpl(com.example.server.IMyAidlInterface impl) {
if (Stub.Proxy.sDefaultImpl == null && impl != null) {
Stub.Proxy.sDefaultImpl = impl;
return true;
}
return false;
}
public static com.example.server.IMyAidlInterface getDefaultImpl() {
return Stub.Proxy.sDefaultImpl;
}
}
public void add(com.example.server.Person person) throws android.os.RemoteException;
public java.util.List<com.example.server.Person> getAll() throws android.os.RemoteException;
}
也就是说在Client端发送数据的时候,实际就是Proxy来发送的,最终会调用transact()方法
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);
}
// 最终会调到Binder的onTransact()。而上面的Stub就是继承自Binder,那么就需要回过头看
// Stub类是如何接收数据的。因为两端是一样的,所以可以用Client端的分析就可以了
boolean r = onTransact(code, data, reply, flags);
if (reply != null) {
reply.setDataPosition(0);
}
return r;
}
至此Client端与Server端一次完整的通信就完成了。
AIDL调用简图
调用时序图
了解了上面的基础之后,那么Client和Server到底是怎么绑定到一起的呢?自然要从bindService入手了:
ContextWrapper.java
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
其中mBase就是Context类。由于Context类是一个抽象类,那么最终就会调用到它的实现类ContextImpl中:
ContextImpl.java
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null,
getUser());
}
最终又会调用bindServiceCommon()方法
ContextImpl.java
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
UserHandle user) {
// 一个很重要的变量 分析完最后的流程时再说
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
mMainThread.getHandler(), flags);
} else {
throw new RuntimeException("Not supported in system context");
}
validateServiceIntent(service);
try {
IBinder token = getActivityToken();
if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
&& mPackageInfo.getApplicationInfo().targetSdkVersion
< android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
flags |= BIND_WAIVE_PRIORITY;
}
service.prepareToLeaveProcess();
// 1
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
if (res < 0) {
throw new SecurityException(
"Not allowed to bind to service " + service);
}
return res != 0;
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
}
看一下上面注释1处的ActivityManagerNative.getDefault()都干了什么:
ActivityManagerNative.java
// 返回了一个IActivityManager实例
static public IActivityManager getDefault() {
return gDefault.get();
}
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
// 获取AMS的IBinder对象
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
// 获得IActivityManager对象 根据上面的例子可以知道 IActivityManager其实就是proxy实例
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
看到asInterface(b)这一句代码,再看之前Client端的IMyAidlInterface.Stub.asInterface(service),不难联想到IActivityManager其实就是一个Aidl接口。
IActivityManager.java
// 和我们自定义的aidl接口一样 都是继承了IInterface
public interface IActivityManager extends IInterface {
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags,
ProfilerInfo profilerInfo, Bundle options) throws RemoteException;
public int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags,
ProfilerInfo profilerInfo, Bundle options, int userId) throws RemoteException;
public int startActivityAsCaller(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int flags, ProfilerInfo profilerInfo, Bundle options, boolean ignoreTargetSecurity,
int userId) throws RemoteException;
······
}
那Stub类和Proxy类在哪呢?
// 其实ActivityManagerNative就是Stub
public abstract class ActivityManagerNative extends Binder implements IActivityManager{
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
// ActivityManagerProxy就等同于例子中的proxy
return new ActivityManagerProxy(obj);
}
......
// ActivityManagerProxy是ActivityManagerNative的内部类
class ActivityManagerProxy implements IActivityManager
{
public int bindService(IApplicationThread caller, IBinder token,
Intent service, String resolvedType, IServiceConnection connection,
int flags, String callingPackage, int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
......
// 同样是调用了transact方法 那么最终会调到Stub也就是ActivityManagerNative的onTransact
mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
data.recycle();
reply.recycle();
return res;
}
}
下面看一下ActivityManagerNative的onTransact()方法的BIND_SERVICE_TRANSACTION这个case的代码:
case BIND_SERVICE_TRANSACTION: {
// 校验
data.enforceInterface(IActivityManager.descriptor);
......
IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
// 按照上面例子的流程 调用到这里的时候会调用到MyService中的方法
// 同理 这里就会调用到AMS中的bindService()
int res = bindService(app, token, service, resolvedType, conn, fl,
callingPackage, userId);
reply.writeNoException();
reply.writeInt(res);
return true;
}
下面则来分析一下AMS中的bindService都干了什么:
public int bindService(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, int flags,
String callingPackage, int userId) throws TransactionTooLargeException {
......
synchronized(this) {
// mServices 的类型是 ActiveServices
return mServices.bindServiceLocked(caller, token, service,
resolvedType, connection, flags, instanceName, callingPackage, userId);
}
}
ActiveServices.java
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String instanceName, String callingPackage, final int userId)
throws TransactionTooLargeException {
......
// 第一步
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
if (s.app != null && b.intent.received) {
try {
c.conn.connected(s.name, b.intent.binder, false);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + s.shortInstanceName
+ " to connection " + c.conn.asBinder()
+ " (in " + c.binding.client.processName + ")", e);
}
if (b.intent.apps.size() == 1 && b.intent.doRebind) {
// 第二步
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
} else if (!b.intent.requested) {
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
getServiceMapLocked(s.userId).ensureNotStartingBackgroundLocked(s);
} finally {
Binder.restoreCallingIdentity(origId);
}
return 1;
}
上面注释中的第一步的作用是创建一个service,第二步则是去进行绑定。下面分开来看源码:
第一步:创建Service
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
......
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
+ " app=" + app);
// 如果Service端已经启动 并且 ApplicationThread不为空
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
// 启动服务
realStartServiceLocked(r, app, execInFg);
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
}
}
}
......
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
......
// 调用ApplicationThread的scheduleCreateService()
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
app.getReportedProcState());
r.postNotification();
created = true;
} catch (DeadObjectException e) {
Slog.w(TAG, "Application dead when creating service " + r);
mAm.appDiedLocked(app);
throw e;
}
下面则会进入到ApplicationThread当中:
// 方法很简单 准备了一些token,以及服务的相关信息 并发送了一个handler消息CREATE_SERVICE
public final void scheduleCreateService(IBinder token,
ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
updateProcessState(processState, false);
CreateServiceData s = new CreateServiceData();
s.token = token;
s.info = info;
s.compatInfo = compatInfo;
sendMessage(H.CREATE_SERVICE, s);
}
private void handleCreateService(CreateServiceData data) {
unscheduleGcIdler();
unscheduleGcIdler();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
// 通过类加载器去生成Service实例 那么这个Service就是上面例子中自己定义的MyService
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to instantiate service " + data.info.name
+ ": " + e.toString(), e);
}
}
try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());
// 调用MyService的onCreate();
service.onCreate();
// 缓存起来 下次用到的话就直接使用 而不会再创建了
mServices.put(data.token, service);
......
}
}
第二步:绑定Service
// rebind参数为true则表示已经绑定过了 false则没有绑定
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord I,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
if (r.app == null || r.app.thread == null) {
return false;
}
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
bumpServiceExecutingLocked(r, execInFg, "bind");
r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
// 调用ApplicationThread的scheduleBindService方法
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.getReportedProcState());
......
}
return true;
}
public final void scheduleBindService(IBinder token, Intent intent,
boolean rebind, int processState) {
updateProcessState(processState, false);
BindServiceData s = new BindServiceData();
s.token = token;
s.intent = intent;
s.rebind = rebind;
// 同样是发了一个handler消息
sendMessage(H.BIND_SERVICE, s);
}
private void handleBindService(BindServiceData data) {
// 从缓存中去拿
Service s = mServices.get(data.token);
// 如果存在 也就意味着service已经启动了
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
try {
// 之前没有绑定
if (!data.rebind) {
// 则会调用onBind方法 也就是MyService中的onBind 在MyService的onBind里我们返回了一个myBinder 也就是现在的 IBinder binder
IBinder binder = s.onBind(data.intent);
// 这里在上面已经分析过了 最终会进入调用AMS中的publishService
ActivityManagerNative.getService().publishService(
data.token, data.intent, binder);
} else {
// 反之调用onRebind
s.onRebind(data.intent);
ActivityManagerNative.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
......
}
}
ActivityManagerService.java
public void publishService(IBinder token, Intent intent, IBinder service) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
synchronized(this) {
if (!(token instanceof ServiceRecord)) {
throw new IllegalArgumentException("Invalid service token");
}
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}
}
ActiveServices.java
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
final long origId = Binder.clearCallingIdentity();
......
try {
// 这里最终会调用Client端的onServiceConnection()
// 对比一下onServiceConnected(ComponentName name, IBinder service) {
c.conn.connected(r.name, service);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + r.shortInstanceName
+ " to connection " + c.conn.asBinder()
+ " (in " + c.binding.client.processName + ")", e);
}
......
}
为什么 c.conn.connected()为什么能调用到onServiceConnected(ComponentName name, IBinder service),不知道还记不记得在上面ContextImpl中分析bindServiceCommon()的时候提到的一个重要的变量IServiceConnection。无论if还是else最终都会调到如下方法:
LoadedApk.class
private IServiceConnection getServiceDispatcherCommon(ServiceConnection c,
Context context, Handler handler, Executor executor, int flags) {
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
// 先从缓存中取
if (map != null) {
sd = map.get(c);
}
// 没有则new一个新的
if (sd == null) {
if (executor != null) {
sd = new ServiceDispatcher(c, context, executor, flags);
} else {
sd = new ServiceDispatcher(c, context, handler, flags);
}
......
return sd.getIServiceConnection();
}
}
ServiceDispatcher.class 是LoadedApk.class的内部类
IServiceConnection getIServiceConnection() {
return mIServiceConnection;
}
ServiceDispatcher 是LoadedApk的内部类,而且内部有两个重要的成员变量:
private final ServiceDispatcher.InnerConnection mIServiceConnection;
private final ServiceConnection mConnection;
ServiceConnection是一个接口,就是我们在Client端中创建的。而InnerConnection则是ServiceDispatcher的内部类:
继承自IServiceConnection.Stub 也是通过Binder的形式
private static class InnerConnection extends IServiceConnection.Stub {
@UnsupportedAppUsage
final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
public void connected(ComponentName name, IBinder service, boolean dead)
throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service, dead);
}
}
}
// 最终会调用此方法
public void doConnected(ComponentName name, IBinder service, boolean dead) {
ServiceDispatcher.ConnectionInfo old;
ServiceDispatcher.ConnectionInfo info;
......
if (old != null) {
mConnection.onServiceDisconnected(name);
}
if (dead) {
mConnection.onBindingDied(name);
}
// 最终调用到Client端MainActivity中的匿名内部类
if (service != null) {
mConnection.onServiceConnected(name, service);
} else {
// The binding machinery worked, but the remote returned null from onBind().
mConnection.onNullBinding(name);
}
}
bindService时序图











网友评论