Add (un)linkToDeath to generated interfaces.
(un)linkToDeath is now a part of IBase, and can be
called on any generated HIDL interface. The implementation
is a no-op, except in proxy objects, which are by
definition a different process than the interface they point
to.
Since clients are not aware of the transport implementation, we must
wrap the transport-independent callback in a transport-specific
callback object. In case of binder, that object is a
hidl_binder_death_recipient.
The binder proxy object contains a list of registered death
recipients, as well as a mutex to protect access to the list.
The list is required to allow us to map back transport-independent
callbacks to transport-dependent callbacks in unlinkToDeath().
Bug: 31632518
Test: mma, hidl_test
Change-Id: I5083a8789dd706a886a8a09f8c733031a351a36a
diff --git a/Interface.cpp b/Interface.cpp
index 602b221..29afee1 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -17,7 +17,9 @@
#include "Interface.h"
#include "Annotation.h"
+#include "DeathRecipientType.h"
#include "Method.h"
+#include "ScalarType.h"
#include "StringType.h"
#include "VectorType.h"
@@ -46,6 +48,8 @@
FIRST_HIDL_TRANSACTION = 0x00f00000,
HIDL_DESCRIPTOR_CHAIN_TRANSACTION = FIRST_HIDL_TRANSACTION,
HIDL_SYSPROPS_CHANGED_TRANSACTION,
+ HIDL_LINK_TO_DEATH_TRANSACTION,
+ HIDL_UNLINK_TO_DEATH_TRANSACTION,
LAST_HIDL_TRANSACTION = 0x00ffffff,
};
@@ -55,12 +59,132 @@
mIsJavaCompatibleInProgress(false) {
mReservedMethods.push_back(createDescriptorChainMethod());
mReservedMethods.push_back(createSyspropsChangedMethod());
+ mReservedMethods.push_back(createLinkToDeathMethod());
+ mReservedMethods.push_back(createUnlinkToDeathMethod());
}
std::string Interface::typeName() const {
return "interface " + localName();
}
+Method *Interface::createLinkToDeathMethod() const {
+ auto *results = new std::vector<TypedVar *> {
+ new TypedVar("success", new ScalarType(ScalarType::KIND_BOOL)) };
+ auto *args = new std::vector<TypedVar *> {
+ new TypedVar("recipient", new DeathRecipientType()),
+ new TypedVar("cookie", new ScalarType(ScalarType::KIND_UINT64)) };
+
+ return new Method("linkToDeath",
+ args,
+ results,
+ false /*oneway */,
+ new std::vector<Annotation *>(),
+ HIDL_LINK_TO_DEATH_TRANSACTION,
+ {
+ {IMPL_HEADER,
+ [](auto &out) {
+ out << "(void)cookie;\n"
+ << "return (recipient != nullptr);\n";
+ }
+ },
+ {IMPL_PROXY,
+ [](auto &out) {
+ out << "::android::hardware::hidl_binder_death_recipient *binder_recipient"
+ << " = new ::android::hardware::hidl_binder_death_recipient(recipient, cookie, this);\n"
+ << "std::unique_lock<std::mutex> lock(_hidl_mMutex);\n"
+ << "_hidl_mDeathRecipients.push_back(binder_recipient);\n"
+ << "return (remote()->linkToDeath(binder_recipient)"
+ << " == ::android::OK);\n";
+ }
+ },
+ {IMPL_STUB,
+ [](auto &/*out*/) {
+ // Do nothing
+ }
+ }
+ }, /*cppImpl*/
+ {
+ {IMPL_HEADER,
+ [this](auto &out) {
+ out << "return true;";
+ }
+ },
+ {IMPL_PROXY,
+ [this](auto &out) {
+ // TODO (b/31632518)
+ out << "return false;";
+ }
+ },
+ {IMPL_STUB,
+ [this](auto &/*out*/) {
+ // Do nothing
+ }
+ }
+ } /*javaImpl*/
+ );
+}
+
+Method *Interface::createUnlinkToDeathMethod() const {
+ auto *results = new std::vector<TypedVar *> {
+ new TypedVar("success", new ScalarType(ScalarType::KIND_BOOL)) };
+ auto *args = new std::vector<TypedVar *> {
+ new TypedVar("recipient", new DeathRecipientType()) };
+
+ return new Method("unlinkToDeath",
+ args,
+ results,
+ false /*oneway */,
+ new std::vector<Annotation *>(),
+ HIDL_UNLINK_TO_DEATH_TRANSACTION,
+ {
+ {IMPL_HEADER,
+ [](auto &out) {
+ out << "return (recipient != nullptr);\n";
+ }
+ },
+ {IMPL_PROXY,
+ [](auto &out) {
+ out << "std::unique_lock<std::mutex> lock(_hidl_mMutex);\n"
+ << "for (auto it = _hidl_mDeathRecipients.begin();"
+ << "it != _hidl_mDeathRecipients.end();"
+ << "++it) {\n";
+ out.indent([&] {
+ out.sIf("(*it)->getRecipient() == recipient", [&] {
+ out << "::android::status_t status = remote()->unlinkToDeath(*it);\n"
+ << "_hidl_mDeathRecipients.erase(it);\n"
+ << "return status == ::android::OK;\n";
+ });
+ });
+ out << "}\n";
+ out << "return false;\n";
+ }
+ },
+ {IMPL_STUB,
+ [](auto &/*out*/) {
+ // Do nothing
+ }
+ }
+ }, /*cppImpl*/
+ {
+ {IMPL_HEADER,
+ [this](auto &out) {
+ out << "return true;";
+ }
+ },
+ {IMPL_PROXY,
+ [this](auto &out) {
+ // TODO (b/31632518)
+ out << "return false;";
+ }
+ },
+ {IMPL_STUB,
+ [this](auto &/*out*/) {
+ // Do nothing
+ }
+ }
+ } /*javaImpl*/
+ );
+}
Method *Interface::createSyspropsChangedMethod() const {
return new Method("notifySyspropsChanged",
new std::vector<TypedVar *>() /*args */,
@@ -68,13 +192,13 @@
true /*oneway */,
new std::vector<Annotation *>(),
HIDL_SYSPROPS_CHANGED_TRANSACTION,
- [this](auto &out) { /*cppImpl */
+ { { IMPL_HEADER, [this](auto &out) {
out << "::android::report_sysprop_change();\n";
out << "return ::android::hardware::Void();";
- },
- [this](auto &out) { /* javaImpl */
+ } } }, /*cppImpl */
+ { { IMPL_HEADER, [](auto &out) { /* javaImpl */
out << "android.os.SystemProperties.reportSyspropChanged();";
- }
+ } } } /*javaImpl */
);
}
@@ -90,7 +214,7 @@
false /* oneway */,
new std::vector<Annotation *>(),
HIDL_DESCRIPTOR_CHAIN_TRANSACTION,
- [this](auto &out) { /* cppImpl */
+ { { IMPL_HEADER, [this](auto &out) {
std::vector<const Interface *> chain = typeChain();
out << "_hidl_cb(";
out.block([&] {
@@ -100,8 +224,8 @@
});
out << ");\n";
out << "return ::android::hardware::Void();";
- },
- [this](auto &out) { /* javaImpl */
+ } } }, /* cppImpl */
+ { { IMPL_HEADER, [this](auto &out) {
std::vector<const Interface *> chain = typeChain();
out << "return new java.util.ArrayList<String>(java.util.Arrays.asList(\n";
out.indent(); out.indent();
@@ -112,7 +236,8 @@
}
out << "));";
out.unindent(); out.unindent();
- });
+ } } } /* javaImpl */
+ );
}