libbinder: add BINDER_GET_EXTENDED_ERROR support
This adds basic support to pull extended error information provided by
the driver via BINDER_GET_EXTENDED_ERROR ioctl. For now, we'll only log
the information upon a failed transaction. However, this data can later
be used to handle error scenarios such as retry strategies.
Bug: 28321379
Test: atest binderLibTest
Signed-off-by: Carlos Llamas <cmllamas@google.com>
Change-Id: I8aed63cb0d1aa15aa96db4ab8999e300fef1f505
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 3c97dca..d453ac7 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -989,6 +989,7 @@
if (acquireResult) *acquireResult = err;
if (reply) reply->setError(err);
mLastError = err;
+ logExtendedError();
}
return err;
@@ -1443,6 +1444,23 @@
return ret;
}
+void IPCThreadState::logExtendedError() {
+ struct binder_extended_error ee = {.command = BR_OK};
+
+ if (!ProcessState::isDriverFeatureEnabled(ProcessState::DriverFeature::EXTENDED_ERROR))
+ return;
+
+#if defined(__ANDROID__)
+ if (ioctl(self()->mProcess->mDriverFD, BINDER_GET_EXTENDED_ERROR, &ee) < 0) {
+ ALOGE("Failed to get extended error: %s", strerror(errno));
+ return;
+ }
+#endif
+
+ ALOGE_IF(ee.command != BR_OK, "Binder transaction failure: %d/%d/%d",
+ ee.id, ee.command, ee.param);
+}
+
void IPCThreadState::freeBuffer(Parcel* parcel, const uint8_t* data,
size_t /*dataSize*/,
const binder_size_t* /*objects*/,
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 4a01d81..c4cf3e6 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -415,6 +415,8 @@
static const char* const names[] = {
[static_cast<int>(DriverFeature::ONEWAY_SPAM_DETECTION)] =
DRIVER_FEATURES_PATH "oneway_spam_detection",
+ [static_cast<int>(DriverFeature::EXTENDED_ERROR)] =
+ DRIVER_FEATURES_PATH "extended_error",
};
int fd = open(names[static_cast<int>(feature)], O_RDONLY | O_CLOEXEC);
char on;
diff --git a/libs/binder/binder_module.h b/libs/binder/binder_module.h
index 793795e..7574c29 100644
--- a/libs/binder/binder_module.h
+++ b/libs/binder/binder_module.h
@@ -100,4 +100,23 @@
#define BINDER_ENABLE_ONEWAY_SPAM_DETECTION _IOW('b', 16, __u32)
#endif // BINDER_ENABLE_ONEWAY_SPAM_DETECTION
+#ifndef BINDER_GET_EXTENDED_ERROR
+/* struct binder_extened_error - extended error information
+ * @id: identifier for the failed operation
+ * @command: command as defined by binder_driver_return_protocol
+ * @param: parameter holding a negative errno value
+ *
+ * Used with BINDER_GET_EXTENDED_ERROR. This extends the error information
+ * returned by the driver upon a failed operation. Userspace can pull this
+ * data to properly handle specific error scenarios.
+ */
+struct binder_extended_error {
+ __u32 id;
+ __u32 command;
+ __s32 param;
+};
+
+#define BINDER_GET_EXTENDED_ERROR _IOWR('b', 17, struct binder_extended_error)
+#endif // BINDER_GET_EXTENDED_ERROR
+
#endif // _BINDER_MODULE_H_
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index bf02099..cd6a274 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -216,6 +216,7 @@
static void freeBuffer(Parcel* parcel,
const uint8_t* data, size_t dataSize,
const binder_size_t* objects, size_t objectsSize);
+ static void logExtendedError();
const sp<ProcessState> mProcess;
Vector<BBinder*> mPendingStrongDerefs;
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index 675585e..5820802 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -92,6 +92,7 @@
enum class DriverFeature {
ONEWAY_SPAM_DETECTION,
+ EXTENDED_ERROR,
};
// Determine whether a feature is supported by the binder driver.
static bool isDriverFeatureEnabled(const DriverFeature feature);