xref: /aosp_15_r20/test/dittosuite/src/binder_request.cpp (revision 6fa2df46f119dce7527f5beb2814eca0e6f886ac)
1*6fa2df46SAndroid Build Coastguard Worker // Copyright (C) 2023 The Android Open Source Project
2*6fa2df46SAndroid Build Coastguard Worker //
3*6fa2df46SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*6fa2df46SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*6fa2df46SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*6fa2df46SAndroid Build Coastguard Worker //
7*6fa2df46SAndroid Build Coastguard Worker //      http://www.apache.org/licenses/LICENSE-2.0
8*6fa2df46SAndroid Build Coastguard Worker //
9*6fa2df46SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*6fa2df46SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*6fa2df46SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*6fa2df46SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*6fa2df46SAndroid Build Coastguard Worker // limitations under the License.
14*6fa2df46SAndroid Build Coastguard Worker 
15*6fa2df46SAndroid Build Coastguard Worker #if __ANDROID__
16*6fa2df46SAndroid Build Coastguard Worker 
17*6fa2df46SAndroid Build Coastguard Worker #include <ditto/binder.h>
18*6fa2df46SAndroid Build Coastguard Worker #include <ditto/binder_request.h>
19*6fa2df46SAndroid Build Coastguard Worker #include <ditto/logger.h>
20*6fa2df46SAndroid Build Coastguard Worker #include <cutils/ashmem.h>
21*6fa2df46SAndroid Build Coastguard Worker #include <sys/mman.h>
22*6fa2df46SAndroid Build Coastguard Worker 
23*6fa2df46SAndroid Build Coastguard Worker 
24*6fa2df46SAndroid Build Coastguard Worker namespace dittosuite {
25*6fa2df46SAndroid Build Coastguard Worker 
BinderRequest(const std::string & kName,const Params & params,const std::string & service_name)26*6fa2df46SAndroid Build Coastguard Worker BinderRequest::BinderRequest(const std::string& kName, const Params& params,
27*6fa2df46SAndroid Build Coastguard Worker                              const std::string& service_name)
28*6fa2df46SAndroid Build Coastguard Worker     : Instruction(kName, params), service_name_(service_name) {}
29*6fa2df46SAndroid Build Coastguard Worker 
BinderRequestDitto(const Params & params,const std::string & service_name)30*6fa2df46SAndroid Build Coastguard Worker BinderRequestDitto::BinderRequestDitto(const Params& params, const std::string& service_name)
31*6fa2df46SAndroid Build Coastguard Worker     : BinderRequest(kName, params, service_name) {}
32*6fa2df46SAndroid Build Coastguard Worker 
RunSingle()33*6fa2df46SAndroid Build Coastguard Worker void BinderRequestDitto::RunSingle() {
34*6fa2df46SAndroid Build Coastguard Worker   const int8_t c = 1;
35*6fa2df46SAndroid Build Coastguard Worker 
36*6fa2df46SAndroid Build Coastguard Worker   int8_t ret = service_->sync(c);
37*6fa2df46SAndroid Build Coastguard Worker   if (ret != (~c)) {
38*6fa2df46SAndroid Build Coastguard Worker     LOGF("Wrong result, expected: " + std::to_string(~c) + ", but got: " + std::to_string(ret));
39*6fa2df46SAndroid Build Coastguard Worker   }
40*6fa2df46SAndroid Build Coastguard Worker   LOGD("Returned from Binder request: " + std::to_string(ret));
41*6fa2df46SAndroid Build Coastguard Worker }
42*6fa2df46SAndroid Build Coastguard Worker 
SetUp()43*6fa2df46SAndroid Build Coastguard Worker void BinderRequestDitto::SetUp() {
44*6fa2df46SAndroid Build Coastguard Worker   LOGD("Starting binder requester for service: " + service_name_);
45*6fa2df46SAndroid Build Coastguard Worker   service_ = getBinderService<IDittoBinder>(service_name_);
46*6fa2df46SAndroid Build Coastguard Worker   service_->start();
47*6fa2df46SAndroid Build Coastguard Worker   Instruction::SetUp();
48*6fa2df46SAndroid Build Coastguard Worker }
49*6fa2df46SAndroid Build Coastguard Worker 
TearDownSingle(bool is_last)50*6fa2df46SAndroid Build Coastguard Worker void BinderRequestDitto::TearDownSingle(bool is_last) {
51*6fa2df46SAndroid Build Coastguard Worker   Instruction::TearDownSingle(is_last);
52*6fa2df46SAndroid Build Coastguard Worker   if (is_last) {
53*6fa2df46SAndroid Build Coastguard Worker     LOGD("This is the last, sending termination request");
54*6fa2df46SAndroid Build Coastguard Worker     service_->end();
55*6fa2df46SAndroid Build Coastguard Worker   }
56*6fa2df46SAndroid Build Coastguard Worker }
57*6fa2df46SAndroid Build Coastguard Worker 
BinderRequestMountService(const Params & params)58*6fa2df46SAndroid Build Coastguard Worker BinderRequestMountService::BinderRequestMountService(const Params& params)
59*6fa2df46SAndroid Build Coastguard Worker     : BinderRequest(kName, params, "mount") {}
60*6fa2df46SAndroid Build Coastguard Worker 
RunSingle()61*6fa2df46SAndroid Build Coastguard Worker void BinderRequestMountService::RunSingle() {
62*6fa2df46SAndroid Build Coastguard Worker   bool ret = service_->isUsbMassStorageConnected();
63*6fa2df46SAndroid Build Coastguard Worker   LOGD("Returned from Binder request: " + std::to_string(ret));
64*6fa2df46SAndroid Build Coastguard Worker }
65*6fa2df46SAndroid Build Coastguard Worker 
SetUp()66*6fa2df46SAndroid Build Coastguard Worker void BinderRequestMountService::SetUp() {
67*6fa2df46SAndroid Build Coastguard Worker   LOGD("Starting binder requester for service: " + service_name_);
68*6fa2df46SAndroid Build Coastguard Worker   service_ = getBinderService<android::IMountService>(service_name_);
69*6fa2df46SAndroid Build Coastguard Worker   Instruction::SetUp();
70*6fa2df46SAndroid Build Coastguard Worker }
71*6fa2df46SAndroid Build Coastguard Worker 
TearDownSingle(bool last)72*6fa2df46SAndroid Build Coastguard Worker void BinderRequestMountService::TearDownSingle(bool last) {
73*6fa2df46SAndroid Build Coastguard Worker   Instruction::TearDownSingle(last);
74*6fa2df46SAndroid Build Coastguard Worker }
75*6fa2df46SAndroid Build Coastguard Worker 
GenericBinderRequest(const Params & params,std::string service_name,int32_t code,const google::protobuf::RepeatedPtrField<dittosuiteproto::BinderRequest_GenericService_ParcelInput> parcel_input)76*6fa2df46SAndroid Build Coastguard Worker GenericBinderRequest::GenericBinderRequest(const Params& params,
77*6fa2df46SAndroid Build Coastguard Worker     std::string service_name, int32_t code,
78*6fa2df46SAndroid Build Coastguard Worker     const google::protobuf::RepeatedPtrField
79*6fa2df46SAndroid Build Coastguard Worker       <dittosuiteproto::BinderRequest_GenericService_ParcelInput> parcel_input)
80*6fa2df46SAndroid Build Coastguard Worker     : BinderRequest(kName, params, service_name), parcel_input_(parcel_input),
81*6fa2df46SAndroid Build Coastguard Worker      service_name_(service_name), code_(code) {}
82*6fa2df46SAndroid Build Coastguard Worker 
SetUp()83*6fa2df46SAndroid Build Coastguard Worker void GenericBinderRequest::SetUp() {
84*6fa2df46SAndroid Build Coastguard Worker   android::sp<android::IServiceManager> sm = android::defaultServiceManager();
85*6fa2df46SAndroid Build Coastguard Worker   service_ = sm->checkService(String16(service_name_.c_str(), service_name_.length()));
86*6fa2df46SAndroid Build Coastguard Worker }
87*6fa2df46SAndroid Build Coastguard Worker 
TearDownSingle(bool last)88*6fa2df46SAndroid Build Coastguard Worker void GenericBinderRequest::TearDownSingle(bool last) {
89*6fa2df46SAndroid Build Coastguard Worker   Instruction::TearDownSingle(last);
90*6fa2df46SAndroid Build Coastguard Worker }
91*6fa2df46SAndroid Build Coastguard Worker 
ParseAshmemWithPath(std::string path,android::Parcel & parcel)92*6fa2df46SAndroid Build Coastguard Worker int ParseAshmemWithPath(std::string path, android::Parcel& parcel) {
93*6fa2df46SAndroid Build Coastguard Worker   int fd = open(path.c_str(), O_RDONLY);
94*6fa2df46SAndroid Build Coastguard Worker   struct stat statbuf;
95*6fa2df46SAndroid Build Coastguard Worker   int afd = -1;
96*6fa2df46SAndroid Build Coastguard Worker   void* ptr = MAP_FAILED;
97*6fa2df46SAndroid Build Coastguard Worker   if (fd < 0) {
98*6fa2df46SAndroid Build Coastguard Worker     LOGF("Could not open " + path);
99*6fa2df46SAndroid Build Coastguard Worker     return -1;
100*6fa2df46SAndroid Build Coastguard Worker   }
101*6fa2df46SAndroid Build Coastguard Worker   if (fstat(fd, &statbuf) != 0) {
102*6fa2df46SAndroid Build Coastguard Worker     LOGF("Could not stat " + path);
103*6fa2df46SAndroid Build Coastguard Worker     goto error_close_fd;
104*6fa2df46SAndroid Build Coastguard Worker   }
105*6fa2df46SAndroid Build Coastguard Worker   afd = ashmem_create_region("ditto", statbuf.st_size);
106*6fa2df46SAndroid Build Coastguard Worker   if (afd < 0) {
107*6fa2df46SAndroid Build Coastguard Worker     LOGF("ashmem_create_region failed " + path);
108*6fa2df46SAndroid Build Coastguard Worker     goto error_close_fd;
109*6fa2df46SAndroid Build Coastguard Worker   }
110*6fa2df46SAndroid Build Coastguard Worker   ptr = mmap(NULL, statbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, afd, 0);
111*6fa2df46SAndroid Build Coastguard Worker   if (ptr == MAP_FAILED) {
112*6fa2df46SAndroid Build Coastguard Worker     LOGF("mmap failed " + path);
113*6fa2df46SAndroid Build Coastguard Worker     goto error_close_afd;
114*6fa2df46SAndroid Build Coastguard Worker   }
115*6fa2df46SAndroid Build Coastguard Worker   if (read(fd, ptr, statbuf.st_size) < 0) {
116*6fa2df46SAndroid Build Coastguard Worker     LOGF("read failed " + path);
117*6fa2df46SAndroid Build Coastguard Worker     goto error_unmap;
118*6fa2df46SAndroid Build Coastguard Worker   }
119*6fa2df46SAndroid Build Coastguard Worker   if (parcel.writeFileDescriptor(afd, true /* take ownership */) == android::OK) {
120*6fa2df46SAndroid Build Coastguard Worker     // successfully parsed. unmap and afd close is done by the binder server.
121*6fa2df46SAndroid Build Coastguard Worker     close(fd);
122*6fa2df46SAndroid Build Coastguard Worker     return 0;
123*6fa2df46SAndroid Build Coastguard Worker   }
124*6fa2df46SAndroid Build Coastguard Worker   LOGF("writeFileDescriptor failed " + path);
125*6fa2df46SAndroid Build Coastguard Worker 
126*6fa2df46SAndroid Build Coastguard Worker error_unmap:
127*6fa2df46SAndroid Build Coastguard Worker   munmap(ptr, statbuf.st_size);
128*6fa2df46SAndroid Build Coastguard Worker error_close_afd:
129*6fa2df46SAndroid Build Coastguard Worker   close(afd);
130*6fa2df46SAndroid Build Coastguard Worker error_close_fd:
131*6fa2df46SAndroid Build Coastguard Worker   close(fd);
132*6fa2df46SAndroid Build Coastguard Worker   return -1;
133*6fa2df46SAndroid Build Coastguard Worker }
134*6fa2df46SAndroid Build Coastguard Worker 
ParseParcelString(const google::protobuf::RepeatedPtrField<dittosuiteproto::BinderRequest_GenericService_ParcelInput> & input,android::Parcel & parcel)135*6fa2df46SAndroid Build Coastguard Worker int ParseParcelString(const google::protobuf::RepeatedPtrField
136*6fa2df46SAndroid Build Coastguard Worker       <dittosuiteproto::BinderRequest_GenericService_ParcelInput>& input,
137*6fa2df46SAndroid Build Coastguard Worker       android::Parcel& parcel) {
138*6fa2df46SAndroid Build Coastguard Worker   for (const auto &it : input ) {
139*6fa2df46SAndroid Build Coastguard Worker     std::string data_str = it.data();
140*6fa2df46SAndroid Build Coastguard Worker     switch (it.type()) {
141*6fa2df46SAndroid Build Coastguard Worker       case dittosuiteproto::BinderRequest_GenericService_ParcelInput_Type_I32: {
142*6fa2df46SAndroid Build Coastguard Worker         parcel.writeInt32(atoi(data_str.c_str()));
143*6fa2df46SAndroid Build Coastguard Worker         break;
144*6fa2df46SAndroid Build Coastguard Worker       }
145*6fa2df46SAndroid Build Coastguard Worker       case dittosuiteproto::BinderRequest_GenericService_ParcelInput_Type_I64: {
146*6fa2df46SAndroid Build Coastguard Worker         parcel.writeInt64(atoll(data_str.c_str()));
147*6fa2df46SAndroid Build Coastguard Worker         break;
148*6fa2df46SAndroid Build Coastguard Worker       }
149*6fa2df46SAndroid Build Coastguard Worker       case dittosuiteproto::BinderRequest_GenericService_ParcelInput_Type_STRING_16: {
150*6fa2df46SAndroid Build Coastguard Worker         parcel.writeString16(String16(data_str.c_str(), data_str.length()));
151*6fa2df46SAndroid Build Coastguard Worker         break;
152*6fa2df46SAndroid Build Coastguard Worker       }
153*6fa2df46SAndroid Build Coastguard Worker       case dittosuiteproto::BinderRequest_GenericService_ParcelInput_Type_F: {
154*6fa2df46SAndroid Build Coastguard Worker         parcel.writeFloat(atof(data_str.c_str()));
155*6fa2df46SAndroid Build Coastguard Worker         break;
156*6fa2df46SAndroid Build Coastguard Worker       }
157*6fa2df46SAndroid Build Coastguard Worker       case dittosuiteproto::BinderRequest_GenericService_ParcelInput_Type_D: {
158*6fa2df46SAndroid Build Coastguard Worker         parcel.writeDouble(atof(data_str.c_str()));
159*6fa2df46SAndroid Build Coastguard Worker         break;
160*6fa2df46SAndroid Build Coastguard Worker       }
161*6fa2df46SAndroid Build Coastguard Worker       case dittosuiteproto::BinderRequest_GenericService_ParcelInput_Type_NULL_: {
162*6fa2df46SAndroid Build Coastguard Worker         parcel.writeStrongBinder(nullptr);
163*6fa2df46SAndroid Build Coastguard Worker         break;
164*6fa2df46SAndroid Build Coastguard Worker       }
165*6fa2df46SAndroid Build Coastguard Worker       case dittosuiteproto::BinderRequest_GenericService_ParcelInput_Type_FD: {
166*6fa2df46SAndroid Build Coastguard Worker         parcel.writeFileDescriptor(atoi(data_str.c_str()), true /* take ownership */);
167*6fa2df46SAndroid Build Coastguard Worker         break;
168*6fa2df46SAndroid Build Coastguard Worker       }
169*6fa2df46SAndroid Build Coastguard Worker       case dittosuiteproto::BinderRequest_GenericService_ParcelInput_Type_FD_PATH: {
170*6fa2df46SAndroid Build Coastguard Worker         int fd = open(data_str.c_str(), O_RDONLY);
171*6fa2df46SAndroid Build Coastguard Worker         if (fd < 0) {
172*6fa2df46SAndroid Build Coastguard Worker           LOGF("Could not open " + data_str);
173*6fa2df46SAndroid Build Coastguard Worker           return -1;
174*6fa2df46SAndroid Build Coastguard Worker         }
175*6fa2df46SAndroid Build Coastguard Worker         parcel.writeFileDescriptor(fd, true /* take ownership */);
176*6fa2df46SAndroid Build Coastguard Worker         break;
177*6fa2df46SAndroid Build Coastguard Worker       }
178*6fa2df46SAndroid Build Coastguard Worker       case dittosuiteproto::BinderRequest_GenericService_ParcelInput_Type_ASHMEM_FD_PATH: {
179*6fa2df46SAndroid Build Coastguard Worker         if (ParseAshmemWithPath(data_str.c_str(), parcel) < 0) {
180*6fa2df46SAndroid Build Coastguard Worker           return -1;
181*6fa2df46SAndroid Build Coastguard Worker         }
182*6fa2df46SAndroid Build Coastguard Worker         break;
183*6fa2df46SAndroid Build Coastguard Worker       }
184*6fa2df46SAndroid Build Coastguard Worker       case dittosuiteproto::BinderRequest_GenericService_ParcelInput_Type_PARCEL: {
185*6fa2df46SAndroid Build Coastguard Worker         int res = 0;
186*6fa2df46SAndroid Build Coastguard Worker         auto inputs = it.nested_parcel().parcel_inputs();
187*6fa2df46SAndroid Build Coastguard Worker         if (inputs.size() == 0) {
188*6fa2df46SAndroid Build Coastguard Worker           //  Null parcelable flag.
189*6fa2df46SAndroid Build Coastguard Worker           res = parcel.writeInt32(0);
190*6fa2df46SAndroid Build Coastguard Worker         } else {
191*6fa2df46SAndroid Build Coastguard Worker           //  Non-Null parcelable flag.
192*6fa2df46SAndroid Build Coastguard Worker           res = parcel.writeInt32(1);
193*6fa2df46SAndroid Build Coastguard Worker           if (res < 0) return res;
194*6fa2df46SAndroid Build Coastguard Worker           res = ParseParcelString(it.nested_parcel().parcel_inputs(), parcel);
195*6fa2df46SAndroid Build Coastguard Worker         }
196*6fa2df46SAndroid Build Coastguard Worker         if (res < 0) {
197*6fa2df46SAndroid Build Coastguard Worker           return res;
198*6fa2df46SAndroid Build Coastguard Worker         }
199*6fa2df46SAndroid Build Coastguard Worker         break;
200*6fa2df46SAndroid Build Coastguard Worker       }
201*6fa2df46SAndroid Build Coastguard Worker       default:
202*6fa2df46SAndroid Build Coastguard Worker         break;
203*6fa2df46SAndroid Build Coastguard Worker     }
204*6fa2df46SAndroid Build Coastguard Worker   }
205*6fa2df46SAndroid Build Coastguard Worker   return  0;
206*6fa2df46SAndroid Build Coastguard Worker }
207*6fa2df46SAndroid Build Coastguard Worker 
RunSingle()208*6fa2df46SAndroid Build Coastguard Worker void GenericBinderRequest::RunSingle() {
209*6fa2df46SAndroid Build Coastguard Worker   android::Parcel data, reply;
210*6fa2df46SAndroid Build Coastguard Worker   data.markForBinder(service_);
211*6fa2df46SAndroid Build Coastguard Worker   data.writeInterfaceToken(service_ ? service_->getInterfaceDescriptor() : String16());
212*6fa2df46SAndroid Build Coastguard Worker   if (ParseParcelString(parcel_input_, data)) {
213*6fa2df46SAndroid Build Coastguard Worker     LOGF("Error parsing parcel string\n");
214*6fa2df46SAndroid Build Coastguard Worker     return;
215*6fa2df46SAndroid Build Coastguard Worker   }
216*6fa2df46SAndroid Build Coastguard Worker 
217*6fa2df46SAndroid Build Coastguard Worker   service_->transact(code_, data, &reply);
218*6fa2df46SAndroid Build Coastguard Worker 
219*6fa2df46SAndroid Build Coastguard Worker   std::stringstream ss;
220*6fa2df46SAndroid Build Coastguard Worker   ss << reply;
221*6fa2df46SAndroid Build Coastguard Worker   LOGD("Returned from Binder transact:\n" + ss.str());
222*6fa2df46SAndroid Build Coastguard Worker }
223*6fa2df46SAndroid Build Coastguard Worker }  // namespace dittosuite
224*6fa2df46SAndroid Build Coastguard Worker 
225*6fa2df46SAndroid Build Coastguard Worker #endif
226