1 /* 2 * Copyright (C) 2016 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 #define LOG_TAG "HidlSupport" 18 19 #include <hidl/HidlBinderSupport.h> 20 21 // C includes 22 #include <unistd.h> 23 24 // C++ includes 25 #include <fstream> 26 #include <sstream> 27 28 namespace android { 29 namespace hardware { 30 31 const size_t hidl_memory::kOffsetOfHandle = offsetof(hidl_memory, mHandle); 32 const size_t hidl_memory::kOffsetOfName = offsetof(hidl_memory, mName); 33 static_assert(hidl_memory::kOffsetOfHandle == 0, "wrong offset"); 34 static_assert(hidl_memory::kOffsetOfName == 24, "wrong offset"); 35 36 status_t readEmbeddedFromParcel(const hidl_memory& memory, 37 const Parcel &parcel, size_t parentHandle, size_t parentOffset) { 38 const native_handle_t *handle; 39 ::android::status_t _hidl_err = parcel.readNullableEmbeddedNativeHandle( 40 parentHandle, 41 parentOffset + hidl_memory::kOffsetOfHandle, 42 &handle); 43 44 if (_hidl_err == ::android::OK) { 45 _hidl_err = readEmbeddedFromParcel( 46 memory.name(), 47 parcel, 48 parentHandle, 49 parentOffset + hidl_memory::kOffsetOfName); 50 } 51 52 return _hidl_err; 53 } 54 55 status_t writeEmbeddedToParcel(const hidl_memory &memory, 56 Parcel *parcel, size_t parentHandle, size_t parentOffset) { 57 status_t _hidl_err = parcel->writeEmbeddedNativeHandle( 58 memory.handle(), 59 parentHandle, 60 parentOffset + hidl_memory::kOffsetOfHandle); 61 62 if (_hidl_err == ::android::OK) { 63 _hidl_err = writeEmbeddedToParcel( 64 memory.name(), 65 parcel, 66 parentHandle, 67 parentOffset + hidl_memory::kOffsetOfName); 68 } 69 70 return _hidl_err; 71 } 72 // static 73 const size_t hidl_string::kOffsetOfBuffer = offsetof(hidl_string, mBuffer); 74 static_assert(hidl_string::kOffsetOfBuffer == 0, "wrong offset"); 75 76 status_t readEmbeddedFromParcel(const hidl_string &string , 77 const Parcel &parcel, size_t parentHandle, size_t parentOffset) { 78 const void *out; 79 80 status_t status = parcel.readEmbeddedBuffer( 81 string.size() + 1, 82 nullptr /* buffer_handle */, 83 parentHandle, 84 parentOffset + hidl_string::kOffsetOfBuffer, 85 &out); 86 87 if (status != OK) { 88 return status; 89 } 90 91 // Always safe to access out[string.size()] because we read size+1 bytes 92 if (static_cast<const char *>(out)[string.size()] != '\0') { 93 ALOGE("Received unterminated hidl_string buffer."); 94 return BAD_VALUE; 95 } 96 97 return OK; 98 } 99 100 status_t writeEmbeddedToParcel(const hidl_string &string, 101 Parcel *parcel, size_t parentHandle, size_t parentOffset) { 102 return parcel->writeEmbeddedBuffer( 103 string.c_str(), 104 string.size() + 1, 105 nullptr /* handle */, 106 parentHandle, 107 parentOffset + hidl_string::kOffsetOfBuffer); 108 } 109 110 android::status_t writeToParcel(const hidl_version &version, android::hardware::Parcel& parcel) { 111 return parcel.writeUint32(static_cast<uint32_t>(version.get_major()) << 16 | version.get_minor()); 112 } 113 114 hidl_version* readFromParcel(const android::hardware::Parcel& parcel) { 115 uint32_t version; 116 android::status_t status = parcel.readUint32(&version); 117 if (status != OK) { 118 return nullptr; 119 } else { 120 return new hidl_version(version >> 16, version & 0xFFFF); 121 } 122 } 123 124 status_t readFromParcel(Status *s, const Parcel& parcel) { 125 int32_t exception; 126 status_t status = parcel.readInt32(&exception); 127 if (status != OK) { 128 s->setFromStatusT(status); 129 return status; 130 } 131 132 // Skip over fat response headers. Not used (or propagated) in native code. 133 if (exception == Status::EX_HAS_REPLY_HEADER) { 134 // Note that the header size includes the 4 byte size field. 135 const int32_t header_start = parcel.dataPosition(); 136 int32_t header_size; 137 status = parcel.readInt32(&header_size); 138 if (status != OK) { 139 s->setFromStatusT(status); 140 return status; 141 } 142 parcel.setDataPosition(header_start + header_size); 143 // And fat response headers are currently only used when there are no 144 // exceptions, so act like there was no error. 145 exception = Status::EX_NONE; 146 } 147 148 if (exception == Status::EX_NONE) { 149 *s = Status::ok(); 150 return status; 151 } 152 153 // The remote threw an exception. Get the message back. 154 String16 message; 155 status = parcel.readString16(&message); 156 if (status != OK) { 157 s->setFromStatusT(status); 158 return status; 159 } 160 161 s->setException(exception, String8(message)); 162 163 return status; 164 } 165 166 status_t writeToParcel(const Status &s, Parcel* parcel) { 167 // Something really bad has happened, and we're not going to even 168 // try returning rich error data. 169 if (s.exceptionCode() == Status::EX_TRANSACTION_FAILED) { 170 return s.transactionError(); 171 } 172 173 status_t status = parcel->writeInt32(s.exceptionCode()); 174 if (status != OK) { return status; } 175 if (s.exceptionCode() == Status::EX_NONE) { 176 // We have no more information to write. 177 return status; 178 } 179 status = parcel->writeString16(String16(s.exceptionMessage())); 180 return status; 181 } 182 183 void configureBinderRpcThreadpool(size_t maxThreads, bool callerWillJoin) { 184 ProcessState::self()->setThreadPoolConfiguration(maxThreads, callerWillJoin /*callerJoinsPool*/); 185 } 186 187 void joinBinderRpcThreadpool() { 188 IPCThreadState::self()->joinThreadPool(); 189 } 190 191 } // namespace hardware 192 } // namespace android 193