← 返回文章流

Android Binder源码分析:AIDL及匿名服务传输

前面介绍的通过ServiceManager添加服务和获取服务,这些服务都是有名称的,我们可以通过ServiceManager来获取它。除此之外Android系统中还有一类Binder服务是匿名它,它们如何让客户端获得代理对象,并且使用呢,本文就一探究竟。 AIDL 介绍 AIDL全称为Android接口定义语言,是Android系统提供的一款可供用户用来抽象IPC的工具,它提供了语法让我们来定义跨进程通讯的服务接口,也就是.aidl文件,它也提供了工具,帮助我们把定义文件专程目标语言的代码。 我们自己使用AIDL创建的服务,或者一部分系统内的服务,比如IWindowSession、IApplicationThread等,这些多是运行在App进程,一般都不是系统服务,因此都是匿名的。我们这里以IApplicationThread来分析AIDL创建的匿名服务是怎么传递Binder给使用端的。 以IApplicationThread来分析,则服务端是我们的App进程,而客户端则是system_server进程。作为AIDL创建的Binder,首先会有一个AIDL文件,这里是IApplicationThread.aidl,其中定义了一些跨进程调用的方法,部分内容如下: package android.app; ... oneway interface IApplicationThread { void scheduleReceiver(in Intent intent, in ActivityInfo info, in CompatibilityInfo compatInfo, int resultCode, in String data, in Bundle extras, boolean sync, int sendingUser, int processState); @UnsupportedAppUsage void scheduleStopService(IBinder token); ... } 当前Android AIDL已经支持生成Java、C++、Rust的代码,对于IApplicationThread这里我们只需关注生成Java版本的代码即可。生成的代码在IApplicationThread当中,大概如下所示: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 public interface IApplicationThread extends android.os.IInterface { public static class Default implements android.app.IApplicationThread { @Override public void scheduleReceiver(android.content.Intent ...) throws android.os.RemoteException {} @Override public android.os.IBinder asBinder() { return null; } } public abstract static class Stub extends android.os.Binder implements android.app.IApplicationThread { public Stub() { this.attachInterface(this, DESCRIPTOR); } public static android.app.IApplicationThread asInterface(android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof android.app.IApplicationThread))) { return ((android.app.IApplicationThread) iin); } return new android.app.IApplicationThread.Stub.Proxy(obj); } @Override public android.os.IBinder asBinder() { return this; } public static java.lang.String getDefaultTransactionName(int transactionCode) { switch (transactionCode) { case TRANSACTION_scheduleReceiver:{ return "scheduleReceiver"; } case TRANSACTION_scheduleCreateService: { return "scheduleCreateService"; } default: { return null; } } } public java.lang.String getTransactionName(int transactionCode) { return this.getDefaultTransactionName(transactionCode); } @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; if (code >= android.os.IBinder.FIRST_CALL_TRANSACTION && code <= android.os.IBinder.LAST_CALL_TRANSACTION) { data.enforceInterface(descriptor); } switch (code) { case INTERFACE_TRANSACTION:{ reply.writeString(descriptor); return true; } } switch (code) { case TRANSACTION_scheduleReceiver:{ android.content.Intent _arg0; _arg0 = data.readTypedObject(android.content.Intent.CREATOR); ... int _arg8; _arg8 = data.readInt(); data.enforceNoDataAvail(); this.scheduleReceiver(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7, _arg8); break; } ... default:{ return super.onTransact(code, data, reply, flags); } } return true; } private static class Proxy implements android.app.IApplicationThread { 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 scheduleReceiver( android.content.Intent intent, ... int processState) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); ... _data.writeTypedObject(intent, 0); boolean _status = mRemote.transact( Stub.TRANSACTION_scheduleReceiver, _data, null, android.os.IBinder.FLAG_ONEWAY); } finally { _data.recycle(); } } ... } public static final java.lang.String DESCRIPTOR = "android.app.IApplicationThread"; static final int TRANSACTION_scheduleReceiver = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_scheduleCreateService = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); ... public int getMaxTransactionId() { return 57; } } ... public void scheduleReceiver( android.content.Intent intent, ... int processState) throws android.os.RemoteException; } 对于Java代码,AIDL会生成一个跟AIDL同名的接口,同时继承自IInterface,同时还会创建内部类,分别为Default和Stub。Default为默认实现,大多数情况下是没有的,因为我们自己会实现。而Stub为抽象类,我们自己实现的时候会使用它,它以及继承自Binder,AIDL工具帮助我们把Parcel读写相关的代码已经生成,我们只需要去继承它,实现业务逻辑即可。而Stub中还有一个内部类Proxy,这个类用于Binder服务的客户端使用。对于IApplicationThread的实现,在ActivityThread当中。 匿名服务的传

来自 码农明明桑作者主页
在原博客阅读全文 (新标签页打开)

以上内容来自博客订阅源,版权归原作者。关注作者后可以在 关注列表 第一时间查看作者文章。

一起聊聊 0

尊重不同观点

还没有评论。欢迎分享第一个想法。

RSS SUBSCRIPTIONS

选择 RSS 订阅

把博客汇的文章添加到你常用的阅读器。

关注文章 RSS 订阅本订阅需要登录后使用