summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Steven Moreland <smoreland@google.com> 2018-09-18 02:07:17 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2018-09-18 02:07:17 +0000
commitcede3a30d61447e0d4c80a9ab7c427bf1539c985 (patch)
tree1f80f00f3b20bae697cd6ba1d28de538a144e0ae
parent619425313528e85ecdfc09ce468bcd2f1184c2bf (diff)
parent9a51db882461dc9a772bbe9decde905b02e78c2a (diff)
Merge "Add AStatus to libbinder_ndk."
-rw-r--r--libs/binder/ndk/include_ndk/android/binder_parcel.h11
-rw-r--r--libs/binder/ndk/include_ndk/android/binder_status.h87
-rw-r--r--libs/binder/ndk/parcel.cpp11
-rw-r--r--libs/binder/ndk/status.cpp53
-rw-r--r--libs/binder/ndk/status_internal.h11
5 files changed, 173 insertions, 0 deletions
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index e871ed12b1..862802523e 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -66,6 +66,17 @@ binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binde
*/
binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder);
+/**
+ * Writes an AStatus object to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeStatusHeader(AParcel* parcel, const AStatus* status);
+
+/**
+ * Reads an AStatus from the next location in a non-null parcel. Ownership is passed to the caller
+ * of this function.
+ */
+binder_status_t AParcel_readStatusHeader(const AParcel* parcel, AStatus** status);
+
// @START
/**
* Writes int32_t value to the next location in a non-null parcel.
diff --git a/libs/binder/ndk/include_ndk/android/binder_status.h b/libs/binder/ndk/include_ndk/android/binder_status.h
index bc8e44a334..d9c36d219b 100644
--- a/libs/binder/ndk/include_ndk/android/binder_status.h
+++ b/libs/binder/ndk/include_ndk/android/binder_status.h
@@ -89,6 +89,93 @@ enum {
*/
typedef int32_t binder_exception_t;
+/**
+ * This is a helper class that encapsulates a standard way to keep track of and chain binder errors
+ * along with service specific errors.
+ *
+ * It is not required to be used in order to parcel/receive transactions, but it is required in
+ * order to be compatible with standard AIDL transactions.
+ */
+struct AStatus;
+typedef struct AStatus AStatus;
+
+/**
+ * New status which is considered a success.
+ */
+__attribute__((warn_unused_result)) AStatus* AStatus_newOk();
+
+/**
+ * New status with exception code.
+ */
+__attribute__((warn_unused_result)) AStatus* AStatus_fromExceptionCode(
+ binder_exception_t exception);
+
+/**
+ * New status with exception code and message.
+ */
+__attribute__((warn_unused_result)) AStatus* AStatus_fromExceptionCodeWithMessage(
+ binder_exception_t exception, const char* message);
+
+/**
+ * New status with a service speciic error.
+ *
+ * This is considered to be EX_TRANSACTION_FAILED with extra information.
+ */
+__attribute__((warn_unused_result)) AStatus* AStatus_fromServiceSpecificError(
+ int32_t serviceSpecific);
+
+/**
+ * New status with a service specific error and message.
+ *
+ * This is considered to be EX_TRANSACTION_FAILED with extra information.
+ */
+__attribute__((warn_unused_result)) AStatus* AStatus_fromServiceSpecificErrorWithMessage(
+ int32_t serviceSpecific, const char* message);
+
+/**
+ * New status with binder_status_t. This is typically for low level failures when a binder_status_t
+ * is returned by an API on AIBinder or AParcel, and that is to be returned from a method returning
+ * an AStatus instance.
+ */
+__attribute__((warn_unused_result)) AStatus* AStatus_fromStatus(binder_status_t status);
+
+/**
+ * Whether this object represents a successful transaction.
+ */
+bool AStatus_isOk(const AStatus* status);
+
+/**
+ * The exception that this status object represents.
+ */
+binder_exception_t AStatus_getExceptionCode(const AStatus* status);
+
+/**
+ * The service specific error if this object represents one. If this object represents a different
+ * kind of exception or is ok, this function will return 0. Just because this function returns 0
+ * does not mean that the transaction was a success.
+ */
+int32_t AStatus_getServiceSpecificError(const AStatus* status);
+
+/**
+ * The status if this object represents one. If this object represents a different kind of exception
+ * or is ok, this function will return 0. Just because this function returns 0 does not mean that
+ * the transaction was a success.
+ */
+binder_status_t AStatus_getStatus(const AStatus* status);
+
+/**
+ * If there is a message associated with this status, this will return that message. If there is no
+ * message, this will return an empty string.
+ *
+ * The returned string has the lifetime of the status object passed into this function.
+ */
+const char* AStatus_getMessage(const AStatus* status);
+
+/**
+ * Deletes memory associated with the status instance.
+ */
+void AStatus_delete(AStatus** status);
+
__END_DECLS
/** @} */
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index e506847349..a063657dd6 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -62,6 +62,17 @@ binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder
*binder = ret.get();
return PruneStatusT(status);
}
+binder_status_t AParcel_writeStatusHeader(AParcel* parcel, const AStatus* status) {
+ return PruneStatusT(status->get()->writeToParcel(parcel->get()));
+}
+binder_status_t AParcel_readStatusHeader(const AParcel* parcel, AStatus** status) {
+ ::android::binder::Status bstatus;
+ binder_status_t ret = PruneStatusT(bstatus.readFromParcel(*parcel->get()));
+ if (ret == EX_NONE) {
+ *status = new AStatus(std::move(bstatus));
+ }
+ return ret;
+}
// See gen_parcel_helper.py. These auto-generated read/write methods use the same types for
// libbinder and this library.
diff --git a/libs/binder/ndk/status.cpp b/libs/binder/ndk/status.cpp
index 626a9b2731..deb0392cc7 100644
--- a/libs/binder/ndk/status.cpp
+++ b/libs/binder/ndk/status.cpp
@@ -22,6 +22,59 @@
using ::android::status_t;
using ::android::binder::Status;
+AStatus* AStatus_newOk() {
+ return new AStatus();
+}
+
+AStatus* AStatus_fromExceptionCode(binder_exception_t exception) {
+ return new AStatus(Status::fromExceptionCode(exception));
+}
+
+AStatus* AStatus_fromExceptionCodeWithMessage(binder_exception_t exception, const char* message) {
+ return new AStatus(Status::fromExceptionCode(exception, message));
+}
+
+AStatus* AStatus_fromServiceSpecificError(int32_t serviceSpecific) {
+ return new AStatus(Status::fromServiceSpecificError(serviceSpecific));
+}
+
+AStatus* AStatus_fromServiceSpecificErrorWithMessage(int32_t serviceSpecific, const char* message) {
+ return new AStatus(Status::fromServiceSpecificError(serviceSpecific, message));
+}
+
+AStatus* AStatus_fromStatus(binder_status_t status) {
+ return new AStatus(Status::fromStatusT(status));
+}
+
+bool AStatus_isOk(const AStatus* status) {
+ return status->get()->isOk();
+}
+
+binder_exception_t AStatus_getExceptionCode(const AStatus* status) {
+ return PruneException(status->get()->exceptionCode());
+}
+
+int32_t AStatus_getServiceSpecificError(const AStatus* status) {
+ return status->get()->serviceSpecificErrorCode();
+}
+
+binder_status_t AStatus_getStatus(const AStatus* status) {
+ return PruneStatusT(status->get()->transactionError());
+}
+
+const char* AStatus_getMessage(const AStatus* status) {
+ return status->get()->exceptionMessage().c_str();
+}
+
+void AStatus_delete(AStatus** status) {
+ if (status == nullptr) {
+ return;
+ }
+
+ delete *status;
+ *status = nullptr;
+}
+
binder_status_t PruneStatusT(status_t status) {
if (status > 0) return status;
diff --git a/libs/binder/ndk/status_internal.h b/libs/binder/ndk/status_internal.h
index 41b124cf27..8c32baf83f 100644
--- a/libs/binder/ndk/status_internal.h
+++ b/libs/binder/ndk/status_internal.h
@@ -21,6 +21,17 @@
#include <binder/Status.h>
#include <utils/Errors.h>
+struct AStatus {
+ AStatus() {} // ok
+ AStatus(::android::binder::Status&& status) : mStatus(std::move(status)) {}
+
+ ::android::binder::Status* get() { return &mStatus; }
+ const ::android::binder::Status* get() const { return &mStatus; }
+
+private:
+ ::android::binder::Status mStatus;
+};
+
// This collapses the statuses into the declared range.
binder_status_t PruneStatusT(android::status_t status);