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