Revert "Revert "Move HidlInstrumentor to HidlInternal and namespace details.""
This reverts commit f9fd88291caa3a2bab89c1b8ff128b1659da81b4.
Test: make libhidlbase
Change-Id: I85eb85bd9e89c28026e9865f799dce2b0df584fc
diff --git a/base/HidlInternal.cpp b/base/HidlInternal.cpp
index 45afda3..9c0efbb 100644
--- a/base/HidlInternal.cpp
+++ b/base/HidlInternal.cpp
@@ -19,6 +19,14 @@
#include <hidl/HidlInternal.h>
#include <android-base/logging.h>
+#include <cutils/properties.h>
+
+#ifdef LIBHIDL_TARGET_DEBUGGABLE
+#include <dirent.h>
+#include <dlfcn.h>
+#include <hidl-util/FQName.h>
+#include <regex>
+#endif
namespace android {
namespace hardware {
@@ -28,6 +36,113 @@
LOG(FATAL) << message;
}
+// ----------------------------------------------------------------------
+// HidlInstrumentor implementation.
+HidlInstrumentor::HidlInstrumentor(
+ const std::string &package,
+ const std::string &interface)
+ : mInstrumentationLibPackage(package), mInterfaceName(interface) {
+ configureInstrumentation(false);
+}
+
+HidlInstrumentor:: ~HidlInstrumentor() {}
+
+void HidlInstrumentor::configureInstrumentation(bool log) {
+ bool enable_instrumentation = property_get_bool(
+ "hal.instrumentation.enable",
+ false);
+ if (enable_instrumentation != mEnableInstrumentation) {
+ mEnableInstrumentation = enable_instrumentation;
+ if (mEnableInstrumentation) {
+ if (log) {
+ LOG(INFO) << "Enable instrumentation.";
+ }
+ registerInstrumentationCallbacks (&mInstrumentationCallbacks);
+ } else {
+ if (log) {
+ LOG(INFO) << "Disable instrumentation.";
+ }
+ mInstrumentationCallbacks.clear();
+ }
+ }
+}
+
+void HidlInstrumentor::registerInstrumentationCallbacks(
+ std::vector<InstrumentationCallback> *instrumentationCallbacks) {
+#ifdef LIBHIDL_TARGET_DEBUGGABLE
+ std::vector<std::string> instrumentationLibPaths;
+ char instrumentation_lib_path[PROPERTY_VALUE_MAX];
+ if (property_get("hal.instrumentation.lib.path",
+ instrumentation_lib_path,
+ "") > 0) {
+ instrumentationLibPaths.push_back(instrumentation_lib_path);
+ } else {
+ instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_SYSTEM);
+ instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_VENDOR);
+ instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_ODM);
+ }
+
+ for (auto path : instrumentationLibPaths) {
+ DIR *dir = opendir(path.c_str());
+ if (dir == 0) {
+ LOG(WARNING) << path << " does not exist. ";
+ return;
+ }
+
+ struct dirent *file;
+ while ((file = readdir(dir)) != NULL) {
+ if (!isInstrumentationLib(file))
+ continue;
+
+ void *handle = dlopen((path + file->d_name).c_str(), RTLD_NOW);
+ char *error;
+ if (handle == nullptr) {
+ LOG(WARNING) << "couldn't load file: " << file->d_name
+ << " error: " << dlerror();
+ continue;
+ }
+
+ dlerror(); /* Clear any existing error */
+
+ using cb_fun = void (*)(
+ const InstrumentationEvent,
+ const char *,
+ const char *,
+ const char *,
+ const char *,
+ std::vector<void *> *);
+ FQName package_name = FQName(mInstrumentationLibPackage);
+ auto cb = (cb_fun)dlsym(handle, ("HIDL_INSTRUMENTATION_FUNCTION_"
+ + package_name.tokenName() + "_"
+ + mInterfaceName).c_str());
+ if ((error = dlerror()) != NULL) {
+ LOG(WARNING)
+ << "couldn't find symbol: HIDL_INSTRUMENTATION_FUNCTION_"
+ << mInterfaceName << ", error: " << error;
+ continue;
+ }
+ instrumentationCallbacks->push_back(cb);
+ LOG(INFO) << "Register instrumentation callback from "
+ << file->d_name;
+ }
+ closedir(dir);
+ }
+#else
+ // No-op for user builds.
+ return;
+#endif
+}
+
+bool HidlInstrumentor::isInstrumentationLib(const dirent *file) {
+#ifdef LIBHIDL_TARGET_DEBUGGABLE
+ if (file->d_type != DT_REG) return false;
+ std::cmatch cm;
+ std::regex e("^" + mInstrumentationLibPackage + "(.*).profiler.so$");
+ if (std::regex_match(file->d_name, cm, e)) return true;
+#endif
+ return false;
+}
+
} // namespace details
} // namespace hardware
} // namespace android