Merge "Add (un)linkToDeath support to HwBinder."
am: 7705363166
Change-Id: I007b2fc2982d164176607cd8f2d0ccc9ebde982c
This commit is contained in:
@@ -39,6 +39,9 @@ public class HwRemoteBinder implements IHwBinder {
|
|||||||
public native final void transact(
|
public native final void transact(
|
||||||
int code, HwParcel request, HwParcel reply, int flags);
|
int code, HwParcel request, HwParcel reply, int flags);
|
||||||
|
|
||||||
|
public native boolean linkToDeath(DeathRecipient recipient, long cookie);
|
||||||
|
public native boolean unlinkToDeath(DeathRecipient recipient);
|
||||||
|
|
||||||
private static native final long native_init();
|
private static native final long native_init();
|
||||||
|
|
||||||
private native final void native_setup_empty();
|
private native final void native_setup_empty();
|
||||||
@@ -52,5 +55,9 @@ public class HwRemoteBinder implements IHwBinder {
|
|||||||
128 /* size */);
|
128 /* size */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final void sendDeathNotice(DeathRecipient recipient, long cookie) {
|
||||||
|
recipient.serviceDied(cookie);
|
||||||
|
}
|
||||||
|
|
||||||
private long mNativeContext;
|
private long mNativeContext;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,4 +26,16 @@ public interface IHwBinder {
|
|||||||
int code, HwParcel request, HwParcel reply, int flags);
|
int code, HwParcel request, HwParcel reply, int flags);
|
||||||
|
|
||||||
public IHwInterface queryLocalInterface(String descriptor);
|
public IHwInterface queryLocalInterface(String descriptor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for receiving a callback when the process hosting a service
|
||||||
|
* has gone away.
|
||||||
|
*/
|
||||||
|
public interface DeathRecipient {
|
||||||
|
public void serviceDied(long cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean linkToDeath(DeathRecipient recipient, long cookie);
|
||||||
|
|
||||||
|
public boolean unlinkToDeath(DeathRecipient recipient);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include <JNIHelp.h>
|
#include <JNIHelp.h>
|
||||||
#include <android_runtime/AndroidRuntime.h>
|
#include <android_runtime/AndroidRuntime.h>
|
||||||
#include <hidl/Status.h>
|
#include <hidl/Status.h>
|
||||||
|
#include <ScopedUtfChars.h>
|
||||||
#include <nativehelper/ScopedLocalRef.h>
|
#include <nativehelper/ScopedLocalRef.h>
|
||||||
|
|
||||||
#include "core_jni_helpers.h"
|
#include "core_jni_helpers.h"
|
||||||
@@ -38,26 +39,196 @@ using android::AndroidRuntime;
|
|||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
static struct fields_t {
|
static struct fields_t {
|
||||||
|
jclass proxy_class;
|
||||||
jfieldID contextID;
|
jfieldID contextID;
|
||||||
jmethodID constructID;
|
jmethodID constructID;
|
||||||
|
jmethodID sendDeathNotice;
|
||||||
|
} gProxyOffsets;
|
||||||
|
|
||||||
} gFields;
|
static struct class_offsets_t
|
||||||
|
{
|
||||||
|
jmethodID mGetName;
|
||||||
|
} gClassOffsets;
|
||||||
|
|
||||||
|
static JavaVM* jnienv_to_javavm(JNIEnv* env)
|
||||||
|
{
|
||||||
|
JavaVM* vm;
|
||||||
|
return env->GetJavaVM(&vm) >= 0 ? vm : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JNIEnv* javavm_to_jnienv(JavaVM* vm)
|
||||||
|
{
|
||||||
|
JNIEnv* env;
|
||||||
|
return vm->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0 ? env : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
class HwBinderDeathRecipient : public hardware::IBinder::DeathRecipient
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HwBinderDeathRecipient(JNIEnv* env, jobject object, jlong cookie, const sp<HwBinderDeathRecipientList>& list)
|
||||||
|
: mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)),
|
||||||
|
mObjectWeak(NULL), mCookie(cookie), mList(list)
|
||||||
|
{
|
||||||
|
// These objects manage their own lifetimes so are responsible for final bookkeeping.
|
||||||
|
// The list holds a strong reference to this object.
|
||||||
|
list->add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void binderDied(const wp<hardware::IBinder>& who)
|
||||||
|
{
|
||||||
|
if (mObject != NULL) {
|
||||||
|
JNIEnv* env = javavm_to_jnienv(mVM);
|
||||||
|
|
||||||
|
env->CallStaticVoidMethod(gProxyOffsets.proxy_class, gProxyOffsets.sendDeathNotice, mObject, mCookie);
|
||||||
|
if (env->ExceptionCheck()) {
|
||||||
|
ALOGE("Uncaught exception returned from death notification.");
|
||||||
|
env->ExceptionClear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize with our containing HwBinderDeathRecipientList so that we can't
|
||||||
|
// delete the global ref on mObject while the list is being iterated.
|
||||||
|
sp<HwBinderDeathRecipientList> list = mList.promote();
|
||||||
|
if (list != NULL) {
|
||||||
|
AutoMutex _l(list->lock());
|
||||||
|
|
||||||
|
// Demote from strong ref to weak after binderDied() has been delivered,
|
||||||
|
// to allow the DeathRecipient and BinderProxy to be GC'd if no longer needed.
|
||||||
|
mObjectWeak = env->NewWeakGlobalRef(mObject);
|
||||||
|
env->DeleteGlobalRef(mObject);
|
||||||
|
mObject = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearReference()
|
||||||
|
{
|
||||||
|
sp<HwBinderDeathRecipientList> list = mList.promote();
|
||||||
|
if (list != NULL) {
|
||||||
|
list->remove(this);
|
||||||
|
} else {
|
||||||
|
ALOGE("clearReference() on JDR %p but DRL wp purged", this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool matches(jobject obj) {
|
||||||
|
bool result;
|
||||||
|
JNIEnv* env = javavm_to_jnienv(mVM);
|
||||||
|
|
||||||
|
if (mObject != NULL) {
|
||||||
|
result = env->IsSameObject(obj, mObject);
|
||||||
|
} else {
|
||||||
|
jobject me = env->NewLocalRef(mObjectWeak);
|
||||||
|
result = env->IsSameObject(obj, me);
|
||||||
|
env->DeleteLocalRef(me);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void warnIfStillLive() {
|
||||||
|
if (mObject != NULL) {
|
||||||
|
// Okay, something is wrong -- we have a hard reference to a live death
|
||||||
|
// recipient on the VM side, but the list is being torn down.
|
||||||
|
JNIEnv* env = javavm_to_jnienv(mVM);
|
||||||
|
ScopedLocalRef<jclass> objClassRef(env, env->GetObjectClass(mObject));
|
||||||
|
ScopedLocalRef<jstring> nameRef(env,
|
||||||
|
(jstring) env->CallObjectMethod(objClassRef.get(), gClassOffsets.mGetName));
|
||||||
|
ScopedUtfChars nameUtf(env, nameRef.get());
|
||||||
|
if (nameUtf.c_str() != NULL) {
|
||||||
|
ALOGW("BinderProxy is being destroyed but the application did not call "
|
||||||
|
"unlinkToDeath to unlink all of its death recipients beforehand. "
|
||||||
|
"Releasing leaked death recipient: %s", nameUtf.c_str());
|
||||||
|
} else {
|
||||||
|
ALOGW("BinderProxy being destroyed; unable to get DR object name");
|
||||||
|
env->ExceptionClear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~HwBinderDeathRecipient()
|
||||||
|
{
|
||||||
|
JNIEnv* env = javavm_to_jnienv(mVM);
|
||||||
|
if (mObject != NULL) {
|
||||||
|
env->DeleteGlobalRef(mObject);
|
||||||
|
} else {
|
||||||
|
env->DeleteWeakGlobalRef(mObjectWeak);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
JavaVM* const mVM;
|
||||||
|
jobject mObject;
|
||||||
|
jweak mObjectWeak; // will be a weak ref to the same VM-side DeathRecipient after binderDied()
|
||||||
|
jlong mCookie;
|
||||||
|
wp<HwBinderDeathRecipientList> mList;
|
||||||
|
};
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
HwBinderDeathRecipientList::HwBinderDeathRecipientList() {
|
||||||
|
}
|
||||||
|
|
||||||
|
HwBinderDeathRecipientList::~HwBinderDeathRecipientList() {
|
||||||
|
AutoMutex _l(mLock);
|
||||||
|
|
||||||
|
for (const sp<HwBinderDeathRecipient>& deathRecipient : mList) {
|
||||||
|
deathRecipient->warnIfStillLive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HwBinderDeathRecipientList::add(const sp<HwBinderDeathRecipient>& recipient) {
|
||||||
|
AutoMutex _l(mLock);
|
||||||
|
|
||||||
|
mList.push_back(recipient);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HwBinderDeathRecipientList::remove(const sp<HwBinderDeathRecipient>& recipient) {
|
||||||
|
AutoMutex _l(mLock);
|
||||||
|
|
||||||
|
List< sp<HwBinderDeathRecipient> >::iterator iter;
|
||||||
|
for (iter = mList.begin(); iter != mList.end(); iter++) {
|
||||||
|
if (*iter == recipient) {
|
||||||
|
mList.erase(iter);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sp<HwBinderDeathRecipient> HwBinderDeathRecipientList::find(jobject recipient) {
|
||||||
|
AutoMutex _l(mLock);
|
||||||
|
|
||||||
|
for (const sp<HwBinderDeathRecipient>& deathRecipient : mList) {
|
||||||
|
if (deathRecipient->matches(recipient)) {
|
||||||
|
return deathRecipient;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mutex& HwBinderDeathRecipientList::lock() {
|
||||||
|
return mLock;
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void JHwRemoteBinder::InitClass(JNIEnv *env) {
|
void JHwRemoteBinder::InitClass(JNIEnv *env) {
|
||||||
ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));
|
jclass clazz = FindClassOrDie(env, CLASS_PATH);
|
||||||
|
|
||||||
gFields.contextID =
|
gProxyOffsets.proxy_class = MakeGlobalRefOrDie(env, clazz);
|
||||||
GetFieldIDOrDie(env, clazz.get(), "mNativeContext", "J");
|
gProxyOffsets.contextID =
|
||||||
|
GetFieldIDOrDie(env, clazz, "mNativeContext", "J");
|
||||||
|
gProxyOffsets.constructID = GetMethodIDOrDie(env, clazz, "<init>", "()V");
|
||||||
|
gProxyOffsets.sendDeathNotice = GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
|
||||||
|
"(Landroid/os/IHwBinder$DeathRecipient;J)V");
|
||||||
|
|
||||||
gFields.constructID = GetMethodIDOrDie(env, clazz.get(), "<init>", "()V");
|
clazz = FindClassOrDie(env, "java/lang/Class");
|
||||||
|
gClassOffsets.mGetName = GetMethodIDOrDie(env, clazz, "getName", "()Ljava/lang/String;");
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
sp<JHwRemoteBinder> JHwRemoteBinder::SetNativeContext(
|
sp<JHwRemoteBinder> JHwRemoteBinder::SetNativeContext(
|
||||||
JNIEnv *env, jobject thiz, const sp<JHwRemoteBinder> &context) {
|
JNIEnv *env, jobject thiz, const sp<JHwRemoteBinder> &context) {
|
||||||
sp<JHwRemoteBinder> old =
|
sp<JHwRemoteBinder> old =
|
||||||
(JHwRemoteBinder *)env->GetLongField(thiz, gFields.contextID);
|
(JHwRemoteBinder *)env->GetLongField(thiz, gProxyOffsets.contextID);
|
||||||
|
|
||||||
if (context != NULL) {
|
if (context != NULL) {
|
||||||
context->incStrong(NULL /* id */);
|
context->incStrong(NULL /* id */);
|
||||||
@@ -67,7 +238,7 @@ sp<JHwRemoteBinder> JHwRemoteBinder::SetNativeContext(
|
|||||||
old->decStrong(NULL /* id */);
|
old->decStrong(NULL /* id */);
|
||||||
}
|
}
|
||||||
|
|
||||||
env->SetLongField(thiz, gFields.contextID, (long)context.get());
|
env->SetLongField(thiz, gProxyOffsets.contextID, (long)context.get());
|
||||||
|
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
@@ -75,7 +246,7 @@ sp<JHwRemoteBinder> JHwRemoteBinder::SetNativeContext(
|
|||||||
// static
|
// static
|
||||||
sp<JHwRemoteBinder> JHwRemoteBinder::GetNativeContext(
|
sp<JHwRemoteBinder> JHwRemoteBinder::GetNativeContext(
|
||||||
JNIEnv *env, jobject thiz) {
|
JNIEnv *env, jobject thiz) {
|
||||||
return (JHwRemoteBinder *)env->GetLongField(thiz, gFields.contextID);
|
return (JHwRemoteBinder *)env->GetLongField(thiz, gProxyOffsets.contextID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
@@ -84,7 +255,7 @@ jobject JHwRemoteBinder::NewObject(
|
|||||||
ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));
|
ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));
|
||||||
|
|
||||||
// XXX Have to look up the constructor here because otherwise that static
|
// XXX Have to look up the constructor here because otherwise that static
|
||||||
// class initializer isn't called and gFields.constructID is undefined :(
|
// class initializer isn't called and gProxyOffsets.constructID is undefined :(
|
||||||
|
|
||||||
jmethodID constructID = GetMethodIDOrDie(env, clazz.get(), "<init>", "()V");
|
jmethodID constructID = GetMethodIDOrDie(env, clazz.get(), "<init>", "()V");
|
||||||
|
|
||||||
@@ -97,6 +268,7 @@ jobject JHwRemoteBinder::NewObject(
|
|||||||
JHwRemoteBinder::JHwRemoteBinder(
|
JHwRemoteBinder::JHwRemoteBinder(
|
||||||
JNIEnv *env, jobject thiz, const sp<hardware::IBinder> &binder)
|
JNIEnv *env, jobject thiz, const sp<hardware::IBinder> &binder)
|
||||||
: mBinder(binder) {
|
: mBinder(binder) {
|
||||||
|
mDeathRecipientList = new HwBinderDeathRecipientList();
|
||||||
jclass clazz = env->GetObjectClass(thiz);
|
jclass clazz = env->GetObjectClass(thiz);
|
||||||
CHECK(clazz != NULL);
|
CHECK(clazz != NULL);
|
||||||
|
|
||||||
@@ -114,7 +286,7 @@ JHwRemoteBinder::~JHwRemoteBinder() {
|
|||||||
mClass = NULL;
|
mClass = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sp<hardware::IBinder> JHwRemoteBinder::getBinder() {
|
sp<hardware::IBinder> JHwRemoteBinder::getBinder() const {
|
||||||
return mBinder;
|
return mBinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,6 +294,10 @@ void JHwRemoteBinder::setBinder(const sp<hardware::IBinder> &binder) {
|
|||||||
mBinder = binder;
|
mBinder = binder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sp<HwBinderDeathRecipientList> JHwRemoteBinder::getDeathRecipientList() const {
|
||||||
|
return mDeathRecipientList;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -174,6 +350,73 @@ static void JHwRemoteBinder_native_transact(
|
|||||||
signalExceptionForError(env, err);
|
signalExceptionForError(env, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static jboolean JHwRemoteBinder_linkToDeath(JNIEnv* env, jobject thiz,
|
||||||
|
jobject recipient, jlong cookie)
|
||||||
|
{
|
||||||
|
if (recipient == NULL) {
|
||||||
|
jniThrowNullPointerException(env, NULL);
|
||||||
|
return JNI_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp<JHwRemoteBinder> context = JHwRemoteBinder::GetNativeContext(env, thiz);
|
||||||
|
sp<hardware::IBinder> binder = context->getBinder();
|
||||||
|
|
||||||
|
if (!binder->localBinder()) {
|
||||||
|
HwBinderDeathRecipientList* list = (context->getDeathRecipientList()).get();
|
||||||
|
sp<HwBinderDeathRecipient> jdr = new HwBinderDeathRecipient(env, recipient, cookie, list);
|
||||||
|
status_t err = binder->linkToDeath(jdr, NULL, 0);
|
||||||
|
if (err != NO_ERROR) {
|
||||||
|
// Failure adding the death recipient, so clear its reference
|
||||||
|
// now.
|
||||||
|
jdr->clearReference();
|
||||||
|
return JNI_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return JNI_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static jboolean JHwRemoteBinder_unlinkToDeath(JNIEnv* env, jobject thiz,
|
||||||
|
jobject recipient)
|
||||||
|
{
|
||||||
|
jboolean res = JNI_FALSE;
|
||||||
|
if (recipient == NULL) {
|
||||||
|
jniThrowNullPointerException(env, NULL);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp<JHwRemoteBinder> context = JHwRemoteBinder::GetNativeContext(env, thiz);
|
||||||
|
sp<hardware::IBinder> binder = context->getBinder();
|
||||||
|
|
||||||
|
if (!binder->localBinder()) {
|
||||||
|
status_t err = NAME_NOT_FOUND;
|
||||||
|
|
||||||
|
// If we find the matching recipient, proceed to unlink using that
|
||||||
|
HwBinderDeathRecipientList* list = (context->getDeathRecipientList()).get();
|
||||||
|
sp<HwBinderDeathRecipient> origJDR = list->find(recipient);
|
||||||
|
if (origJDR != NULL) {
|
||||||
|
wp<hardware::IBinder::DeathRecipient> dr;
|
||||||
|
err = binder->unlinkToDeath(origJDR, NULL, 0, &dr);
|
||||||
|
if (err == NO_ERROR && dr != NULL) {
|
||||||
|
sp<hardware::IBinder::DeathRecipient> sdr = dr.promote();
|
||||||
|
HwBinderDeathRecipient* jdr = static_cast<HwBinderDeathRecipient*>(sdr.get());
|
||||||
|
if (jdr != NULL) {
|
||||||
|
jdr->clearReference();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err == NO_ERROR || err == DEAD_OBJECT) {
|
||||||
|
res = JNI_TRUE;
|
||||||
|
} else {
|
||||||
|
jniThrowException(env, "java/util/NoSuchElementException",
|
||||||
|
"Death link does not exist");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static JNINativeMethod gMethods[] = {
|
static JNINativeMethod gMethods[] = {
|
||||||
{ "native_init", "()J", (void *)JHwRemoteBinder_native_init },
|
{ "native_init", "()J", (void *)JHwRemoteBinder_native_init },
|
||||||
|
|
||||||
@@ -183,6 +426,14 @@ static JNINativeMethod gMethods[] = {
|
|||||||
{ "transact",
|
{ "transact",
|
||||||
"(IL" PACKAGE_PATH "/HwParcel;L" PACKAGE_PATH "/HwParcel;I)V",
|
"(IL" PACKAGE_PATH "/HwParcel;L" PACKAGE_PATH "/HwParcel;I)V",
|
||||||
(void *)JHwRemoteBinder_native_transact },
|
(void *)JHwRemoteBinder_native_transact },
|
||||||
|
|
||||||
|
{"linkToDeath",
|
||||||
|
"(Landroid/os/IHwBinder$DeathRecipient;J)Z",
|
||||||
|
(void*)JHwRemoteBinder_linkToDeath},
|
||||||
|
|
||||||
|
{"unlinkToDeath",
|
||||||
|
"(Landroid/os/IHwBinder$DeathRecipient;)Z",
|
||||||
|
(void*)JHwRemoteBinder_unlinkToDeath},
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|||||||
@@ -20,10 +20,33 @@
|
|||||||
#include <android-base/macros.h>
|
#include <android-base/macros.h>
|
||||||
#include <hwbinder/Binder.h>
|
#include <hwbinder/Binder.h>
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
|
#include <utils/List.h>
|
||||||
|
#include <utils/Mutex.h>
|
||||||
#include <utils/RefBase.h>
|
#include <utils/RefBase.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
|
// Per-IBinder death recipient bookkeeping. This is how we reconcile local jobject
|
||||||
|
// death recipient references passed in through JNI with the permanent corresponding
|
||||||
|
// HwBinderDeathRecipient objects.
|
||||||
|
|
||||||
|
class HwBinderDeathRecipient;
|
||||||
|
|
||||||
|
class HwBinderDeathRecipientList : public RefBase {
|
||||||
|
List< sp<HwBinderDeathRecipient> > mList;
|
||||||
|
Mutex mLock;
|
||||||
|
|
||||||
|
public:
|
||||||
|
HwBinderDeathRecipientList();
|
||||||
|
~HwBinderDeathRecipientList();
|
||||||
|
|
||||||
|
void add(const sp<HwBinderDeathRecipient>& recipient);
|
||||||
|
void remove(const sp<HwBinderDeathRecipient>& recipient);
|
||||||
|
sp<HwBinderDeathRecipient> find(jobject recipient);
|
||||||
|
|
||||||
|
Mutex& lock(); // Use with care; specifically for mutual exclusion during binder death
|
||||||
|
};
|
||||||
|
|
||||||
struct JHwRemoteBinder : public RefBase {
|
struct JHwRemoteBinder : public RefBase {
|
||||||
static void InitClass(JNIEnv *env);
|
static void InitClass(JNIEnv *env);
|
||||||
|
|
||||||
@@ -37,8 +60,9 @@ struct JHwRemoteBinder : public RefBase {
|
|||||||
JHwRemoteBinder(
|
JHwRemoteBinder(
|
||||||
JNIEnv *env, jobject thiz, const sp<hardware::IBinder> &binder);
|
JNIEnv *env, jobject thiz, const sp<hardware::IBinder> &binder);
|
||||||
|
|
||||||
sp<hardware::IBinder> getBinder();
|
sp<hardware::IBinder> getBinder() const;
|
||||||
void setBinder(const sp<hardware::IBinder> &binder);
|
void setBinder(const sp<hardware::IBinder> &binder);
|
||||||
|
sp<HwBinderDeathRecipientList> getDeathRecipientList() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~JHwRemoteBinder();
|
virtual ~JHwRemoteBinder();
|
||||||
@@ -48,7 +72,7 @@ private:
|
|||||||
jobject mObject;
|
jobject mObject;
|
||||||
|
|
||||||
sp<hardware::IBinder> mBinder;
|
sp<hardware::IBinder> mBinder;
|
||||||
|
sp<HwBinderDeathRecipientList> mDeathRecipientList;
|
||||||
DISALLOW_COPY_AND_ASSIGN(JHwRemoteBinder);
|
DISALLOW_COPY_AND_ASSIGN(JHwRemoteBinder);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user