diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-02-21 00:21:30 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-02-21 00:21:30 +0000 |
commit | b954e4cbd748da80e64bdea0dc654404d7b326d7 (patch) | |
tree | b5e6cfe1f61f8679e3b15ff40fd8e3191dcac076 | |
parent | 053b7f4247dc72e23103d3dd3fbec95fef04e5fa (diff) | |
parent | 40b07b8734e1c472db5e9ea7a43c9f0fb05bb814 (diff) | |
download | dittosuite-b954e4cbd748da80e64bdea0dc654404d7b326d7.tar.gz |
Snap for 11473990 from 40b07b8734e1c472db5e9ea7a43c9f0fb05bb814 to sdk-release
Change-Id: Ifb5813c7e3ba50dfefb5d9203f8475628f9a6e8f
-rw-r--r-- | Android.bp | 1 | ||||
-rw-r--r-- | example/android/binder_gen.ditto | 24 | ||||
-rw-r--r-- | include/ditto/binder_request.h | 18 | ||||
-rw-r--r-- | schema/benchmark.proto | 37 | ||||
-rw-r--r-- | src/binder_request.cpp | 133 | ||||
-rw-r--r-- | src/instruction.cpp | 2 | ||||
-rw-r--r-- | src/instruction_factory.cpp | 7 |
7 files changed, 221 insertions, 1 deletions
@@ -29,6 +29,7 @@ cc_defaults { ], shared_libs: [ "libbinder", + "libcutils", "liblog", "libutils", "libprotobuf-cpp-full", diff --git a/example/android/binder_gen.ditto b/example/android/binder_gen.ditto new file mode 100644 index 0000000..a4b0374 --- /dev/null +++ b/example/android/binder_gen.ditto @@ -0,0 +1,24 @@ +main: { + multithreading: { + threads: [ + { + instruction: { + binder_request: { + generic_service: { + name: "time_zone_detector", + code: 6, + parcel_input: [{ + type: STRING_16, + data: "Asia/Calcutta" + }] + }, + }, + repeat: 2, + period_us: 1000, + } + spawn: 2, + } + ] + } +}, +global {} diff --git a/include/ditto/binder_request.h b/include/ditto/binder_request.h index 3c856b2..3a8629e 100644 --- a/include/ditto/binder_request.h +++ b/include/ditto/binder_request.h @@ -72,6 +72,24 @@ class BinderRequestMountService : public BinderRequest { void TearDownSingle(bool last) override; }; +class GenericBinderRequest : public BinderRequest { + public: + inline static const std::string kName = "binder_request_generic"; + explicit GenericBinderRequest(const Params& params, + std::string service_name, int32_t code, + const google::protobuf::RepeatedPtrField<dittosuiteproto::BinderRequest_GenericService_ParcelInput> parcel_input); + + protected: + void RunSingle() override; + const google::protobuf::RepeatedPtrField<dittosuiteproto::BinderRequest_GenericService_ParcelInput> parcel_input_; + std::string service_name_; + int32_t code_; + android::sp<android::IBinder> service_; + + private: + void SetUp() override; + void TearDownSingle(bool is_last) override; +}; } // namespace dittosuite #endif diff --git a/schema/benchmark.proto b/schema/benchmark.proto index 197c1d7..166b7f8 100644 --- a/schema/benchmark.proto +++ b/schema/benchmark.proto @@ -39,9 +39,46 @@ message BinderRequest { enum RunningService { MOUNT_SERVICE = 0; }; + message GenericService { + message ParcelInput { + enum Type { + // Write the 32-bit integer into the send parcel. + I32 = 0; + // Write the 64-bit integer into the send parcel. + I64 = 1; + // Write the UTF-16 string STR into the send parcel. + STRING_16 = 2; + // Write the 32-bit single-precision number into the send parcel. + F = 3; + // Write the 64-bit double-precision number into the send parcel. + D = 4; + // Write a null binder into the send parcel. + NULL = 5; + // Data: File name + // Write a file descriptor for the file with given path into the send + // parcel. + FD_PATH = 6; + // Data: FD number + // Write the file descriptor into the send parcel. + FD = 8; + // Data: File name + // Write an ashmem file descriptor for a region containing the data + // from file the given path into the send parcel. + ASHMEM_FD_PATH = 7; + } + optional Type type = 1; + oneof data_oneof { + string data = 2; + } + } + optional string name = 1; + optional int32 code = 2; + repeated ParcelInput parcel_input = 3; + } oneof service_oneof { string service_name = 1; RunningService running_service = 2; + GenericService generic_service = 3; } } diff --git a/src/binder_request.cpp b/src/binder_request.cpp index d9a31b3..321c926 100644 --- a/src/binder_request.cpp +++ b/src/binder_request.cpp @@ -17,6 +17,9 @@ #include <ditto/binder.h> #include <ditto/binder_request.h> #include <ditto/logger.h> +#include <cutils/ashmem.h> +#include <sys/mman.h> + namespace dittosuite { @@ -70,6 +73,136 @@ void BinderRequestMountService::TearDownSingle(bool last) { Instruction::TearDownSingle(last); } +GenericBinderRequest::GenericBinderRequest(const Params& params, + std::string service_name, int32_t code, + const google::protobuf::RepeatedPtrField + <dittosuiteproto::BinderRequest_GenericService_ParcelInput> parcel_input) + : BinderRequest(kName, params, service_name), parcel_input_(parcel_input), + service_name_(service_name), code_(code) {} + +void GenericBinderRequest::SetUp() { + android::sp<android::IServiceManager> sm = android::defaultServiceManager(); + service_ = sm->checkService(String16(service_name_.c_str(), service_name_.length())); +} + +void GenericBinderRequest::TearDownSingle(bool last) { + Instruction::TearDownSingle(last); +} + +int ParseAshmemWithPath(std::string path, android::Parcel& parcel) { + int fd = open(path.c_str(), O_RDONLY); + struct stat statbuf; + int afd = -1; + void* ptr = MAP_FAILED; + if (fd < 0) { + LOGF("Could not open " + path); + return -1; + } + if (fstat(fd, &statbuf) != 0) { + LOGF("Could not stat " + path); + goto error_close_fd; + } + afd = ashmem_create_region("ditto", statbuf.st_size); + if (afd < 0) { + LOGF("ashmem_create_region failed " + path); + goto error_close_fd; + } + ptr = mmap(NULL, statbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, afd, 0); + if (ptr == MAP_FAILED) { + LOGF("mmap failed " + path); + goto error_close_afd; + } + if (read(fd, ptr, statbuf.st_size) < 0) { + LOGF("read failed " + path); + goto error_unmap; + } + if (parcel.writeFileDescriptor(afd, true /* take ownership */) == android::OK) { + // successfully parsed. unmap and afd close is done by the binder server. + close(fd); + return 0; + } + LOGF("writeFileDescriptor failed " + path); + +error_unmap: + munmap(ptr, statbuf.st_size); +error_close_afd: + close(afd); +error_close_fd: + close(fd); + return -1; +} + +int ParseParcelString(const google::protobuf::RepeatedPtrField + <dittosuiteproto::BinderRequest_GenericService_ParcelInput>& input, + android::Parcel& parcel) { + for (const auto &it : input ) { + std::string data_str = it.data(); + switch (it.type()) { + case dittosuiteproto::BinderRequest_GenericService_ParcelInput_Type_I32: { + parcel.writeInt32(atoi(data_str.c_str())); + break; + } + case dittosuiteproto::BinderRequest_GenericService_ParcelInput_Type_I64: { + parcel.writeInt64(atoll(data_str.c_str())); + break; + } + case dittosuiteproto::BinderRequest_GenericService_ParcelInput_Type_STRING_16: { + parcel.writeString16(String16(data_str.c_str(), data_str.length())); + break; + } + case dittosuiteproto::BinderRequest_GenericService_ParcelInput_Type_F: { + parcel.writeFloat(atof(data_str.c_str())); + break; + } + case dittosuiteproto::BinderRequest_GenericService_ParcelInput_Type_D: { + parcel.writeDouble(atof(data_str.c_str())); + break; + } + case dittosuiteproto::BinderRequest_GenericService_ParcelInput_Type_NULL_: { + parcel.writeStrongBinder(nullptr); + break; + } + case dittosuiteproto::BinderRequest_GenericService_ParcelInput_Type_FD: { + parcel.writeFileDescriptor(atoi(data_str.c_str()), true /* take ownership */); + break; + } + case dittosuiteproto::BinderRequest_GenericService_ParcelInput_Type_FD_PATH: { + int fd = open(data_str.c_str(), O_RDONLY); + if (fd < 0) { + LOGF("Could not open " + data_str); + return -1; + } + parcel.writeFileDescriptor(fd, true /* take ownership */); + break; + } + case dittosuiteproto::BinderRequest_GenericService_ParcelInput_Type_ASHMEM_FD_PATH: { + if (ParseAshmemWithPath(data_str.c_str(), parcel) < 0) { + return -1; + } + break; + } + default: + break; + } + } + return 0; +} + +void GenericBinderRequest::RunSingle() { + android::Parcel data, reply; + data.markForBinder(service_); + data.writeInterfaceToken(service_ ? service_->getInterfaceDescriptor() : String16()); + if (ParseParcelString(parcel_input_, data)) { + LOGF("Error parsing parcel string\n"); + return; + } + + service_->transact(code_, data, &reply); + + std::stringstream ss; + ss << reply; + LOGD("Returned from Binder transact:\n" + ss.str()); +} } // namespace dittosuite #endif diff --git a/src/instruction.cpp b/src/instruction.cpp index 41e0964..8cdd7da 100644 --- a/src/instruction.cpp +++ b/src/instruction.cpp @@ -65,7 +65,7 @@ void Instruction::RunSynchronized(pthread_barrier_t* barrier, const Multithreadi std::thread Instruction::SpawnThread(pthread_barrier_t* barrier, const MultithreadingParams& params) { - return std::thread([=] { RunSynchronized(barrier, params); }); + return std::thread([=, this] { RunSynchronized(barrier, params); }); } void Instruction::TearDown() {} diff --git a/src/instruction_factory.cpp b/src/instruction_factory.cpp index cef9c1b..69c48d0 100644 --- a/src/instruction_factory.cpp +++ b/src/instruction_factory.cpp @@ -258,11 +258,17 @@ std::unique_ptr<Instruction> InstructionFactory::CreateFromProtoInstruction( return std::make_unique<BinderRequestMountService>(instruction_params); break; } + case RequestService::kGenericService: { + const auto& options = proto_instruction.binder_request(); + const auto& generic_service = options.generic_service(); + return std::make_unique<GenericBinderRequest>(instruction_params, generic_service.name(), generic_service.code(), generic_service.parcel_input()); + } case RequestService::SERVICE_ONEOF_NOT_SET: { LOGF("No service specified for BinderRequest"); break; } } + break; } case InstructionType::kBinderService: { const auto& options = proto_instruction.binder_service(); @@ -295,6 +301,7 @@ std::unique_ptr<Instruction> InstructionFactory::CreateFromProtoInstruction( } case InstructionType::INSTRUCTION_ONEOF_NOT_SET: { LOGF("Instruction was not set in .ditto file"); + break; } default: { LOGF("Invalid instruction was set in .ditto file"); |