blob: cd05c3da7c0892fc5e6de740d27a9a54f34c0a55 [file] [log] [blame]
Yifan Hong7f97f442016-11-14 18:31:05 -08001/*
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
Steven Moreland9cbef742018-06-26 16:23:50 -070021#include <InternalStatic.h> // TODO(b/69122224): remove this include, for getOrCreateCachedBinder
22
Yifan Hong777bef92017-02-01 15:50:36 -080023// C includes
24#include <unistd.h>
25
26// C++ includes
27#include <fstream>
28#include <sstream>
29
Yifan Hong7f97f442016-11-14 18:31:05 -080030namespace android {
31namespace hardware {
32
Steven Moreland108d09d2017-05-05 16:15:38 -070033hidl_binder_death_recipient::hidl_binder_death_recipient(const sp<hidl_death_recipient> &recipient,
34 uint64_t cookie, const sp<::android::hidl::base::V1_0::IBase> &base) :
35 mRecipient(recipient), mCookie(cookie), mBase(base) {
36}
37
38void hidl_binder_death_recipient::binderDied(const wp<IBinder>& /*who*/) {
39 sp<hidl_death_recipient> recipient = mRecipient.promote();
Martijn Coenen25508802017-07-05 12:21:00 +020040 if (recipient != nullptr && mBase != nullptr) {
Steven Moreland108d09d2017-05-05 16:15:38 -070041 recipient->serviceDied(mCookie, mBase);
42 }
Martijn Coenen25508802017-07-05 12:21:00 +020043 mBase = nullptr;
Steven Moreland108d09d2017-05-05 16:15:38 -070044}
45
46wp<hidl_death_recipient> hidl_binder_death_recipient::getRecipient() {
47 return mRecipient;
48}
49
Nirav Atre564a8d22018-07-26 18:29:12 -070050const size_t hidl_handle::kOffsetOfNativeHandle = offsetof(hidl_handle, mHandle);
51static_assert(hidl_handle::kOffsetOfNativeHandle == 0, "wrong offset");
52
53status_t readEmbeddedFromParcel(const hidl_handle& /* handle */,
54 const Parcel &parcel, size_t parentHandle, size_t parentOffset) {
55 const native_handle_t *handle;
56 status_t _hidl_err = parcel.readNullableEmbeddedNativeHandle(
57 parentHandle,
58 parentOffset + hidl_handle::kOffsetOfNativeHandle,
59 &handle);
60
61 return _hidl_err;
62}
63
64status_t writeEmbeddedToParcel(const hidl_handle &handle,
65 Parcel *parcel, size_t parentHandle, size_t parentOffset) {
66 status_t _hidl_err = parcel->writeEmbeddedNativeHandle(
67 handle.getNativeHandle(),
68 parentHandle,
69 parentOffset + hidl_handle::kOffsetOfNativeHandle);
70
71 return _hidl_err;
72}
73
Martijn Coenen30791002016-12-01 15:40:46 +010074const size_t hidl_memory::kOffsetOfHandle = offsetof(hidl_memory, mHandle);
75const size_t hidl_memory::kOffsetOfName = offsetof(hidl_memory, mName);
Hridya Valsaraju6d4acb12017-03-03 14:24:43 -080076static_assert(hidl_memory::kOffsetOfHandle == 0, "wrong offset");
77static_assert(hidl_memory::kOffsetOfName == 24, "wrong offset");
Martijn Coenen30791002016-12-01 15:40:46 +010078
Martijn Coenen9d3eb352017-04-18 20:28:03 -070079status_t readEmbeddedFromParcel(const hidl_memory& memory,
Martijn Coenen30791002016-12-01 15:40:46 +010080 const Parcel &parcel, size_t parentHandle, size_t parentOffset) {
Nirav Atre564a8d22018-07-26 18:29:12 -070081 // TODO(b/111883309): Invoke readEmbeddedFromParcel(hidl_handle, ...).
Steven Moreland1f535a22017-01-06 19:25:49 -080082 const native_handle_t *handle;
83 ::android::status_t _hidl_err = parcel.readNullableEmbeddedNativeHandle(
Martijn Coenen30791002016-12-01 15:40:46 +010084 parentHandle,
Steven Moreland1f535a22017-01-06 19:25:49 -080085 parentOffset + hidl_memory::kOffsetOfHandle,
86 &handle);
Martijn Coenen30791002016-12-01 15:40:46 +010087
Steven Moreland1f535a22017-01-06 19:25:49 -080088 if (_hidl_err == ::android::OK) {
89 _hidl_err = readEmbeddedFromParcel(
Martijn Coenen9d3eb352017-04-18 20:28:03 -070090 memory.name(),
Steven Moreland1f535a22017-01-06 19:25:49 -080091 parcel,
92 parentHandle,
93 parentOffset + hidl_memory::kOffsetOfName);
Martijn Coenen30791002016-12-01 15:40:46 +010094 }
95
Martijn Coenen30791002016-12-01 15:40:46 +010096 return _hidl_err;
97}
98
99status_t writeEmbeddedToParcel(const hidl_memory &memory,
100 Parcel *parcel, size_t parentHandle, size_t parentOffset) {
Nirav Atre564a8d22018-07-26 18:29:12 -0700101 // TODO(b/111883309): Invoke writeEmbeddedToParcel(hidl_handle, ...).
Martijn Coenen30791002016-12-01 15:40:46 +0100102 status_t _hidl_err = parcel->writeEmbeddedNativeHandle(
103 memory.handle(),
104 parentHandle,
105 parentOffset + hidl_memory::kOffsetOfHandle);
106
107 if (_hidl_err == ::android::OK) {
108 _hidl_err = writeEmbeddedToParcel(
109 memory.name(),
110 parcel,
111 parentHandle,
112 parentOffset + hidl_memory::kOffsetOfName);
113 }
114
115 return _hidl_err;
116}
Yifan Hong7f97f442016-11-14 18:31:05 -0800117const size_t hidl_string::kOffsetOfBuffer = offsetof(hidl_string, mBuffer);
Hridya Valsaraju6d4acb12017-03-03 14:24:43 -0800118static_assert(hidl_string::kOffsetOfBuffer == 0, "wrong offset");
Yifan Hong7f97f442016-11-14 18:31:05 -0800119
Martijn Coenen9d3eb352017-04-18 20:28:03 -0700120status_t readEmbeddedFromParcel(const hidl_string &string ,
Yifan Hong7f97f442016-11-14 18:31:05 -0800121 const Parcel &parcel, size_t parentHandle, size_t parentOffset) {
Steven Moreland1f535a22017-01-06 19:25:49 -0800122 const void *out;
Martijn Coenen9d3eb352017-04-18 20:28:03 -0700123
124 status_t status = parcel.readEmbeddedBuffer(
125 string.size() + 1,
Yifan Hong7f97f442016-11-14 18:31:05 -0800126 nullptr /* buffer_handle */,
127 parentHandle,
Steven Moreland1f535a22017-01-06 19:25:49 -0800128 parentOffset + hidl_string::kOffsetOfBuffer,
129 &out);
Martijn Coenen9d3eb352017-04-18 20:28:03 -0700130
131 if (status != OK) {
132 return status;
133 }
134
135 // Always safe to access out[string.size()] because we read size+1 bytes
136 if (static_cast<const char *>(out)[string.size()] != '\0') {
137 ALOGE("Received unterminated hidl_string buffer.");
138 return BAD_VALUE;
139 }
140
141 return OK;
Yifan Hong7f97f442016-11-14 18:31:05 -0800142}
143
144status_t writeEmbeddedToParcel(const hidl_string &string,
145 Parcel *parcel, size_t parentHandle, size_t parentOffset) {
146 return parcel->writeEmbeddedBuffer(
147 string.c_str(),
148 string.size() + 1,
149 nullptr /* handle */,
150 parentHandle,
151 parentOffset + hidl_string::kOffsetOfBuffer);
152}
153
154android::status_t writeToParcel(const hidl_version &version, android::hardware::Parcel& parcel) {
155 return parcel.writeUint32(static_cast<uint32_t>(version.get_major()) << 16 | version.get_minor());
156}
157
158hidl_version* readFromParcel(const android::hardware::Parcel& parcel) {
159 uint32_t version;
160 android::status_t status = parcel.readUint32(&version);
161 if (status != OK) {
162 return nullptr;
163 } else {
164 return new hidl_version(version >> 16, version & 0xFFFF);
165 }
166}
167
168status_t readFromParcel(Status *s, const Parcel& parcel) {
169 int32_t exception;
Yifan Hong7f97f442016-11-14 18:31:05 -0800170 status_t status = parcel.readInt32(&exception);
171 if (status != OK) {
172 s->setFromStatusT(status);
173 return status;
174 }
175
176 // Skip over fat response headers. Not used (or propagated) in native code.
177 if (exception == Status::EX_HAS_REPLY_HEADER) {
178 // Note that the header size includes the 4 byte size field.
179 const int32_t header_start = parcel.dataPosition();
180 int32_t header_size;
181 status = parcel.readInt32(&header_size);
182 if (status != OK) {
183 s->setFromStatusT(status);
184 return status;
185 }
186 parcel.setDataPosition(header_start + header_size);
187 // And fat response headers are currently only used when there are no
188 // exceptions, so act like there was no error.
189 exception = Status::EX_NONE;
190 }
191
192 if (exception == Status::EX_NONE) {
193 *s = Status::ok();
194 return status;
195 }
196
197 // The remote threw an exception. Get the message back.
198 String16 message;
199 status = parcel.readString16(&message);
200 if (status != OK) {
201 s->setFromStatusT(status);
202 return status;
203 }
204
Steven Moreland72db40f2017-03-09 18:15:27 -0800205 s->setException(exception, String8(message));
Yifan Hong7f97f442016-11-14 18:31:05 -0800206
207 return status;
208}
209
210status_t writeToParcel(const Status &s, Parcel* parcel) {
211 // Something really bad has happened, and we're not going to even
212 // try returning rich error data.
213 if (s.exceptionCode() == Status::EX_TRANSACTION_FAILED) {
214 return s.transactionError();
215 }
216
217 status_t status = parcel->writeInt32(s.exceptionCode());
218 if (status != OK) { return status; }
219 if (s.exceptionCode() == Status::EX_NONE) {
220 // We have no more information to write.
221 return status;
222 }
223 status = parcel->writeString16(String16(s.exceptionMessage()));
Yifan Hong7f97f442016-11-14 18:31:05 -0800224 return status;
225}
226
Steven Moreland9cbef742018-06-26 16:23:50 -0700227sp<IBinder> getOrCreateCachedBinder(::android::hidl::base::V1_0::IBase* ifacePtr) {
Steven Moreland9fd33872018-06-26 18:14:22 -0700228 LOG_ALWAYS_FATAL_IF(ifacePtr->isRemote(), "%s does not have a way to construct remote binders",
229 __func__);
Steven Moreland9cbef742018-06-26 16:23:50 -0700230
231 std::string descriptor = details::getDescriptor(ifacePtr);
232 if (descriptor.empty()) {
233 // interfaceDescriptor fails
234 return nullptr;
235 }
236
237 // for get + set
238 std::unique_lock<std::mutex> _lock = details::gBnMap.lock();
239
240 wp<BHwBinder> wBnObj = details::gBnMap.getLocked(ifacePtr, nullptr);
241 sp<IBinder> sBnObj = wBnObj.promote();
242
243 if (sBnObj == nullptr) {
244 auto func = details::getBnConstructorMap().get(descriptor, nullptr);
245 if (!func) {
246 // TODO(b/69122224): remove this static variable when prebuilts updated
247 func = details::gBnConstructorMap.get(descriptor, nullptr);
Steven Moreland9cbef742018-06-26 16:23:50 -0700248 }
Steven Moreland9fd33872018-06-26 18:14:22 -0700249 LOG_ALWAYS_FATAL_IF(func == nullptr, "%s gBnConstructorMap returned null for %s", __func__,
250 descriptor.c_str());
Steven Moreland9cbef742018-06-26 16:23:50 -0700251
252 sBnObj = sp<IBinder>(func(static_cast<void*>(ifacePtr)));
Steven Moreland9fd33872018-06-26 18:14:22 -0700253 LOG_ALWAYS_FATAL_IF(sBnObj == nullptr, "%s Bn constructor function returned null for %s",
254 __func__, descriptor.c_str());
Steven Moreland9cbef742018-06-26 16:23:50 -0700255
Steven Moreland9fd33872018-06-26 18:14:22 -0700256 details::gBnMap.setLocked(ifacePtr, static_cast<BHwBinder*>(sBnObj.get()));
Steven Moreland9cbef742018-06-26 16:23:50 -0700257 }
258
259 return sBnObj;
260}
261
Steven Moreland50815be2018-05-24 12:35:44 -0700262static bool gThreadPoolConfigured = false;
263
Steven Moreland6cf8fa22017-02-21 13:38:17 -0800264void configureBinderRpcThreadpool(size_t maxThreads, bool callerWillJoin) {
Steven Moreland50815be2018-05-24 12:35:44 -0700265 status_t ret = ProcessState::self()->setThreadPoolConfiguration(
266 maxThreads, callerWillJoin /*callerJoinsPool*/);
267 LOG_ALWAYS_FATAL_IF(ret != OK, "Could not setThreadPoolConfiguration: %d", ret);
268
269 gThreadPoolConfigured = true;
Steven Moreland6cf8fa22017-02-21 13:38:17 -0800270}
271
272void joinBinderRpcThreadpool() {
Steven Morelandcd329a82018-05-29 13:30:11 -0700273 LOG_ALWAYS_FATAL_IF(!gThreadPoolConfigured,
274 "HIDL joinRpcThreadpool without calling configureRpcThreadPool.");
Steven Moreland6cf8fa22017-02-21 13:38:17 -0800275 IPCThreadState::self()->joinThreadPool();
276}
277
Martijn Coenen3f5ac4c2017-11-27 15:09:28 -0800278int setupBinderPolling() {
279 int fd;
280 int err = IPCThreadState::self()->setupPolling(&fd);
281
Steven Morelandcd329a82018-05-29 13:30:11 -0700282 LOG_ALWAYS_FATAL_IF(err != OK, "Failed to setup binder polling: %d (%s)", err, strerror(err));
Martijn Coenen3f5ac4c2017-11-27 15:09:28 -0800283
284 return err == OK ? fd : -1;
285}
286
287status_t handleBinderPoll() {
288 return IPCThreadState::self()->handlePolledCommands();
289}
290
Steven Morelandd40af8e2018-05-01 16:33:21 -0700291void addPostCommandTask(const std::function<void(void)> task) {
292 IPCThreadState::self()->addPostCommandTask(task);
293}
294
Yifan Hong7f97f442016-11-14 18:31:05 -0800295} // namespace hardware
296} // namespace android