Access atrace HAL to get available categories

This code is not used yet. It is just the wrapper layers
to allow traced probes to talk to the atrace HAL.

Bug: 127378737
Test: Code is never reached for now

Change-Id: I062d29ec5ba7dd54c8c7f4ea6efaa3d3b854aee0
diff --git a/Android.bp b/Android.bp
index da3e1cb..33bfe98 100644
--- a/Android.bp
+++ b/Android.bp
@@ -254,6 +254,7 @@
     "src/traced/probes/filesystem/lru_inode_cache.cc",
     "src/traced/probes/filesystem/prefix_finder.cc",
     "src/traced/probes/filesystem/range_tree.cc",
+    "src/traced/probes/ftrace/atrace_hal_wrapper.cc",
     "src/traced/probes/ftrace/atrace_wrapper.cc",
     "src/traced/probes/ftrace/cpu_reader.cc",
     "src/traced/probes/ftrace/cpu_stats_parser.cc",
@@ -350,10 +351,12 @@
 cc_library_shared {
   name: "libperfetto_android_internal",
   srcs: [
+    "src/android_internal/atrace_hal.cc",
     "src/android_internal/health_hal.cc",
     "src/android_internal/power_stats_hal.cc",
   ],
   shared_libs: [
+    "android.hardware.atrace@1.0",
     "android.hardware.health@2.0",
     "android.hardware.power.stats@1.0",
     "libbase",
@@ -615,6 +618,7 @@
     "src/traced/probes/filesystem/lru_inode_cache.cc",
     "src/traced/probes/filesystem/prefix_finder.cc",
     "src/traced/probes/filesystem/range_tree.cc",
+    "src/traced/probes/ftrace/atrace_hal_wrapper.cc",
     "src/traced/probes/ftrace/atrace_wrapper.cc",
     "src/traced/probes/ftrace/cpu_reader.cc",
     "src/traced/probes/ftrace/cpu_stats_parser.cc",
@@ -2915,6 +2919,7 @@
     "src/traced/probes/filesystem/prefix_finder_unittest.cc",
     "src/traced/probes/filesystem/range_tree.cc",
     "src/traced/probes/filesystem/range_tree_unittest.cc",
+    "src/traced/probes/ftrace/atrace_hal_wrapper.cc",
     "src/traced/probes/ftrace/atrace_wrapper.cc",
     "src/traced/probes/ftrace/cpu_reader.cc",
     "src/traced/probes/ftrace/cpu_reader_unittest.cc",
diff --git a/src/android_internal/BUILD.gn b/src/android_internal/BUILD.gn
index baf21a6..36734fd 100644
--- a/src/android_internal/BUILD.gn
+++ b/src/android_internal/BUILD.gn
@@ -19,6 +19,7 @@
     "../../gn:default_deps",
   ]
   sources = [
+    "atrace_hal.h",
     "health_hal.h",
     "power_stats_hal.h",
   ]
@@ -34,12 +35,14 @@
   ]
   if (perfetto_build_with_android) {
     sources = [
+      "atrace_hal.cc",
       "health_hal.cc",
       "power_stats_hal.cc",
     ]
     libs = [
       "android.hardware.health@2.0",
       "android.hardware.power.stats@1.0",
+      "android.hardware.atrace@1.0",
       "base",
       "log",
       "hidlbase",
diff --git a/src/android_internal/atrace_hal.cc b/src/android_internal/atrace_hal.cc
new file mode 100644
index 0000000..67e445d
--- /dev/null
+++ b/src/android_internal/atrace_hal.cc
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/android_internal/atrace_hal.h"
+
+#include <android/hardware/atrace/1.0/IAtraceDevice.h>
+#include <iostream>
+
+namespace perfetto {
+namespace android_internal {
+
+using android::hardware::atrace::V1_0::IAtraceDevice;
+using android::hardware::atrace::V1_0::TracingCategory;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+
+namespace {
+
+android::sp<IAtraceDevice> g_atraceHal;
+
+bool GetService() {
+  if (!g_atraceHal)
+    g_atraceHal = IAtraceDevice::getService();
+
+  return g_atraceHal != nullptr;
+}
+
+}  // namespace
+
+bool GetCategories(TracingVendorCategory* categories, size_t* size_of_arr) {
+  const size_t in_array_size = *size_of_arr;
+  *size_of_arr = 0;
+  if (!GetService())
+    return false;
+
+  auto category_cb = [categories, size_of_arr,
+                      &in_array_size](hidl_vec<TracingCategory> r) {
+    *size_of_arr = std::min(in_array_size, r.size());
+    for (int i = 0; i < *size_of_arr; ++i) {
+      const TracingCategory& cat = r[i];
+      TracingVendorCategory& result = categories[i];
+      strncpy(result.name, cat.name.c_str(), sizeof(result.name));
+      strncpy(result.description, cat.description.c_str(),
+              sizeof(result.description));
+      result.name[sizeof(result.name) - 1] = '\0';
+      result.description[sizeof(result.description) - 1] = '\0';
+    }
+  };
+
+  g_atraceHal->listCategories(category_cb);
+  return true;
+}
+
+}  // namespace android_internal
+}  // namespace perfetto
diff --git a/src/android_internal/atrace_hal.h b/src/android_internal/atrace_hal.h
new file mode 100644
index 0000000..7037fa1
--- /dev/null
+++ b/src/android_internal/atrace_hal.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_ANDROID_INTERNAL_ATRACE_HAL_H_
+#define SRC_ANDROID_INTERNAL_ATRACE_HAL_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// This header declares proxy functions defined in
+// libperfetto_android_internal.so that allow traced_probes to access internal
+// android functions (e.g., hwbinder).
+// Do not add any include to either perfetto headers or android headers. See
+// README.md for more.
+
+namespace perfetto {
+namespace android_internal {
+
+struct TracingVendorCategory {
+  // The name identifying the category.
+  char name[64];
+
+  // A longer description of the category.
+  char description[256];
+};
+
+extern "C" {
+
+// These functions are not thread safe unless specified otherwise.
+
+bool __attribute__((visibility("default")))
+GetCategories(TracingVendorCategory*, size_t* size_of_arr);
+
+}  // extern "C"
+
+}  // namespace android_internal
+}  // namespace perfetto
+
+#endif  // SRC_ANDROID_INTERNAL_ATRACE_HAL_H_
diff --git a/src/traced/probes/ftrace/BUILD.gn b/src/traced/probes/ftrace/BUILD.gn
index cd38398..3903a20 100644
--- a/src/traced/probes/ftrace/BUILD.gn
+++ b/src/traced/probes/ftrace/BUILD.gn
@@ -108,15 +108,19 @@
     "../../../../protos/perfetto/trace/ftrace:zero",
     "../../../tracing",
   ]
+  libs = [ "dl" ]  # for dlopen()
   deps = [
     ":format_parser",
     "..:data_source",
     "../../../../gn:default_deps",
     "../../../../include/perfetto/traced",
+    "../../../android_internal:headers",
     "../../../base",
     "../../../protozero",
   ]
   sources = [
+    "atrace_hal_wrapper.cc",
+    "atrace_hal_wrapper.h",
     "atrace_wrapper.cc",
     "atrace_wrapper.h",
     "cpu_reader.cc",
diff --git a/src/traced/probes/ftrace/atrace_hal_wrapper.cc b/src/traced/probes/ftrace/atrace_hal_wrapper.cc
new file mode 100644
index 0000000..6e3f29f
--- /dev/null
+++ b/src/traced/probes/ftrace/atrace_hal_wrapper.cc
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "src/traced/probes/ftrace/atrace_hal_wrapper.h"
+
+#include <dlfcn.h>
+
+#include "src/android_internal/atrace_hal.h"
+
+namespace perfetto {
+
+namespace {
+constexpr size_t kMaxNumCategories = 64;
+}
+
+struct AtraceHalWrapper::DynamicLibLoader {
+  using ScopedDlHandle = base::ScopedResource<void*, dlclose, nullptr>;
+
+  DynamicLibLoader() {
+    static const char kLibName[] = "libperfetto_android_internal.so";
+    handle_.reset(dlopen(kLibName, RTLD_NOW));
+    if (!handle_) {
+      PERFETTO_PLOG("dlopen(%s) failed", kLibName);
+      return;
+    }
+    void* fn = dlsym(*handle_, "GetCategories");
+    if (!fn) {
+      PERFETTO_PLOG("dlsym(GetCategories) failed");
+      return;
+    }
+    get_categories_ = reinterpret_cast<decltype(get_categories_)>(fn);
+  }
+
+  std::vector<android_internal::TracingVendorCategory> GetCategories() {
+    if (!get_categories_)
+      return std::vector<android_internal::TracingVendorCategory>();
+
+    std::vector<android_internal::TracingVendorCategory> categories(
+        kMaxNumCategories);
+    size_t num_cat = categories.size();
+    get_categories_(&categories[0], &num_cat);
+    categories.resize(num_cat);
+    return categories;
+  }
+
+ private:
+  decltype(&android_internal::GetCategories) get_categories_ = nullptr;
+  ScopedDlHandle handle_;
+};
+
+AtraceHalWrapper::AtraceHalWrapper() {
+  lib_.reset(new DynamicLibLoader());
+}
+
+AtraceHalWrapper::~AtraceHalWrapper() = default;
+
+std::vector<AtraceHalWrapper::TracingVendorCategory>
+AtraceHalWrapper::GetAvailableCategories() {
+  auto details = lib_->GetCategories();
+  std::vector<AtraceHalWrapper::TracingVendorCategory> result;
+  for (size_t i = 0; i < details.size(); i++) {
+    AtraceHalWrapper::TracingVendorCategory cat;
+    cat.name = details[i].name;
+    cat.description = details[i].description;
+    result.emplace_back(cat);
+  }
+  return result;
+}
+
+}  // namespace perfetto
diff --git a/src/traced/probes/ftrace/atrace_hal_wrapper.h b/src/traced/probes/ftrace/atrace_hal_wrapper.h
new file mode 100644
index 0000000..883388b
--- /dev/null
+++ b/src/traced/probes/ftrace/atrace_hal_wrapper.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_TRACED_PROBES_FTRACE_ATRACE_HAL_WRAPPER_H_
+#define SRC_TRACED_PROBES_FTRACE_ATRACE_HAL_WRAPPER_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "perfetto/base/scoped_file.h"
+
+namespace perfetto {
+
+class AtraceHalWrapper {
+ public:
+  AtraceHalWrapper();
+  ~AtraceHalWrapper();
+
+  struct TracingVendorCategory {
+    // The name identifying the category.
+    std::string name;
+
+    // A longer description of the category.
+    std::string description;
+  };
+
+  std::vector<TracingVendorCategory> GetAvailableCategories();
+
+ private:
+  struct DynamicLibLoader;
+
+  std::unique_ptr<DynamicLibLoader> lib_;
+};
+
+}  // namespace perfetto
+
+#endif  // SRC_TRACED_PROBES_FTRACE_ATRACE_HAL_WRAPPER_H_