• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "aidl_test_client_file_descriptors.h"
18 
19 #include <iostream>
20 #include <vector>
21 
22  #include <errno.h>
23 #include <string.h>
24 #include <unistd.h>
25 
26 #include <android-base/unique_fd.h>
27 #include <binder/ParcelFileDescriptor.h>
28 
29 // libbase
30 using android::base::unique_fd;
31 
32 // libutils:
33 using android::sp;
34 
35 // libbinder:
36 using android::binder::Status;
37 
38 // generated
39 using android::aidl::tests::ITestService;
40 
41 using android::os::ParcelFileDescriptor;
42 
43 using std::cerr;
44 using std::cout;
45 using std::endl;
46 using std::string;
47 using std::vector;
48 
49 namespace android {
50 namespace aidl {
51 namespace tests {
52 namespace client {
53 
54 #define FdByName(_fd) #_fd, _fd
55 
DoWrite(const string & name,const unique_fd & fd,const string & buf)56 bool DoWrite(const string& name, const unique_fd& fd, const string& buf) {
57   int wrote;
58 
59   while ((wrote = write(fd.get(), buf.data(), buf.size())) < 0 && errno == EINTR);
60 
61   if (wrote == (signed)buf.size()) {
62     return true;
63   }
64 
65   if (wrote < 0) {
66     cerr << "Error writing to file descriptor '" << name << "': "
67         << strerror(errno) << endl;
68   } else {
69     cerr << "File descriptor '" << name << "'accepted short data." << endl;
70   }
71 
72   return false;
73 }
74 
DoRead(const string & name,const unique_fd & fd,const string & expected)75 bool DoRead(const string& name, const unique_fd& fd, const string& expected) {
76   size_t length = expected.size();
77   int got;
78   string buf;
79   buf.resize(length);
80 
81   while ((got = read(fd.get(), &buf[0], length)) < 0 && errno == EINTR);
82 
83   if (got < 0) {
84     cerr << "Error reading from '" << name << "': " << strerror(errno) << endl;
85     return false;
86   }
87 
88   if (buf != expected) {
89     cerr << "Expected '" << expected << "' got '" << buf << "'" << endl;
90     return false;
91   }
92 
93   return true;
94 }
95 
DoPipe(unique_fd * read_side,unique_fd * write_side)96 bool DoPipe(unique_fd* read_side, unique_fd* write_side) {
97   int fds[2];
98   unique_fd return_fd;
99 
100   if (pipe(fds)) {
101     cout << "Error creating pipes: " << strerror(errno) << endl;
102     return false;
103   }
104 
105   read_side->reset(fds[0]);
106   write_side->reset(fds[1]);
107   return true;
108 }
109 
ConfirmFileDescriptors(const sp<ITestService> & s)110 bool ConfirmFileDescriptors(const sp<ITestService>& s) {
111   Status status;
112   cout << "Confirming passing and returning file descriptors works." << endl;
113 
114   unique_fd return_fd;
115   unique_fd read_fd;
116   unique_fd write_fd;
117 
118   if (!DoPipe(&read_fd, &write_fd)) {
119     return false;
120   }
121 
122   status = s->RepeatFileDescriptor(std::move(write_fd), &return_fd);
123 
124   if (!status.isOk()) {
125     cerr << "Could not repeat file descriptors." << endl;
126     return false;
127   }
128 
129   /* A note on some of the spookier stuff going on here: IIUC writes to pipes
130    * should be atomic and non-blocking so long as the total size doesn't exceed
131    * PIPE_BUF. We thus play a bit fast and loose with failure modes here.
132    */
133 
134   bool ret =
135       DoWrite(FdByName(return_fd), "ReturnString") &&
136       DoRead(FdByName(read_fd), "ReturnString");
137 
138   return ret;
139 }
140 
ConfirmFileDescriptorArrays(const sp<ITestService> & s)141 bool ConfirmFileDescriptorArrays(const sp<ITestService>& s) {
142   Status status;
143   cout << "Confirming passing and returning file descriptor arrays works." << endl;
144 
145   vector<unique_fd> array;
146   array.resize(2);
147 
148   if (!DoPipe(&array[0], &array[1])) {
149     return false;
150   }
151 
152   vector<unique_fd> repeated;
153   vector<unique_fd> reversed;
154 
155   status = s->ReverseFileDescriptorArray(array, &repeated, &reversed);
156 
157   if (!status.isOk()) {
158     cerr << "Could not reverse file descriptor array." << endl;
159     return false;
160   }
161 
162   bool ret =
163       DoWrite(FdByName(array[1]), "First") &&
164       DoWrite(FdByName(repeated[1]), "Second") &&
165       DoWrite(FdByName(reversed[0]), "Third") &&
166       DoRead(FdByName(reversed[1]), "FirstSecondThird");
167 
168   return ret;
169 }
170 
ConfirmParcelFileDescriptors(const sp<ITestService> & s)171 bool ConfirmParcelFileDescriptors(const sp<ITestService>& s) {
172   Status status;
173   cout << "Confirming passing and returning parcel file descriptors works." << endl;
174 
175   unique_fd read_fd;
176   unique_fd write_fd;
177 
178   if (!DoPipe(&read_fd, &write_fd)) {
179     return false;
180   }
181 
182   ParcelFileDescriptor return_fd;
183 
184   status = s->RepeatParcelFileDescriptor(ParcelFileDescriptor(std::move(write_fd)), &return_fd);
185 
186   if (!status.isOk()) {
187     cerr << "Could not repeat parcel file descriptors." << endl;
188     return false;
189   }
190 
191   /* A note on some of the spookier stuff going on here: IIUC writes to pipes
192    * should be atomic and non-blocking so long as the total size doesn't exceed
193    * PIPE_BUF. We thus play a bit fast and loose with failure modes here.
194    */
195 
196   bool ret = DoWrite(FdByName(return_fd.release()), "ReturnString") &&
197              DoRead(FdByName(read_fd), "ReturnString");
198 
199   return ret;
200 }
201 
ConfirmParcelFileDescriptorArrays(const sp<ITestService> & s)202 bool ConfirmParcelFileDescriptorArrays(const sp<ITestService>& s) {
203   Status status;
204   cout << "Confirming passing and returning parcel file descriptor arrays works." << endl;
205 
206   vector<unique_fd> array;
207   array.resize(2);
208 
209   if (!DoPipe(&array[0], &array[1])) {
210     return false;
211   }
212 
213   vector<ParcelFileDescriptor> input;
214   for (auto& fd : array) {
215     input.push_back(ParcelFileDescriptor(std::move(fd)));
216   }
217 
218   vector<ParcelFileDescriptor> repeated;
219   vector<ParcelFileDescriptor> reversed;
220 
221   status = s->ReverseParcelFileDescriptorArray(input, &repeated, &reversed);
222 
223   if (!status.isOk()) {
224     cerr << "Could not reverse file descriptor array." << endl;
225     return false;
226   }
227 
228   bool ret = DoWrite(FdByName(input[1].release()), "First") &&
229              DoWrite(FdByName(repeated[1].release()), "Second") &&
230              DoWrite(FdByName(reversed[0].release()), "Third") &&
231              DoRead(FdByName(input[0].release()), "FirstSecondThird");
232 
233   return ret;
234 }
235 
236 }  // namespace client
237 }  // namespace tests
238 }  // namespace aidl
239 }  // namespace android
240