• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <InternalStatic.h>  // TODO(b/69122224): remove this include, for getOrCreateCachedBinder
22 #include <android/hidl/base/1.0/BpHwBase.h>
23 #include <hwbinder/IPCThreadState.h>
24 
25 // C includes
26 #include <inttypes.h>
27 #include <unistd.h>
28 
29 // C++ includes
30 #include <fstream>
31 #include <sstream>
32 
33 namespace android {
34 namespace hardware {
35 
hidl_binder_death_recipient(const sp<hidl_death_recipient> & recipient,uint64_t cookie,const sp<::android::hidl::base::V1_0::IBase> & base)36 hidl_binder_death_recipient::hidl_binder_death_recipient(const sp<hidl_death_recipient> &recipient,
37         uint64_t cookie, const sp<::android::hidl::base::V1_0::IBase> &base) :
38     mRecipient(recipient), mCookie(cookie), mBase(base) {
39 }
40 
binderDied(const wp<IBinder> &)41 void hidl_binder_death_recipient::binderDied(const wp<IBinder>& /*who*/) {
42     sp<hidl_death_recipient> recipient = mRecipient.promote();
43     if (recipient != nullptr && mBase != nullptr) {
44         recipient->serviceDied(mCookie, mBase);
45     }
46     mBase = nullptr;
47 }
48 
getRecipient()49 wp<hidl_death_recipient> hidl_binder_death_recipient::getRecipient() {
50     return mRecipient;
51 }
52 
53 const size_t hidl_handle::kOffsetOfNativeHandle = offsetof(hidl_handle, mHandle);
54 static_assert(hidl_handle::kOffsetOfNativeHandle == 0, "wrong offset");
55 
readEmbeddedFromParcel(const hidl_handle &,const Parcel & parcel,size_t parentHandle,size_t parentOffset)56 status_t readEmbeddedFromParcel(const hidl_handle& /* handle */,
57         const Parcel &parcel, size_t parentHandle, size_t parentOffset) {
58     const native_handle_t *handle;
59     status_t _hidl_err = parcel.readNullableEmbeddedNativeHandle(
60             parentHandle,
61             parentOffset + hidl_handle::kOffsetOfNativeHandle,
62             &handle);
63 
64     return _hidl_err;
65 }
66 
writeEmbeddedToParcel(const hidl_handle & handle,Parcel * parcel,size_t parentHandle,size_t parentOffset)67 status_t writeEmbeddedToParcel(const hidl_handle &handle,
68         Parcel *parcel, size_t parentHandle, size_t parentOffset) {
69     status_t _hidl_err = parcel->writeEmbeddedNativeHandle(
70             handle.getNativeHandle(),
71             parentHandle,
72             parentOffset + hidl_handle::kOffsetOfNativeHandle);
73 
74     return _hidl_err;
75 }
76 
77 const size_t hidl_memory::kOffsetOfHandle = offsetof(hidl_memory, mHandle);
78 const size_t hidl_memory::kOffsetOfName = offsetof(hidl_memory, mName);
79 static_assert(hidl_memory::kOffsetOfHandle == 0, "wrong offset");
80 static_assert(hidl_memory::kOffsetOfName == 24, "wrong offset");
81 
readEmbeddedFromParcel(const hidl_memory & memory,const Parcel & parcel,size_t parentHandle,size_t parentOffset)82 status_t readEmbeddedFromParcel(const hidl_memory& memory,
83         const Parcel &parcel, size_t parentHandle, size_t parentOffset) {
84     // TODO(b/111883309): Invoke readEmbeddedFromParcel(hidl_handle, ...).
85     const native_handle_t *handle;
86     ::android::status_t _hidl_err = parcel.readNullableEmbeddedNativeHandle(
87             parentHandle,
88             parentOffset + hidl_memory::kOffsetOfHandle,
89             &handle);
90 
91     if (_hidl_err == ::android::OK) {
92         _hidl_err = readEmbeddedFromParcel(
93                 memory.name(),
94                 parcel,
95                 parentHandle,
96                 parentOffset + hidl_memory::kOffsetOfName);
97     }
98 
99     // hidl_memory's size is stored in uint64_t, but mapMemory's mmap will map
100     // size in size_t. If size is over SIZE_MAX, mapMemory could succeed
101     // but the mapped memory's actual size will be smaller than the reported size.
102     if (memory.size() > SIZE_MAX) {
103         ALOGE("Cannot use memory with %" PRId64 " bytes because it is too large.", memory.size());
104         android_errorWriteLog(0x534e4554, "79376389");
105         return BAD_VALUE;
106     }
107 
108     return _hidl_err;
109 }
110 
writeEmbeddedToParcel(const hidl_memory & memory,Parcel * parcel,size_t parentHandle,size_t parentOffset)111 status_t writeEmbeddedToParcel(const hidl_memory &memory,
112         Parcel *parcel, size_t parentHandle, size_t parentOffset) {
113     // TODO(b/111883309): Invoke writeEmbeddedToParcel(hidl_handle, ...).
114     status_t _hidl_err = parcel->writeEmbeddedNativeHandle(
115             memory.handle(),
116             parentHandle,
117             parentOffset + hidl_memory::kOffsetOfHandle);
118 
119     if (_hidl_err == ::android::OK) {
120         _hidl_err = writeEmbeddedToParcel(
121             memory.name(),
122             parcel,
123             parentHandle,
124             parentOffset + hidl_memory::kOffsetOfName);
125     }
126 
127     return _hidl_err;
128 }
129 const size_t hidl_string::kOffsetOfBuffer = offsetof(hidl_string, mBuffer);
130 static_assert(hidl_string::kOffsetOfBuffer == 0, "wrong offset");
131 
readEmbeddedFromParcel(const hidl_string & string,const Parcel & parcel,size_t parentHandle,size_t parentOffset)132 status_t readEmbeddedFromParcel(const hidl_string &string ,
133         const Parcel &parcel, size_t parentHandle, size_t parentOffset) {
134     const void *out;
135 
136     status_t status = parcel.readEmbeddedBuffer(
137             string.size() + 1,
138             nullptr /* buffer_handle */,
139             parentHandle,
140             parentOffset + hidl_string::kOffsetOfBuffer,
141             &out);
142 
143     if (status != OK) {
144         return status;
145     }
146 
147     // Always safe to access out[string.size()] because we read size+1 bytes
148     if (static_cast<const char *>(out)[string.size()] != '\0') {
149         ALOGE("Received unterminated hidl_string buffer.");
150         return BAD_VALUE;
151     }
152 
153     return OK;
154 }
155 
writeEmbeddedToParcel(const hidl_string & string,Parcel * parcel,size_t parentHandle,size_t parentOffset)156 status_t writeEmbeddedToParcel(const hidl_string &string,
157         Parcel *parcel, size_t parentHandle, size_t parentOffset) {
158     return parcel->writeEmbeddedBuffer(
159             string.c_str(),
160             string.size() + 1,
161             nullptr /* handle */,
162             parentHandle,
163             parentOffset + hidl_string::kOffsetOfBuffer);
164 }
165 
writeToParcel(const hidl_version & version,android::hardware::Parcel & parcel)166 android::status_t writeToParcel(const hidl_version &version, android::hardware::Parcel& parcel) {
167     return parcel.writeUint32(static_cast<uint32_t>(version.get_major()) << 16 | version.get_minor());
168 }
169 
readFromParcel(const android::hardware::Parcel & parcel)170 hidl_version* readFromParcel(const android::hardware::Parcel& parcel) {
171     uint32_t version;
172     android::status_t status = parcel.readUint32(&version);
173     if (status != OK) {
174         return nullptr;
175     } else {
176         return new hidl_version(version >> 16, version & 0xFFFF);
177     }
178 }
179 
readFromParcel(Status * s,const Parcel & parcel)180 status_t readFromParcel(Status *s, const Parcel& parcel) {
181     int32_t exception;
182     status_t status = parcel.readInt32(&exception);
183     if (status != OK) {
184         s->setFromStatusT(status);
185         return status;
186     }
187 
188     if (exception == Status::EX_NONE) {
189         *s = Status::ok();
190         return status;
191     }
192 
193     // The remote threw an exception.  Get the message back.
194     String16 message;
195     status = parcel.readString16(&message);
196     if (status != OK) {
197         s->setFromStatusT(status);
198         return status;
199     }
200 
201     s->setException(exception, String8(message));
202 
203     return status;
204 }
205 
writeToParcel(const Status & s,Parcel * parcel)206 status_t writeToParcel(const Status &s, Parcel* parcel) {
207     // Something really bad has happened, and we're not going to even
208     // try returning rich error data.
209     if (s.exceptionCode() == Status::EX_TRANSACTION_FAILED) {
210         return s.transactionError();
211     }
212 
213     status_t status = parcel->writeInt32(s.exceptionCode());
214     if (status != OK) { return status; }
215     if (s.exceptionCode() == Status::EX_NONE) {
216         // We have no more information to write.
217         return status;
218     }
219     status = parcel->writeString16(String16(s.exceptionMessage()));
220     return status;
221 }
222 
getOrCreateCachedBinder(::android::hidl::base::V1_0::IBase * ifacePtr)223 sp<IBinder> getOrCreateCachedBinder(::android::hidl::base::V1_0::IBase* ifacePtr) {
224     if (ifacePtr == nullptr) {
225         return nullptr;
226     }
227 
228     if (ifacePtr->isRemote()) {
229         using ::android::hidl::base::V1_0::BpHwBase;
230 
231         BpHwBase* bpBase = static_cast<BpHwBase*>(ifacePtr);
232         BpHwRefBase* bpRefBase = static_cast<BpHwRefBase*>(bpBase);
233         return sp<IBinder>(bpRefBase->remote());
234     }
235 
236     std::string descriptor = details::getDescriptor(ifacePtr);
237     if (descriptor.empty()) {
238         // interfaceDescriptor fails
239         return nullptr;
240     }
241 
242     // for get + set
243     std::unique_lock<std::mutex> _lock = details::gBnMap->lock();
244 
245     wp<BHwBinder> wBnObj = details::gBnMap->getLocked(ifacePtr, nullptr);
246     sp<IBinder> sBnObj = wBnObj.promote();
247 
248     if (sBnObj == nullptr) {
249         auto func = details::getBnConstructorMap().get(descriptor, nullptr);
250         if (!func) {
251             // TODO(b/69122224): remove this static variable when prebuilts updated
252             func = details::gBnConstructorMap->get(descriptor, nullptr);
253         }
254         LOG_ALWAYS_FATAL_IF(func == nullptr, "%s gBnConstructorMap returned null for %s", __func__,
255                             descriptor.c_str());
256 
257         sBnObj = sp<IBinder>(func(static_cast<void*>(ifacePtr)));
258         LOG_ALWAYS_FATAL_IF(sBnObj == nullptr, "%s Bn constructor function returned null for %s",
259                             __func__, descriptor.c_str());
260 
261         details::gBnMap->setLocked(ifacePtr, static_cast<BHwBinder*>(sBnObj.get()));
262     }
263 
264     return sBnObj;
265 }
266 
267 static bool gThreadPoolConfigured = false;
268 
configureBinderRpcThreadpool(size_t maxThreads,bool callerWillJoin)269 void configureBinderRpcThreadpool(size_t maxThreads, bool callerWillJoin) {
270     status_t ret = ProcessState::self()->setThreadPoolConfiguration(
271         maxThreads, callerWillJoin /*callerJoinsPool*/);
272     LOG_ALWAYS_FATAL_IF(ret != OK, "Could not setThreadPoolConfiguration: %d", ret);
273 
274     gThreadPoolConfigured = true;
275 }
276 
joinBinderRpcThreadpool()277 void joinBinderRpcThreadpool() {
278     LOG_ALWAYS_FATAL_IF(!gThreadPoolConfigured,
279                         "HIDL joinRpcThreadpool without calling configureRpcThreadPool.");
280     IPCThreadState::self()->joinThreadPool();
281 }
282 
setupBinderPolling()283 int setupBinderPolling() {
284     int fd;
285     int err = IPCThreadState::self()->setupPolling(&fd);
286 
287     LOG_ALWAYS_FATAL_IF(err != OK, "Failed to setup binder polling: %d (%s)", err, strerror(err));
288 
289     return err == OK ? fd : -1;
290 }
291 
handleBinderPoll()292 status_t handleBinderPoll() {
293     return IPCThreadState::self()->handlePolledCommands();
294 }
295 
addPostCommandTask(const std::function<void (void)> task)296 void addPostCommandTask(const std::function<void(void)> task) {
297     IPCThreadState::self()->addPostCommandTask(task);
298 }
299 
300 }  // namespace hardware
301 }  // namespace android
302