继承上一篇博客Android Binder框架实现之Framework层Binder服务注册过程源码分析未完成的意愿我们接着继续分析,在上一篇博客中我们主要干了如下几件事情(当然前提是各位小伙伴有看前篇的博客):
服务被注册了,当然是被用来使用的而不是被当作花瓶的,那么Android必然也提供了对应的方法在Framewrok层获取Binder服务,而今天的博客将会接着继续分析Framework层获取Binder服务过程。
注意
:本篇的介绍是基于Android 7.xx平台为基础的,其中涉及的代码路径如下:framework/base/core/java/android/os/
---IInterface.java
---IServiceManager.java
---ServiceManager.java
---ServiceManagerNative.java(内含ServiceManagerProxy类)
framework/base/core/java/android/os/
---IBinder.java
---Binder.java(内含BinderProxy类)
---Parcel.java
framework/base/core/java/com/android/internal/os/
---BinderInternal.java
framework/base/core/jni/
---AndroidRuntime.cpp
---android_os_Parcel.cpp
---android_util_Binder.cpp
frameworks/native/libs/binder/BpBinder.cpp
frameworks/native/include/binder/IBinder.h
frameworks/native/libs/binder/Binder.cpp
frameworks/native/include/binder/Parcel.h
frameworks/native/libs/binder/Parcel.cpp
frameworks/base/core/jni/core_jni_helpers.h
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
frameworks//base/core/java/android/app/ActivityThread.java
在上一篇博客中我们以AMS为例讲述了怎么将其注册到servicemanager中,这里我们依然以它为例讲述怎么获取到它的代理端ActivityManager的,我们通常的获取手段如下:
//ActivityManagerNative.java
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ActivityManagerProxy(obj);
}
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");//详见章节1.1
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
}
//ServiceManager.java
private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);//从Hash表中查询是否有合适的,如果没有则向servicemanager服务大管家查询
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
这里可以看到设计了一个缓存机制,即每次获取服务前都会查找缓存HashMap
//ServiceManager.java
public static void initServiceCache(Map<String, IBinder> cache) {
if (sCache.size() != 0) {
throw new IllegalStateException("setServiceCache may only be called once");
}
sCache.putAll(cache);
}
但是我咋没有看到调用该方法啊,我还是不死心,终于在ActivityThread.java类中的bindApplication方法中有找到了(至于bindApplication方法吗我想对于Android 应用进程启动的小伙们来说应该都很熟悉,不是很了解的可以移步到Android 应用进程启动大揭秘中),如下:
//ActivityThread.java
public final void bindApplication(String processName, ApplicationInfo appInfo,
List<ProviderInfo> providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) {
if (services != null) {
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
...
}
getIServiceManager()方法已经在Android Binder框架实现之Framework层Binder服务注册过程源码分析中进行了详细分析,该函数返回一个ServiceManagerProxy对象,因此调用ServiceManagerProxy对象的getService函数来完成服务查询。
//ServiceManagerNative.java
public IBinder getService(String name) throws RemoteException {
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);
//从reply里面解析出获取的IBinder对象
IBinder binder = reply.readStrongBinder();
reply.recycle();
data.recycle();
return binder;
}
我们通过前面的博客Android Binder框架实现之Parcel详解一分析应该知道了Parcel是用来打包传递数据的一个载体,此时我们将相关要传递的数据打包到Parcel中后,其中存储内容如下:
通过前面的博客分析我们也知道了ServiceManagerProxy代理服务端变量mRmote指向BinderProxy(0),而BinderProxy(0)又将会指向BpBinder(0),其数据结构关系如下:
至于BpBinder怎么借助BInder驱动将请求查询服务发送请求发送到servicemanager进程中的这个我们就不分析了,该过程可以参见Android Binder框架实现之Native层getService的实现过程,这里我大概介绍下基本过程:
好吗,上面的总结我也不指望小伙们能一下子理解清楚(能理解捋顺的小伙伴也不会看这个博客了),小伙们在这里只需要有一个概念就是通过上面的mRemote.transact然后借助Binder驱动会从servicemanager查询的结果返回到客户端进程中的reply的Parcel容器数据里,然后该返回结果中存在一个句柄值可以通过Binder驱动调用到远端服务进程就OK了。
//Parcel.java
private static native IBinder nativeReadStrongBinder(long nativePtr);
public final IBinder readStrongBinder() {
return nativeReadStrongBinder(mNativePtr);//详见章节1.4
}
依然是老配方和老套路,通过JNI调用到Native层进行相关的处理。这里的readStrongBinder可以认为是前面注册服务中writeStrongBinder的逆向过程。
//android_os_Parcel.cpp
static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
//这里的javaObjectForIBinder是不是很熟悉,在注册服务中我们有讲述到主要是将BpBinder(C++)转换成Java层的BinderProxy
//我们这里只重点关注parcel->readStrongBinder()
return javaObjectForIBinder(env, parcel->readStrongBinder());//详见章节1.4.1
}
return NULL;
}
此处android_os_Parcel_readStrongBinder函数的逻辑可以分为两层:
status_t Parcel::readStrongBinder(sp<IBinder>* val) const
{
return unflatten_binder(ProcessState::self(), *this, val);//详见1.4.3
}
sp<IBinder> Parcel::readStrongBinder() const
{
sp<IBinder> val;
readStrongBinder(&val);
return val;
}
前有注册服务时候的flatten_binder扁平化Binder对象,现有unflatten_binder反扁平化Binder对象,你们是全家桶是吗!前饼果子来一套,切克闹!
//Parcel.cpp
status_t unflatten_binder(const sp<ProcessState>& proc,
const Parcel& in, sp<IBinder>* out)
{
//flat_binder_object应该是熟悉面孔了吗,主要用来解析Parcel中的存储的Binder数据类型
const flat_binder_object* flat = in.readObject(false);
if (flat) {
switch (flat->type) {
case BINDER_TYPE_BINDER:
...
case BINDER_TYPE_HANDLE://会走该分支,因为我们是跨进程获取Binder服务的代理端
//该过程主要是通过获取远程服务端引用的句柄,创建BpBinder
*out = proc->getStrongProxyForHandle(flat->handle);//详见章节1.4.4
return finish_unflatten_binder(
static_cast<BpBinder*>(out->get()), *flat, in);
}
}
return BAD_TYPE;
}
这里的flat_binder_object结构体是我们的老熟人了,其被设计用来解析存储Parcel中的Bidner对象类型数据(即可以是Binder实体服务,也可以是Binder引用对象,男女通吃老少皆宜!)。然后我们知道此时从Binder驱动中读取回来的是远程Binder服务的Binder引用类型,所以会走BINDER_TYPE_HANDLE分支,该分支干的事情吗也不多,主要如下:
//ProcessState.h
struct handle_entry {
IBinder* binder;
RefBase::weakref_type* refs;
};
Vector<handle_entry>mHandleToObject;
//ProcessState.cpp
ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
{
const size_t N=mHandleToObject.size();
if (N <= (size_t)handle) {
handle_entry e;
e.binder = NULL;
e.refs = NULL;
status_t err = mHandleToObject.insertAt(e, N, handle+1-N);
if (err < NO_ERROR) return NULL;
}
return &mHandleToObject.editItemAt(handle);
}
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);//查询mHandleToObject列表中是否有该handle的记录,即该进程以前是否有获取过该服务
if (e != NULL) {//找到了
// We need to create a new BpBinder if there isn't currently one, OR we
// are unable to acquire a weak reference on this current one. See comment
// in getWeakProxyForHandle() for more info about this.
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {//这里的handle为0是专属席位,是给ServiceManagerProxy的,所以我们和此处无缘
Parcel data;
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, NULL, 0);
if (status == DEAD_OBJECT)
return NULL;
}
//根据handle创建BpBinder
b = new BpBinder(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
// This little bit of nastyness is to allow us to add a primary
// reference to the remote proxy when this team doesn't have one
// but another team is sending the handle to us.
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
经过重重险阻,最终创建了指向AMS Binder服务端的BpBinder代理对象。而我们在章节1.4中说过javaObjectForIBinder将native层BpBinder对象转换为Java层BinderProxy对象。 这里我们通过ServiceManager.getService最终获取了指向目标Binder服务端的代理对象BinderProxy。但是我们知道BinderProxy是用来和Binder驱动进行通信的,那么怎么和服务端的业务逻辑牵涉起来呢,这个我们章节1.5再来分析。回到章节1.4.3还有最后一个小点finish_unflatten_binder看看它干了啥,其实没有干啥:
//Parcel.cpp
inline static status_t finish_unflatten_binder(
BpBinder* /*proxy*/, const flat_binder_object& /*flat*/,
const Parcel& /*in*/)
{
return NO_ERROR;
}