Merge "Allow equality checking and hash for HIDL interface proxies."

This commit is contained in:
Treehugger Robot
2017-11-02 03:39:42 +00:00
committed by Gerrit Code Review
3 changed files with 76 additions and 1 deletions

View File

@@ -156,4 +156,27 @@ public class HidlSupport {
// Should not reach here.
throw new UnsupportedOperationException();
}
/**
* Test that two interfaces are equal. This is the Java equivalent to C++
* interfacesEqual function.
* This essentially calls .equals on the internal binder objects (via Binder()).
* - If both interfaces are proxies, asBinder() returns a {@link HwRemoteBinder}
* object, and they are compared in {@link HwRemoteBinder#equals}.
* - If both interfaces are stubs, asBinder() returns the object itself. By default,
* auto-generated IFoo.Stub does not override equals(), but an implementation can
* optionally override it, and {@code interfacesEqual} will use it here.
*/
public static boolean interfacesEqual(IHwInterface lft, Object rgt) {
if (lft == rgt) {
return true;
}
if (lft == null || rgt == null) {
return false;
}
if (!(rgt instanceof IHwInterface)) {
return false;
}
return Objects.equals(lft.asBinder(), ((IHwInterface) rgt).asBinder());
}
}

View File

@@ -63,4 +63,9 @@ public class HwRemoteBinder implements IHwBinder {
}
private long mNativeContext;
@Override
public final native boolean equals(Object other);
@Override
public final native int hashCode();
}

View File

@@ -22,9 +22,13 @@
#include "android_os_HwParcel.h"
#include <nativehelper/JNIHelp.h>
#include <android/hidl/base/1.0/IBase.h>
#include <android/hidl/base/1.0/BpHwBase.h>
#include <android/hidl/base/1.0/BnHwBase.h>
#include <android_runtime/AndroidRuntime.h>
#include <hidl/Status.h>
#include <hidl/HidlTransportSupport.h>
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedUtfChars.h>
#include <nativehelper/ScopedLocalRef.h>
@@ -413,6 +417,44 @@ static jboolean JHwRemoteBinder_unlinkToDeath(JNIEnv* env, jobject thiz,
return res;
}
static sp<hidl::base::V1_0::IBase> toIBase(JNIEnv* env, jclass hwRemoteBinderClazz, jobject jbinder)
{
if (jbinder == nullptr) {
return nullptr;
}
if (!env->IsInstanceOf(jbinder, hwRemoteBinderClazz)) {
return nullptr;
}
sp<JHwRemoteBinder> context = JHwRemoteBinder::GetNativeContext(env, jbinder);
sp<hardware::IBinder> cbinder = context->getBinder();
return hardware::fromBinder<hidl::base::V1_0::IBase, hidl::base::V1_0::BpHwBase,
hidl::base::V1_0::BnHwBase>(cbinder);
}
// equals iff other is also a non-null android.os.HwRemoteBinder object
// and getBinder() returns the same object.
// In particular, if other is an android.os.HwBinder object (for stubs) then
// it returns false.
static jboolean JHwRemoteBinder_equals(JNIEnv* env, jobject thiz, jobject other)
{
if (env->IsSameObject(thiz, other)) {
return true;
}
if (other == NULL) {
return false;
}
ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));
return hardware::interfacesEqual(toIBase(env, clazz.get(), thiz), toIBase(env, clazz.get(), other));
}
static jint JHwRemoteBinder_hashCode(JNIEnv* env, jobject thiz) {
jlong longHash = reinterpret_cast<jlong>(
JHwRemoteBinder::GetNativeContext(env, thiz)->getBinder().get());
return static_cast<jint>(longHash ^ (longHash >> 32)); // See Long.hashCode()
}
static JNINativeMethod gMethods[] = {
{ "native_init", "()J", (void *)JHwRemoteBinder_native_init },
@@ -430,6 +472,11 @@ static JNINativeMethod gMethods[] = {
{"unlinkToDeath",
"(Landroid/os/IHwBinder$DeathRecipient;)Z",
(void*)JHwRemoteBinder_unlinkToDeath},
{"equals", "(Ljava/lang/Object;)Z",
(void*)JHwRemoteBinder_equals},
{"hashCode", "()I", (void*)JHwRemoteBinder_hashCode},
};
namespace android {