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 #define LOG_TAG "HidlSupport"
17 
18 #include <hidl/HidlSupport.h>
19 
20 #include <unordered_map>
21 
22 #include <android-base/logging.h>
23 #include <android-base/parseint.h>
24 
25 namespace android {
26 namespace hardware {
27 
28 namespace details {
29 bool debuggable() {
30 #ifdef LIBHIDL_TARGET_DEBUGGABLE
31     return true;
32 #else
33     return false;
34 #endif
35 }
36 }  // namespace details
37 
38 hidl_handle::hidl_handle() : mHandle(nullptr), mOwnsHandle(false) {
39     memset(mPad, 0, sizeof(mPad));
40 }
41 
42 hidl_handle::~hidl_handle() {
43     freeHandle();
44 }
45 
46 hidl_handle::hidl_handle(const native_handle_t* handle) : hidl_handle() {
47     mHandle = handle;
48     mOwnsHandle = false;
49 }
50 
51 // copy constructor.
52 hidl_handle::hidl_handle(const hidl_handle& other) : hidl_handle() {
53     mOwnsHandle = false;
54     *this = other;
55 }
56 
57 // move constructor.
58 hidl_handle::hidl_handle(hidl_handle&& other) noexcept : hidl_handle() {
59     mOwnsHandle = false;
60     *this = std::move(other);
61 }
62 
63 // assignment operators
64 hidl_handle &hidl_handle::operator=(const hidl_handle &other) {
65     if (this == &other) {
66         return *this;
67     }
68     freeHandle();
69     if (other.mHandle != nullptr) {
70         mHandle = native_handle_clone(other.mHandle);
71         if (mHandle == nullptr) {
72             PLOG(FATAL) << "Failed to clone native_handle in hidl_handle";
73         }
74         mOwnsHandle = true;
75     } else {
76         mHandle = nullptr;
77         mOwnsHandle = false;
78     }
79     return *this;
80 }
81 
82 hidl_handle &hidl_handle::operator=(const native_handle_t *native_handle) {
83     freeHandle();
84     mHandle = native_handle;
85     mOwnsHandle = false;
86     return *this;
87 }
88 
89 hidl_handle& hidl_handle::operator=(hidl_handle&& other) noexcept {
90     if (this != &other) {
91         freeHandle();
92         mHandle = other.mHandle;
93         mOwnsHandle = other.mOwnsHandle;
94         other.mHandle = nullptr;
95         other.mOwnsHandle = false;
96     }
97     return *this;
98 }
99 
100 void hidl_handle::setTo(native_handle_t* handle, bool shouldOwn) {
101     freeHandle();
102     mHandle = handle;
103     mOwnsHandle = shouldOwn;
104 }
105 
106 const native_handle_t* hidl_handle::operator->() const {
107     return mHandle;
108 }
109 
110 // implicit conversion to const native_handle_t*
111 hidl_handle::operator const native_handle_t *() const {
112     return mHandle;
113 }
114 
115 // explicit conversion
116 const native_handle_t *hidl_handle::getNativeHandle() const {
117     return mHandle;
118 }
119 
120 void hidl_handle::freeHandle() {
121     if (mOwnsHandle && mHandle != nullptr) {
122         // This can only be true if:
123         // 1. Somebody called setTo() with shouldOwn=true, so we know the handle
124         //    wasn't const to begin with.
125         // 2. Copy/assignment from another hidl_handle, in which case we have
126         //    cloned the handle.
127         // 3. Move constructor from another hidl_handle, in which case the original
128         //    hidl_handle must have been non-const as well.
129         native_handle_t *handle = const_cast<native_handle_t*>(
130                 static_cast<const native_handle_t*>(mHandle));
131         native_handle_close(handle);
132         native_handle_delete(handle);
133         mHandle = nullptr;
134     }
135 }
136 
137 static const char *const kEmptyString = "";
138 
139 hidl_string::hidl_string() : mBuffer(kEmptyString), mSize(0), mOwnsBuffer(false) {
140     memset(mPad, 0, sizeof(mPad));
141 }
142 
143 hidl_string::~hidl_string() {
144     clear();
145 }
146 
147 hidl_string::hidl_string(const char *s) : hidl_string() {
148     if (s == nullptr) {
149         return;
150     }
151 
152     copyFrom(s, strlen(s));
153 }
154 
155 hidl_string::hidl_string(const char *s, size_t length) : hidl_string() {
156     copyFrom(s, length);
157 }
158 
159 hidl_string::hidl_string(const hidl_string &other): hidl_string() {
160     copyFrom(other.c_str(), other.size());
161 }
162 
163 hidl_string::hidl_string(const std::string &s) : hidl_string() {
164     copyFrom(s.c_str(), s.size());
165 }
166 
167 hidl_string::hidl_string(hidl_string&& other) noexcept : hidl_string() {
168     moveFrom(std::forward<hidl_string>(other));
169 }
170 
171 hidl_string& hidl_string::operator=(hidl_string&& other) noexcept {
172     if (this != &other) {
173         clear();
174         moveFrom(std::forward<hidl_string>(other));
175     }
176     return *this;
177 }
178 
179 hidl_string &hidl_string::operator=(const hidl_string &other) {
180     if (this != &other) {
181         clear();
182         copyFrom(other.c_str(), other.size());
183     }
184 
185     return *this;
186 }
187 
188 hidl_string &hidl_string::operator=(const char *s) {
189     clear();
190 
191     if (s == nullptr) {
192         return *this;
193     }
194 
195     copyFrom(s, strlen(s));
196     return *this;
197 }
198 
199 hidl_string &hidl_string::operator=(const std::string &s) {
200     clear();
201     copyFrom(s.c_str(), s.size());
202     return *this;
203 }
204 
205 hidl_string::operator std::string() const {
206     return std::string(mBuffer, mSize);
207 }
208 
209 std::ostream& operator<<(std::ostream& os, const hidl_string& str) {
210     os << str.c_str();
211     return os;
212 }
213 
214 void hidl_string::copyFrom(const char *data, size_t size) {
215     // assume my resources are freed.
216 
217     if (size >= UINT32_MAX) {
218         LOG(FATAL) << "string size can't exceed 2^32 bytes: " << size;
219     }
220     char *buf = (char *)malloc(size + 1);
221     memcpy(buf, data, size);
222     buf[size] = '\0';
223     mBuffer = buf;
224 
225     mSize = static_cast<uint32_t>(size);
226     mOwnsBuffer = true;
227 }
228 
229 void hidl_string::moveFrom(hidl_string &&other) {
230     // assume my resources are freed.
231 
232     mBuffer = std::move(other.mBuffer);
233     mSize = other.mSize;
234     mOwnsBuffer = other.mOwnsBuffer;
235 
236     other.mOwnsBuffer = false;
237     other.clear();
238 }
239 
240 void hidl_string::clear() {
241     if (mOwnsBuffer && (mBuffer != kEmptyString)) {
242         free(const_cast<char *>(static_cast<const char *>(mBuffer)));
243     }
244 
245     mBuffer = kEmptyString;
246     mSize = 0;
247     mOwnsBuffer = false;
248 }
249 
250 void hidl_string::setToExternal(const char *data, size_t size) {
251     if (size > UINT32_MAX) {
252         LOG(FATAL) << "string size can't exceed 2^32 bytes: " << size;
253     }
254 
255     // When the binder driver copies this data into its buffer, it must
256     // have a zero byte there because the remote process will have a pointer
257     // directly into the read-only binder buffer. If we manually copy the
258     // data now to add a zero, then we lose the efficiency of this method.
259     // Checking here (it's also checked in the parceling code later).
260     CHECK(data[size] == '\0');
261 
262     clear();
263 
264     mBuffer = data;
265     mSize = static_cast<uint32_t>(size);
266     mOwnsBuffer = false;
267 }
268 
269 const char *hidl_string::c_str() const {
270     return mBuffer;
271 }
272 
273 size_t hidl_string::size() const {
274     return mSize;
275 }
276 
277 bool hidl_string::empty() const {
278     return mSize == 0;
279 }
280 
281 sp<HidlMemory> HidlMemory::getInstance(const hidl_memory& mem) {
282     sp<HidlMemory> instance = new HidlMemory();
283     instance->hidl_memory::operator=(mem);
284     return instance;
285 }
286 
287 sp<HidlMemory> HidlMemory::getInstance(hidl_memory&& mem) {
288     sp<HidlMemory> instance = new HidlMemory();
289     instance->hidl_memory::operator=(std::move(mem));
290     return instance;
291 }
292 
293 sp<HidlMemory> HidlMemory::getInstance(const hidl_string& name, int fd, uint64_t size) {
294     native_handle_t* handle = native_handle_create(1, 0);
295     if (!handle) {
296         close(fd);
297         LOG(ERROR) << "native_handle_create fails";
298         return new HidlMemory();
299     }
300     handle->data[0] = fd;
301 
302     hidl_handle hidlHandle;
303     hidlHandle.setTo(handle, true /* shouldOwn */);
304 
305     sp<HidlMemory> instance = new HidlMemory(name, std::move(hidlHandle), size);
306     return instance;
307 }
308 
309 HidlMemory::HidlMemory() : hidl_memory() {}
310 
311 HidlMemory::HidlMemory(const hidl_string& name, hidl_handle&& handle, size_t size)
312         : hidl_memory(name, std::move(handle), size) {}
313 
314 // it's required to have at least one out-of-line method to avoid weak vtable
315 HidlMemory::~HidlMemory() {}
316 
317 }  // namespace hardware
318 }  // namespace android
319 
320 
321