之前介绍了Binder跨进程通信中AIDL文件的具体实现流程,之后又实现Native层、framework层Binder框架的具体使用范例。其使用规范都是基于底层设计好的框架之上,本章节就针对其框架,步步分析其实现流程背后的原理,对着代码一步一步追溯到源头,废话不多说,Fucking Code!
ServiceManager的获取流程
对于上层应用来说,获取ServiceManager大管家的方式无非两种,一种是framework层获取,一种是Native层获取,具体对应方式如下
framework层获取SM
原生API获取服务流程浅析
对于Java层获取SM方式,相信对于应用层开发来说非常熟悉了,我们可以通过类ServiceManager.getService()方法,通过传入服务名称来获取对应的远程代理服务对象。例如获取闹钟服务时,调用代码 getSystemService(Context.ALARM_SERVICE) 即可获取相应服务,然而其内部获取的流程是如何实现的呢?下面我们追溯代码看一下具体调用流程。
通过Activity的getSystemService()方法,我们追溯下去
@Override public Object getSystemService(@ServiceName @NonNull String name) { if (getBaseContext() == null) { throw new IllegalStateException( "System services not available to Activities before onCreate()"); } if (WINDOW_SERVICE.equals(name)) { return mWindowManager; } else if (SEARCH_SERVICE.equals(name)) { ensureSearchManager(); return mSearchManager; } return super.getSystemService(name); }
通过super.getSystemService(name)调用父类的getSystemService
ContextThemeWrapper的getSystemService
@Override public Object getSystemService(String name) { if (LAYOUT_INFLATER_SERVICE.equals(name)) { if (mInflater == null) { mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this); } return mInflater; } return getBaseContext().getSystemService(name); }
通过getBaseContext()调用父类的方法
public Context getBaseContext() { return mBase; } @Override public Object getSystemService(String name) { return mBase.getSystemService(name); }
其中的mBase实际指向Context类
Context的具体方法实现
public abstract @Nullable Object getSystemService(@ServiceName @NonNull String name);
貌似到这里就停下来,其提供一个抽象方法由子类实现,最后是谁来实现呢?Context类有一个实现类ContextImp,我们来看一下里面的内容。
ContextImp的getSystemService方法
@Override public Object getSystemService(String name) { return SystemServiceRegistry.getSystemService(this, name); }
间接调用了SystemServiceRegistry类的getSystemService()方法
SystemServiceRegistry具体方法
public static Object getSystemService(ContextImpl ctx, String name) { ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name); return fetcher != null ? fetcher.getService(ctx) : null; }
由类名SystemServiceRegistry可知,此类和服务注册有关,其内部有两个重要的静态私有成员常量(final修饰的变量)中保存了Hash列表,如下:
private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES = new HashMap<Class<?>, String>(); private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS = new HashMap<String, ServiceFetcher<?>>();
其中ServiceFetcher为一个接口,其返回一个范性T,SystemServiceRegistry内部有三个具体类实现了此接口
static abstract interface ServiceFetcher<T> { T getService(ContextImpl ctx); } // 其中的一个实现类如下 static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> { private final int mCacheIndex; public CachedServiceFetcher() { mCacheIndex = sServiceCacheSize++; } @Override @SuppressWarnings("unchecked") public final T getService(ContextImpl ctx) { final Object[] cache = ctx.mServiceCache; synchronized (cache) { // Fetch or create the service. Object service = cache[mCacheIndex]; if (service == null) { service = createService(ctx); cache[mCacheIndex] = service; } return (T)service; } } public abstract T createService(ContextImpl ctx); }
在类的前面有一大片的静态代码块,其中涉及到了服务的初始化注册代码。
SystemServiceRegistry静态代码块
static { ... registerService(Context.ALARM_SERVICE, AlarmManager.class, new CachedServiceFetcher<AlarmManager>() { @Override public AlarmManager createService(ContextImpl ctx) { IBinder b = ServiceManager.getService(Context.ALARM_SERVICE); IAlarmManager service = IAlarmManager.Stub.asInterface(b); return new AlarmManager(service, ctx); }}); ... }
通过registerService()方法,缓存系统相关服务,方便用户获取
private static <T> void registerService(String serviceName, Class<T> serviceClass, ServiceFetcher<T> serviceFetcher) { SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName); SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher); }
- 参数一:服务名称
- 参数二:服务具体类文件
- 参数三:服务对应的ServiceFetcher对象
到这里基本就可以看到最终的调用结果,即通过SM获取IBinder远程服务代理对象,然后通过IAlarmManager.Stub.asInterface()方法将IBinder对象转换成可以使用的IAlarmManager服务对象
IBinder b = ServiceManager.getService(Context.ALARM_SERVICE);
IAlarmManager service = IAlarmManager.Stub.asInterface(b);
到这里,是不是和AIDL中流程分析很相似呢?不错,其调用获取、转换方式基本都是一致的。下面我们来具体分析真正的SM获取流程。
framework层获取sm分析
上面小结分析得出最终调用的方式为IBinder b = ServiceManager.getService(Context.ALARM_SERVICE);,我们就由此开始分析。
ServiceManager.getService()
//getService()最终获取了指向目标Binder服务端的代理对象BinderProxy public static IBinder getService(String name) { try { //其中sCache = new HashMap<String, IBinder>() 以hashmap格式缓存已组成的名称 // 请求获取服务过程中,先从缓存中查询是否存在,如果缓存中不存在的话,再通过binder交互来查询相应的服务 IBinder service = sCache.get(name); if (service != null) { return service; } else { //调用的是ServiceManagerNative的ServiceManagerProxy的getService() return getIServiceManager().getService(name); } } catch (RemoteException e) { Log.e(TAG, "error in getService", e); } return null; }
代码注释很详细,sCache为一个HashMap,键值分别为服务名、IBinder对象。首先从缓存中获取服务的IBinder对象,不存在,就调用getIServiceManager().getService(name)来获取。
getIServiceManager().getService()
//返回的是ServiceManagerProxy对象 private static IServiceManager getIServiceManager() { if (sServiceManager != null) { return sServiceManager; } // Find the service manager // ServiceManagerNative.asInterface(BinderInternal.getContextObject()) == new ServiceManagerProxy(new BinderProxy()) sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject()); return sServiceManager; }
getIServiceManager获取到类内部的静态的IServiceManager对象,IServiceManager接口继承自IInterface接口,是不是又是很亲切,哈哈!其最终对应的是SM的远程代理对象ServiceManagerProxy。这里首先透露一下,ServiceManagerNative.asInterface(BinderInternal.getContextObject())方法通过jni调用c层代码,获取位于c层的handle值为0的binder引用对象,其对应的正是ServiceManager对象大管家。
获取到了SM大管家,通过传入的服务名称即可获取相应的远程代理服务对象了。由于IServiceManager继承自IInterface接口,所以我们需要找到实现IServiceManager接口的类即可找到具体的实现方法。BinderInternal.getContextObject()
ServiceManagerNative.getService()
ServiceManagerProxy实际上在ServiceManagerNative文件中,ServiceManagerProxy类有一个IBinder对象mRemote,其是Binder驱动为服务分配的远程服务代理对象,这个和AIDL中分析的相一致,而mRemote对象就是和Binder驱动进行通信的关键。/** * 其成员变量mRemote指向BinderProxy对象 * ServiceManagerProxy的addService, getService方法最终是交由mRemote来完成 */ class ServiceManagerProxy implements IServiceManager { //mRemote是BinderProxy的对象,该BinderProxy对象对应于BpBinder(0) //其作为binder代理管家,指向native层的大管家Service Manager public ServiceManagerProxy(IBinder remote) { mRemote = remote; } public IBinder asBinder() { return mRemote; } //getService()最终获取了指向目标Binder服务端的代理对象BinderProxy public IBinder getService(String name) throws RemoteException { //此处需要将java层的Parcel转成Native层的Parcel Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IServiceManager.descriptor); data.writeString(name); //mRemote为BinderProxy对象 mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0); //从replay里面解析出获取的IBinder对象,调用Parcel.java中native方法 //最终创建了指向Binder服务端的BpBinder代理对象 IBinder binder = reply.readStrongBinder(); reply.recycle(); data.recycle(); return binder; } public IBinder checkService(String name) throws RemoteException { ... } public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException { ... } public String[] listServices() throws RemoteException { ... } public void setPermissionController(IPermissionController controller) throws RemoteException { ... } private IBinder mRemote; }
由上代码可以看出getService()方法,最终由Parcel数据封装服务信息,调用mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0)方法与Binder驱动进行交互。
在AIDL分析文章中介绍类Binder和IBinder的作用,现在我们查看一下其具体的代码。Binder文件一览分析
public class Binder implements IBinder { public IInterface queryLocalInterface(String descriptor) { ... } protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { if (code == INTERFACE_TRANSACTION) { reply.writeString(getInterfaceDescriptor()); return true; } else if (code == DUMP_TRANSACTION) { ParcelFileDescriptor fd = data.readFileDescriptor(); String[] args = data.readStringArray(); if (fd != null) { try { dump(fd.getFileDescriptor(), args); } finally { try { fd.close(); } catch (IOException e) { // swallowed, not propagated back to the caller } } } // Write the StrictMode header. if (reply != null) { reply.writeNoException(); } else { StrictMode.clearGatheredViolations(); } return true; } return false; } public final boolean transact(int code, Parcel data, 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; } private boolean execTransact(int code, long dataObj, long replyObj, int flags) { Parcel data = Parcel.obtain(dataObj); Parcel reply = Parcel.obtain(replyObj); boolean res; try { res = onTransact(code, data, reply, flags); } catch (RemoteException e) { if ((flags & FLAG_ONEWAY) != 0) { Log.w(TAG, "Binder call failed.", e); } else { reply.setDataPosition(0); reply.writeException(e); } res = true; } catch (RuntimeException e) { if ((flags & FLAG_ONEWAY) != 0) { Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e); } else { reply.setDataPosition(0); reply.writeException(e); } res = true; } catch (OutOfMemoryError e) { RuntimeException re = new RuntimeException("Out of memory", e); reply.setDataPosition(0); reply.writeException(re); res = true; } checkParcel(this, code, reply, "Unreasonably large binder reply buffer"); reply.recycle(); data.recycle(); ... StrictMode.clearGatheredViolations(); return res; } } final class BinderProxy implements IBinder { public native boolean pingBinder(); public native boolean isBinderAlive(); public IInterface queryLocalInterface(String descriptor) { return null; } //最终交由Native层的BpBinder::transact()完成 //另外,该方法可抛出RemoteException public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { //用于检测Parcel大小是否大于800k Binder.checkParcel(this, code, data, "Unreasonably large binder buffer"); return transactNative(code, data, reply, flags); } public native String getInterfaceDescriptor() throws RemoteException; //对应android_util_Binder.cpp下android_os_BinderProxy_transact具体方法 public native boolean transactNative(int code, Parcel data, Parcel reply, int flags) throws RemoteException; public native void linkToDeath(DeathRecipient recipient, int flags) throws RemoteException; public native boolean unlinkToDeath(DeathRecipient recipient, int flags); public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeFileDescriptor(fd); data.writeStringArray(args); try { transact(DUMP_TRANSACTION, data, reply, FLAG_ONEWAY); } finally { data.recycle(); reply.recycle(); } } BinderProxy() { mSelf = new WeakReference(this); } @Override protected void finalize() throws Throwable { try { destroy(); } finally { super.finalize(); } } private native final void destroy(); private static final void sendDeathNotice(DeathRecipient recipient) { if (false) Log.v("JavaBinder", "sendDeathNotice to " + recipient); try { recipient.binderDied(); } catch (RuntimeException exc) { Log.w("BinderNative", "Uncaught exception from death notification", exc); } } final private WeakReference mSelf; private long mObject; private long mOrgue; }
代码比较多,这里知识贴出来大概通览一遍,如果是对AIDL文件实现流程很清晰的话,便会很快的找到共同点。这里作一个大概的解读。
- BinderProxy实现IBinder接口,ServiceManagerProxy内的IBinder对象mRemote即是SM远程代理实例,mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0)便是通过BinderProxy类的transact方法,继而进入jni通过c调用与Binder驱动进行交互。
- Binder也实现了IBinder接口,但是其对应的是Server端的对象,是本地Binder服务。其接受远程mRemote代理对象通过Binder驱动传来请求,处理并返回。此期间Client端处于堵塞状态。自定义的Server端服务可以通过继承Binder,实现其onTransact方法即可,此方法由于驱动支持,会自动调用。
- 进程间数据均由Parcel封装,data.***方法由底层jni实现,便于与驱动交互。