Support (un)linkToDeath in Java.
Test: mma, hidl_test_java
Bug: 31632518
Change-Id: Ic324deb5b0b17340328a08e736e07b47a7bea59b
diff --git a/DeathRecipientType.cpp b/DeathRecipientType.cpp
index 952064c..5ac58fe 100644
--- a/DeathRecipientType.cpp
+++ b/DeathRecipientType.cpp
@@ -48,7 +48,8 @@
}
std::string DeathRecipientType::getJavaType(bool /* forInitializer */) const {
- return "android.os.IBinder.DeathRecipient";
+ // TODO(b/33440494) decouple from hwbinder
+ return "android.os.IHwBinder.DeathRecipient";
}
std::string DeathRecipientType::getVtsType() const {
diff --git a/Interface.cpp b/Interface.cpp
index 29afee1..1e40bd2 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -97,11 +97,7 @@
<< " == ::android::OK);\n";
}
},
- {IMPL_STUB,
- [](auto &/*out*/) {
- // Do nothing
- }
- }
+ {IMPL_STUB, nullptr}
}, /*cppImpl*/
{
{IMPL_HEADER,
@@ -111,15 +107,10 @@
},
{IMPL_PROXY,
[this](auto &out) {
- // TODO (b/31632518)
- out << "return false;";
+ out << "return mRemote.linkToDeath(recipient, cookie);\n";
}
},
- {IMPL_STUB,
- [this](auto &/*out*/) {
- // Do nothing
- }
- }
+ {IMPL_STUB, nullptr}
} /*javaImpl*/
);
}
@@ -159,29 +150,20 @@
out << "return false;\n";
}
},
- {IMPL_STUB,
- [](auto &/*out*/) {
- // Do nothing
- }
- }
+ {IMPL_STUB, nullptr /* don't generate code */}
}, /*cppImpl*/
{
{IMPL_HEADER,
[this](auto &out) {
- out << "return true;";
+ out << "return true;\n";
}
},
{IMPL_PROXY,
[this](auto &out) {
- // TODO (b/31632518)
- out << "return false;";
+ out << "return mRemote.unlinkToDeath(recipient);\n";
}
},
- {IMPL_STUB,
- [this](auto &/*out*/) {
- // Do nothing
- }
- }
+ {IMPL_STUB, nullptr /* don't generate code */}
} /*javaImpl*/
);
}
diff --git a/Method.cpp b/Method.cpp
index a085497..e41ebd0 100644
--- a/Method.cpp
+++ b/Method.cpp
@@ -75,7 +75,9 @@
CHECK(mIsHidlReserved);
auto it = mCppImpl.find(type);
if (it != mCppImpl.end()) {
- it->second(out);
+ if (it->second != nullptr) {
+ it->second(out);
+ }
}
}
@@ -83,7 +85,9 @@
CHECK(mIsHidlReserved);
auto it = mJavaImpl.find(type);
if (it != mJavaImpl.end()) {
- it->second(out);
+ if (it->second != nullptr) {
+ it->second(out);
+ }
}
}
diff --git a/test/java_test/hidl_test_java_native.cpp b/test/java_test/hidl_test_java_native.cpp
index 654947b..f86e43f 100644
--- a/test/java_test/hidl_test_java_native.cpp
+++ b/test/java_test/hidl_test_java_native.cpp
@@ -104,6 +104,7 @@
Return<void> callMeLater(const sp<IBazCallback>& cb) override;
Return<void> iAmFreeNow() override;
+ Return<void> dieNow() override;
Return<IBaz::SomeEnum> useAnEnum(IBaz::SomeEnum zzz) override;
@@ -538,6 +539,11 @@
return Void();
}
+Return<void> Baz::dieNow() {
+ exit(1);
+ return Void();
+}
+
Return<IBaz::SomeEnum> Baz::useAnEnum(IBaz::SomeEnum zzz) {
LOG(INFO) << "useAnEnum " << (int)zzz;
diff --git a/test/java_test/src/com/android/commands/hidl_test_java/HidlTestJava.java b/test/java_test/src/com/android/commands/hidl_test_java/HidlTestJava.java
index 0b28781..5252fbf 100644
--- a/test/java_test/src/com/android/commands/hidl_test_java/HidlTestJava.java
+++ b/test/java_test/src/com/android/commands/hidl_test_java/HidlTestJava.java
@@ -317,6 +317,41 @@
return out.toString();
}
+ final class HidlDeathRecipient implements HwBinder.DeathRecipient {
+ final Object mLock = new Object();
+ boolean mCalled = false;
+ long mCookie = 0;
+
+ @Override
+ public void serviceDied(long cookie) {
+ synchronized (mLock) {
+ mCalled = true;
+ mCookie = cookie;
+ mLock.notify();
+ }
+ }
+
+ public boolean cookieMatches(long cookie) {
+ synchronized (mLock) {
+ return mCookie == cookie;
+ }
+ }
+
+ public boolean waitUntilServiceDied(long timeoutMillis) {
+ synchronized(mLock) {
+ while (!mCalled) {
+ try {
+ mLock.wait(timeoutMillis);
+ } catch (InterruptedException e) {
+ continue; // Spin for another loop
+ }
+ break; // got notified or timeout hit
+ }
+ return mCalled;
+ }
+ }
+ };
+
private void ExpectTrue(boolean x) {
if (x) {
return;
@@ -699,6 +734,26 @@
proxy.callMeLater(new BazCallback());
System.gc();
proxy.iAmFreeNow();
+
+ // --- DEATH RECIPIENT TESTING ---
+ // This must always be done last, since it will kill the native server process
+ HidlDeathRecipient recipient1 = new HidlDeathRecipient();
+ HidlDeathRecipient recipient2 = new HidlDeathRecipient();
+
+ final int cookie1 = 0x1481;
+ final int cookie2 = 0x1482;
+ ExpectTrue(proxy.linkToDeath(recipient1, cookie1));
+ ExpectTrue(proxy.linkToDeath(recipient2, cookie2));
+ ExpectTrue(proxy.unlinkToDeath(recipient2));
+ try {
+ proxy.dieNow();
+ } catch (RuntimeException e) {
+ // Expected
+ }
+ ExpectTrue(recipient1.waitUntilServiceDied(2000 /*timeoutMillis*/));
+ ExpectTrue(!recipient2.waitUntilServiceDied(2000 /*timeoutMillis*/));
+ ExpectTrue(recipient1.cookieMatches(cookie1));
+ Log.d(TAG, "OK, exiting");
}
class Baz extends IBaz.Stub {
@@ -900,6 +955,10 @@
}
}
+ public void dieNow() {
+ // Not tested in Java
+ }
+
public byte useAnEnum(byte zzz) {
Log.d(TAG, "useAnEnum " + zzz);
return SomeEnum.quux;