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',