Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9a51db88 authored by Steven Moreland's avatar Steven Moreland
Browse files

Add AStatus to libbinder_ndk.

This object encapsulates the way that Java AIDL (the SDK) Statuses work
by wrapping the C++ Status class which also encapsulates this.

Test: runtests.sh
Bug: 111445392
Change-Id: I6cc9bd20cf4f83f49d1a546ae7b1e10734fc6535
parent f18615b5
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -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.
+87 −0
Original line number Diff line number Diff line
@@ -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

/** @} */
+11 −0
Original line number Diff line number Diff line
@@ -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.
+53 −0
Original line number Diff line number Diff line
@@ -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;

+11 −0
Original line number Diff line number Diff line
@@ -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);