diff options
| -rw-r--r-- | libs/binder/Binder.cpp | 4 | ||||
| -rw-r--r-- | libs/binder/BinderRecordReplay.cpp | 19 | ||||
| -rw-r--r-- | libs/binder/include/binder/BinderRecordReplay.h | 10 | ||||
| -rw-r--r-- | libs/binder/tests/binderRecordedTransactionTest.cpp | 5 |
4 files changed, 30 insertions, 8 deletions
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp index 5e725a91f2..da5affb274 100644 --- a/libs/binder/Binder.cpp +++ b/libs/binder/Binder.cpp @@ -407,8 +407,10 @@ status_t BBinder::transact( AutoMutex lock(e->mLock); if (mRecordingOn) { Parcel emptyReply; + timespec ts; + timespec_get(&ts, TIME_UTC); auto transaction = - android::binder::debug::RecordedTransaction::fromDetails(code, flags, data, + android::binder::debug::RecordedTransaction::fromDetails(code, flags, ts, data, reply ? *reply : emptyReply, err); diff --git a/libs/binder/BinderRecordReplay.cpp b/libs/binder/BinderRecordReplay.cpp index 94637853f9..8ba18a87f8 100644 --- a/libs/binder/BinderRecordReplay.cpp +++ b/libs/binder/BinderRecordReplay.cpp @@ -101,18 +101,24 @@ static_assert(PADDING8(8) == 0); // End Chunk may therefore produce a empty, meaningless RecordedTransaction. RecordedTransaction::RecordedTransaction(RecordedTransaction&& t) noexcept { - mHeader = {t.getCode(), t.getFlags(), t.getReturnedStatus(), t.getVersion()}; + mHeader = t.mHeader; 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) { RecordedTransaction t; - t.mHeader = {code, flags, static_cast<int32_t>(err), - dataParcel.isForRpc() ? static_cast<uint32_t>(1) : static_cast<uint32_t>(0)}; + t.mHeader = {code, + flags, + static_cast<int32_t>(err), + dataParcel.isForRpc() ? static_cast<uint32_t>(1) : static_cast<uint32_t>(0), + static_cast<int64_t>(timestamp.tv_sec), + static_cast<int32_t>(timestamp.tv_nsec), + 0}; if (t.mSent.setData(dataParcel.data(), dataParcel.dataSize()) != android::NO_ERROR) { LOG(INFO) << "Failed to set sent parcel data."; @@ -175,6 +181,7 @@ std::optional<RecordedTransaction> RecordedTransaction::fromFile(const unique_fd LOG(INFO) << "Failed to read transactionHeader from fd " << fd.get(); return std::nullopt; } + lseek(fd.get(), chunk.padding, SEEK_CUR); break; } case DATA_PARCEL_CHUNK: { @@ -292,6 +299,12 @@ int32_t RecordedTransaction::getReturnedStatus() const { return mHeader.statusReturned; } +timespec RecordedTransaction::getTimestamp() const { + time_t sec = mHeader.timestampSeconds; + int32_t nsec = mHeader.timestampNanoseconds; + return (timespec){.tv_sec = sec, .tv_nsec = nsec}; +} + uint32_t RecordedTransaction::getVersion() const { return mHeader.version; } diff --git a/libs/binder/include/binder/BinderRecordReplay.h b/libs/binder/include/binder/BinderRecordReplay.h index 609e5be8d1..ff983f08c2 100644 --- a/libs/binder/include/binder/BinderRecordReplay.h +++ b/libs/binder/include/binder/BinderRecordReplay.h @@ -34,8 +34,8 @@ public: 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, - const Parcel& data, const Parcel& reply, - status_t err); + 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; @@ -43,6 +43,7 @@ public: uint32_t getCode() const; uint32_t getFlags() const; int32_t getReturnedStatus() const; + timespec getTimestamp() const; uint32_t getVersion() const; const Parcel& getDataParcel() const; const Parcel& getReplyParcel() const; @@ -60,9 +61,12 @@ private: uint32_t flags = 0; int32_t statusReturned = 0; uint32_t version = 0; // !0 iff Rpc + int64_t timestampSeconds = 0; + int32_t timestampNanoseconds = 0; + int32_t reserved = 0; }; #pragma clang diagnostic pop - static_assert(sizeof(TransactionHeader) == 16); + static_assert(sizeof(TransactionHeader) == 32); static_assert(sizeof(TransactionHeader) % 8 == 0); TransactionHeader mHeader; diff --git a/libs/binder/tests/binderRecordedTransactionTest.cpp b/libs/binder/tests/binderRecordedTransactionTest.cpp index 67e482d2fb..2ece3156ee 100644 --- a/libs/binder/tests/binderRecordedTransactionTest.cpp +++ b/libs/binder/tests/binderRecordedTransactionTest.cpp @@ -28,7 +28,8 @@ TEST(BinderRecordedTransaction, RoundTripEncoding) { d.writeInt64(2); Parcel r; r.writeInt32(99); - auto transaction = RecordedTransaction::fromDetails(1, 42, d, r, 0); + timespec ts = {1232456, 567890}; + auto transaction = RecordedTransaction::fromDetails(1, 42, ts, d, r, 0); auto file = std::tmpfile(); auto fd = unique_fd(fcntl(fileno(file), F_DUPFD, 1)); @@ -42,6 +43,8 @@ TEST(BinderRecordedTransaction, RoundTripEncoding) { EXPECT_EQ(retrievedTransaction->getCode(), 1); EXPECT_EQ(retrievedTransaction->getFlags(), 42); + EXPECT_EQ(retrievedTransaction->getTimestamp().tv_sec, ts.tv_sec); + EXPECT_EQ(retrievedTransaction->getTimestamp().tv_nsec, ts.tv_nsec); EXPECT_EQ(retrievedTransaction->getDataParcel().dataSize(), 12); EXPECT_EQ(retrievedTransaction->getReplyParcel().dataSize(), 4); EXPECT_EQ(retrievedTransaction->getReturnedStatus(), 0); |