Add ability to retrieve energy metrics for power rails

Added code to interface with Power Stats HAL, in order
to retrieve energy measurements for the available
rails.

Bug: 122584217
Test: Manual
Change-Id: Ia68eddf731e67896edd044cccd855543d986167b
diff --git a/Android.bp b/Android.bp
index 8395fec..31afc19 100644
--- a/Android.bp
+++ b/Android.bp
@@ -335,9 +335,11 @@
   name: "libperfetto_android_internal",
   srcs: [
     "src/android_internal/health_hal.cc",
+    "src/android_internal/power_stats_hal.cc",
   ],
   shared_libs: [
     "android.hardware.health@2.0",
+    "android.hardware.power.stats@1.0",
     "libbase",
     "libhidlbase",
     "libhidltransport",
diff --git a/src/android_internal/BUILD.gn b/src/android_internal/BUILD.gn
index 0930238..baf21a6 100644
--- a/src/android_internal/BUILD.gn
+++ b/src/android_internal/BUILD.gn
@@ -20,6 +20,7 @@
   ]
   sources = [
     "health_hal.h",
+    "power_stats_hal.h",
   ]
 }
 
@@ -34,14 +35,16 @@
   if (perfetto_build_with_android) {
     sources = [
       "health_hal.cc",
+      "power_stats_hal.cc",
     ]
     libs = [
       "android.hardware.health@2.0",
+      "android.hardware.power.stats@1.0",
       "base",
       "log",
-      "hwbinder",
       "hidlbase",
       "hidltransport",
+      "hwbinder",
       "utils",
     ]
   }
diff --git a/src/android_internal/health_hal.h b/src/android_internal/health_hal.h
index 5f489af..e83d8c3 100644
--- a/src/android_internal/health_hal.h
+++ b/src/android_internal/health_hal.h
@@ -39,7 +39,7 @@
 
 extern "C" {
 
-// Thse functions are not thread safe unless specified otherwise.
+// These functions are not thread safe unless specified otherwise.
 
 bool __attribute__((visibility("default")))
 GetBatteryCounter(BatteryCounter, int64_t*);
diff --git a/src/android_internal/power_stats_hal.cc b/src/android_internal/power_stats_hal.cc
new file mode 100644
index 0000000..9027e4e
--- /dev/null
+++ b/src/android_internal/power_stats_hal.cc
@@ -0,0 +1,110 @@
+/*
+ * 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/power_stats_hal.h"
+
+#include <string.h>
+
+#include <algorithm>
+
+#include <android/hardware/power/stats/1.0/IPowerStats.h>
+
+namespace perfetto {
+namespace android_internal {
+
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::power::stats::V1_0::EnergyData;
+using android::hardware::power::stats::V1_0::IPowerStats;
+using android::hardware::power::stats::V1_0::RailInfo;
+using android::hardware::power::stats::V1_0::Status;
+
+namespace {
+
+android::sp<IPowerStats> g_svc;
+
+bool GetService() {
+  if (!g_svc)
+    g_svc = IPowerStats::getService();
+
+  return g_svc != nullptr;
+}
+
+}  // namespace
+
+bool GetAvailableRails(RailDescriptor* rail_descriptors, size_t* size_of_arr) {
+  const size_t in_array_size = *size_of_arr;
+  *size_of_arr = 0;
+  if (!GetService())
+    return false;
+
+  Status status;
+  auto rails_cb = [rail_descriptors, size_of_arr, &in_array_size, &status](
+                      hidl_vec<RailInfo> r, Status s) {
+    status = s;
+    if (status == Status::SUCCESS) {
+      *size_of_arr = std::min(in_array_size, r.size());
+      for (int i = 0; i < *size_of_arr; ++i) {
+        const RailInfo& rail_info = r[i];
+        RailDescriptor& descriptor = rail_descriptors[i];
+
+        descriptor.index = rail_info.index;
+        descriptor.sampling_rate = rail_info.samplingRate;
+
+        strncpy(descriptor.rail_name, rail_info.railName.c_str(),
+                sizeof(descriptor.rail_name));
+        strncpy(descriptor.subsys_name, rail_info.subsysName.c_str(),
+                sizeof(descriptor.subsys_name));
+        descriptor.rail_name[sizeof(descriptor.rail_name) - 1] = '\0';
+        descriptor.subsys_name[sizeof(descriptor.subsys_name) - 1] = '\0';
+      }
+    }
+  };
+
+  Return<void> ret = g_svc->getRailInfo(rails_cb);
+  return status == Status::SUCCESS;
+}
+
+bool GetRailEnergyData(RailEnergyData* rail_energy_array, size_t* size_of_arr) {
+  const size_t in_array_size = *size_of_arr;
+  *size_of_arr = 0;
+
+  if (!GetService())
+    return false;
+
+  Status status;
+  auto energy_cb = [rail_energy_array, size_of_arr, &in_array_size, &status](
+                       hidl_vec<EnergyData> m, Status s) {
+    status = s;
+    if (status == Status::SUCCESS) {
+      *size_of_arr = std::min(in_array_size, m.size());
+      for (int i = 0; i < *size_of_arr; ++i) {
+        const EnergyData& measurement = m[i];
+        RailEnergyData& element = rail_energy_array[i];
+
+        element.index = measurement.index;
+        element.timestamp = measurement.timestamp;
+        element.energy = measurement.energy;
+      }
+    }
+  };
+
+  Return<void> ret = g_svc->getEnergyData(hidl_vec<uint32_t>(), energy_cb);
+  return status == Status::SUCCESS;
+}
+
+}  // namespace android_internal
+}  // namespace perfetto
diff --git a/src/android_internal/power_stats_hal.h b/src/android_internal/power_stats_hal.h
new file mode 100644
index 0000000..6773b19
--- /dev/null
+++ b/src/android_internal/power_stats_hal.h
@@ -0,0 +1,67 @@
+/*
+ * 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_POWER_STATS_HAL_H_
+#define SRC_ANDROID_INTERNAL_POWER_STATS_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 RailDescriptor {
+  // Index corresponding to the rail
+  uint32_t index;
+  // Name of the rail
+  char rail_name[64];
+  // Name of the subsystem to which this rail belongs
+  char subsys_name[64];
+  // Hardware sampling rate
+  uint32_t sampling_rate;
+};
+
+struct RailEnergyData {
+  // Index corresponding to RailDescriptor.index
+  uint32_t index;
+  // Time since device boot(CLOCK_BOOTTIME) in milli-seconds
+  uint64_t timestamp;
+  // Accumulated energy since device boot in microwatt-seconds (uWs)
+  uint64_t energy;
+};
+
+extern "C" {
+
+// These functions are not thread safe unless specified otherwise.
+
+bool __attribute__((visibility("default")))
+GetAvailableRails(RailDescriptor*, size_t* size_of_arr);
+
+bool __attribute__((visibility("default")))
+GetRailEnergyData(RailEnergyData*, size_t* size_of_arr);
+
+}  // extern "C"
+
+}  // namespace android_internal
+}  // namespace perfetto
+
+#endif  // SRC_ANDROID_INTERNAL_POWER_STATS_HAL_H_
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index e77e4a2..e2c8ec1 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -73,6 +73,7 @@
 # Shared libraries which are directly translated to Android system equivalents.
 library_whitelist = [
     'android.hardware.health@2.0',
+    "android.hardware.power.stats@1.0",
     'android',
     'base',
     'binder',