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