注册

Binder Java 层服务注册过程分析

1. Java 层整体框架


在分析之前,我们要明白,Java 只是一层方便 Java 程序使用的接口,Binder 的核心功能实现都是通过 JNI 调用到 Native 层来实现的,这里先给出 Java 层的整体框架图:



接下来几篇文章我们逐步分析,解密整张框架图。


2. 服务注册


Binder 程序示例之 Java 篇 中介绍的示例程序中,Server 端我们使用如下代码注册我们定义的服务:

ServiceManager.addService("hello", new HelloService());

addService 是 frameworks/base/core/java/android/os/ServiceManager.java 中定义的静态方法:

@UnsupportedAppUsage
public static void addService(String name, IBinder service) {
addService(name, service, false, IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT);
}

@UnsupportedAppUsage
public static void addService(String name, IBinder service, boolean allowIsolated) {
addService(name, service, allowIsolated, IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT);
}

@UnsupportedAppUsage
public static void addService(String name, IBinder service, boolean allowIsolated,int dumpPriority) {
try {
getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}

通过层层调用,调用到 getIServiceManager().addService(name, service, allowIsolated, dumpPriority); :


2.1 getIServiceManager()


我们先看看 getIServiceManager,该方法是定义在 ServiceManager 类中的静态方法:

//frameworks/base/core/java/android/os/ServiceManager.java
@UnsupportedAppUsage
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}

// 等价于 new ServiceManagerProxy(new BinderProxy(0))
// 但是实际过程有点曲折
sServiceManager = ServiceManagerNative
.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
return sServiceManager;
}

接着我们逐一分析三个方法调用:

BinderInternal.getContextObject()
Binder.allowBlocking
ServiceManagerNative.asInterface

2.1.1 BinderInternal.getContextObject

//frameworks/base/core/java/com/android/internal/os/BinderInternal.java
// 返回一个 BinderProxy 对象
@UnsupportedAppUsage
public static final native IBinder getContextObject();

getContextObject 是一个 native 方法,在之前的文章中我们提到 BinderInternal 在进程启动时注册了其 native 方法,其 native 实现在 frameworks/base/core/jni/android_util_Binder.cpp 中:

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
//此处返回的是 new BpBinder(0)
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
//此处返回的是 new BinderProxy()
return javaObjectForIBinder(env, b);
}

接着看 getContextObject 的实现:

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
}

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;

AutoMutex _l(mLock);

handle_entry* e = lookupHandleLocked(handle);

if (e != nullptr) {
IBinder* b = e->binder;
if (b == nullptr || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
Parcel data;
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, nullptr, 0);
if (status == DEAD_OBJECT)
return nullptr;
}

//走这里
b = BpBinder::create(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}

return result;
}

BpBinder* BpBinder::create(int32_t handle) {
int32_t trackedUid = -1;
if (sCountByUidEnabled) {
trackedUid = IPCThreadState::self()->getCallingUid();
AutoMutex _l(sTrackingLock);
uint32_t trackedValue = sTrackingMap[trackedUid];
if (CC_UNLIKELY(trackedValue & LIMIT_REACHED_MASK)) {
if (sBinderProxyThrottleCreate) {
return nullptr;
}
} else {
if ((trackedValue & COUNTING_VALUE_MASK) >= sBinderProxyCountHighWatermark) {
ALOGE("Too many binder proxy objects sent to uid %d from uid %d (%d proxies held)",
getuid(), trackedUid, trackedValue);
sTrackingMap[trackedUid] |= LIMIT_REACHED_MASK;
if (sLimitCallback) sLimitCallback(trackedUid);
if (sBinderProxyThrottleCreate) {
ALOGI("Throttling binder proxy creates from uid %d in uid %d until binder proxy"
" count drops below %d",
trackedUid, getuid(), sBinderProxyCountLowWatermark);
return nullptr;
}
}
}
sTrackingMap[trackedUid]++;
}
//走这里
return new BpBinder(handle, trackedUid);
}

代码看着很繁琐,实际流程其实很简单就是 new BpBinder(0)


接着看 javaObjectForIBinder 的实现:

//frameworks/base/core/jni/android_util_Binder.cpp

//当前情景下, val 的类型是 BpBinder
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
if (val == NULL) return NULL;

if (val->checkSubclass(&gBinderOffsets)) {
// It's a JavaBBinder created by ibinderForJavaObject. Already has Java object.
jobject object = static_cast<JavaBBinder*>(val.get())->object();
LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
return object;
}

//构造 BinderProxyNativeData 结构体
BinderProxyNativeData* nativeData = new BinderProxyNativeData();
nativeData->mOrgue = new DeathRecipientList;
nativeData->mObject = val;

//gBinderProxyOffsets 中保存了 BinderProxy 类相关的信息
//调用 Java 层 GetInstance 方法获得一个 BinderProxy 对象
jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
if (env->ExceptionCheck()) { //异常处理
// In the exception case, getInstance still took ownership of nativeData.
return NULL;
}
BinderProxyNativeData* actualNativeData = getBPNativeData(env, object);
if (actualNativeData == nativeData) {
// Created a new Proxy
uint32_t numProxies = gNumProxies.fetch_add(1, std::memory_order_relaxed);
uint32_t numLastWarned = gProxiesWarned.load(std::memory_order_relaxed);
if (numProxies >= numLastWarned + PROXY_WARN_INTERVAL) {
// Multiple threads can get here, make sure only one of them gets to
// update the warn counter.
if (gProxiesWarned.compare_exchange_strong(numLastWarned,
numLastWarned + PROXY_WARN_INTERVAL, std::memory_order_relaxed)) {
ALOGW("Unexpectedly many live BinderProxies: %d\n", numProxies);
}
}
} else {
delete nativeData;
}

//返回 BinderProxy
return object;
}

native 代码调用了 BinderProxy 的 getInstance 方法:

// frameworks/base/core/java/android/os/BinderProxy.java
private static BinderProxy getInstance(long nativeData, long iBinder) {
BinderProxy result;
synchronized (sProxyMap) {
try {
result = sProxyMap.get(iBinder);
if (result != null) {
return result;
}
result = new BinderProxy(nativeData);
} catch (Throwable e) {
// We're throwing an exception (probably OOME); don't drop nativeData.
NativeAllocationRegistry.applyFreeFunction(NoImagePreloadHolder.sNativeFinalizer,
nativeData);
throw e;
}
NoImagePreloadHolder.sRegistry.registerNativeAllocation(result, nativeData);
// The registry now owns nativeData, even if registration threw an exception.
sProxyMap.set(iBinder, result);
}
return result;
}

代码很繁琐,但是从结果上来说还是比较简单的:



  • getContextObject 函数 new 了一个 BpBinder(c++结构体),其内部的 handle 是 0
  • javaObjectForIBinder 函数 new 了一个 BinderProxy(Java 对象),其内部成员 mNativeData 是一个 native 层指针,指向一个 BinderProxyNativeData,BinderProxyNativeData 的成员 mObject 指向上述的 BpBinder。

整体结构用一个图表示如下:



2.1.2 Binder.allowBlocking

    //这里传入的是 BinderProxy 对象
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;
}

这个方法比较简单,主要是设置 binder 的成员变量 mWarnOnBlocking 为 false。从名字来看,作用是允许阻塞调用。


2.1.3 ServiceManagerNative.asInterface

    //frameworks/base/core/java/android/os/ServiceManagerNative.java
//传入的参数是 BinderProxy
@UnsupportedAppUsage
static public IServiceManager asInterface(IBinder obj)
{
if (obj == null) {
return null;
}

//返回 null
IServiceManager in =
(IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}

//走这里,构建一个 ServiceManagerProxy
return new ServiceManagerProxy(obj);
}

//从名字来看,本来要做缓存的,但是没有做
// frameworks/base/core/java/android/os/BinderProxy.java
public IInterface queryLocalInterface(String descriptor) {
return null;
}


最终是构建一个 ServiceManagerProxy 结构体。其内部持有一个 BinderProxy 。


至此,getIServiceManager 的整体流程就分析完了。


2.2 addService

    // frameworks/base/core/java/android/os/ServiceManagerNative.java
public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
data.writeStrongBinder(service);
data.writeInt(allowIsolated ? 1 : 0);
data.writeInt(dumpPriority);
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}

构造两个 Parcel 结构,然后调用 mRemote.transact 发起远程过程调用。


mRemote 就是 new ServiceManagerProxy 时传入的 BinderProxy:

 public ServiceManagerProxy(IBinder remote) {
mRemote = remote;
}

进入 frameworks/base/core/java/android/os/BinderProxy.java 查看:

public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");

//......

try {
//关注这里
return transactNative(code, data, reply, flags);
} finally {
//......
}
}

//native 方法
public native boolean transactNative(int code, Parcel data, Parcel reply,int flags) throws RemoteException;


transact 会调用 transactNative 发起远程调用,transactNative 是一个 native 方法,具体实现在 frameworks/base/core/jni/android_util_Binder.cpp

// obj 对应类型为 BinderProxy
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
if (dataObj == NULL) {
jniThrowNullPointerException(env, NULL);
return JNI_FALSE;
}

// Java 对象 转为 c++ 对象
Parcel* data = parcelForJavaObject(env, dataObj);
if (data == NULL) {
return JNI_FALSE;
}

// Java 对象 转为 c++ 对象
Parcel* reply = parcelForJavaObject(env, replyObj);
if (reply == NULL && replyObj != NULL) {
return JNI_FALSE;
}

//拿到 BinderProxyNativeData 成员的 mObject,实际是一个 BpBinder
IBinder* target = getBPNativeData(env, obj)->mObject.get();
if (target == NULL) {
jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
return JNI_FALSE;
}

ALOGV("Java code calling transact on %p in Java object %p with code %" PRId32 "\n",
target, obj, code);


bool time_binder_calls;
int64_t start_millis;
if (kEnableBinderSample) {
// Only log the binder call duration for things on the Java-level main thread.
// But if we don't
time_binder_calls = should_time_binder_calls();

if (time_binder_calls) {
start_millis = uptimeMillis();
}
}

//BpBinder 发起远程调用
status_t err = target->transact(code, *data, reply, flags);

if (kEnableBinderSample) {
if (time_binder_calls) {
conditionally_log_binder_call(start_millis, target, code);
}
}

if (err == NO_ERROR) {
return JNI_TRUE;
} else if (err == UNKNOWN_TRANSACTION) {
return JNI_FALSE;
}

signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/, data->dataSize());
return JNI_FALSE;
}


可以看出,绕了一圈还是通过 native 层的 BpBinder 发起远程调用,native 层的调用过程可以参考之前的文章Binder 服务注册过程情景分析之 C++ 篇


关于


我叫阿豪,2015 年本科毕业于国防科技大学指挥自动化专业,毕业后,从事信息化装备的研发工作。主要研究方向为 Android Framework 与 Linux Kernel,2023年春节后开始做 Android Framework 相关的技术分享。


作者:阿豪元代码
链接:https://juejin.cn/post/7246777406387748921
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册