Extra branches for getService.
getService should treat failures differently. Failure check
happens at (for hwbinder):
1. defaultServiceManager() == nullptr
2. defaultServiceManager()->get transaction error
3. get returns null
4. in castFrom, calling interfaceChain transaction error
4.1 DEAD_OBJECT
4.2 other transaction error
5. interfaceChain succeeds but cast fails (mismatch)
Test: boots
Test: screenshot / camera / maps
Test: calling Debug.getMemoryInfo from apps does not hang
Test: kill system_server, audio still works
Test: adb push
$OUT/data/nativetest/VtsHalNfcV1_0TargetTest/VtsHalNfcV1_0TargetTest
/data/local/tmp && adb shell /data/local/tmp/VtsHalNfcV1_0TargetTest
Bug: 36153684
Bug: 36611652
Change-Id: I664f8d1a1ccc0e623f31cc7b3b435acc487298d1
diff --git a/generateCpp.cpp b/generateCpp.cpp
index 51ebdc5..27d843c 100644
--- a/generateCpp.cpp
+++ b/generateCpp.cpp
@@ -240,18 +240,35 @@
<< "break;\n";
}).endl();
- out << "iface = " << interfaceName << "::castFrom(ret);\n";
- out.sIf("iface == nullptr", [&] {
- // 1. race condition. hwservicemanager drops the service
- // from waitForHwService to here
- // 2. service is dead (castFrom cannot call interfaceChain)
- // 3. returned service isn't of correct type; this is a bug
- // to hwservicemanager or to the service itself (interfaceChain
- // is not consistent)
- // In all cases, try again.
+ out << "::android::sp<" << gIBaseFqName.cppName() << "> base = ret;\n";
+ out.sIf("base == nullptr", [&] {
+ // race condition. hwservicemanager drops the service
+ // from waitForHwService to here
out << "ALOGW(\"getService: found null hwbinder interface\");\n"
<< "break;\n";
}).endl();
+ out << "::android::hardware::Return<::android::sp<" << interfaceName
+ << ">> castRet = " << interfaceName << "::castFrom(base, true /* emitError */);\n";
+ out.sIf("!castRet.isOk()", [&] {
+ out.sIf("castRet.isDeadObject()", [&] {
+ // service is dead (castFrom cannot call interfaceChain)
+ out << "ALOGW(\"getService: found dead hwbinder service\");\n"
+ << "break;\n";
+ }).sElse([&] {
+ out << "ALOGW(\"getService: cannot call into hwbinder service: %s"
+ << "; No permission? Check for selinux denials.\", "
+ << "castRet.description().c_str());\n"
+ << "break;\n";
+ }).endl();
+ }).endl();
+ out << "iface = castRet;\n";
+ out.sIf("iface == nullptr", [&] {
+ // returned service isn't of correct type; this is a bug
+ // to hwservicemanager or to the service itself (interfaceChain
+ // is not consistent).
+ out << "ALOGW(\"getService: received incompatible service; bug in hwservicemanager?\");\n"
+ << "break;\n";
+ }).endl();
out << "return iface;\n";
}).endl();
@@ -473,12 +490,12 @@
std::string childTypeResult = iface->getCppResultType();
for (const Interface *superType : iface->typeChain()) {
- out << "static "
+ out << "static ::android::hardware::Return<"
<< childTypeResult
- << " castFrom("
+ << "> castFrom("
<< superType->getCppArgumentType()
<< " parent"
- << ");\n";
+ << ", bool emitError = false);\n";
}
out << "\nstatic const char* descriptor;\n\n";
@@ -1883,13 +1900,15 @@
}
for (const Interface *superType : iface->typeChain()) {
- out << "// static \n"
+ out << "// static \n::android::hardware::Return<"
<< childTypeResult
- << " "
+ << "> "
<< iface->localName()
<< "::castFrom("
<< superType->getCppArgumentType()
- << " parent) {\n";
+ << " parent, bool "
+ << (iface == superType ? "/* emitError */" : "emitError")
+ << ") {\n";
out.indent();
if (iface == superType) {
out << "return parent;\n";
@@ -1904,7 +1923,7 @@
out.indent();
out << "parent, \""
<< iface->fqName().string()
- << "\");\n";
+ << "\", emitError);\n";
out.unindent();
out.unindent();
}