blob: 3b964f0b8fcaefde074e955d569e5d29b43895e6 [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) {
61 LOG(ERROR) << "getTransportFromManifest: Cannot find vendor interface manifest.";
62 return vintf::Transport::EMPTY;
63 }
Yifan Hong20273f92017-01-30 14:13:19 -080064 size_t majorVer;
65 size_t minorVer;
66 if ( !::android::base::ParseUint(fqName.getPackageMajorVersion(), &majorVer)
67 || !::android::base::ParseUint(fqName.getPackageMinorVersion(), &minorVer)) {
68 LOG(ERROR) << "getTransportFromManifest: " << fqName.string()
69 << " does not specify a version.";
70 return vintf::Transport::EMPTY;
71 }
72 vintf::Transport tr = vm->getTransport(package, vintf::Version{majorVer, minorVer});
Yifan Hong44c0e572017-01-20 15:41:52 -080073 if (tr == vintf::Transport::EMPTY) {
74 LOG(WARNING) << "getTransportFromManifest: Cannot find entry "
Yifan Hong20273f92017-01-30 14:13:19 -080075 << package << fqName.atVersion() << " in vendor interface manifest.";
Yifan Hong44c0e572017-01-20 15:41:52 -080076 } else {
Yifan Hong20273f92017-01-30 14:13:19 -080077 LOG(INFO) << "getTransportFromManifest: " << package << fqName.atVersion()
Yifan Hong44c0e572017-01-20 15:41:52 -080078 << " declares transport method " << to_string(tr);
Yifan Hong20273f92017-01-30 14:13:19 -080079 }
Yifan Hong44c0e572017-01-20 15:41:52 -080080 return tr;
81}
82
Yifan Hong20273f92017-01-30 14:13:19 -080083vintf::Transport getTransport(const std::string &name) {
84 FQName fqName(name);
85 if (!fqName.isValid()) {
86 LOG(WARNING) << name << " is not a valid fully-qualified name.";
87 return vintf::Transport::EMPTY;
88 }
89 if (fqName.inPackage("android.hidl")) {
90 return getTransportForFrameworkPackages(name);
91 }
92 return getTransportForHals(fqName);
93}
94
Martijn Coenen04b91c02017-01-19 14:14:21 +010095hidl_handle::hidl_handle() {
96 mHandle = nullptr;
97 mOwnsHandle = false;
98}
99
100hidl_handle::~hidl_handle() {
101 freeHandle();
102}
103
104hidl_handle::hidl_handle(const native_handle_t *handle) {
105 mHandle = handle;
106 mOwnsHandle = false;
107}
108
109// copy constructor.
110hidl_handle::hidl_handle(const hidl_handle &other) {
111 mOwnsHandle = false;
112 *this = other;
113}
114
115// move constructor.
116hidl_handle::hidl_handle(hidl_handle &&other) {
117 mOwnsHandle = false;
118 *this = std::move(other);
119}
120
121// assignment operators
122hidl_handle &hidl_handle::operator=(const hidl_handle &other) {
123 if (this == &other) {
124 return *this;
125 }
126 freeHandle();
127 if (other.mHandle != nullptr) {
128 mHandle = native_handle_clone(other.mHandle);
129 if (mHandle == nullptr) {
130 LOG(FATAL) << "Failed to clone native_handle in hidl_handle.";
131 }
132 mOwnsHandle = true;
133 } else {
134 mHandle = nullptr;
135 mOwnsHandle = false;
136 }
137 return *this;
138}
139
140hidl_handle &hidl_handle::operator=(const native_handle_t *native_handle) {
141 freeHandle();
142 mHandle = native_handle;
143 mOwnsHandle = false;
144 return *this;
145}
146
147hidl_handle &hidl_handle::operator=(hidl_handle &&other) {
148 if (this != &other) {
149 freeHandle();
150 mHandle = other.mHandle;
151 mOwnsHandle = other.mOwnsHandle;
152 other.mHandle = nullptr;
153 other.mOwnsHandle = false;
154 }
155 return *this;
156}
157
158void hidl_handle::setTo(native_handle_t* handle, bool shouldOwn) {
159 mHandle = handle;
160 mOwnsHandle = shouldOwn;
161}
162
163const native_handle_t* hidl_handle::operator->() const {
164 return mHandle;
165}
166
167// implicit conversion to const native_handle_t*
168hidl_handle::operator const native_handle_t *() const {
169 return mHandle;
170}
171
172// explicit conversion
173const native_handle_t *hidl_handle::getNativeHandle() const {
174 return mHandle;
175}
176
177void hidl_handle::freeHandle() {
178 if (mOwnsHandle && mHandle != nullptr) {
179 // This can only be true if:
180 // 1. Somebody called setTo() with shouldOwn=true, so we know the handle
181 // wasn't const to begin with.
182 // 2. Copy/assignment from another hidl_handle, in which case we have
183 // cloned the handle.
184 // 3. Move constructor from another hidl_handle, in which case the original
185 // hidl_handle must have been non-const as well.
186 native_handle_t *handle = const_cast<native_handle_t*>(
187 static_cast<const native_handle_t*>(mHandle));
188 native_handle_close(handle);
189 native_handle_delete(handle);
190 mHandle = nullptr;
191 }
192}
193
Martijn Coenen72110162016-08-19 14:28:25 +0200194static const char *const kEmptyString = "";
195
196hidl_string::hidl_string()
Yifan Hong602b85a2016-10-24 13:40:01 -0700197 : mBuffer(kEmptyString),
Martijn Coenen72110162016-08-19 14:28:25 +0200198 mSize(0),
Yifan Hong602b85a2016-10-24 13:40:01 -0700199 mOwnsBuffer(false) {
Martijn Coenen72110162016-08-19 14:28:25 +0200200}
201
202hidl_string::~hidl_string() {
203 clear();
204}
205
Steven Morelande03c0872016-10-24 10:43:50 -0700206hidl_string::hidl_string(const char *s) : hidl_string() {
Yifan Hong602b85a2016-10-24 13:40:01 -0700207 copyFrom(s, strlen(s));
Steven Morelande03c0872016-10-24 10:43:50 -0700208}
209
Steven Moreland53120f72017-01-12 09:39:26 -0800210hidl_string::hidl_string(const char *s, size_t length) : hidl_string() {
211 copyFrom(s, length);
212}
213
Yifan Hong602b85a2016-10-24 13:40:01 -0700214hidl_string::hidl_string(const hidl_string &other): hidl_string() {
215 copyFrom(other.c_str(), other.size());
216}
217
218hidl_string::hidl_string(const std::string &s) : hidl_string() {
219 copyFrom(s.c_str(), s.size());
220}
221
222hidl_string::hidl_string(hidl_string &&other): hidl_string() {
223 moveFrom(std::forward<hidl_string>(other));
224}
225
226hidl_string &hidl_string::operator=(hidl_string &&other) {
227 if (this != &other) {
228 clear();
229 moveFrom(std::forward<hidl_string>(other));
230 }
231 return *this;
Martijn Coenen72110162016-08-19 14:28:25 +0200232}
233
234hidl_string &hidl_string::operator=(const hidl_string &other) {
235 if (this != &other) {
Yifan Hong602b85a2016-10-24 13:40:01 -0700236 clear();
237 copyFrom(other.c_str(), other.size());
Martijn Coenen72110162016-08-19 14:28:25 +0200238 }
239
240 return *this;
241}
242
243hidl_string &hidl_string::operator=(const char *s) {
Yifan Hong602b85a2016-10-24 13:40:01 -0700244 clear();
245 copyFrom(s, strlen(s));
246 return *this;
Martijn Coenen72110162016-08-19 14:28:25 +0200247}
248
Yifan Hong602b85a2016-10-24 13:40:01 -0700249hidl_string &hidl_string::operator=(const std::string &s) {
Martijn Coenen72110162016-08-19 14:28:25 +0200250 clear();
Yifan Hong602b85a2016-10-24 13:40:01 -0700251 copyFrom(s.c_str(), s.size());
252 return *this;
253}
Martijn Coenen72110162016-08-19 14:28:25 +0200254
Steven Morelanda2a81842017-01-20 14:48:15 -0800255bool hidl_string::operator< (const hidl_string &rhs) const {
256 return strcmp(mBuffer, rhs.mBuffer) < 0;
257}
258
Yifan Hong602b85a2016-10-24 13:40:01 -0700259hidl_string::operator std::string() const {
260 return std::string(mBuffer, mSize);
261}
262
263hidl_string::operator const char *() const {
264 return mBuffer;
265}
266
267void hidl_string::copyFrom(const char *data, size_t size) {
268 // assume my resources are freed.
269
Martijn Coenen4ca39a02016-11-11 15:58:51 +0100270 if (size > UINT32_MAX) {
271 LOG(FATAL) << "string size can't exceed 2^32 bytes.";
272 }
Yifan Hong602b85a2016-10-24 13:40:01 -0700273 char *buf = (char *)malloc(size + 1);
274 memcpy(buf, data, size);
275 buf[size] = '\0';
276 mBuffer = buf;
Martijn Coenen72110162016-08-19 14:28:25 +0200277
Martijn Coenen4ca39a02016-11-11 15:58:51 +0100278 mSize = static_cast<uint32_t>(size);
Martijn Coenen72110162016-08-19 14:28:25 +0200279 mOwnsBuffer = true;
Yifan Hong602b85a2016-10-24 13:40:01 -0700280}
Martijn Coenen72110162016-08-19 14:28:25 +0200281
Yifan Hong602b85a2016-10-24 13:40:01 -0700282void hidl_string::moveFrom(hidl_string &&other) {
283 // assume my resources are freed.
284
285 mBuffer = other.mBuffer;
286 mSize = other.mSize;
287 mOwnsBuffer = other.mOwnsBuffer;
288
289 other.mOwnsBuffer = false;
Martijn Coenen72110162016-08-19 14:28:25 +0200290}
291
292void hidl_string::clear() {
293 if (mOwnsBuffer && (mBuffer != kEmptyString)) {
Martijn Coenen4ca39a02016-11-11 15:58:51 +0100294 free(const_cast<char *>(static_cast<const char *>(mBuffer)));
Martijn Coenen72110162016-08-19 14:28:25 +0200295 }
296
Yifan Hong602b85a2016-10-24 13:40:01 -0700297 mBuffer = kEmptyString;
Martijn Coenen72110162016-08-19 14:28:25 +0200298 mSize = 0;
Yifan Hong602b85a2016-10-24 13:40:01 -0700299 mOwnsBuffer = false;
Martijn Coenen72110162016-08-19 14:28:25 +0200300}
301
302void hidl_string::setToExternal(const char *data, size_t size) {
Martijn Coenen4ca39a02016-11-11 15:58:51 +0100303 if (size > UINT32_MAX) {
304 LOG(FATAL) << "string size can't exceed 2^32 bytes.";
305 }
Martijn Coenen72110162016-08-19 14:28:25 +0200306 clear();
307
Yifan Hong602b85a2016-10-24 13:40:01 -0700308 mBuffer = data;
Martijn Coenen4ca39a02016-11-11 15:58:51 +0100309 mSize = static_cast<uint32_t>(size);
Martijn Coenen72110162016-08-19 14:28:25 +0200310 mOwnsBuffer = false;
311}
312
313const char *hidl_string::c_str() const {
Yifan Hong602b85a2016-10-24 13:40:01 -0700314 return mBuffer;
Martijn Coenen72110162016-08-19 14:28:25 +0200315}
316
317size_t hidl_string::size() const {
318 return mSize;
319}
320
321bool hidl_string::empty() const {
322 return mSize == 0;
323}
324
Zhuoyao Zhang28e03af2016-10-21 11:25:49 -0700325// ----------------------------------------------------------------------
326// HidlInstrumentor implementation.
Zhuoyao Zhang93c1e3a2017-01-23 17:37:49 -0800327HidlInstrumentor::HidlInstrumentor(
328 const std::string &package,
329 const std::string &interface)
330 : mInstrumentationLibPackage(package), mInterfaceName(interface) {
Zhuoyao Zhang5a643b92017-01-03 17:31:53 -0800331 configureInstrumentation(false);
Zhuoyao Zhang28e03af2016-10-21 11:25:49 -0700332}
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700333
Zhuoyao Zhang28e03af2016-10-21 11:25:49 -0700334HidlInstrumentor:: ~HidlInstrumentor() {}
335
Zhuoyao Zhang5a643b92017-01-03 17:31:53 -0800336void HidlInstrumentor::configureInstrumentation(bool log) {
337 bool enable_instrumentation = property_get_bool(
338 "hal.instrumentation.enable",
339 false);
340 if (enable_instrumentation != mEnableInstrumentation) {
341 mEnableInstrumentation = enable_instrumentation;
342 if (mEnableInstrumentation) {
343 if (log) {
344 LOG(INFO) << "Enable instrumentation.";
345 }
346 registerInstrumentationCallbacks (&mInstrumentationCallbacks);
347 } else {
348 if (log) {
349 LOG(INFO) << "Disable instrumentation.";
350 }
351 mInstrumentationCallbacks.clear();
352 }
353 }
354}
355
Zhuoyao Zhang28e03af2016-10-21 11:25:49 -0700356void HidlInstrumentor::registerInstrumentationCallbacks(
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700357 std::vector<InstrumentationCallback> *instrumentationCallbacks) {
Dan Willemsen6365a872016-09-13 16:29:54 -0700358#ifdef LIBHIDL_TARGET_DEBUGGABLE
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700359 std::vector<std::string> instrumentationLibPaths;
Zhuoyao Zhang8bed09f2016-10-26 18:12:47 -0700360 char instrumentation_lib_path[PROPERTY_VALUE_MAX];
361 if (property_get("hal.instrumentation.lib.path",
362 instrumentation_lib_path,
363 "") > 0) {
364 instrumentationLibPaths.push_back(instrumentation_lib_path);
365 } else {
366 instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_SYSTEM);
367 instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_VENDOR);
368 instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_ODM);
369 }
370
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700371 for (auto path : instrumentationLibPaths) {
372 DIR *dir = opendir(path.c_str());
373 if (dir == 0) {
Steven Moreland7096f542016-11-07 11:20:33 -0800374 LOG(WARNING) << path << " does not exist. ";
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700375 return;
376 }
377
378 struct dirent *file;
379 while ((file = readdir(dir)) != NULL) {
Zhuoyao Zhang5a643b92017-01-03 17:31:53 -0800380 if (!isInstrumentationLib(file))
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700381 continue;
382
383 void *handle = dlopen((path + file->d_name).c_str(), RTLD_NOW);
Zhuoyao Zhang93c1e3a2017-01-23 17:37:49 -0800384 char *error;
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700385 if (handle == nullptr) {
386 LOG(WARNING) << "couldn't load file: " << file->d_name
387 << " error: " << dlerror();
388 continue;
389 }
Zhuoyao Zhang93c1e3a2017-01-23 17:37:49 -0800390
391 dlerror(); /* Clear any existing error */
392
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700393 using cb_fun = void (*)(
394 const InstrumentationEvent,
395 const char *,
396 const char *,
397 const char *,
398 const char *,
399 std::vector<void *> *);
Zhuoyao Zhang93c1e3a2017-01-23 17:37:49 -0800400 auto cb = (cb_fun)dlsym(handle,
401 ("HIDL_INSTRUMENTATION_FUNCTION_" + mInterfaceName).c_str());
402 if ((error = dlerror()) != NULL) {
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700403 LOG(WARNING)
Zhuoyao Zhang93c1e3a2017-01-23 17:37:49 -0800404 << "couldn't find symbol: HIDL_INSTRUMENTATION_FUNCTION_"
405 << mInterfaceName << ", error: " << error;
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700406 continue;
407 }
408 instrumentationCallbacks->push_back(cb);
409 LOG(INFO) << "Register instrumentation callback from "
410 << file->d_name;
411 }
412 closedir(dir);
413 }
414#else
415 // No-op for user builds.
416 return;
417#endif
418}
419
Zhuoyao Zhang5a643b92017-01-03 17:31:53 -0800420bool HidlInstrumentor::isInstrumentationLib(const dirent *file) {
Dan Willemsen6365a872016-09-13 16:29:54 -0700421#ifdef LIBHIDL_TARGET_DEBUGGABLE
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700422 if (file->d_type != DT_REG) return false;
423 std::cmatch cm;
Zhuoyao Zhang93c1e3a2017-01-23 17:37:49 -0800424 std::regex e("^" + mInstrumentationLibPackage + "(.*).profiler.so$");
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700425 if (std::regex_match(file->d_name, cm, e)) return true;
Zhuoyao Zhang7e1286c2016-09-12 17:28:48 -0700426#endif
427 return false;
428}
429
Martijn Coenen72110162016-08-19 14:28:25 +0200430} // namespace hardware
431} // namespace android
432
433