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 "HidlInternal" 18 19 #include <hidl/HidlInternal.h> 20 21 #include <android-base/logging.h> 22 #include <cutils/properties.h> 23 24 #ifdef LIBHIDL_TARGET_DEBUGGABLE 25 #include <dirent.h> 26 #include <dlfcn.h> 27 #include <regex> 28 #endif 29 30 namespace android { 31 namespace hardware { 32 namespace details { 33 34 void logAlwaysFatal(const char *message) { 35 LOG(FATAL) << message; 36 } 37 38 // ---------------------------------------------------------------------- 39 // HidlInstrumentor implementation. 40 HidlInstrumentor::HidlInstrumentor(const std::string& package, const std::string& interface) 41 : mEnableInstrumentation(false), 42 mInstrumentationLibPackage(package), 43 mInterfaceName(interface) { 44 configureInstrumentation(false); 45 } 46 47 HidlInstrumentor:: ~HidlInstrumentor() {} 48 49 void HidlInstrumentor::configureInstrumentation(bool log) { 50 bool enableInstrumentation = property_get_bool( 51 "hal.instrumentation.enable", 52 false); 53 if (enableInstrumentation != mEnableInstrumentation) { 54 mEnableInstrumentation = enableInstrumentation; 55 if (mEnableInstrumentation) { 56 if (log) { 57 LOG(INFO) << "Enable instrumentation."; 58 } 59 registerInstrumentationCallbacks (&mInstrumentationCallbacks); 60 } else { 61 if (log) { 62 LOG(INFO) << "Disable instrumentation."; 63 } 64 mInstrumentationCallbacks.clear(); 65 } 66 } 67 } 68 69 void HidlInstrumentor::registerInstrumentationCallbacks( 70 std::vector<InstrumentationCallback> *instrumentationCallbacks) { 71 #ifdef LIBHIDL_TARGET_DEBUGGABLE 72 std::vector<std::string> instrumentationLibPaths; 73 char instrumentationLibPath[PROPERTY_VALUE_MAX]; 74 if (property_get("hal.instrumentation.lib.path", 75 instrumentationLibPath, 76 "") > 0) { 77 instrumentationLibPaths.push_back(instrumentationLibPath); 78 } else { 79 instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_SYSTEM); 80 instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_VNDK_SP); 81 instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_VENDOR); 82 instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_ODM); 83 } 84 85 for (auto path : instrumentationLibPaths) { 86 DIR *dir = opendir(path.c_str()); 87 if (dir == 0) { 88 LOG(WARNING) << path << " does not exist. "; 89 return; 90 } 91 92 struct dirent *file; 93 while ((file = readdir(dir)) != NULL) { 94 if (!isInstrumentationLib(file)) 95 continue; 96 97 void *handle = dlopen((path + file->d_name).c_str(), RTLD_NOW); 98 char *error; 99 if (handle == nullptr) { 100 LOG(WARNING) << "couldn't load file: " << file->d_name 101 << " error: " << dlerror(); 102 continue; 103 } 104 105 dlerror(); /* Clear any existing error */ 106 107 using cbFun = void (*)( 108 const InstrumentationEvent, 109 const char *, 110 const char *, 111 const char *, 112 const char *, 113 std::vector<void *> *); 114 std::string package = mInstrumentationLibPackage; 115 for (size_t i = 0; i < package.size(); i++) { 116 if (package[i] == '.') { 117 package[i] = '_'; 118 continue; 119 } 120 121 if (package[i] == '@') { 122 package[i] = '_'; 123 package.insert(i + 1, "V"); 124 continue; 125 } 126 } 127 auto cb = (cbFun)dlsym(handle, ("HIDL_INSTRUMENTATION_FUNCTION_" 128 + package + "_" + mInterfaceName).c_str()); 129 if ((error = dlerror()) != NULL) { 130 LOG(WARNING) 131 << "couldn't find symbol: HIDL_INSTRUMENTATION_FUNCTION_" 132 << package << "_" << mInterfaceName << ", error: " << error; 133 continue; 134 } 135 instrumentationCallbacks->push_back(cb); 136 LOG(INFO) << "Register instrumentation callback from " 137 << file->d_name; 138 } 139 closedir(dir); 140 } 141 #else 142 // No-op for user builds. 143 (void) instrumentationCallbacks; 144 return; 145 #endif 146 } 147 148 bool HidlInstrumentor::isInstrumentationLib(const dirent *file) { 149 #ifdef LIBHIDL_TARGET_DEBUGGABLE 150 if (file->d_type != DT_REG) return false; 151 std::cmatch cm; 152 std::regex e("^" + mInstrumentationLibPackage + "(.*).profiler.so$"); 153 if (std::regex_match(file->d_name, cm, e)) return true; 154 #else 155 (void) file; 156 #endif 157 return false; 158 } 159 160 } // namespace details 161 } // namespace hardware 162 } // namespace android 163