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

Commit c150630e authored by Fabián Cañas's avatar Fabián Cañas Committed by Gerrit Code Review
Browse files

Merge "Add interfaceDescriptor to RecordedTransaction"

parents a7546573 6c0c9639
Loading
Loading
Loading
Loading
+3 −5
Original line number Diff line number Diff line
@@ -409,11 +409,9 @@ status_t BBinder::transact(
            Parcel emptyReply;
            timespec ts;
            timespec_get(&ts, TIME_UTC);
            auto transaction =
                    android::binder::debug::RecordedTransaction::fromDetails(code, flags, ts, data,
                                                                             reply ? *reply
                                                                                   : emptyReply,
                                                                             err);
            auto transaction = android::binder::debug::RecordedTransaction::
                    fromDetails(getInterfaceDescriptor(), code, flags, ts, data,
                                reply ? *reply : emptyReply, err);
            if (transaction) {
                if (status_t err = transaction->dumpToFile(e->mRecordingFd); err != NO_ERROR) {
                    LOG(INFO) << "Failed to dump RecordedTransaction to file with error " << err;
+43 −21
Original line number Diff line number Diff line
@@ -106,18 +106,16 @@ static_assert(PADDING8(8) == 0);
// End Chunk may therefore produce an empty, meaningless RecordedTransaction.

RecordedTransaction::RecordedTransaction(RecordedTransaction&& t) noexcept {
    mHeader = t.mHeader;
    mData = t.mData;
    mSent.setData(t.getDataParcel().data(), t.getDataParcel().dataSize());
    mReply.setData(t.getReplyParcel().data(), t.getReplyParcel().dataSize());
}

std::optional<RecordedTransaction> RecordedTransaction::fromDetails(uint32_t code, uint32_t flags,
                                                                    timespec timestamp,
                                                                    const Parcel& dataParcel,
                                                                    const Parcel& replyParcel,
                                                                    status_t err) {
std::optional<RecordedTransaction> RecordedTransaction::fromDetails(
        const String16& interfaceName, uint32_t code, uint32_t flags, timespec timestamp,
        const Parcel& dataParcel, const Parcel& replyParcel, status_t err) {
    RecordedTransaction t;
    t.mHeader = {code,
    t.mData.mHeader = {code,
                       flags,
                       static_cast<int32_t>(err),
                       dataParcel.isForRpc() ? static_cast<uint32_t>(1) : static_cast<uint32_t>(0),
@@ -125,6 +123,14 @@ std::optional<RecordedTransaction> RecordedTransaction::fromDetails(uint32_t cod
                       static_cast<int32_t>(timestamp.tv_nsec),
                       0};

    t.mData.mInterfaceName = String8(interfaceName);
    if (interfaceName.size() != t.mData.mInterfaceName.bytes()) {
        LOG(ERROR) << "Interface Name is not valid. Contains characters that aren't single byte "
                      "utf-8: "
                   << interfaceName;
        return std::nullopt;
    }

    if (t.mSent.setData(dataParcel.data(), dataParcel.dataSize()) != android::NO_ERROR) {
        LOG(ERROR) << "Failed to set sent parcel data.";
        return std::nullopt;
@@ -142,6 +148,7 @@ enum {
    HEADER_CHUNK = 1,
    DATA_PARCEL_CHUNK = 2,
    REPLY_PARCEL_CHUNK = 3,
    INTERFACE_NAME_CHUNK = 4,
    END_CHUNK = 0x00ffffff,
};

@@ -220,7 +227,11 @@ std::optional<RecordedTransaction> RecordedTransaction::fromFile(const unique_fd
                               << sizeof(TransactionHeader) << ".";
                    return std::nullopt;
                }
                t.mHeader = *reinterpret_cast<TransactionHeader*>(payloadMap);
                t.mData.mHeader = *reinterpret_cast<TransactionHeader*>(payloadMap);
                break;
            }
            case INTERFACE_NAME_CHUNK: {
                t.mData.mInterfaceName.setTo(reinterpret_cast<char*>(payloadMap), chunk.dataSize);
                break;
            }
            case DATA_PARCEL_CHUNK: {
@@ -291,10 +302,17 @@ android::status_t RecordedTransaction::writeChunk(borrowed_fd fd, uint32_t chunk
android::status_t RecordedTransaction::dumpToFile(const unique_fd& fd) const {
    if (NO_ERROR !=
        writeChunk(fd, HEADER_CHUNK, sizeof(TransactionHeader),
                   reinterpret_cast<const uint8_t*>(&mHeader))) {
                   reinterpret_cast<const uint8_t*>(&(mData.mHeader)))) {
        LOG(ERROR) << "Failed to write transactionHeader to fd " << fd.get();
        return UNKNOWN_ERROR;
    }
    if (NO_ERROR !=
        writeChunk(fd, INTERFACE_NAME_CHUNK, mData.mInterfaceName.size() * sizeof(uint8_t),
                   reinterpret_cast<const uint8_t*>(mData.mInterfaceName.string()))) {
        LOG(INFO) << "Failed to write Interface Name Chunk to fd " << fd.get();
        return UNKNOWN_ERROR;
    }

    if (NO_ERROR != writeChunk(fd, DATA_PARCEL_CHUNK, mSent.dataSize(), mSent.data())) {
        LOG(ERROR) << "Failed to write sent Parcel to fd " << fd.get();
        return UNKNOWN_ERROR;
@@ -310,26 +328,30 @@ android::status_t RecordedTransaction::dumpToFile(const unique_fd& fd) const {
    return NO_ERROR;
}

const android::String8& RecordedTransaction::getInterfaceName() const {
    return mData.mInterfaceName;
}

uint32_t RecordedTransaction::getCode() const {
    return mHeader.code;
    return mData.mHeader.code;
}

uint32_t RecordedTransaction::getFlags() const {
    return mHeader.flags;
    return mData.mHeader.flags;
}

int32_t RecordedTransaction::getReturnedStatus() const {
    return mHeader.statusReturned;
    return mData.mHeader.statusReturned;
}

timespec RecordedTransaction::getTimestamp() const {
    time_t sec = mHeader.timestampSeconds;
    int32_t nsec = mHeader.timestampNanoseconds;
    time_t sec = mData.mHeader.timestampSeconds;
    int32_t nsec = mData.mHeader.timestampNanoseconds;
    return (timespec){.tv_sec = sec, .tv_nsec = nsec};
}

uint32_t RecordedTransaction::getVersion() const {
    return mHeader.version;
    return mData.mHeader.version;
}

const Parcel& RecordedTransaction::getDataParcel() const {
+8 −2
Original line number Diff line number Diff line
@@ -33,13 +33,15 @@ public:
    // Filled with the first transaction from fd.
    static std::optional<RecordedTransaction> fromFile(const android::base::unique_fd& fd);
    // Filled with the arguments.
    static std::optional<RecordedTransaction> fromDetails(uint32_t code, uint32_t flags,
    static std::optional<RecordedTransaction> fromDetails(const String16& interfaceName,
                                                          uint32_t code, uint32_t flags,
                                                          timespec timestamp, const Parcel& data,
                                                          const Parcel& reply, status_t err);
    RecordedTransaction(RecordedTransaction&& t) noexcept;

    [[nodiscard]] status_t dumpToFile(const android::base::unique_fd& fd) const;

    const String8& getInterfaceName() const;
    uint32_t getCode() const;
    uint32_t getFlags() const;
    int32_t getReturnedStatus() const;
@@ -69,7 +71,11 @@ private:
    static_assert(sizeof(TransactionHeader) == 32);
    static_assert(sizeof(TransactionHeader) % 8 == 0);

    struct MovableData { // movable
        TransactionHeader mHeader;
        String8 mInterfaceName;
    };
    MovableData mData;
    Parcel mSent;
    Parcel mReply;
};
+9 −3
Original line number Diff line number Diff line
@@ -24,13 +24,16 @@ using android::base::unique_fd;
using android::binder::debug::RecordedTransaction;

TEST(BinderRecordedTransaction, RoundTripEncoding) {
    android::String16 interfaceName("SampleInterface");
    Parcel d;
    d.writeInt32(12);
    d.writeInt64(2);
    Parcel r;
    r.writeInt32(99);
    timespec ts = {1232456, 567890};
    auto transaction = RecordedTransaction::fromDetails(1, 42, ts, d, r, 0);

    auto transaction = RecordedTransaction::fromDetails(interfaceName, 1, 42, ts, d, r, 0);
    EXPECT_TRUE(transaction.has_value());

    auto file = std::tmpfile();
    auto fd = unique_fd(fcntl(fileno(file), F_DUPFD, 1));
@@ -42,6 +45,7 @@ TEST(BinderRecordedTransaction, RoundTripEncoding) {

    auto retrievedTransaction = RecordedTransaction::fromFile(fd);

    EXPECT_EQ(retrievedTransaction->getInterfaceName(), android::String8(interfaceName));
    EXPECT_EQ(retrievedTransaction->getCode(), 1);
    EXPECT_EQ(retrievedTransaction->getFlags(), 42);
    EXPECT_EQ(retrievedTransaction->getTimestamp().tv_sec, ts.tv_sec);
@@ -57,13 +61,14 @@ TEST(BinderRecordedTransaction, RoundTripEncoding) {
}

TEST(BinderRecordedTransaction, Checksum) {
    android::String16 interfaceName("SampleInterface");
    Parcel d;
    d.writeInt32(12);
    d.writeInt64(2);
    Parcel r;
    r.writeInt32(99);
    timespec ts = {1232456, 567890};
    auto transaction = RecordedTransaction::fromDetails(1, 42, ts, d, r, 0);
    auto transaction = RecordedTransaction::fromDetails(interfaceName, 1, 42, ts, d, r, 0);

    auto file = std::tmpfile();
    auto fd = unique_fd(fcntl(fileno(file), F_DUPFD, 1));
@@ -91,6 +96,7 @@ TEST(BinderRecordedTransaction, PayloadsExceedPageBoundaries) {
    std::vector<uint8_t> largePayload;
    uint8_t filler = 0xaa;
    largePayload.insert(largePayload.end(), largeDataSize, filler);
    android::String16 interfaceName("SampleInterface");
    Parcel d;
    d.writeInt32(12);
    d.writeInt64(2);
@@ -98,7 +104,7 @@ TEST(BinderRecordedTransaction, PayloadsExceedPageBoundaries) {
    Parcel r;
    r.writeInt32(99);
    timespec ts = {1232456, 567890};
    auto transaction = RecordedTransaction::fromDetails(1, 42, ts, d, r, 0);
    auto transaction = RecordedTransaction::fromDetails(interfaceName, 1, 42, ts, d, r, 0);

    auto file = std::tmpfile();
    auto fd = unique_fd(fcntl(fileno(file), F_DUPFD, 1));