大家都知道Binder機制主要由ServiceManager,Binder實體對象,Binder代理對象三個組件,顧我們想要在Java世界實現Binder機制也需要事項這個三個組件
Service Manager的Java代理對象的類型為ServiceManagerProxy
類型,想要獲取這個對象需要先在C++層創建一個句柄值為0的Binder代理對象,然后在Java層創建一個對應的Java服務代理對象。
最終是ServiceManager類獲取到ServiceManagerProxy對象,并保存在了sServiceManager成員變量中,通過這個變量我們又可以得到getService(),listService(),checkService(),addService()
等操作Java服務的方法。
//framworks/base/core/java/android/os/ServiceManager.java
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
//framworks/base/core/java/android/os/ServiceManagerNative.java
static public IServiceManager asInterface(IBinder obj)
{
if (obj == null) {
return null;
}
IServiceManager in =
(IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ServiceManagerProxy(obj);
}
然后大家會問?Java服務代理對象是從哪里獲取的呢?
看到那個黃色的小框了沒有,Java服務對象就是通過JNI方法獲取的
getContextObject()
方法是JNI方法,JNI教程參考,它由android_os_BinderInternal_getContextObject來實現
//framworks/base/core/jni/android_util_Binder.cpp
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
}
然后我們需要具體解析的javaObjectForIBinder()
,看名字就知道他就是將Java對象轉換為IBinder對象的關鍵方法
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
if (val == NULL) return NULL;
if (val->checkSubclass(&gBinderOffsets)) {
// One of our own!
jobject object = static_cast<JavaBBinder*>(val.get())->object();
LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
return object;
}
// For the rest of the function we will hold this lock, to serialize
// looking/creation of Java proxies for native Binder proxies.
AutoMutex _l(mProxyLock);
// Someone else's... do we know about it?
jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
if (object != NULL) {
jobject res = jniGetReferent(env, object);
if (res != NULL) {
ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res);
return res;
}
LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get());
android_atomic_dec(&gNumProxyRefs);
val->detachObject(&gBinderProxyOffsets);
env->DeleteGlobalRef(object);
}
object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
if (object != NULL) {
LOGDEATH("objectForBinder %p: created new proxy %p !\n", val.get(), object);
// The proxy holds a reference to the native object.
env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
val->incStrong((void*)javaObjectForIBinder);
// The native object needs to hold a weak reference back to the
// proxy, so we can retrieve the same proxy if it is still active.
jobject refObject = env->NewGlobalRef(
env->GetObjectField(object, gBinderProxyOffsets.mSelf));
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup);
// Also remember the death recipients registered on this proxy
sp<DeathRecipientList> drl = new DeathRecipientList;
drl->incStrong((void*)javaObjectForIBinder);
env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));
// Note that a new object reference has been created.
android_atomic_inc(&gNumProxyRefs);
incRefsCreated(env);
}
return object;
}
參數val要么指向一個Binder代理對象,要么指向一個Binder本地對象。當它指向一個Binder本地對象時,他的類型為JavaBBinder,后者繼承BBinder類。
frameworks/base/libs/binder/Binder.cpp
bool IBinder::checkSubclass(const void* /*subclassID*/) const
{
return false;
}
大家看到checkSubclass是用來檢測val指向Binder代理對象,還是JavaBBinder對象,默認值返回false。但是JavaBBinder類重寫了其父類BBinder的父類IBinder的成員函數checkSubclass(),所以只要subclassID
指向全局變量gBinderOffsets
就返回true。
- 當val指向的是一個JavaBBinder對象的時候就返回true,并通過成員方法
object()
獲取Java對象,mobject
指向Java層中的一個Binder對象。
//framworks/base/core/jni/android_util_Binder.cpp
class JavaBBinder : public BBinder
{
public:
JavaBBinder(JNIEnv* env, jobject object)
: mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
{
ALOGV("Creating JavaBBinder %p\n", this);
android_atomic_inc(&gNumLocalRefs);
incRefsCreated(env);
}
bool checkSubclass(const void* subclassID) const
{
return subclassID == &gBinderOffsets;
}
jobject object() const
{
return mObject;
}
......
private:
jobject const mObject;
}
- 當val指向的是一個句柄值等于0的Binder代理對象的時候,它最終返回的是一個java層的服務代理對象,即BinderProxy對象。
jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
if (object != NULL) {
jobject res = jniGetReferent(env, object);
if (res != NULL) {
ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res);
return res;
}
LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get());
android_atomic_dec(&gNumProxyRefs);
val->detachObject(&gBinderProxyOffsets);
env->DeleteGlobalRef(object);
}
這段代碼的功能主要是檢查當前進程是否已經創建BinderProxy對象。如果是,則返回指向該BinderProxy對象的WeakRefenrence對象object
。但是object
指向的BinderProxy可能已經失效,因此需要繼續檢查,并將其升級為強引用對象。若object
升級成功則返回BinderProxy對象,如果升級失敗則解除它與無效的BinderProxy對象的對應關系。
如何將Binder代理對象與外部對象關聯?
例:函數javaObjectForBinder在為一個Binder代理對象(BpBinder)創建一個Java服務對象(BinderProxy)時,就會將創建出來的Java服務代理對象(BinderProxy)保存在Binder代理對象(BpBinder)的成員變量mObjects
中。但是一個Binder代理對象(BpBinder)不僅僅是關聯一個外部對象,所以需要為每一個外部對象設置一個參數,而Java服務代理對象(BinderPorxy)所使用的參數就是gBinderProxyOffsets
的地址。
ObjectManager 是定義在BpBinder內部的一個類。定義了外部對象操作函數attach(增),find(查),detach(刪)。kill函數用來清理與Binder代理對象管理的外部對象。
class ObjectManager
{
public:
ObjectManager();
~ObjectManager();
void attach( const void* objectID,
void* object,
void* cleanupCookie,
IBinder::object_cleanup_func func);
void* find(const void* objectID) const;
void detach(const void* objectID);
void kill();
private:
ObjectManager(const ObjectManager&);
ObjectManager& operator=(const ObjectManager&);
struct entry_t
{
void* object; // 指向外部對象的一個弱引用對象
void* cleanupCookie; //fun所指向的清理函數的一個調用參數
IBinder::object_cleanup_func func; // 函數指針,用來清理Object指向的外部對象
};
//維護與一個Binder代理對象所關聯的外部對象,這些外部對象都使用entry_t結構體來描述
KeyedVector<const void*, entry_t> mObjects;
相應的Binder代理對象也提供了三個成員函數,attchObject,findObject,detachObject用來增查刪與它關聯的外部對象,具體實現是調用內部類的成員變量mObjects的成員函數attach,find,detach實現。
void BpBinder::attachObject(
const void* objectID, void* object, void* cleanupCookie,
object_cleanup_func func)
{
AutoMutex _l(mLock);
ALOGV("Attaching object %p to binder %p (manager=%p)", object, this, &mObjects);
mObjects.attach(objectID, object, cleanupCookie, func);
}
void* BpBinder::findObject(const void* objectID) const
{
AutoMutex _l(mLock);
return mObjects.find(objectID);
}
void BpBinder::detachObject(const void* objectID)
{
AutoMutex _l(mLock);
mObjects.detach(objectID);
}
參考:
《Android系統源代碼情景分析》