blob: 3bd68afcb351579bd3e3e3c542c7563cf9cad7cd [file] [log] [blame]
Martijn Coenen72110162016-08-19 14:28:25 +02001/*
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 */
Martijn Coenen30791002016-12-01 15:40:46 +010016#define LOG_TAG "HidlSupport"
Martijn Coenen72110162016-08-19 14:28:25 +020017
18#include <hidl/HidlSupport.h>
19
Yifan Hong20273f92017-01-30 14:13:19 -080020#include <unordered_map>
21
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -070022#include <android-base/logging.h>
Yifan Hong20273f92017-01-30 14:13:19 -080023#include <android-base/parseint.h>
24#include <hidl-util/FQName.h>
Yifan Hong44c0e572017-01-20 15:41:52 -080025#include <vintf/VendorManifest.h>
26#include <vintf/parse_string.h>
Martijn Coenen30791002016-12-01 15:40:46 +010027
Martijn Coenen4ca39a02016-11-11 15:58:51 +010028#ifdef LIBHIDL_TARGET_DEBUGGABLE
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -070029#include <cutils/properties.h>
Steven Moreland337e6b62017-01-18 17:25:13 -080030#include <dlfcn.h>
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -070031#include <regex>
Yifan Hong602b85a2016-10-24 13:40:01 -070032#include <utility>
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -070033#endif
34
Martijn Coenen72110162016-08-19 14:28:25 +020035namespace android {
36namespace hardware {
Yifan Hong20273f92017-01-30 14:13:19 -080037vintf::Transport getTransportForFrameworkPackages(const std::string &name) {
38 // TODO(b/34772739): check with VNDK team to see if this should be in an XML.
39 const static std::unordered_map<std::string, vintf::Transport> sTransports {
40 {"android.hidl.manager@1.0::IServiceManager", vintf::Transport::HWBINDER},
41 {"android.hidl.memory@1.0::IAllocator" , vintf::Transport::HWBINDER},
42 {"android.hidl.memory@1.0::IMapper" , vintf::Transport::PASSTHROUGH},
43 {"android.hidl.memory@1.0::IMemory" , vintf::Transport::PASSTHROUGH},
44 };
45 auto it = sTransports.find(name);
46 if (it == sTransports.end()) {
47 LOG(WARNING) << "getTransportForFrameworkPackages: Cannot find entry "
48 << name << " in the static map.";
49 return vintf::Transport::EMPTY;
50 } else {
51 LOG(INFO) << "getTransportForFrameworkPackages: " << name
52 << " declares transport method " << to_string(it->second);
53 }
54 return it->second;
55}
Martijn Coenen72110162016-08-19 14:28:25 +020056
Yifan Hong20273f92017-01-30 14:13:19 -080057vintf::Transport getTransportForHals(const FQName &fqName) {
58 const std::string package = fqName.package();
Yifan Hong44c0e572017-01-20 15:41:52 -080059 const vintf::VendorManifest *vm = vintf::VendorManifest::Get();
60 if (vm == nullptr) {
Steven Moreland01732732017-02-02 18:42:49 -080061 LOG(WARNING) << "getTransportFromManifest: Cannot find vendor interface manifest.";
Yifan Hong44c0e572017-01-20 15:41:52 -080062 return vintf::Transport::EMPTY;
63 }
Yifan Honge682a5a2017-02-13 18:14:39 +000064 if (!fqName.hasVersion()) {
Yifan Hong20273f92017-01-30 14:13:19 -080065 LOG(ERROR) << "getTransportFromManifest: " << fqName.string()
66 << " does not specify a version.";
67 return vintf::Transport::EMPTY;
68 }
Yifan Honge682a5a2017-02-13 18:14:39 +000069 vintf::Transport tr = vm->getTransport(package,
70 vintf::Version{fqName.getPackageMajorVersion(), fqName.getPackageMinorVersion()});
Yifan Hong44c0e572017-01-20 15:41:52 -080071 if (tr == vintf::Transport::EMPTY) {
72 LOG(WARNING) << "getTransportFromManifest: Cannot find entry "
Yifan Hong20273f92017-01-30 14:13:19 -080073 << package << fqName.atVersion() << " in vendor interface manifest.";
Yifan Hong44c0e572017-01-20 15:41:52 -080074 } else {
Yifan Hong20273f92017-01-30 14:13:19 -080075 LOG(INFO) << "getTransportFromManifest: " << package << fqName.atVersion()
Yifan Hong44c0e572017-01-20 15:41:52 -080076 << " declares transport method " << to_string(tr);
Yifan Hong20273f92017-01-30 14:13:19 -080077 }
Yifan Hong44c0e572017-01-20 15:41:52 -080078 return tr;
79}
80
Yifan Hong20273f92017-01-30 14:13:19 -080081vintf::Transport getTransport(const std::string &name) {
82 FQName fqName(name);
83 if (!fqName.isValid()) {
84 LOG(WARNING) << name << " is not a valid fully-qualified name.";
85 return vintf::Transport::EMPTY;
86 }
87 if (fqName.inPackage("android.hidl")) {
88 return getTransportForFrameworkPackages(name);
89 }
90 return getTransportForHals(fqName);
91}
92
Martijn Coenen04b91c02017-01-19 14:14:21 +010093hidl_handle::hidl_handle() {
94 mHandle = nullptr;
95 mOwnsHandle = false;
96}
97
98hidl_handle::~hidl_handle() {
99 freeHandle();
100}
101
102hidl_handle::hidl_handle(const native_handle_t *handle) {
103 mHandle = handle;
104 mOwnsHandle = false;
105}
106
107// copy constructor.
108hidl_handle::hidl_handle(const hidl_handle &other) {
109 mOwnsHandle = false;
110 *this = other;
111}
112
113// move constructor.
114hidl_handle::hidl_handle(hidl_handle &&other) {
115 mOwnsHandle = false;
116 *this = std::move(other);
117}
118
119// assignment operators
120hidl_handle &hidl_handle::operator=(const hidl_handle &other) {
121 if (this == &other) {
122 return *this;
123 }
124 freeHandle();
125 if (other.mHandle != nullptr) {
126 mHandle = native_handle_clone(other.mHandle);
127 if (mHandle == nullptr) {
128 LOG(FATAL) << "Failed to clone native_handle in hidl_handle.";
129 }
130 mOwnsHandle = true;
131 } else {
132 mHandle = nullptr;
133 mOwnsHandle = false;
134 }
135 return *this;
136}
137
138hidl_handle &hidl_handle::operator=(const native_handle_t *native_handle) {
139 freeHandle();
140 mHandle = native_handle;
141 mOwnsHandle = false;
142 return *this;
143}
144
145hidl_handle &hidl_handle::operator=(hidl_handle &&other) {
146 if (this != &other) {
147 freeHandle();
148 mHandle = other.mHandle;
149 mOwnsHandle = other.mOwnsHandle;
150 other.mHandle = nullptr;
151 other.mOwnsHandle = false;
152 }
153 return *this;
154}
155
156void hidl_handle::setTo(native_handle_t* handle, bool shouldOwn) {
157 mHandle = handle;
158 mOwnsHandle = shouldOwn;
159}
160
161const native_handle_t* hidl_handle::operator->() const {
162 return mHandle;
163}
164
165// implicit conversion to const native_handle_t*
166hidl_handle::operator const native_handle_t *() const {
167 return mHandle;
168}
169
170// explicit conversion
171const native_handle_t *hidl_handle::getNativeHandle() const {
172 return mHandle;
173}
174
175void hidl_handle::freeHandle() {
176 if (mOwnsHandle && mHandle != nullptr) {
177 // This can only be true if:
178 // 1. Somebody called setTo() with shouldOwn=true, so we know the handle
179 // wasn't const to begin with.
180 // 2. Copy/assignment from another hidl_handle, in which case we have
181 // cloned the handle.
182 // 3. Move constructor from another hidl_handle, in which case the original
183 // hidl_handle must have been non-const as well.
184 native_handle_t *handle = const_cast<native_handle_t*>(
185 static_cast<const native_handle_t*>(mHandle));
186 native_handle_close(handle);
187 native_handle_delete(handle);
188 mHandle = nullptr;
189 }
190}
191
Martijn Coenen72110162016-08-19 14:28:25 +0200192static const char *const kEmptyString = "";
193
194hidl_string::hidl_string()
Yifan Hong602b85a2016-10-24 13:40:01 -0700195 : mBuffer(kEmptyString),
Martijn Coenen72110162016-08-19 14:28:25 +0200196 mSize(0),
Yifan Hong602b85a2016-10-24 13:40:01 -0700197 mOwnsBuffer(false) {
Martijn Coenen72110162016-08-19 14:28:25 +0200198}
199
200hidl_string::~hidl_string() {
201 clear();
202}
203
Steven Morelande03c0872016-10-24 10:43:50 -0700204hidl_string::hidl_string(const char *s) : hidl_string() {
Yifan Hong602b85a2016-10-24 13:40:01 -0700205 copyFrom(s, strlen(s));
Steven Morelande03c0872016-10-24 10:43:50 -0700206}
207
Steven Moreland53120f72017-01-12 09:39:26 -0800208hidl_string::hidl_string(const char *s, size_t length) : hidl_string() {
209 copyFrom(s, length);
210}
211
Yifan Hong602b85a2016-10-24 13:40:01 -0700212hidl_string::hidl_string(const hidl_string &other): hidl_string() {
213 copyFrom(other.c_str(), other.size());
214}
215
216hidl_string::hidl_string(const std::string &s) : hidl_string() {
217 copyFrom(s.c_str(), s.size());
218}
219
220hidl_string::hidl_string(hidl_string &&other): hidl_string() {
221 moveFrom(std::forward<hidl_string>(other));
222}
223
224hidl_string &hidl_string::operator=(hidl_string &&other) {
225 if (this != &other) {
226 clear();
227 moveFrom(std::forward<hidl_string>(other));
228 }
229 return *this;
Martijn Coenen72110162016-08-19 14:28:25 +0200230}
231
232hidl_string &hidl_string::operator=(const hidl_string &other) {
233 if (this != &other) {
Yifan Hong602b85a2016-10-24 13:40:01 -0700234 clear();
235 copyFrom(other.c_str(), other.size());
Martijn Coenen72110162016-08-19 14:28:25 +0200236 }
237
238 return *this;
239}
240
241hidl_string &hidl_string::operator=(const char *s) {
Yifan Hong602b85a2016-10-24 13:40:01 -0700242 clear();
243 copyFrom(s, strlen(s));
244 return *this;
Martijn Coenen72110162016-08-19 14:28:25 +0200245}
246
Yifan Hong602b85a2016-10-24 13:40:01 -0700247hidl_string &hidl_string::operator=(const std::string &s) {
Martijn Coenen72110162016-08-19 14:28:25 +0200248 clear();
Yifan Hong602b85a2016-10-24 13:40:01 -0700249 copyFrom(s.c_str(), s.size());
250 return *this;
251}
Martijn Coenen72110162016-08-19 14:28:25 +0200252
Yifan Hong602b85a2016-10-24 13:40:01 -0700253hidl_string::operator std::string() const {
254 return std::string(mBuffer, mSize);
255}
256
257hidl_string::operator const char *() const {
258 return mBuffer;
259}
260
261void hidl_string::copyFrom(const char *data, size_t size) {
262 // assume my resources are freed.
263
Martijn Coenen4ca39a02016-11-11 15:58:51 +0100264 if (size > UINT32_MAX) {
265 LOG(FATAL) << "string size can't exceed 2^32 bytes.";
266 }
Yifan Hong602b85a2016-10-24 13:40:01 -0700267 char *buf = (char *)malloc(size + 1);
268 memcpy(buf, data, size);
269 buf[size] = '\0';
270 mBuffer = buf;
Martijn Coenen72110162016-08-19 14:28:25 +0200271
Martijn Coenen4ca39a02016-11-11 15:58:51 +0100272 mSize = static_cast<uint32_t>(size);
Martijn Coenen72110162016-08-19 14:28:25 +0200273 mOwnsBuffer = true;
Yifan Hong602b85a2016-10-24 13:40:01 -0700274}
Martijn Coenen72110162016-08-19 14:28:25 +0200275
Yifan Hong602b85a2016-10-24 13:40:01 -0700276void hidl_string::moveFrom(hidl_string &&other) {
277 // assume my resources are freed.
278
279 mBuffer = other.mBuffer;
280 mSize = other.mSize;
281 mOwnsBuffer = other.mOwnsBuffer;
282
283 other.mOwnsBuffer = false;
Martijn Coenen72110162016-08-19 14:28:25 +0200284}
285
286void hidl_string::clear() {
287 if (mOwnsBuffer && (mBuffer != kEmptyString)) {
Martijn Coenen4ca39a02016-11-11 15:58:51 +0100288 free(const_cast<char *>(static_cast<const char *>(mBuffer)));
Martijn Coenen72110162016-08-19 14:28:25 +0200289 }
290
Yifan Hong602b85a2016-10-24 13:40:01 -0700291 mBuffer = kEmptyString;
Martijn Coenen72110162016-08-19 14:28:25 +0200292 mSize = 0;
Yifan Hong602b85a2016-10-24 13:40:01 -0700293 mOwnsBuffer = false;
Martijn Coenen72110162016-08-19 14:28:25 +0200294}
295
296void hidl_string::setToExternal(const char *data, size_t size) {
Martijn Coenen4ca39a02016-11-11 15:58:51 +0100297 if (size > UINT32_MAX) {
298 LOG(FATAL) << "string size can't exceed 2^32 bytes.";
299 }
Martijn Coenen72110162016-08-19 14:28:25 +0200300 clear();
301
Yifan Hong602b85a2016-10-24 13:40:01 -0700302 mBuffer = data;
Martijn Coenen4ca39a02016-11-11 15:58:51 +0100303 mSize = static_cast<uint32_t>(size);
Martijn Coenen72110162016-08-19 14:28:25 +0200304 mOwnsBuffer = false;
305}
306
307const char *hidl_string::c_str() const {
Yifan Hong602b85a2016-10-24 13:40:01 -0700308 return mBuffer;
Martijn Coenen72110162016-08-19 14:28:25 +0200309}
310
311size_t hidl_string::size() const {
312 return mSize;
313}
314
315bool hidl_string::empty() const {
316 return mSize == 0;
317}
318
Zhuoyao Zhang28e03af2016-10-21 11:25:49 -0700319// ----------------------------------------------------------------------
320// HidlInstrumentor implementation.
Zhuoyao Zhang93c1e3a2017-01-23 17:37:49 -0800321HidlInstrumentor::HidlInstrumentor(
322 const std::string &package,
323 const std::string &interface)
324 : mInstrumentationLibPackage(package), mInterfaceName(interface) {
Zhuoyao Zhang5a643b92017-01-03 17:31:53 -0800325 configureInstrumentation(false);
Zhuoyao Zhang28e03af2016-10-21 11:25:49 -0700326}
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700327
Zhuoyao Zhang28e03af2016-10-21 11:25:49 -0700328HidlInstrumentor:: ~HidlInstrumentor() {}
329
Zhuoyao Zhang5a643b92017-01-03 17:31:53 -0800330void HidlInstrumentor::configureInstrumentation(bool log) {
331 bool enable_instrumentation = property_get_bool(
332 "hal.instrumentation.enable",
333 false);
334 if (enable_instrumentation != mEnableInstrumentation) {
335 mEnableInstrumentation = enable_instrumentation;
336 if (mEnableInstrumentation) {
337 if (log) {
338 LOG(INFO) << "Enable instrumentation.";
339 }
340 registerInstrumentationCallbacks (&mInstrumentationCallbacks);
341 } else {
342 if (log) {
343 LOG(INFO) << "Disable instrumentation.";
344 }
345 mInstrumentationCallbacks.clear();
346 }
347 }
348}
349
Zhuoyao Zhang28e03af2016-10-21 11:25:49 -0700350void HidlInstrumentor::registerInstrumentationCallbacks(
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700351 std::vector<InstrumentationCallback> *instrumentationCallbacks) {
Dan Willemsen6365a872016-09-13 16:29:54 -0700352#ifdef LIBHIDL_TARGET_DEBUGGABLE
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700353 std::vector<std::string> instrumentationLibPaths;
Zhuoyao Zhang8bed09f2016-10-26 18:12:47 -0700354 char instrumentation_lib_path[PROPERTY_VALUE_MAX];
355 if (property_get("hal.instrumentation.lib.path",
356 instrumentation_lib_path,
357 "") > 0) {
358 instrumentationLibPaths.push_back(instrumentation_lib_path);
359 } else {
360 instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_SYSTEM);
361 instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_VENDOR);
362 instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_ODM);
363 }
364
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700365 for (auto path : instrumentationLibPaths) {
366 DIR *dir = opendir(path.c_str());
367 if (dir == 0) {
Steven Moreland7096f542016-11-07 11:20:33 -0800368 LOG(WARNING) << path << " does not exist. ";
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700369 return;
370 }
371
372 struct dirent *file;
373 while ((file = readdir(dir)) != NULL) {
Zhuoyao Zhang5a643b92017-01-03 17:31:53 -0800374 if (!isInstrumentationLib(file))
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700375 continue;
376
377 void *handle = dlopen((path + file->d_name).c_str(), RTLD_NOW);
Zhuoyao Zhang93c1e3a2017-01-23 17:37:49 -0800378 char *error;
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700379 if (handle == nullptr) {
380 LOG(WARNING) << "couldn't load file: " << file->d_name
381 << " error: " << dlerror();
382 continue;
383 }
Zhuoyao Zhang93c1e3a2017-01-23 17:37:49 -0800384
385 dlerror(); /* Clear any existing error */
386
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700387 using cb_fun = void (*)(
388 const InstrumentationEvent,
389 const char *,
390 const char *,
391 const char *,
392 const char *,
393 std::vector<void *> *);
Zhuoyao Zhang2236bd12017-02-09 15:45:22 -0800394 FQName package_name = FQName(mInstrumentationLibPackage);
395 auto cb = (cb_fun)dlsym(handle, ("HIDL_INSTRUMENTATION_FUNCTION_"
396 + package_name.tokenName() + "_"
397 + mInterfaceName).c_str());
Zhuoyao Zhang93c1e3a2017-01-23 17:37:49 -0800398 if ((error = dlerror()) != NULL) {
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700399 LOG(WARNING)
Zhuoyao Zhang93c1e3a2017-01-23 17:37:49 -0800400 << "couldn't find symbol: HIDL_INSTRUMENTATION_FUNCTION_"
401 << mInterfaceName << ", error: " << error;
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700402 continue;
403 }
404 instrumentationCallbacks->push_back(cb);
405 LOG(INFO) << "Register instrumentation callback from "
406 << file->d_name;
407 }
408 closedir(dir);
409 }
410#else
411 // No-op for user builds.
412 return;
413#endif
414}
415
Zhuoyao Zhang5a643b92017-01-03 17:31:53 -0800416bool HidlInstrumentor::isInstrumentationLib(const dirent *file) {
Dan Willemsen6365a872016-09-13 16:29:54 -0700417#ifdef LIBHIDL_TARGET_DEBUGGABLE
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700418 if (file->d_type != DT_REG) return false;
419 std::cmatch cm;
Zhuoyao Zhang93c1e3a2017-01-23 17:37:49 -0800420 std::regex e("^" + mInstrumentationLibPackage + "(.*).profiler.so$");
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700421 if (std::regex_match(file->d_name, cm, e)) return true;
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700422#endif
423 return false;
424}
425
Martijn Coenen72110162016-08-19 14:28:25 +0200426} // namespace hardware
427} // namespace android
428
429