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 28 // libbase 29 using android::base::unique_fd; 30 31 // libutils: 32 using android::sp; 33 34 // libbinder: 35 using android::binder::Status; 36 37 // generated 38 using android::aidl::tests::ITestService; 39 40 using std::cerr; 41 using std::cout; 42 using std::endl; 43 using std::string; 44 using std::vector; 45 46 namespace android { 47 namespace aidl { 48 namespace tests { 49 namespace client { 50 51 #define FdByName(_fd) #_fd, _fd 52 53 bool DoWrite(const string& name, const unique_fd& fd, const string& buf) { 54 int wrote; 55 56 while ((wrote = write(fd.get(), buf.data(), buf.size())) < 0 && errno == EINTR); 57 58 if (wrote == (signed)buf.size()) { 59 return true; 60 } 61 62 if (wrote < 0) { 63 cerr << "Error writing to file descriptor '" << name << "': " 64 << strerror(errno) << endl; 65 } else { 66 cerr << "File descriptor '" << name << "'accepted short data." << endl; 67 } 68 69 return false; 70 } 71 72 bool DoRead(const string& name, const unique_fd& fd, const string& expected) { 73 size_t length = expected.size(); 74 int got; 75 string buf; 76 buf.resize(length); 77 78 while ((got = read(fd.get(), &buf[0], length)) < 0 && errno == EINTR); 79 80 if (got < 0) { 81 cerr << "Error reading from '" << name << "': " << strerror(errno) << endl; 82 return false; 83 } 84 85 if (buf != expected) { 86 cerr << "Expected '" << expected << "' got '" << buf << "'" << endl; 87 return false; 88 } 89 90 return true; 91 } 92 93 bool DoPipe(unique_fd* read_side, unique_fd* write_side) { 94 int fds[2]; 95 unique_fd return_fd; 96 97 if (pipe(fds)) { 98 cout << "Error creating pipes: " << strerror(errno) << endl; 99 return false; 100 } 101 102 read_side->reset(fds[0]); 103 write_side->reset(fds[1]); 104 return true; 105 } 106 107 bool ConfirmFileDescriptors(const sp<ITestService>& s) { 108 Status status; 109 cout << "Confirming passing and returning file descriptors works." << endl; 110 111 unique_fd return_fd; 112 unique_fd read_fd; 113 unique_fd write_fd; 114 115 if (!DoPipe(&read_fd, &write_fd)) { 116 return false; 117 } 118 119 status = s->RepeatFileDescriptor(write_fd, &return_fd); 120 121 if (!status.isOk()) { 122 cerr << "Could not repeat file descriptors." << endl; 123 return false; 124 } 125 126 /* A note on some of the spookier stuff going on here: IIUC writes to pipes 127 * should be atomic and non-blocking so long as the total size doesn't exceed 128 * PIPE_BUF. We thus play a bit fast and loose with failure modes here. 129 */ 130 131 bool ret = 132 DoWrite(FdByName(return_fd), "ReturnString") && 133 DoRead(FdByName(read_fd), "ReturnString"); 134 135 return ret; 136 } 137 138 bool ConfirmFileDescriptorArrays(const sp<ITestService>& s) { 139 Status status; 140 cout << "Confirming passing and returning file descriptor arrays works." << endl; 141 142 vector<unique_fd> array; 143 array.resize(2); 144 145 if (!DoPipe(&array[0], &array[1])) { 146 return false; 147 } 148 149 vector<unique_fd> repeated; 150 vector<unique_fd> reversed; 151 152 status = s->ReverseFileDescriptorArray(array, &repeated, &reversed); 153 154 if (!status.isOk()) { 155 cerr << "Could not reverse file descriptor array." << endl; 156 return false; 157 } 158 159 bool ret = 160 DoWrite(FdByName(array[1]), "First") && 161 DoWrite(FdByName(repeated[1]), "Second") && 162 DoWrite(FdByName(reversed[0]), "Third") && 163 DoRead(FdByName(reversed[1]), "FirstSecondThird"); 164 165 return ret; 166 } 167 168 } // namespace client 169 } // namespace tests 170 } // namespace aidl 171 } // namespace android 172