diff options
| author | 2018-09-18 02:07:17 +0000 | |
|---|---|---|
| committer | 2018-09-18 02:07:17 +0000 | |
| commit | cede3a30d61447e0d4c80a9ab7c427bf1539c985 (patch) | |
| tree | 1f80f00f3b20bae697cd6ba1d28de538a144e0ae | |
| parent | 619425313528e85ecdfc09ce468bcd2f1184c2bf (diff) | |
| parent | 9a51db882461dc9a772bbe9decde905b02e78c2a (diff) | |
Merge "Add AStatus to libbinder_ndk."
| -rw-r--r-- | libs/binder/ndk/include_ndk/android/binder_parcel.h | 11 | ||||
| -rw-r--r-- | libs/binder/ndk/include_ndk/android/binder_status.h | 87 | ||||
| -rw-r--r-- | libs/binder/ndk/parcel.cpp | 11 | ||||
| -rw-r--r-- | libs/binder/ndk/status.cpp | 53 | ||||
| -rw-r--r-- | libs/binder/ndk/status_internal.h | 11 |
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); |