本文主要是介绍从app bindService分析binder客户端,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
从 bindService() 分析 Binder 客户端
大家都知道的是 Binder 采用的是 C/S 架构思想,由 Client 端发起调用请求,由 Server 执行请求并返回结果(没有结果)。
写 App 程序进行 IPC 调用时,需要在调用端中 bindService
获取服务端的 Binder
接口对象,再调用方法。这篇文章尝试通过 bindService
方法的核心调用过程,分析Binder客户端的流程。
bindService()
我们在 Activity
中写到的 bindService(Intent service, ServiceConnection conn, BindServiceFlags flags)
调用到的是 ContextWrapper
中的方法。
// frameworks/base/core/java/android/content/ContextWrapper.java@UnsupportedAppUsage
Context mBase;@Override
public boolean bindService(@NonNull Intent service, @NonNull ServiceConnection conn,@NonNull BindServiceFlags flags) {return mBase.bindService(service, conn, flags);
}
在 ContextWrapper.bindService
调用到了 mBase.bindService(service, conn, flags)
,最终会调用到 ContextImpl.bindService()
方法。
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {warnIfCallingFromSystemProcess();return bindServiceCommon(service, conn, Integer.toUnsignedLong(flags), null,mMainThread.getHandler(), null, getUser());
}private boolean bindServiceCommon(Intent service, ServiceConnection conn, long flags,String instanceName, Handler handler, Executor executor, UserHandle user) {IServiceConnection sd;// ......try {IBinder token = getActivityToken();// ......service.prepareToLeaveProcess(this); // 同一进程内,内部的比较 leavingPackage=false// 下面是执行的 bindService 过程中的一个关键方法调用int res = ActivityManager.getService().bindServiceInstance(mMainThread.getApplicationThread(), getActivityToken(), service,service.resolveTypeIfNeeded(getContentResolver()),sd, flags, instanceName, getOpPackageName(), user.getIdentifier());// ......return res != 0;} catch (RemoteException e) {throw e.rethrowFromSystemServer();}
}
获取 AMS binder对象
主要关注主要流程的实现,因此移除一些代码,全部的代码放开很占篇幅。很多更深层源码的理解,涉及到更深的知识,也有超出我理解的范围的地方,请不吝赐教。
在 bindServiceCommon()
方法中,主要流程调用到了
int res = ActivityManager.getService().bindServiceInstance(mMainThread.getApplicationThread(), getActivityToken(), service,service.resolveTypeIfNeeded(getContentResolver()),sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
这条语句中,先通过 ActivityManager.getService()
获取到 ActivityManagerService
的 Binder 对象。
// frameworks/base/core/java/android/app/ActivityManager.java@UnsupportedAppUsage
public static IActivityManager getService() {return IActivityManagerSingleton.get();
}// 定义 singleton 对象。
@UnsupportedAppUsage
private static final Singleton<IActivityManager> IActivityManagerSingleton =new Singleton<IActivityManager>() {@Overrideprotected IActivityManager create() {// 从 ServiceManager 中获取 AMS 的 binder 对象final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);final IActivityManager am = IActivityManager.Stub.asInterface(b);return am;}};
基于当前分析的流程,getService(String name)
的参数值是 Context.ACTIVITY_SERVICE
。
// frameworks/base/core/java/android/os/ServiceManager.java@UnsupportedAppUsage
private static IServiceManager sServiceManager;// IServiceManager 这是接口类型,对应的是 IServiceManager.aidl 文件编译后得到的java类型。
@UnsupportedAppUsage
private static IServiceManager getIServiceManager() {if (sServiceManager != null) {return sServiceManager;}// Find the service managersServiceManager = ServiceManagerNative.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));return sServiceManager;
}// 执行的逻辑比较简单,在缓存列表中查找 name 对应的 Binder 对象,
@UnsupportedAppUsage
public static IBinder getService(String name) { // 此时这里的值是 Context.ACTIVITY_SERVICEtry {IBinder service = sCache.get(name);if (service != null) {return service;} else {return Binder.allowBlocking(rawGetService(name)); // 这是获取 Binder 对象的关键。}} catch (RemoteException e) {Log.e(TAG, "error in getService", e);}return null;
}private static IBinder rawGetService(String name) throws RemoteException {final long start = sStatLogger.getTime();final IBinder binder = getIServiceManager().getService(name);final int time = (int) sStatLogger.logDurationStat(Stats.GET_SERVICE, start);final int myUid = Process.myUid();final boolean isCore = UserHandle.isCore(myUid);// ...... 后续的代码中,并没有对 binder 对象作出关键的修改。return binder;
}
从 getService()
调用到 Binder.allowBloking()
。
// frameworks/base/core/java/android/os/Binder.java// 方法的返回还是传入的 binder
public static IBinder allowBlocking(IBinder binder) {try {if (binder instanceof BinderProxy) {((BinderProxy) binder).mWarnOnBlocking = false;} else if (binder != null && binder.getInterfaceDescriptor() != null&& binder.queryLocalInterface(binder.getInterfaceDescriptor()) == null) {Log.w(TAG, "Unable to allow blocking on interface " + binder);}} catch (RemoteException ignored) {}return binder;
}
allowBlocking
方法中,没有处理具体的修改,针对传入的 binder
也没有作出影响执行流程的修改。因此,回到 ServiceManager.getService()
方法中,关键的执行流程在 rawGetService(name)
方法中。
在 ServiceManager.rawGetService(String name)
方法中,关键在
final IBinder binder = getIServiceManager().getService(name); // 这个 binder 对象值最终方法返回的对象。
getIServiceManager()
返回的是 IServiceManager
类型,对应的是 IServiceManager.aidl
文件编译后得到的java接口类型。在它的实现中,调用 ServiceManagerNative.asInterface()
方法。
// frameworks/base/core/java/android/os/ServiceManagerNative.javapublic final class ServiceManagerNative {private ServiceManagerNative() {}// 参数 obj 将是获取到的服务端的 Binder 对象,整个设计是 代理模式 。@UnsupportedAppUsagepublic static IServiceManager asInterface(IBinder obj) {if (obj == null) {return null;}// ServiceManager is never localreturn new ServiceManagerProxy(obj);}
}
ServiceManagerNative
的方法中返回的是带有 Binder 对象的 ServiceManagerProxy
代理类。
紧接着:要知道 ServiceManagerNative.asInterface(IBinder)
是从怎么获取到的?
从方法调用上,返回到 ServiceManager.getIServiceManager()
方法中,之前分析到 Binder.allowBlocking(IBinder)
方法内并没有对参数作出关键的修改,因此 Binder 需要从BinderInternal.getContextObject()
的调用中获取。
// frameworks/base/core/java/com/android/internal/os/BinderInternal.java@UnsupportedAppUsage
public static final native IBinder getContextObject();
从上面这个方法定义可知,这是一个 JNI 调用,需要知道 getContextObject()
方法对应的 C/C++ 层的具体实现函数。
要在 Android 系统中找 JNI 接口定义的注册位置, jni 接口是属于java虚拟机的一部分,因此大概的位置应该要在 VM 相关的代码中查找,就查找到 AndroidRuntime.cpp 看看是不是会有与 Binder 注册有关的函数。
static const RegJNIRec gRegJNI[] = {// .... }
可以看到这个数组的声明,在这里可以看到很多
register_*
的函数注册,可以搜索到register_android_os_Binder
的注册,进而查找到文件android_util_Binder.cpp
文件,对应的register_android_os_Binder
函数定义也有。另一个查找方式就是全局搜索文件内容
getContextObject
,再过滤信息找到 JNI 定义位置。
在查找到 Binder 相关注册函数在文件 android_util_Binder.cpp
文件。
// frameworks/base/core/jni/android_util_Binder.cppint register_android_os_Binder(JNIEnv* env)
{if (int_register_android_os_Binder(env) < 0)return -1;if (int_register_android_os_BinderInternal(env) < 0) // 看到 BinderInternal 类的注册函数return -1;if (int_register_android_os_BinderProxy(env) < 0)return -1;// ......return 0;
}const char* const kBinderProxyPathName = "android/os/BinderProxy";static int int_register_android_os_BinderProxy(JNIEnv* env)
{// ...... 加载 Java 层的异常类。// JNI调用,找到 Java 层类 android.os.BinderProxy,得到 jclass 对象。jclass clazz = FindClassOrDie(env, kBinderProxyPathName);gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);gBinderProxyOffsets.mGetInstance = GetStaticMethodIDOrDie(env, clazz, "getInstance","(JJ)Landroid/os/BinderProxy;");gBinderProxyOffsets.mSendDeathNotice =GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice","(Landroid/os/IBinder$DeathRecipient;Landroid/os/IBinder;)V");gBinderProxyOffsets.mNativeData = GetFieldIDOrDie(env, clazz, "mNativeData", "J");clazz = FindClassOrDie(env, "java/lang/Class");gClassOffsets.mGetName = GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;");return RegisterMethodsOrDie(env, kBinderProxyPathName,gBinderProxyMethods, NELEM(gBinderProxyMethods));
}static const JNINativeMethod gBinderInternalMethods[] = { // BinderInternal 方法对应关系/* name, signature, funcPtr */{ "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },// ...... 其他要注册的函数
};// BidnerInternal java类的包限定名的目录形式
const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";static int int_register_android_os_BinderInternal(JNIEnv* env)
{jclass clazz = FindClassOrDie(env, kBinderInternalPathName); // 找到java类// ......BpBinder::setLimitCallback(android_os_BinderInternal_proxyLimitcallback);return RegisterMethodsOrDie(env, kBinderInternalPathName,gBinderInternalMethods, NELEM(gBinderInternalMethods));
}
在函数 int_register_android_os_BinderInternal()
中进行了函数的注册,在函数数组 gBinderInternalMethods[]
的第一个看到了要查找的目标 getContextObject
,对应的函数是 android_os_BinderInternal_getContextObject
(实现在 android_util.Binder.cpp 文件)。
// frameworks/base/core/jni/android_util_Binder.cppstatic jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{sp<IBinder> b = ProcessState::self()->getContextObject(NULL);return javaObjectForIBinder(env, b);
}
ProcessState
是每一个进程创建起都有的进程对象。
// frameworks/native/libs/binder/ProcessState.cppsp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{// 获取 IBinder 对象并返回。sp<IBinder> context = getStrongProxyForHandle(0); // 参数 0 是 servicemanager 进程idif (context) {// The root object is special since we get it directly from the driver, it is never// written by Parcell::writeStrongBinder.internal::Stability::markCompilationUnit(context.get());} else {ALOGW("Not able to get context object on %s.", mDriverName.c_str());}return context;
}sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{sp<IBinder> result;std::unique_lock<std::mutex> _l(mLock);if (handle == 0 && the_context_object != nullptr) return the_context_object;// 在数组Vector在中查找 handle_entry,若刚开始数组大小是 0,系统会创建一个 handle_entry,放入到数组中。handle_entry* e = lookupHandleLocked(handle); if (e != nullptr) {IBinder* b = e->binder; // 在数组是大小是0的情况下,这里的 binder=nullptr。if (b == nullptr || !e->refs->attemptIncWeak(this)) {if (handle == 0) { // 本篇幅中,这个 handle 传入的就是 0。IPCThreadState* ipc = IPCThreadState::self();CallRestriction originalCallRestriction = ipc->getCallRestriction();ipc->setCallRestriction(CallRestriction::NONE);Parcel data;status_t status = ipc->transact(0, IBinder::PING_TRANSACTION, data, nullptr, 0);ipc->setCallRestriction(originalCallRestriction);if (status == DEAD_OBJECT)return nullptr;}// 创建 BpBinder 对象。sp<BpBinder> b = BpBinder::PrivateAccessor::create(handle);e->binder = b.get();if (b) e->refs = b->getWeakRefs();result = b;} else {result.force_set(b);e->refs->decWeak(this);}}return result;
}
这里获取到了 C/C++ 层的 IBinder(实际是 BpBinder) 对象。
Binder 客户端 获取 Binder 对象执行到这里获取到 IBinder
对象。我们再往回逐步查看,ProcessState::getContextObject()
-> android_util_Binder::android_os_BinderInternal_getContextObject()
。 在 C/C++层获取到 IBinder
对象之后,调用了 javaObjectForIBinder()
函数。
// frameworks/base/core/jni/android_util_Binder.cppjobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{if (val == NULL) return NULL;if (val->checkSubclass(&gBinderOffsets)) {jobject object = static_cast<JavaBBinder*>(val.get())->object();LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);return object;}BinderProxyNativeData* nativeData = new BinderProxyNativeData();nativeData->mOrgue = new DeathRecipientList;nativeData->mObject = val;// 通过JNI调用 android.os.BinderProxy::getInstance() 方法,创建Java层 BinderProxy 对象。jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());if (env->ExceptionCheck()) {return NULL;}BinderProxyNativeData* actualNativeData = getBPNativeData(env, object);if (actualNativeData != nativeData) {delete nativeData;}return object;
}
这个函数的作用即是将 C/C++ 层的 BpBinder
对象的数据转换成 Java 层 BinderProxy
对象数据。
执行完这个函数后,就会将 android.os.BinderProxy
对象作为 Java 层 getContextObject()
的返回值返回。这样ServiceManager::getIServiceManager()
执行完成,返回到 ServiceManager::rawGetService()
方法。
private static IBinder rawGetService(String name) throws RemoteException {final long start = sStatLogger.getTime();// 上述一切的重点在于 getIServiceManager() 任何获取 Client 端的 BinderProxy(BpBidner)。// 它返回的就是 ServiceManagerProxy,其中封装有 BinderProxy 对象。final IBinder binder = getIServiceManager().getService(name);// ......return binder;
}
在这里将 binder 返回,再返回到 ActivityManager.getService()
的最初位置,接着调用 bindServiceInstance()
方法。
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.javafinal ActiveServices mServices;public int bindServiceInstance(IApplicationThread caller, IBinder token, Intent service,String resolvedType, IServiceConnection connection, long flags, String instanceName,String callingPackage, int userId) throws TransactionTooLargeException {return bindServiceInstance(caller, token, service, resolvedType, connection, flags,instanceName, false, INVALID_UID, null, null, callingPackage, userId);
}private int bindServiceInstance(IApplicationThread caller, IBinder token, Intent service,String resolvedType, IServiceConnection connection, long flags, String instanceName,boolean isSdkSandboxService, int sdkSandboxClientAppUid,String sdkSandboxClientAppPackage,IApplicationThread sdkSandboxClientApplicationThread,String callingPackage, int userId)throws TransactionTooLargeException {// ......try {// ......synchronized (this) {return mServices.bindServiceLocked(caller, token, service, resolvedType, connection,flags, instanceName, isSdkSandboxService, sdkSandboxClientAppUid,sdkSandboxClientAppPackage, sdkSandboxClientApplicationThread,callingPackage, userId);}} finally {Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);}
}
这样来完成从 Client 端获取到 Server 端的 Binder 代理,从而调用到 Server 端的方法。
后续会上一张图
这篇关于从app bindService分析binder客户端的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!