1337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland/*
2337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland * Copyright (C) 2016 The Android Open Source Project
3337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland *
4337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland * Licensed under the Apache License, Version 2.0 (the "License");
5337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland * you may not use this file except in compliance with the License.
6337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland * You may obtain a copy of the License at
7337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland *
8337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland *      http://www.apache.org/licenses/LICENSE-2.0
9337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland *
10337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland * Unless required by applicable law or agreed to in writing, software
11337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland * distributed under the License is distributed on an "AS IS" BASIS,
12337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland * See the License for the specific language governing permissions and
14337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland * limitations under the License.
15337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland */
16337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland
17337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland#define LOG_TAG "HidlInternal"
18337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland
19337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland#include <hidl/HidlInternal.h>
20337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland
21337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland#include <android-base/logging.h>
227a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang#include <cutils/properties.h>
237a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang
247a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang#ifdef LIBHIDL_TARGET_DEBUGGABLE
257a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang#include <dirent.h>
267a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang#include <dlfcn.h>
277a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang#include <regex>
287a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang#endif
29337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland
30337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Morelandnamespace android {
31337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Morelandnamespace hardware {
32337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Morelandnamespace details {
33337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland
34b7370304cbf33a6ff53ec3955cda0bf18920df48Hridya Valsarajuvoid logAlwaysFatal(const char *message) {
35337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland    LOG(FATAL) << message;
36337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland}
37337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland
387a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang// ----------------------------------------------------------------------
397a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang// HidlInstrumentor implementation.
40384792b1ed77d03d7a76f1de6880a812a0073802Steven MorelandHidlInstrumentor::HidlInstrumentor(const std::string& package, const std::string& interface)
41384792b1ed77d03d7a76f1de6880a812a0073802Steven Moreland    : mEnableInstrumentation(false),
42384792b1ed77d03d7a76f1de6880a812a0073802Steven Moreland      mInstrumentationLibPackage(package),
43384792b1ed77d03d7a76f1de6880a812a0073802Steven Moreland      mInterfaceName(interface) {
447a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang    configureInstrumentation(false);
457a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang}
467a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang
477a57de61a2017790b61ac211729a3b275f29c9baZhuoyao ZhangHidlInstrumentor:: ~HidlInstrumentor() {}
487a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang
497a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhangvoid HidlInstrumentor::configureInstrumentation(bool log) {
50384792b1ed77d03d7a76f1de6880a812a0073802Steven Moreland    bool enableInstrumentation = property_get_bool(
517a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang            "hal.instrumentation.enable",
527a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang            false);
53384792b1ed77d03d7a76f1de6880a812a0073802Steven Moreland    if (enableInstrumentation != mEnableInstrumentation) {
54384792b1ed77d03d7a76f1de6880a812a0073802Steven Moreland        mEnableInstrumentation = enableInstrumentation;
557a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang        if (mEnableInstrumentation) {
567a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang            if (log) {
577a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang                LOG(INFO) << "Enable instrumentation.";
587a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang            }
597a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang            registerInstrumentationCallbacks (&mInstrumentationCallbacks);
607a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang        } else {
617a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang            if (log) {
627a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang                LOG(INFO) << "Disable instrumentation.";
637a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang            }
647a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang            mInstrumentationCallbacks.clear();
657a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang        }
667a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang    }
677a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang}
687a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang
697a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhangvoid HidlInstrumentor::registerInstrumentationCallbacks(
707a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang        std::vector<InstrumentationCallback> *instrumentationCallbacks) {
717a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang#ifdef LIBHIDL_TARGET_DEBUGGABLE
727a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang    std::vector<std::string> instrumentationLibPaths;
73384792b1ed77d03d7a76f1de6880a812a0073802Steven Moreland    char instrumentationLibPath[PROPERTY_VALUE_MAX];
747a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang    if (property_get("hal.instrumentation.lib.path",
75384792b1ed77d03d7a76f1de6880a812a0073802Steven Moreland                     instrumentationLibPath,
767a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang                     "") > 0) {
77384792b1ed77d03d7a76f1de6880a812a0073802Steven Moreland        instrumentationLibPaths.push_back(instrumentationLibPath);
787a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang    } else {
797a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang        instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_SYSTEM);
807a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang        instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_VENDOR);
817a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang        instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_ODM);
827a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang    }
837a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang
847a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang    for (auto path : instrumentationLibPaths) {
857a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang        DIR *dir = opendir(path.c_str());
867a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang        if (dir == 0) {
877a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang            LOG(WARNING) << path << " does not exist. ";
887a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang            return;
897a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang        }
907a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang
917a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang        struct dirent *file;
927a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang        while ((file = readdir(dir)) != NULL) {
937a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang            if (!isInstrumentationLib(file))
947a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang                continue;
957a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang
967a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang            void *handle = dlopen((path + file->d_name).c_str(), RTLD_NOW);
977a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang            char *error;
987a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang            if (handle == nullptr) {
997a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang                LOG(WARNING) << "couldn't load file: " << file->d_name
1007a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang                    << " error: " << dlerror();
1017a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang                continue;
1027a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang            }
1037a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang
1047a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang            dlerror(); /* Clear any existing error */
1057a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang
106384792b1ed77d03d7a76f1de6880a812a0073802Steven Moreland            using cbFun = void (*)(
1077a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang                    const InstrumentationEvent,
1087a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang                    const char *,
1097a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang                    const char *,
1107a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang                    const char *,
1117a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang                    const char *,
1127a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang                    std::vector<void *> *);
113819c05d28de72983177620902990dff360e80e73Steven Moreland            std::string package = mInstrumentationLibPackage;
114819c05d28de72983177620902990dff360e80e73Steven Moreland            for (size_t i = 0; i < package.size(); i++) {
115819c05d28de72983177620902990dff360e80e73Steven Moreland                if (package[i] == '.') {
116819c05d28de72983177620902990dff360e80e73Steven Moreland                    package[i] = '_';
117819c05d28de72983177620902990dff360e80e73Steven Moreland                    continue;
118819c05d28de72983177620902990dff360e80e73Steven Moreland                }
119819c05d28de72983177620902990dff360e80e73Steven Moreland
120819c05d28de72983177620902990dff360e80e73Steven Moreland                if (package[i] == '@') {
121819c05d28de72983177620902990dff360e80e73Steven Moreland                    package[i] = '_';
122819c05d28de72983177620902990dff360e80e73Steven Moreland                    package.insert(i + 1, "V");
123819c05d28de72983177620902990dff360e80e73Steven Moreland                    continue;
124819c05d28de72983177620902990dff360e80e73Steven Moreland                }
125819c05d28de72983177620902990dff360e80e73Steven Moreland            }
126384792b1ed77d03d7a76f1de6880a812a0073802Steven Moreland            auto cb = (cbFun)dlsym(handle, ("HIDL_INSTRUMENTATION_FUNCTION_"
127819c05d28de72983177620902990dff360e80e73Steven Moreland                        + package + "_" + mInterfaceName).c_str());
1287a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang            if ((error = dlerror()) != NULL) {
1297a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang                LOG(WARNING)
1307a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang                    << "couldn't find symbol: HIDL_INSTRUMENTATION_FUNCTION_"
131819c05d28de72983177620902990dff360e80e73Steven Moreland                    << package << "_" << mInterfaceName << ", error: " << error;
1327a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang                continue;
1337a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang            }
1347a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang            instrumentationCallbacks->push_back(cb);
1357a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang            LOG(INFO) << "Register instrumentation callback from "
1367a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang                << file->d_name;
1377a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang        }
1387a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang        closedir(dir);
1397a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang    }
1407a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang#else
1417a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang    // No-op for user builds.
142ead33e2b4cb281a1be53e44a6621d9ec959f4a33Steven Moreland    (void) instrumentationCallbacks;
1437a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang    return;
1447a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang#endif
1457a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang}
1467a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang
1477a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhangbool HidlInstrumentor::isInstrumentationLib(const dirent *file) {
1487a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang#ifdef LIBHIDL_TARGET_DEBUGGABLE
1497a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang    if (file->d_type != DT_REG) return false;
1507a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang    std::cmatch cm;
1517a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang    std::regex e("^" + mInstrumentationLibPackage + "(.*).profiler.so$");
1527a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang    if (std::regex_match(file->d_name, cm, e)) return true;
153ead33e2b4cb281a1be53e44a6621d9ec959f4a33Steven Moreland#else
154ead33e2b4cb281a1be53e44a6621d9ec959f4a33Steven Moreland    (void) file;
1557a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang#endif
1567a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang    return false;
1577a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang}
1587a57de61a2017790b61ac211729a3b275f29c9baZhuoyao Zhang
159337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland}  // namespace details
160337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland}  // namespace hardware
161337c3ae7f5ce6e94d6ccaaa7fb4ac92c4069b2ddSteven Moreland}  // namespace android
162