在 Framework 中使用 AIDL 服务,其发布和获取是两个重要方法,本文尝试探究其源码的实现。
我们知道手机在开机过程中,会启动一个 ServiceManger 的服务,它就是服务的大管家。AIDL 服务的发布和获取也是要通过这个大管家来 *** 作的,下面是大管家的路径。
/frameworks/native/cmds/servicemanager/ServiceManager.cpp
- 1 AIDL 的发布方法
- publishBinderService
- 2 服务的获取方法
- getService
- 3 ServiceManger 相关类图
该方法定义在 SystemService.java 中,有多个重载方法,最后都调到了下面这个方法。
/frameworks/base/services/core/java/com/android/server/SystemService.java
429 /**
430 * Publish the service so it is accessible to other services and apps.
431 *
432 * @param name the name of the new service
433 * @param service the service object
434 * @param allowIsolated set to true to allow isolated sandboxed processes
435 * to access this service
436 * @param dumpPriority supported dump priority levels as a bitmask
437 *
438 * @hide
439 */
440 protected final void publishBinderService(String name, IBinder service,
441 boolean allowIsolated, int dumpPriority) {
442 ServiceManager.addService(name, service, allowIsolated, dumpPriority);
443 }
进一步调到 ServiceManager.addService
,这里的 ServiceManager 还是 java 层的。我们继续看看它内部的实现
194 public static void addService(String name, IBinder service, boolean allowIsolated,
195 int dumpPriority) {
196 try {
197 getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
198 } catch (RemoteException e) {
199 Log.e(TAG, "error in addService", e);
200 }
201 }
接着 getIServiceManager
看下去,它最终会通过 binder 获得大管家 ServiceManger 的代理对象 ServiceManagerProxy。
110 private static IServiceManager getIServiceManager() {
111 if (sServiceManager != null) {
112 return sServiceManager;
113 }
114 //要获取一个binder服务,serviceManger
115 // Find the service manager
116 sServiceManager = ServiceManagerNative
117 .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
118 return sServiceManager;
119 }
关于 ServiceManagerNative.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()))
中的参数。十分重要的一点是 BinderInternal.getContextObject 函数最终返回的是一个BinderProxy 对象,该 BinderProxy 对象对应于 BpBinder(0),其作为 binder代理端,指向 native 层大管家 service Manager。
这里一定要记住!!!
在这个对象中包含一个名称为 sProxyMap 的 ProxyMap 对象,Native 层的 BpBinder 对象作为 key,BinderProxy 对象作为Value,存入该ProxyMap对象中。BpBinder 和 BinderProxy 其实是一个东西:远程 binder 的实体,不同是前者 Native 层、后者 Java 层。至于 Binder.allowBlocking
,一顿 *** 作后,返回的还是传入的 BinderProxy 对象,不用关注。
这部分内容具体可以看看下面这篇文章。https://juejin.cn/post/7058834333963911205#heading-2
我们继续关注 ServiceManagerNative.asInterface 的实现。
27 public final class ServiceManagerNative {
28 private ServiceManagerNative() {}
...
//上面的代码就是调用到了这个方法
37 @UnsupportedAppUsage
38 public static IServiceManager asInterface(IBinder obj) {
39 if (obj == null) {
40 return null;
41 }
42
43 // ServiceManager is never local
44 return new ServiceManagerProxy(obj);//new 一个代理对象,要代理我们的 ServiceManager
45 }
46 }
47
48 // This class should be deleted and replaced with IServiceManager.Stub whenever
49 // mRemote is no longer used
50 class ServiceManagerProxy implements IServiceManager {
51 public ServiceManagerProxy(IBinder remote) {
52 mRemote = remote;
//下面这行是不是很熟悉,这不就是我们获取 binder 服务的 *** 作嘛
//所以这里是要获取 IServiceManager
53 mServiceManager = IServiceManager.Stub.asInterface(remote);
54 }
123 }
上面代码,是把在 ServiceManger.java 传入的 BinderProxy 对象,转化成 ServiceManger,从而获得 native 层的服务大管家。
经过以上分析,我们知道了,注册 AIDL 服务,也是一个跨进程通信的过程,通过 binder 调用的是 native 层的 ServiceManger。
不难发现 framework 层的调用工作实际都交给了 ServiceMangerProxy 来做;而 ServiceMangerProxy 又依靠它的成员变量 BinderProxy,BinderProxy 通过 jni 方式,走到了 native 层,最终完成调用。
详细过程请看这篇文章。
http://gityuan.com/2015/11/21/binder-framework/
首先也是从 java 层的 ServiceManger 开始,返回的结果是一个 IBinder 类型对象,需要经过 .Stub.asInterface(IBinder)
的 *** 作转化成对应服务。
/frameworks/base/core/java/android/os/ServiceManager.java
121 /**
122 * Returns a reference to a service with the given name.
123 *
124 * @param name the name of the service to get
125 * @return a reference to the service, or null
if the service doesn't exist
126 */
127 @UnsupportedAppUsage
128 public static IBinder getService(String name) {
129 try {
130 IBinder service = sCache.get(name);
131 if (service != null) {
132 return service;
133 } else {
134 return Binder.allowBlocking(rawGetService(name));
135 }
136 } catch (RemoteException e) {
137 Log.e(TAG, "error in getService", e);
138 }
139 return null;
140 }
141
首先尝试从缓存中获取需要的 IBinder 对象。
38 /**
39 * Cache for the "well known" services, such as WM and AM.
40 */
41 @UnsupportedAppUsage
42 private static Map<String, IBinder> sCache = new ArrayMap<String, IBinder>();
当缓存中没有时,使用 Binder.allowBlocking(rawGetService(name))
方法,重点是 rawGetService(name)
。
private static IBinder rawGetService(String name) throws RemoteException {
...
334
335 final IBinder binder = getIServiceManager().getService(name);
...
384 return binder;
385 }
386 }
这里走到了和发布服务同样的地方 getIServiceManager,一顿 *** 作后获得了服务大管家 ServiceManger 的客户端 binder,实现跨进程调用 getService 方法。
3 ServiceManger 相关类图为了便于理解,我做了一个简单的类图,并不完全,主要是帮助理解上面内容的。
ServiceManagerProxy:只有这一个类实现了 ServiceManager 接口,所以 framework 层的相关调用最后都会找到它。他的 mRemote 是一个 BinderProxy 类型对象。
ServiceManagerNative: ServiceManagerProxy 类是放在这个类的包下的,对外不可见。因此需要通过这个类间接获得 ServiceManagerProxy 类对象。
ServiceManager:这个是 java 层的 ServiceManager,不是大管家,感觉就是负责接待的喽啰,有事就找他,他再找大佬。它通过 ServiceManagerNative 获得 ServiceManagerProxy 对象,BinderInternal.getContextObject() 这个获取真正大管家 IBinder 的 *** 作就是此时作为参数传入的。
BinderProxy:暂时只知道它能调用到 native 层,具体怎么实现的还未探究。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)