summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-02-02 23:58:37 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-02-02 23:58:37 +0000
commit5508d331c326a9ffd1426a73698413cb7d578665 (patch)
tree39c8d20886a76130742bb4fdc69749874a21d39e
parentd354261df449fd6148e2b741498a4b32c57bf1a2 (diff)
parente4127a7e5bb05096c138ae44a035f2bf52fecc2b (diff)
downloadpixel-simpleperf-release.tar.gz
Snap for 11400057 from e4127a7e5bb05096c138ae44a035f2bf52fecc2b to simpleperf-releasesimpleperf-release
Change-Id: I9ade56d2e5781f6695c07512c4f29a492284f4ad
-rw-r--r--battery_mitigation/BatteryMitigation.cpp23
-rw-r--r--common/pixel-common-device.mk4
-rw-r--r--health/Android.bp4
-rw-r--r--misc_writer/include/misc_writer/misc_writer.h1
-rw-r--r--misc_writer/misc_writer.cpp17
-rw-r--r--misc_writer/misc_writer_test.cpp5
-rw-r--r--pixelstats/Android.bp9
-rw-r--r--pixelstats/BrownoutDetectedReporter.cpp3
-rw-r--r--pixelstats/ChargeStatsReporter.cpp2
-rw-r--r--pixelstats/DisplayStatsReporter.cpp174
-rw-r--r--pixelstats/MitigationDurationReporter.cpp207
-rw-r--r--pixelstats/SysfsCollector.cpp576
-rw-r--r--pixelstats/UeventListener.cpp35
-rw-r--r--pixelstats/include/pixelstats/DisplayStatsReporter.h69
-rw-r--r--pixelstats/include/pixelstats/MitigationDurationReporter.h82
-rw-r--r--pixelstats/include/pixelstats/SysfsCollector.h34
-rw-r--r--pixelstats/include/pixelstats/UeventListener.h43
-rw-r--r--pixelstats/pixelatoms.proto285
-rw-r--r--power-libperfmgr/aidl/PowerSessionManager.cpp6
-rw-r--r--power-libperfmgr/libperfmgr/FileNode.cc5
-rw-r--r--power-libperfmgr/libperfmgr/HintManager.cc12
-rw-r--r--power-libperfmgr/libperfmgr/include/perfmgr/FileNode.h4
-rw-r--r--power-libperfmgr/libperfmgr/tests/RequestGroupTest.cc2
-rw-r--r--thermal/Android.bp179
-rw-r--r--thermal/Thermal.cpp133
-rw-r--r--thermal/Thermal.h6
-rw-r--r--thermal/tests/mock_thermal_helper.cpp24
-rw-r--r--thermal/tests/mock_thermal_helper.h70
-rw-r--r--thermal/tests/thermal_looper_test.cpp96
-rw-r--r--thermal/thermal-helper.cpp232
-rw-r--r--thermal/thermal-helper.h95
-rw-r--r--thermal/utils/power_files.cpp85
-rw-r--r--thermal/utils/power_files.h13
-rw-r--r--thermal/utils/powerhal_helper.cpp99
-rw-r--r--thermal/utils/powerhal_helper.h28
-rw-r--r--thermal/utils/thermal_files.cpp5
-rw-r--r--thermal/utils/thermal_info.cpp119
-rw-r--r--thermal/utils/thermal_info.h16
-rw-r--r--thermal/utils/thermal_stats_helper.cpp3
-rw-r--r--thermal/utils/thermal_throttling.cpp80
-rw-r--r--thermal/utils/thermal_throttling.h3
-rw-r--r--vibrator/cs40l26/Hardware.h101
-rw-r--r--vibrator/cs40l26/Vibrator.cpp143
-rw-r--r--vibrator/cs40l26/Vibrator.h15
-rw-r--r--vibrator/cs40l26/android.hardware.vibrator-service.cs40l26-dual.rc7
-rw-r--r--vibrator/cs40l26/android.hardware.vibrator-service.cs40l26.rc7
-rw-r--r--vibrator/cs40l26/apex/Android.bp63
-rw-r--r--vibrator/cs40l26/apex/apex_manifest.json4
-rw-r--r--vibrator/cs40l26/apex/com.google.pixel.vibrator.hal.avbpubkeybin1032 -> 0 bytes
-rw-r--r--vibrator/cs40l26/apex/com.google.pixel.vibrator.hal.pem52
-rw-r--r--vibrator/cs40l26/apex/com.google.pixel.vibrator.hal.pk8bin2373 -> 0 bytes
-rw-r--r--vibrator/cs40l26/apex/com.google.pixel.vibrator.hal.x509.pem34
-rw-r--r--vibrator/cs40l26/apex/file_contexts3
-rw-r--r--vibrator/cs40l26/device.mk4
-rw-r--r--vibrator/cs40l26/tests/mocks.h2
-rw-r--r--vibrator/cs40l26/tests/test-vibrator.cpp4
-rw-r--r--vibrator/drv2624/apex/Android.bp59
-rw-r--r--vibrator/drv2624/apex/apex_manifest.json4
-rw-r--r--vibrator/drv2624/apex/com.android.vibrator.drv2624.enable.rc29
-rw-r--r--vibrator/drv2624/apex/com.android.vibrator.drv2624.pem51
-rw-r--r--vibrator/drv2624/apex/com.android.vibrator.drv2624.pk8bin2374 -> 0 bytes
-rw-r--r--vibrator/drv2624/apex/com.android.vibrator.drv2624.pubkeybin1032 -> 0 bytes
-rw-r--r--vibrator/drv2624/apex/com.android.vibrator.drv2624.rc18
-rw-r--r--vibrator/drv2624/apex/com.android.vibrator.drv2624.x509.pem34
-rw-r--r--vibrator/drv2624/apex/com.android.vibrator.drv2624.xml7
-rw-r--r--vibrator/drv2624/apex/file_contexts2
-rw-r--r--vibrator/drv2624/apex/key.pem52
67 files changed, 2684 insertions, 899 deletions
diff --git a/battery_mitigation/BatteryMitigation.cpp b/battery_mitigation/BatteryMitigation.cpp
index 98419fc5..6aadaa48 100644
--- a/battery_mitigation/BatteryMitigation.cpp
+++ b/battery_mitigation/BatteryMitigation.cpp
@@ -18,7 +18,8 @@
#include <sstream>
-#define MAX_BROWNOUT_DATA_AGE_SECONDS 300
+#define MAX_BROWNOUT_DATA_AGE_MINUTES 5
+#define ONE_SECOND_IN_US 1000000
namespace android {
namespace hardware {
@@ -48,8 +49,24 @@ bool BatteryMitigation::isMitigationLogTimeValid(std::chrono::system_clock::time
std::istringstream ss(pattern_match.str());
ss >> std::get_time(&triggeredTimestamp, timestampFormat);
auto logFileTime = std::chrono::system_clock::from_time_t(mktime(&triggeredTimestamp));
- auto delta = std::chrono::duration_cast<std::chrono::seconds>(startTime - logFileTime);
- if ((delta.count() < MAX_BROWNOUT_DATA_AGE_SECONDS) && (delta.count() > 0)) {
+ auto epoch_logFileTime = logFileTime.time_since_epoch().count() / ONE_SECOND_IN_US;
+
+ // Convert start time to same format
+ auto time_sec = std::chrono::system_clock::to_time_t(startTime);
+ struct tm start_tm;
+ std::stringstream oss;
+ localtime_r(&time_sec, &start_tm);
+ oss << std::put_time(&start_tm, timestampFormat) << std::flush;
+ std::tm startTimestamp = {};
+ std::istringstream st(oss.str());
+ st >> std::get_time(&startTimestamp, timestampFormat);
+ auto start = std::chrono::system_clock::from_time_t(mktime(&startTimestamp));
+ auto epoch_startTime = start.time_since_epoch().count() / ONE_SECOND_IN_US;
+
+ auto delta = epoch_startTime - epoch_logFileTime;
+ auto delta_minutes = delta / 60;
+
+ if ((delta_minutes < MAX_BROWNOUT_DATA_AGE_MINUTES) && (delta_minutes >= 0)) {
return true;
}
}
diff --git a/common/pixel-common-device.mk b/common/pixel-common-device.mk
index e9d92957..5df9cda2 100644
--- a/common/pixel-common-device.mk
+++ b/common/pixel-common-device.mk
@@ -4,10 +4,6 @@ PRODUCT_COPY_FILES += \
BOARD_VENDOR_SEPOLICY_DIRS += hardware/google/pixel-sepolicy/common/vendor
SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS += hardware/google/pixel-sepolicy/common/system_ext
-# Write flags to the vendor space in /misc partition.
-PRODUCT_PACKAGES += \
- misc_writer
-
# Enable atrace categories and tools for pixel devices
PRODUCT_PACKAGES += \
atrace_categories.txt.pixel \
diff --git a/health/Android.bp b/health/Android.bp
index 3039431d..3b67e1ec 100644
--- a/health/Android.bp
+++ b/health/Android.bp
@@ -35,13 +35,13 @@ cc_library {
export_shared_lib_headers: [
"android.frameworks.stats-V1-ndk",
- "android.hardware.health-V2-ndk",
+ "android.hardware.health-V3-ndk",
"libpixelatoms_defs",
],
shared_libs: [
"android.frameworks.stats-V1-ndk",
- "android.hardware.health-V2-ndk",
+ "android.hardware.health-V3-ndk",
"libbase",
"libbinder_ndk",
"libcutils",
diff --git a/misc_writer/include/misc_writer/misc_writer.h b/misc_writer/include/misc_writer/misc_writer.h
index ce3da5c8..ba1b6857 100644
--- a/misc_writer/include/misc_writer/misc_writer.h
+++ b/misc_writer/include/misc_writer/misc_writer.h
@@ -61,6 +61,7 @@ class MiscWriter {
static constexpr char kTimeOffset[] = "timeoffset=";
static constexpr uint32_t kMaxRamSizeOffsetInVendorSpace = 192;
static constexpr char kMaxRamSize[] = "max-ram-size=";
+ static constexpr uint32_t kSotaStateOffsetInVendorSpace = 224;
// Minimum and maximum valid value for max-ram-size
static constexpr int32_t kRamSizeDefault = -1;
diff --git a/misc_writer/misc_writer.cpp b/misc_writer/misc_writer.cpp
index 8458649f..216b1883 100644
--- a/misc_writer/misc_writer.cpp
+++ b/misc_writer/misc_writer.cpp
@@ -16,12 +16,12 @@
#include "misc_writer/misc_writer.h"
-#include <string.h>
-
#include <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <bootloader_message/bootloader_message.h>
+#include <string.h>
namespace android {
namespace hardware {
@@ -103,6 +103,19 @@ bool MiscWriter::PerformAction(std::optional<size_t> override_offset) {
LOG(ERROR) << "Failed to write " << content << " at offset " << offset << " : " << err;
return false;
}
+
+ if (action_ == MiscWriterActions::kSetSotaFlag) {
+ content = ::android::base::GetProperty("persist.vendor.nfc.factoryota.state", "");
+ if (content.size() != 0 && content.size() <= 40) {
+ offset = kSotaStateOffsetInVendorSpace;
+ if (std::string err;
+ !WriteMiscPartitionVendorSpace(content.data(), content.size(), offset, &err)) {
+ LOG(ERROR) << "Failed to write " << content << " at offset " << offset << " : " << err;
+ return false;
+ }
+ }
+ }
+
return true;
}
diff --git a/misc_writer/misc_writer_test.cpp b/misc_writer/misc_writer_test.cpp
index 651f6409..495ff686 100644
--- a/misc_writer/misc_writer_test.cpp
+++ b/misc_writer/misc_writer_test.cpp
@@ -20,6 +20,7 @@
#include <vector>
#include <android-base/file.h>
+#include <android-base/properties.h>
#include <bootloader_message/bootloader_message.h>
#include <gtest/gtest.h>
@@ -95,6 +96,10 @@ TEST_F(MiscWriterTest, SetClearSota) {
std::string expected = "enable-sota";
CheckMiscPartitionVendorSpaceContent(32, expected);
+ expected = ::android::base::GetProperty("persist.vendor.nfc.factoryota.state", "");
+ if (expected.size() != 0 && expected.size() <= 40)
+ CheckMiscPartitionVendorSpaceContent(224, expected);
+
// Test we can write to the override offset.
size_t override_offset = 12360;
ASSERT_FALSE(misc_writer_->PerformAction(override_offset));
diff --git a/pixelstats/Android.bp b/pixelstats/Android.bp
index f22a15f1..a0e55a36 100644
--- a/pixelstats/Android.bp
+++ b/pixelstats/Android.bp
@@ -149,9 +149,11 @@ cc_library {
"BatteryHealthReporter.cpp",
"BrownoutDetectedReporter.cpp",
"ChargeStatsReporter.cpp",
+ "DisplayStatsReporter.cpp",
"DropDetect.cpp",
"MmMetricsReporter.cpp",
"MitigationStatsReporter.cpp",
+ "MitigationDurationReporter.cpp",
"PcaChargeStats.cpp",
"StatsHelper.cpp",
"SysfsCollector.cpp",
@@ -186,3 +188,10 @@ cc_library {
],
header_libs: ["chre_api"],
}
+
+filegroup {
+ name: "pixelatoms_proto",
+ srcs: [
+ "pixelatoms.proto",
+ ],
+}
diff --git a/pixelstats/BrownoutDetectedReporter.cpp b/pixelstats/BrownoutDetectedReporter.cpp
index 58edc995..e22d2df7 100644
--- a/pixelstats/BrownoutDetectedReporter.cpp
+++ b/pixelstats/BrownoutDetectedReporter.cpp
@@ -47,6 +47,7 @@ using android::hardware::google::pixel::PixelAtoms::BrownoutDetected;
#define DEFAULT_BATTERY_TEMP 9999999
#define DEFAULT_BATTERY_SOC 100
#define DEFAULT_BATTERY_VOLT 5000000
+#define ONE_SECOND_IN_US 1000000
const std::regex kTimestampPattern("^\\S+\\s[0-9]+:[0-9]+:[0-9]+\\S+$");
const std::regex kIrqPattern("^(\\S+)\\striggered\\sat\\s\\S+$");
@@ -212,7 +213,7 @@ long BrownoutDetectedReporter::parseTimestamp(std::string timestamp) {
std::string timestampFormat = "%Y-%m-%d %H:%M:%S";
if (strptime(timestamp.substr(0, 19).c_str(), timestampFormat.c_str(), &triggeredTimestamp)) {
auto logFileTime = std::chrono::system_clock::from_time_t(mktime(&triggeredTimestamp));
- return logFileTime.time_since_epoch().count();
+ return logFileTime.time_since_epoch().count() / ONE_SECOND_IN_US;
}
return 0;
}
diff --git a/pixelstats/ChargeStatsReporter.cpp b/pixelstats/ChargeStatsReporter.cpp
index e3727b85..2354acd4 100644
--- a/pixelstats/ChargeStatsReporter.cpp
+++ b/pixelstats/ChargeStatsReporter.cpp
@@ -117,6 +117,8 @@ void ChargeStatsReporter::ReportChargeStats(const std::shared_ptr<IStats> &stats
tmp[12] = pca_rs[4];
tmp[14] = pca_rs[1];
if (wline_at.empty()) {
+ /* force adapter type to PPS when pca log is available, but not wlc */
+ tmp[0] = PixelAtoms::ChargeStats::ADAPTER_TYPE_USB_PD_PPS;
tmp[8] = pca_ac[0];
tmp[9] = pca_ac[1];
tmp[13] = pca_rs[0];
diff --git a/pixelstats/DisplayStatsReporter.cpp b/pixelstats/DisplayStatsReporter.cpp
new file mode 100644
index 00000000..3aff2225
--- /dev/null
+++ b/pixelstats/DisplayStatsReporter.cpp
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#define LOG_TAG "pixelstats: DisplayStats"
+
+#include <aidl/android/frameworks/stats/IStats.h>
+#include <android-base/file.h>
+#include <android-base/parseint.h>
+#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <android/binder_manager.h>
+#include <hardware/google/pixel/pixelstats/pixelatoms.pb.h>
+#include <pixelstats/DisplayStatsReporter.h>
+#include <utils/Log.h>
+
+#include <cinttypes>
+
+namespace android {
+namespace hardware {
+namespace google {
+namespace pixel {
+
+using aidl::android::frameworks::stats::IStats;
+using aidl::android::frameworks::stats::VendorAtom;
+using aidl::android::frameworks::stats::VendorAtomValue;
+using android::base::ReadFileToString;
+using android::hardware::google::pixel::PixelAtoms::DisplayPanelErrorStats;
+
+DisplayStatsReporter::DisplayStatsReporter() {}
+
+bool DisplayStatsReporter::readDisplayPanelErrorCount(const std::string &path, int64_t *val) {
+ std::string file_contents;
+
+ if (path.empty()) {
+ return false;
+ }
+
+ if (!ReadFileToString(path.c_str(), &file_contents)) {
+ if (errno != ENOENT) {
+ ALOGD("readDisplayPanelErrorCount Unable to read %s - %s", path.c_str(),
+ strerror(errno));
+ }
+ return false;
+ } else {
+ file_contents = android::base::Trim(file_contents);
+ if (!android::base::ParseInt(file_contents, val)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool DisplayStatsReporter::captureDisplayPanelErrorStats(
+ const std::vector<std::string> &display_stats_paths,
+ struct DisplayPanelErrorStats *pcur_data) {
+ bool report_stats = false;
+ std::string path;
+
+ if (display_stats_paths.size() < kNumOfDisplayPanelErrorStats) {
+ ALOGE("Number of display stats paths (%zu) is less than expected (%d)",
+ display_stats_paths.size(), kNumOfDisplayPanelErrorStats);
+ return false;
+ }
+
+ int64_t index = PixelAtoms::DisplayPanelErrorStats::kPrimaryErrorCountTeFieldNumber;
+ index = index - kVendorAtomOffset;
+ path = display_stats_paths[index];
+
+ // Read primary panel error stats.
+ if (!readDisplayPanelErrorCount(path, &(pcur_data->primary_error_count_te))) {
+ pcur_data->primary_error_count_te = prev_data_.primary_error_count_te;
+ } else {
+ report_stats |= (pcur_data->primary_error_count_te > prev_data_.primary_error_count_te);
+ }
+
+ index = PixelAtoms::DisplayPanelErrorStats::kPrimaryErrorCountUnknownFieldNumber;
+ index = index - kVendorAtomOffset;
+ path = display_stats_paths[index];
+ if (!readDisplayPanelErrorCount(path, &(pcur_data->primary_error_count_unknown))) {
+ pcur_data->primary_error_count_unknown = prev_data_.primary_error_count_unknown;
+ } else {
+ report_stats |=
+ (pcur_data->primary_error_count_unknown > prev_data_.primary_error_count_unknown);
+ }
+
+ // Read secondary panel error stats.
+ index = PixelAtoms::DisplayPanelErrorStats::kSecondaryErrorCountTeFieldNumber;
+ index = index - kVendorAtomOffset;
+ path = display_stats_paths[index];
+ if (!readDisplayPanelErrorCount(path, &(pcur_data->secondary_error_count_te))) {
+ pcur_data->secondary_error_count_te = prev_data_.secondary_error_count_te;
+ } else {
+ report_stats |= (pcur_data->secondary_error_count_te > prev_data_.secondary_error_count_te);
+ }
+
+ index = PixelAtoms::DisplayPanelErrorStats::kSecondaryErrorCountUnknownFieldNumber;
+ index = index - kVendorAtomOffset;
+ path = display_stats_paths[index];
+ if (!readDisplayPanelErrorCount(path, &(pcur_data->secondary_error_count_unknown))) {
+ pcur_data->secondary_error_count_unknown = prev_data_.secondary_error_count_unknown;
+ } else {
+ report_stats |= (pcur_data->secondary_error_count_unknown >
+ prev_data_.secondary_error_count_unknown);
+ }
+
+ return report_stats;
+}
+
+void DisplayStatsReporter::logDisplayPanelErrorStats(
+ const std::shared_ptr<IStats> &stats_client,
+ const std::vector<std::string> &display_stats_paths) {
+ struct DisplayPanelErrorStats cur_data = prev_data_;
+
+ if (!captureDisplayPanelErrorStats(display_stats_paths, &cur_data)) {
+ prev_data_ = cur_data;
+ return;
+ }
+
+ VendorAtomValue tmp;
+ int64_t max_error_count = static_cast<int64_t>(INT32_MAX);
+ int error_count;
+ std::vector<VendorAtomValue> values(kNumOfDisplayPanelErrorStats);
+
+ error_count = std::min<int64_t>(
+ cur_data.primary_error_count_te - prev_data_.primary_error_count_te, max_error_count);
+ tmp.set<VendorAtomValue::intValue>(error_count);
+ int64_t index = PixelAtoms::DisplayPanelErrorStats::kPrimaryErrorCountTeFieldNumber;
+ index = index - kVendorAtomOffset;
+ values[index] = tmp;
+
+ error_count = std::min<int64_t>(
+ cur_data.primary_error_count_unknown - prev_data_.primary_error_count_unknown,
+ max_error_count);
+ tmp.set<VendorAtomValue::intValue>(error_count);
+ index = PixelAtoms::DisplayPanelErrorStats::kPrimaryErrorCountUnknownFieldNumber;
+ index = index - kVendorAtomOffset;
+ values[index] = tmp;
+
+ prev_data_ = cur_data;
+
+ ALOGD("Report updated display panel metrics to stats service");
+ // Send vendor atom to IStats HAL
+ VendorAtom event = {.reverseDomainName = "",
+ .atomId = PixelAtoms::Atom::kDisplayPanelErrorStats,
+ .values = std::move(values)};
+ const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
+ if (!ret.isOk())
+ ALOGE("Unable to report display Display Panel stats to Stats service");
+}
+
+void DisplayStatsReporter::logDisplayStats(const std::shared_ptr<IStats> &stats_client,
+ const std::vector<std::string> &display_stats_paths) {
+ logDisplayPanelErrorStats(stats_client, display_stats_paths);
+}
+
+} // namespace pixel
+} // namespace google
+} // namespace hardware
+} // namespace android
diff --git a/pixelstats/MitigationDurationReporter.cpp b/pixelstats/MitigationDurationReporter.cpp
new file mode 100644
index 00000000..b9518f63
--- /dev/null
+++ b/pixelstats/MitigationDurationReporter.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#define LOG_TAG "pixelstats: PowerMitigationDurationCounts"
+
+#include <aidl/android/frameworks/stats/IStats.h>
+#include <android-base/file.h>
+#include <android-base/parseint.h>
+#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <android/binder_manager.h>
+#include <hardware/google/pixel/pixelstats/pixelatoms.pb.h>
+#include <pixelstats/MitigationDurationReporter.h>
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace google {
+namespace pixel {
+
+using aidl::android::frameworks::stats::IStats;
+using aidl::android::frameworks::stats::VendorAtom;
+using aidl::android::frameworks::stats::VendorAtomValue;
+using android::base::ReadFileToString;
+using android::hardware::google::pixel::PixelAtoms::PowerMitigationDurationCounts;
+
+enum DurationOutputOrder {
+ UVLO1,
+ UVLO1_MMWAVE,
+ UVLO1_RFFE,
+ UVLO2,
+ UVLO2_MMWAVE,
+ UVLO2_RFFE,
+ BATOILO,
+ BATOILO_MMWAVE,
+ BATOILO_RFFE,
+ MAIN0,
+ MAIN1,
+ MAIN2,
+ MAIN3,
+ MAIN4,
+ MAIN5,
+ MAIN6,
+ MAIN7,
+ MAIN8,
+ MAIN9,
+ MAIN10,
+ MAIN11,
+ SUB0,
+ SUB1,
+ SUB2,
+ SUB3,
+ SUB4,
+ SUB5,
+ SUB6,
+ SUB7,
+ SUB8,
+ SUB9,
+ SUB10,
+ SUB11,
+};
+
+MitigationDurationReporter::MitigationDurationReporter() {}
+
+bool MitigationDurationReporter::getStatFromLine(const std::string *line, int *val) {
+ std::vector<std::string> strs = android::base::Split(*line, ":");
+ if (strs.size() != 2) {
+ ALOGI("Unable to split %s", line->c_str());
+ return false;
+ }
+ std::string str = strs[1];
+ str = android::base::Trim(str);
+ str.erase(std::remove(str.begin(), str.end(), '\n'), str.cend());
+ if (!android::base::ParseInt(str, val)) {
+ ALOGI("Unable to convert %s to int - %s", str.c_str(), strerror(errno));
+ return false;
+ }
+ return true;
+}
+
+void MitigationDurationReporter::valueAssignmentHelper(std::vector<VendorAtomValue> *values,
+ int *val, int fieldNumber) {
+ VendorAtomValue tmp;
+ tmp.set<VendorAtomValue::intValue>(*val);
+ (*values)[fieldNumber - kVendorAtomOffset] = tmp;
+}
+
+void MitigationDurationReporter::logMitigationDuration(const std::shared_ptr<IStats> &stats_client,
+ const std::string &path) {
+ struct IrqDurationCounts greater_than_thresh = {};
+
+ if (!getIrqDurationCountHelper(path + kGreaterThanTenMsSysfsNode, &greater_than_thresh))
+ return;
+
+ VendorAtomValue tmp;
+ std::vector<VendorAtomValue> values(33);
+
+ valueAssignmentHelper(&values, &greater_than_thresh.uvlo1_none,
+ PowerMitigationDurationCounts::kGreaterThanThreshUvlo1NoneFieldNumber);
+ valueAssignmentHelper(&values, &greater_than_thresh.uvlo1_mmwave,
+ PowerMitigationDurationCounts::kGreaterThanThreshUvlo1MmwaveFieldNumber);
+ valueAssignmentHelper(&values, &greater_than_thresh.uvlo1_rffe,
+ PowerMitigationDurationCounts::kGreaterThanThreshUvlo1RffeFieldNumber);
+
+ valueAssignmentHelper(&values, &greater_than_thresh.uvlo2_none,
+ PowerMitigationDurationCounts::kGreaterThanThreshUvlo2NoneFieldNumber);
+ valueAssignmentHelper(&values, &greater_than_thresh.uvlo2_mmwave,
+ PowerMitigationDurationCounts::kGreaterThanThreshUvlo2MmwaveFieldNumber);
+ valueAssignmentHelper(&values, &greater_than_thresh.uvlo2_rffe,
+ PowerMitigationDurationCounts::kGreaterThanThreshUvlo2RffeFieldNumber);
+
+ valueAssignmentHelper(&values, &greater_than_thresh.batoilo_none,
+ PowerMitigationDurationCounts::kGreaterThanThreshBatoiloNoneFieldNumber);
+ valueAssignmentHelper(
+ &values, &greater_than_thresh.batoilo_mmwave,
+ PowerMitigationDurationCounts::kGreaterThanThreshBatoiloMmwaveFieldNumber);
+ valueAssignmentHelper(&values, &greater_than_thresh.batoilo_rffe,
+ PowerMitigationDurationCounts::kGreaterThanThreshBatoiloRffeFieldNumber);
+
+ int i;
+ for (i = 0; i < MITIGATION_DURATION_MAIN_COUNT; i++) {
+ valueAssignmentHelper(
+ &values, &greater_than_thresh.main[i],
+ PowerMitigationDurationCounts::kGreaterThanThreshMain0FieldNumber + i);
+ }
+
+ for (i = 0; i < MITIGATION_DURATION_SUB_COUNT; i++) {
+ valueAssignmentHelper(&values, &greater_than_thresh.sub[i],
+ PowerMitigationDurationCounts::kGreaterThanThreshSub0FieldNumber + i);
+ }
+
+ // Send vendor atom to IStats HAL
+ VendorAtom event = {.reverseDomainName = "",
+ .atomId = PixelAtoms::Atom::kMitigationDuration,
+ .values = std::move(values)};
+ const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
+ if (!ret.isOk())
+ ALOGE("Unable to report to Stats service");
+}
+
+int MitigationDurationReporter::updateStat(const std::string *line, int *val) {
+ int stat_value;
+ if (!getStatFromLine(line, &stat_value) || *val == stat_value) {
+ return 0;
+ }
+
+ *val = stat_value;
+ return 1;
+}
+
+bool MitigationDurationReporter::getIrqDurationCountHelper(
+ const std::string kMitigationDurationFile, struct IrqDurationCounts *counts) {
+ std::string file_contents;
+
+ if (!ReadFileToString(kMitigationDurationFile, &file_contents)) {
+ ALOGI("Unable to read %s - %s", kMitigationDurationFile.c_str(), strerror(errno));
+ return false;
+ }
+
+ std::vector<std::string> lines = android::base::Split(file_contents, "\n");
+ if (lines.size() < kExpectedNumberOfLines) {
+ ALOGI("Readback size is invalid");
+ return false;
+ }
+
+ int16_t i;
+ int num_stats = 0;
+
+ num_stats += updateStat(&lines[UVLO1], &counts->uvlo1_none);
+ num_stats += updateStat(&lines[UVLO1_MMWAVE], &counts->uvlo1_mmwave);
+ num_stats += updateStat(&lines[UVLO1_RFFE], &counts->uvlo1_rffe);
+ num_stats += updateStat(&lines[UVLO2], &counts->uvlo2_none);
+ num_stats += updateStat(&lines[UVLO2_MMWAVE], &counts->uvlo2_mmwave);
+ num_stats += updateStat(&lines[UVLO2_RFFE], &counts->uvlo2_rffe);
+ num_stats += updateStat(&lines[BATOILO], &counts->batoilo_none);
+ num_stats += updateStat(&lines[BATOILO_MMWAVE], &counts->batoilo_mmwave);
+ num_stats += updateStat(&lines[BATOILO_RFFE], &counts->batoilo_rffe);
+
+ for (i = MAIN0; i <= MAIN11; i++) {
+ num_stats += updateStat(&lines[i], &counts->main[i - MAIN0]);
+ }
+
+ for (i = SUB0; i <= SUB11; i++) {
+ num_stats += updateStat(&lines[i], &counts->sub[i - SUB0]);
+ }
+
+ return num_stats > 0;
+}
+
+} // namespace pixel
+} // namespace google
+} // namespace hardware
+} // namespace android
diff --git a/pixelstats/SysfsCollector.cpp b/pixelstats/SysfsCollector.cpp
index f4cef9bf..4460ca1c 100644
--- a/pixelstats/SysfsCollector.cpp
+++ b/pixelstats/SysfsCollector.cpp
@@ -50,6 +50,7 @@ using android::base::WriteStringToFile;
using android::hardware::google::pixel::PixelAtoms::BatteryCapacity;
using android::hardware::google::pixel::PixelAtoms::BlockStatsReported;
using android::hardware::google::pixel::PixelAtoms::BootStatsInfo;
+using android::hardware::google::pixel::PixelAtoms::DisplayPanelErrorStats;
using android::hardware::google::pixel::PixelAtoms::F2fsAtomicWriteInfo;
using android::hardware::google::pixel::PixelAtoms::F2fsCompressionInfo;
using android::hardware::google::pixel::PixelAtoms::F2fsGcSegmentInfo;
@@ -60,7 +61,11 @@ using android::hardware::google::pixel::PixelAtoms::PcieLinkStatsReported;
using android::hardware::google::pixel::PixelAtoms::StorageUfsHealth;
using android::hardware::google::pixel::PixelAtoms::StorageUfsResetCount;
using android::hardware::google::pixel::PixelAtoms::ThermalDfsStats;
+using android::hardware::google::pixel::PixelAtoms::VendorAudioAdaptedInfoStatsReported;
using android::hardware::google::pixel::PixelAtoms::VendorAudioHardwareStatsReported;
+using android::hardware::google::pixel::PixelAtoms::VendorAudioPcmStatsReported;
+using android::hardware::google::pixel::PixelAtoms::VendorAudioPdmStatsReported;
+using android::hardware::google::pixel::PixelAtoms::VendorAudioThirdPartyEffectStatsReported;
using android::hardware::google::pixel::PixelAtoms::VendorChargeCycles;
using android::hardware::google::pixel::PixelAtoms::VendorHardwareFailed;
using android::hardware::google::pixel::PixelAtoms::VendorLongIRQStatsReported;
@@ -95,6 +100,7 @@ SysfsCollector::SysfsCollector(const struct SysfsPaths &sysfs_paths)
kBrownoutLogPath(sysfs_paths.BrownoutLogPath),
kBrownoutReasonProp(sysfs_paths.BrownoutReasonProp),
kPowerMitigationStatsPath(sysfs_paths.MitigationPath),
+ kPowerMitigationDurationPath(sysfs_paths.MitigationDurationPath),
kSpeakerTemperaturePath(sysfs_paths.SpeakerTemperaturePath),
kSpeakerExcursionPath(sysfs_paths.SpeakerExcursionPath),
kSpeakerHeartbeatPath(sysfs_paths.SpeakerHeartBeatPath),
@@ -105,9 +111,19 @@ SysfsCollector::SysfsCollector(const struct SysfsPaths &sysfs_paths)
kCCARatePath(sysfs_paths.CCARatePath),
kTempResidencyAndResetPaths(sysfs_paths.TempResidencyAndResetPaths),
kLongIRQMetricsPath(sysfs_paths.LongIRQMetricsPath),
+ kStormIRQMetricsPath(sysfs_paths.StormIRQMetricsPath),
+ kIRQStatsResetPath(sysfs_paths.IRQStatsResetPath),
kResumeLatencyMetricsPath(sysfs_paths.ResumeLatencyMetricsPath),
kModemPcieLinkStatsPath(sysfs_paths.ModemPcieLinkStatsPath),
- kWifiPcieLinkStatsPath(sysfs_paths.WifiPcieLinkStatsPath) {}
+ kWifiPcieLinkStatsPath(sysfs_paths.WifiPcieLinkStatsPath),
+ kDisplayStatsPaths(sysfs_paths.DisplayStatsPaths),
+ kPDMStatePath(sysfs_paths.PDMStatePath),
+ kWavesPath(sysfs_paths.WavesPath),
+ kAdaptedInfoCountPath(sysfs_paths.AdaptedInfoCountPath),
+ kAdaptedInfoDurationPath(sysfs_paths.AdaptedInfoDurationPath),
+ kPcmLatencyPath(sysfs_paths.PcmLatencyPath),
+ kPcmCountPath(sysfs_paths.PcmCountPath),
+ kTotalCallCountPath(sysfs_paths.TotalCallCountPath) {}
bool SysfsCollector::ReadFileToInt(const std::string &path, int *val) {
return ReadFileToInt(path.c_str(), val);
@@ -385,6 +401,10 @@ void SysfsCollector::logSpeakerHealthStats(const std::shared_ptr<IStats> &stats_
}
}
+void SysfsCollector::logDisplayStats(const std::shared_ptr<IStats> &stats_client) {
+ display_stats_reporter_.logDisplayStats(stats_client, kDisplayStatsPaths);
+}
+
void SysfsCollector::logThermalStats(const std::shared_ptr<IStats> &stats_client) {
thermal_stats_reporter_.logThermalStats(stats_client, kThermalStatsPaths);
}
@@ -1064,7 +1084,8 @@ void SysfsCollector::logBootStats(const std::shared_ptr<IStats> &stats_client) {
*/
void SysfsCollector::logVendorAudioHardwareStats(const std::shared_ptr<IStats> &stats_client) {
std::string file_contents;
- uint32_t milli_ams_rate, cca_active_rate, cca_enable_rate;
+ uint32_t milli_ams_rate, c1, c2, c3, c4;
+ uint32_t total_call_voice = 0, total_call_voip = 0;
bool isAmsReady = false, isCCAReady = false;
if (kAmsRatePath == nullptr) {
@@ -1088,12 +1109,22 @@ void SysfsCollector::logVendorAudioHardwareStats(const std::shared_ptr<IStats> &
if (!ReadFileToString(kCCARatePath, &file_contents)) {
ALOGD("Unable to read cca_rate path %s", kCCARatePath);
} else {
- if (sscanf(file_contents.c_str(), "%u,%u", &cca_active_rate, &cca_enable_rate) != 2) {
+ if (sscanf(file_contents.c_str(), "%u %u %u %u", &c1, &c2, &c3, &c4) != 4) {
ALOGD("Unable to parse cca rates %s", file_contents.c_str());
} else {
isCCAReady = true;
- ALOGD("cca_active_rate = %u, cca_enable_rate = %u", cca_active_rate,
- cca_enable_rate);
+ }
+ }
+ }
+
+ if (kTotalCallCountPath == nullptr) {
+ ALOGD("Total call count path not specified");
+ } else {
+ if (!ReadFileToString(kTotalCallCountPath, &file_contents)) {
+ ALOGD("Unable to read total call path %s", kTotalCallCountPath);
+ } else {
+ if (sscanf(file_contents.c_str(), "%u %u", &total_call_voice, &total_call_voip) != 2) {
+ ALOGD("Unable to parse total call %s", file_contents.c_str());
}
}
}
@@ -1103,33 +1134,392 @@ void SysfsCollector::logVendorAudioHardwareStats(const std::shared_ptr<IStats> &
return;
}
- std::vector<VendorAtomValue> values(3);
- VendorAtomValue tmp;
+ // Sending ams_rate, total_call, c1 and c2
+ {
+ std::vector<VendorAtomValue> values(7);
+ VendorAtomValue tmp;
+
+ if (isAmsReady) {
+ tmp.set<VendorAtomValue::intValue>(milli_ams_rate);
+ values[VendorAudioHardwareStatsReported::kMilliRateOfAmsPerDayFieldNumber -
+ kVendorAtomOffset] = tmp;
+ }
+
+ tmp.set<VendorAtomValue::intValue>(1);
+ values[VendorAudioHardwareStatsReported::kSourceFieldNumber - kVendorAtomOffset] = tmp;
- if (isAmsReady) {
- tmp.set<VendorAtomValue::intValue>(milli_ams_rate);
- values[VendorAudioHardwareStatsReported::kMilliRateOfAmsPerDayFieldNumber -
+ if (isCCAReady) {
+ tmp.set<VendorAtomValue::intValue>(c1);
+ values[VendorAudioHardwareStatsReported::kCcaActiveCountPerDayFieldNumber -
+ kVendorAtomOffset] = tmp;
+
+ tmp.set<VendorAtomValue::intValue>(c2);
+ values[VendorAudioHardwareStatsReported::kCcaEnableCountPerDayFieldNumber -
+ kVendorAtomOffset] = tmp;
+ }
+
+ tmp.set<VendorAtomValue::intValue>(total_call_voice);
+ values[VendorAudioHardwareStatsReported::kTotalCallCountPerDayFieldNumber -
kVendorAtomOffset] = tmp;
+
+ // Send vendor atom to IStats HAL
+ VendorAtom event = {.reverseDomainName = "",
+ .atomId = PixelAtoms::Atom::kVendorAudioHardwareStatsReported,
+ .values = std::move(values)};
+ const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
+ if (!ret.isOk())
+ ALOGE("Unable to report VendorAudioHardwareStatsReported to Stats service");
+ }
+
+ // Sending total_call, c3 and c4
+ {
+ std::vector<VendorAtomValue> values(7);
+ VendorAtomValue tmp;
+
+ tmp.set<VendorAtomValue::intValue>(0);
+ values[VendorAudioHardwareStatsReported::kSourceFieldNumber - kVendorAtomOffset] = tmp;
+
+ if (isCCAReady) {
+ tmp.set<VendorAtomValue::intValue>(c3);
+ values[VendorAudioHardwareStatsReported::kCcaActiveCountPerDayFieldNumber -
+ kVendorAtomOffset] = tmp;
+
+ tmp.set<VendorAtomValue::intValue>(c4);
+ values[VendorAudioHardwareStatsReported::kCcaEnableCountPerDayFieldNumber -
+ kVendorAtomOffset] = tmp;
+ }
+
+ tmp.set<VendorAtomValue::intValue>(total_call_voip);
+ values[VendorAudioHardwareStatsReported::kTotalCallCountPerDayFieldNumber -
+ kVendorAtomOffset] = tmp;
+
+ // Send vendor atom to IStats HAL
+ VendorAtom event = {.reverseDomainName = "",
+ .atomId = PixelAtoms::Atom::kVendorAudioHardwareStatsReported,
+ .values = std::move(values)};
+ const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
+ if (!ret.isOk())
+ ALOGE("Unable to report VendorAudioHardwareStatsReported to Stats service");
+ }
+}
+
+/**
+ * Report PDM States which indicates microphone background noise level.
+ * This function will report at most 4 atoms showing different background noise type.
+ */
+void SysfsCollector::logVendorAudioPdmStatsReported(const std::shared_ptr<IStats> &stats_client) {
+ std::string file_contents;
+ std::vector<int> pdm_states;
+
+ if (kPDMStatePath == nullptr) {
+ ALOGD("Audio PDM State path not specified");
+ } else {
+ if (!ReadFileToString(kPDMStatePath, &file_contents)) {
+ ALOGD("Unable to read PDM State path %s", kPDMStatePath);
+ } else {
+ std::stringstream file_content_stream(file_contents);
+ while (file_content_stream.good()) {
+ std::string substr;
+ int state;
+ getline(file_content_stream, substr, ',');
+ if (sscanf(substr.c_str(), "%d", &state) != 1) {
+ ALOGD("Unable to parse PDM State %s", file_contents.c_str());
+ } else {
+ pdm_states.push_back(state);
+ ALOGD("Parsed PDM State: %d", state);
+ }
+ }
+ }
+ }
+ if (pdm_states.empty()) {
+ ALOGD("Empty PDM State parsed.");
+ return;
+ }
+
+ if (pdm_states.size() > 4) {
+ ALOGD("Too many values parsed.");
+ return;
+ }
+
+ for (int index = 0; index < pdm_states.size(); index++) {
+ std::vector<VendorAtomValue> values(2);
+ VendorAtomValue tmp;
+
+ if (pdm_states[index] == 0) {
+ continue;
+ }
+
+ tmp.set<VendorAtomValue::intValue>(index);
+ values[VendorAudioPdmStatsReported::kPdmIndexFieldNumber - kVendorAtomOffset] = tmp;
+
+ tmp.set<VendorAtomValue::intValue>(pdm_states[index]);
+ values[VendorAudioPdmStatsReported::kStateFieldNumber - kVendorAtomOffset] = tmp;
+
+ // Send vendor atom to IStats HAL
+ VendorAtom event = {.reverseDomainName = "",
+ .atomId = PixelAtoms::Atom::kVendorAudioPdmStatsReported,
+ .values = std::move(values)};
+
+ const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
+ if (!ret.isOk())
+ ALOGE("Unable to report VendorAudioPdmStatsReported at index %d", index);
+ }
+}
+
+/**
+ * Report Third party audio effects stats.
+ * This function will report at most 5 atoms showing different instance stats.
+ */
+void SysfsCollector::logWavesStats(const std::shared_ptr<IStats> &stats_client) {
+ std::string file_contents;
+ std::vector<std::vector<int>> volume_duration_per_instance;
+
+ constexpr int num_instances = 5;
+ constexpr int num_volume = 10;
+
+ if (kWavesPath == nullptr) {
+ ALOGD("Audio Waves stats path not specified");
+ return;
+ }
+
+ if (!ReadFileToString(kWavesPath, &file_contents)) {
+ ALOGD("Unable to read Wave stats path %s", kWavesPath);
+ } else {
+ std::stringstream file_content_stream(file_contents);
+ int duration;
+ std::vector<int> volume_duration;
+ while (file_content_stream.good() && file_content_stream >> duration) {
+ volume_duration.push_back(duration);
+ if (volume_duration.size() >= num_volume) {
+ volume_duration_per_instance.push_back(volume_duration);
+ volume_duration.clear();
+ }
+ }
+ }
+
+ if (volume_duration_per_instance.size() != num_instances) {
+ ALOGE("Number of instances %zu doesn't match the correct number %d",
+ volume_duration_per_instance.size(), num_instances);
+ return;
+ }
+ for (int i = 0; i < volume_duration_per_instance.size(); i++) {
+ if (volume_duration_per_instance[i].size() != num_volume) {
+ ALOGE("Number of volume %zu doesn't match the correct number %d",
+ volume_duration_per_instance[i].size(), num_volume);
+ return;
+ }
+ }
+
+ std::vector<int> volume_range_field_numbers = {
+ VendorAudioThirdPartyEffectStatsReported::kVolumeRange0ActiveMsPerDayFieldNumber,
+ VendorAudioThirdPartyEffectStatsReported::kVolumeRange1ActiveMsPerDayFieldNumber,
+ VendorAudioThirdPartyEffectStatsReported::kVolumeRange2ActiveMsPerDayFieldNumber,
+ VendorAudioThirdPartyEffectStatsReported::kVolumeRange3ActiveMsPerDayFieldNumber,
+ VendorAudioThirdPartyEffectStatsReported::kVolumeRange4ActiveMsPerDayFieldNumber,
+ VendorAudioThirdPartyEffectStatsReported::kVolumeRange5ActiveMsPerDayFieldNumber,
+ VendorAudioThirdPartyEffectStatsReported::kVolumeRange6ActiveMsPerDayFieldNumber,
+ VendorAudioThirdPartyEffectStatsReported::kVolumeRange7ActiveMsPerDayFieldNumber,
+ VendorAudioThirdPartyEffectStatsReported::kVolumeRange8ActiveMsPerDayFieldNumber,
+ VendorAudioThirdPartyEffectStatsReported::kVolumeRange9ActiveMsPerDayFieldNumber};
+
+ for (int index = 0; index < volume_duration_per_instance.size(); index++) {
+ std::vector<VendorAtomValue> values(11);
+ VendorAtomValue tmp;
+
+ bool has_value = false;
+ for (int volume_index = 0; volume_index < num_volume; volume_index++) {
+ if (volume_duration_per_instance[index][volume_index] > 0) {
+ has_value = true;
+ }
+ }
+ if (!has_value) {
+ continue;
+ }
+
+ tmp.set<VendorAtomValue::intValue>(index);
+ values[VendorAudioThirdPartyEffectStatsReported::kInstanceFieldNumber - kVendorAtomOffset] =
+ tmp;
+
+ for (int volume_index = 0; volume_index < num_volume; volume_index++) {
+ tmp.set<VendorAtomValue::intValue>(volume_duration_per_instance[index][volume_index]);
+ values[volume_range_field_numbers[volume_index] - kVendorAtomOffset] = tmp;
+ }
+ // Send vendor atom to IStats HAL
+ VendorAtom event = {.reverseDomainName = "",
+ .atomId = PixelAtoms::Atom::kVendorAudioThirdPartyEffectStatsReported,
+ .values = std::move(values)};
+
+ const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
+ if (!ret.isOk())
+ ALOGE("Unable to report VendorAudioThirdPartyEffectStatsReported at index %d", index);
+ }
+}
+
+/**
+ * Report Audio Adapted Information stats such as thermal throttling.
+ * This function will report at most 6 atoms showing different instance stats.
+ */
+void SysfsCollector::logAdaptedInfoStats(const std::shared_ptr<IStats> &stats_client) {
+ std::string file_contents;
+ std::vector<int> count_per_feature;
+ std::vector<int> duration_per_feature;
+
+ constexpr int num_features = 6;
+
+ if (kAdaptedInfoCountPath == nullptr) {
+ ALOGD("Audio Adapted Info Count stats path not specified");
+ return;
+ }
+
+ if (kAdaptedInfoDurationPath == nullptr) {
+ ALOGD("Audio Adapted Info Duration stats path not specified");
+ return;
+ }
+
+ if (!ReadFileToString(kAdaptedInfoCountPath, &file_contents)) {
+ ALOGD("Unable to read Adapted Info Count stats path %s", kAdaptedInfoCountPath);
+ } else {
+ std::stringstream file_content_stream(file_contents);
+ int count;
+ while (file_content_stream.good() && file_content_stream >> count) {
+ count_per_feature.push_back(count);
+ }
}
- if (isCCAReady) {
- tmp.set<VendorAtomValue::intValue>(cca_active_rate);
- values[VendorAudioHardwareStatsReported::kRateOfCcaActivePerDayFieldNumber -
+ if (count_per_feature.size() != num_features) {
+ ALOGD("Audio Adapted Info Count doesn't match the number of features. %zu / %d",
+ count_per_feature.size(), num_features);
+ return;
+ }
+
+ if (!ReadFileToString(kAdaptedInfoDurationPath, &file_contents)) {
+ ALOGD("Unable to read Adapted Info Duration stats path %s", kAdaptedInfoDurationPath);
+ } else {
+ std::stringstream file_content_stream(file_contents);
+ int duration;
+ while (file_content_stream.good() && file_content_stream >> duration) {
+ duration_per_feature.push_back(duration);
+ }
+ }
+
+ if (duration_per_feature.size() != num_features) {
+ ALOGD("Audio Adapted Info Duration doesn't match the number of features. %zu / %d",
+ duration_per_feature.size(), num_features);
+ return;
+ }
+
+ for (int index = 0; index < num_features; index++) {
+ std::vector<VendorAtomValue> values(3);
+ VendorAtomValue tmp;
+
+ if (count_per_feature[index] == 0 && duration_per_feature[index] == 0) {
+ continue;
+ }
+
+ tmp.set<VendorAtomValue::intValue>(index);
+ values[VendorAudioAdaptedInfoStatsReported::kFeatureIdFieldNumber - kVendorAtomOffset] =
+ tmp;
+
+ tmp.set<VendorAtomValue::intValue>(count_per_feature[index]);
+ values[VendorAudioAdaptedInfoStatsReported::kActiveCountsPerDayFieldNumber -
kVendorAtomOffset] = tmp;
- tmp.set<VendorAtomValue::intValue>(cca_enable_rate);
- values[VendorAudioHardwareStatsReported::kRateOfCcaEnablePerDayFieldNumber -
+ tmp.set<VendorAtomValue::intValue>(duration_per_feature[index]);
+ values[VendorAudioAdaptedInfoStatsReported::kActiveDurationMsPerDayFieldNumber -
kVendorAtomOffset] = tmp;
+
+ // Send vendor atom to IStats HAL
+ VendorAtom event = {.reverseDomainName = "",
+ .atomId = PixelAtoms::Atom::kVendorAudioAdaptedInfoStatsReported,
+ .values = std::move(values)};
+
+ const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
+ if (!ret.isOk())
+ ALOGE("Unable to report VendorAudioAdaptedInfoStatsReported at index %d", index);
}
+}
- // Send vendor atom to IStats HAL
- VendorAtom event = {.reverseDomainName = "",
- .atomId = PixelAtoms::Atom::kVendorAudioHardwareStatsReported,
- .values = std::move(values)};
+/**
+ * Report audio PCM usage stats such as latency and active count.
+ * This function will report at most 19 atoms showing different PCM type.
+ */
+void SysfsCollector::logPcmUsageStats(const std::shared_ptr<IStats> &stats_client) {
+ std::string file_contents;
+ std::vector<int> count_per_type;
+ std::vector<int> latency_per_type;
- const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
- if (!ret.isOk())
- ALOGE("Unable to report VendorAudioHardwareStatsReported to Stats service");
+ constexpr int num_type = 19;
+
+ if (kPcmLatencyPath == nullptr) {
+ ALOGD("PCM Latency path not specified");
+ return;
+ }
+
+ if (kPcmCountPath == nullptr) {
+ ALOGD("PCM Count path not specified");
+ return;
+ }
+
+ if (!ReadFileToString(kPcmCountPath, &file_contents)) {
+ ALOGD("Unable to read PCM Count path %s", kPcmCountPath);
+ } else {
+ std::stringstream file_content_stream(file_contents);
+ int count;
+ while (file_content_stream.good() && file_content_stream >> count) {
+ count_per_type.push_back(count);
+ }
+ }
+
+ if (count_per_type.size() != num_type) {
+ ALOGD("Audio PCM Count path doesn't match the number of features. %zu / %d",
+ count_per_type.size(), num_type);
+ return;
+ }
+
+ if (!ReadFileToString(kPcmLatencyPath, &file_contents)) {
+ ALOGD("Unable to read PCM Latency path %s", kPcmLatencyPath);
+ } else {
+ std::stringstream file_content_stream(file_contents);
+ int duration;
+ while (file_content_stream.good() && file_content_stream >> duration) {
+ latency_per_type.push_back(duration);
+ }
+ }
+
+ if (latency_per_type.size() != num_type) {
+ ALOGD("Audio PCM Latency path doesn't match the number of features. %zu / %d",
+ latency_per_type.size(), num_type);
+ return;
+ }
+
+ for (int index = 0; index < num_type; index++) {
+ std::vector<VendorAtomValue> values(3);
+ VendorAtomValue tmp;
+
+ if (latency_per_type[index] == 0 && count_per_type[index] == 0) {
+ continue;
+ }
+
+ tmp.set<VendorAtomValue::intValue>(index);
+ values[VendorAudioPcmStatsReported::kTypeFieldNumber - kVendorAtomOffset] = tmp;
+
+ tmp.set<VendorAtomValue::intValue>(latency_per_type[index]);
+ values[VendorAudioPcmStatsReported::kPcmOpenLatencyAvgMsPerDayFieldNumber -
+ kVendorAtomOffset] = tmp;
+
+ tmp.set<VendorAtomValue::intValue>(count_per_type[index]);
+ values[VendorAudioPcmStatsReported::kPcmActiveCountsPerDayFieldNumber - kVendorAtomOffset] =
+ tmp;
+
+ // Send vendor atom to IStats HAL
+ VendorAtom event = {.reverseDomainName = "",
+ .atomId = PixelAtoms::Atom::kVendorAudioPcmStatsReported,
+ .values = std::move(values)};
+
+ const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
+ if (!ret.isOk())
+ ALOGE("Unable to report VendorAudioPcmStatsReported at index %d", index);
+ }
}
/**
@@ -1233,18 +1623,24 @@ void SysfsCollector::logVendorResumeLatencyStats(const std::shared_ptr<IStats> &
ALOGE("Unable to report VendorResumeLatencyStats to Stats service");
}
-bool cmp(const std::pair<int, int64_t> &a, const std::pair<int, int64_t> &b) {
- return a.second > b.second;
-}
-
/**
- * Sort irq stats by irq latency, and load top 5 irq stats.
+ * Read and store top 5 irq stats.
*/
-void process_irqatom_values(std::vector<std::pair<int, int64_t>> sorted_pair,
+void process_irqatom_values(std::string file_contents, int *offset,
std::vector<VendorAtomValue> *values) {
+ const char *data = file_contents.c_str();
+ int bytes_read;
+ int64_t irq_data;
+ int irq_num;
+
+ std::vector<std::pair<int, int64_t>> irq_pair;
+
+ while (sscanf(data + *offset, "%d %" PRId64 "\n%n", &irq_num, &irq_data, &bytes_read) == 2) {
+ irq_pair.push_back(std::make_pair(irq_num, irq_data));
+ *offset += bytes_read;
+ }
VendorAtomValue tmp;
- sort(sorted_pair.begin(), sorted_pair.end(), cmp);
- int irq_stats_size = sorted_pair.size();
+ int irq_stats_size = irq_pair.size();
for (int i = 0; i < 5; i++) {
if (irq_stats_size < 5 && i >= irq_stats_size) {
tmp.set<VendorAtomValue::longValue>(-1);
@@ -1252,9 +1648,9 @@ void process_irqatom_values(std::vector<std::pair<int, int64_t>> sorted_pair,
tmp.set<VendorAtomValue::longValue>(0);
values->push_back(tmp);
} else {
- tmp.set<VendorAtomValue::longValue>(sorted_pair[i].first);
+ tmp.set<VendorAtomValue::longValue>(irq_pair[i].first);
values->push_back(tmp);
- tmp.set<VendorAtomValue::longValue>(sorted_pair[i].second);
+ tmp.set<VendorAtomValue::longValue>(irq_pair[i].second);
values->push_back(tmp);
}
}
@@ -1268,93 +1664,66 @@ void SysfsCollector::logVendorLongIRQStatsReported(const std::shared_ptr<IStats>
if (uart_enabled == "running") {
return;
}
- std::string file_contents;
- if (!kLongIRQMetricsPath) {
+ std::string irq_file_contents, storm_file_contents;
+ if (kLongIRQMetricsPath == nullptr || strlen(kLongIRQMetricsPath) == 0) {
ALOGV("LongIRQ path not specified");
return;
}
- if (!ReadFileToString(kLongIRQMetricsPath, &file_contents)) {
- ALOGE("Unable to LongIRQ %s - %s", kLongIRQMetricsPath, strerror(errno));
+ if (!ReadFileToString(kLongIRQMetricsPath, &irq_file_contents)) {
+ ALOGE("Unable to read LongIRQ %s - %s", kLongIRQMetricsPath, strerror(errno));
+ return;
+ }
+ if (kStormIRQMetricsPath == nullptr || strlen(kStormIRQMetricsPath) == 0) {
+ ALOGV("StormIRQ path not specified");
+ return;
+ }
+ if (!ReadFileToString(kStormIRQMetricsPath, &storm_file_contents)) {
+ ALOGE("Unable to read StormIRQ %s - %s", kStormIRQMetricsPath, strerror(errno));
+ return;
+ }
+ if (kIRQStatsResetPath == nullptr || strlen(kIRQStatsResetPath) == 0) {
+ ALOGV("IRQStatsReset path not specified");
return;
}
int offset = 0;
int bytes_read;
- const char *data = file_contents.c_str();
- int data_len = file_contents.length();
- // Get, process, store softirq stats
- std::vector<std::pair<int, int64_t>> sorted_softirq_pair;
- int64_t softirq_count;
- if (sscanf(data + offset, "long SOFTIRQ count: %" PRId64 "\n%n", &softirq_count, &bytes_read) !=
- 1)
+ const char *data = irq_file_contents.c_str();
+
+ // Get, process softirq stats
+ int64_t irq_count;
+ if (sscanf(data + offset, "long SOFTIRQ count: %" PRId64 "\n%n", &irq_count, &bytes_read) != 1)
return;
offset += bytes_read;
- if (offset >= data_len)
- return;
std::vector<VendorAtomValue> values;
VendorAtomValue tmp;
- if (softirq_count - prev_data.softirq_count < 0) {
- tmp.set<VendorAtomValue::intValue>(-1);
- ALOGI("long softirq count get overflow");
- } else {
- tmp.set<VendorAtomValue::longValue>(softirq_count - prev_data.softirq_count);
- }
+ tmp.set<VendorAtomValue::longValue>(irq_count);
values.push_back(tmp);
if (sscanf(data + offset, "long SOFTIRQ detail (num, latency):\n%n", &bytes_read) != 0)
return;
offset += bytes_read;
- if (offset >= data_len)
- return;
-
- // Iterate over softirq stats and record top 5 long softirq
- int64_t softirq_latency;
- int softirq_num;
- while (sscanf(data + offset, "%d %" PRId64 "\n%n", &softirq_num, &softirq_latency,
- &bytes_read) == 2) {
- sorted_softirq_pair.push_back(std::make_pair(softirq_num, softirq_latency));
- offset += bytes_read;
- if (offset >= data_len)
- return;
- }
- process_irqatom_values(sorted_softirq_pair, &values);
+ process_irqatom_values(data, &offset, &values);
- // Get, process, store irq stats
- std::vector<std::pair<int, int64_t>> sorted_irq_pair;
- int64_t irq_count;
+ // Get, process irq stats
if (sscanf(data + offset, "long IRQ count: %" PRId64 "\n%n", &irq_count, &bytes_read) != 1)
return;
offset += bytes_read;
- if (offset >= data_len)
- return;
- if (irq_count - prev_data.irq_count < 0) {
- tmp.set<VendorAtomValue::intValue>(-1);
- ALOGI("long irq count get overflow");
- } else {
- tmp.set<VendorAtomValue::longValue>(irq_count - prev_data.irq_count);
- }
+ tmp.set<VendorAtomValue::longValue>(irq_count);
values.push_back(tmp);
if (sscanf(data + offset, "long IRQ detail (num, latency):\n%n", &bytes_read) != 0)
return;
offset += bytes_read;
- if (offset >= data_len)
- return;
+ process_irqatom_values(data, &offset, &values);
- int64_t irq_latency;
- int irq_num;
- int index = 0;
- // Iterate over softirq stats and record top 5 long irq
- while (sscanf(data + offset, "%d %" PRId64 "\n%n", &irq_num, &irq_latency, &bytes_read) == 2) {
- sorted_irq_pair.push_back(std::make_pair(irq_num, irq_latency));
- offset += bytes_read;
- if (offset >= data_len && index < 5)
- return;
- index += 1;
- }
- process_irqatom_values(sorted_irq_pair, &values);
+ // Get, process storm irq stats
+ offset = 0;
+ data = storm_file_contents.c_str();
+ if (sscanf(data + offset, "storm IRQ detail (num, storm_count):\n%n", &bytes_read) != 0)
+ return;
+ offset += bytes_read;
+ process_irqatom_values(data, &offset, &values);
- prev_data.softirq_count = softirq_count;
- prev_data.irq_count = irq_count;
// Send vendor atom to IStats HAL
VendorAtom event = {.reverseDomainName = "",
.atomId = PixelAtoms::Atom::kVendorLongIrqStatsReported,
@@ -1362,6 +1731,12 @@ void SysfsCollector::logVendorLongIRQStatsReported(const std::shared_ptr<IStats>
const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
if (!ret.isOk())
ALOGE("Unable to report kVendorLongIRQStatsReported to Stats service");
+
+ // Reset irq stats
+ if (!WriteStringToFile(std::to_string(1), kIRQStatsResetPath)) {
+ ALOGE("Failed to write to stats_reset");
+ return;
+ }
}
void SysfsCollector::logPartitionUsedSpace(const std::shared_ptr<IStats> &stats_client) {
@@ -1510,6 +1885,17 @@ void SysfsCollector::logPcieLinkStats(const std::shared_ptr<IStats> &stats_clien
}
}
+/**
+ * Read the contents of kPowerMitigationDurationPath and report them.
+ */
+void SysfsCollector::logMitigationDurationCounts(const std::shared_ptr<IStats> &stats_client) {
+ if (kPowerMitigationDurationPath == nullptr || strlen(kPowerMitigationDurationPath) == 0) {
+ ALOGE("Mitigation Duration path is invalid!");
+ return;
+ }
+ mitigation_duration_reporter_.logMitigationDuration(stats_client, kPowerMitigationDurationPath);
+}
+
void SysfsCollector::logPerDay() {
const std::shared_ptr<IStats> stats_client = getStatsService();
if (!stats_client) {
@@ -1527,6 +1913,7 @@ void SysfsCollector::logPerDay() {
logBlockStatsReported(stats_client);
logCodec1Failed(stats_client);
logCodecFailed(stats_client);
+ logDisplayStats(stats_client);
logF2fsStats(stats_client);
logF2fsAtomicWriteInfo(stats_client);
logF2fsCompressionInfo(stats_client);
@@ -1547,6 +1934,11 @@ void SysfsCollector::logPerDay() {
logVendorResumeLatencyStats(stats_client);
logPartitionUsedSpace(stats_client);
logPcieLinkStats(stats_client);
+ logMitigationDurationCounts(stats_client);
+ logVendorAudioPdmStatsReported(stats_client);
+ logWavesStats(stats_client);
+ logAdaptedInfoStats(stats_client);
+ logPcmUsageStats(stats_client);
}
void SysfsCollector::aggregatePer5Min() {
diff --git a/pixelstats/UeventListener.cpp b/pixelstats/UeventListener.cpp
index 07c8c954..8af43a01 100644
--- a/pixelstats/UeventListener.cpp
+++ b/pixelstats/UeventListener.cpp
@@ -66,6 +66,7 @@ using aidl::android::frameworks::stats::VendorAtomValue;
using android::sp;
using android::base::ReadFileToString;
using android::base::WriteStringToFile;
+using android::hardware::google::pixel::PixelAtoms::GpuEvent;
using android::hardware::google::pixel::PixelAtoms::PdVidPid;
using android::hardware::google::pixel::PixelAtoms::VendorHardwareFailed;
using android::hardware::google::pixel::PixelAtoms::VendorUsbPortOverheat;
@@ -271,6 +272,34 @@ void UeventListener::ReportTypeCPartnerId(const std::shared_ptr<IStats> &stats_c
}
}
+void UeventListener::ReportGpuEvent(const std::shared_ptr<IStats> &stats_client, const char *driver,
+ const char *gpu_event_type, const char *gpu_event_info) {
+ if (!stats_client || !driver || strncmp(driver, "DRIVER=mali", strlen("DRIVER=mali")) ||
+ !gpu_event_type || !gpu_event_info)
+ return;
+
+ std::vector<std::string> type = android::base::Split(gpu_event_type, "=");
+ std::vector<std::string> info = android::base::Split(gpu_event_info, "=");
+
+ if (type.size() != 2 || info.size() != 2)
+ return;
+
+ if (type[0] != "GPU_UEVENT_TYPE" || info[0] != "GPU_UEVENT_INFO")
+ return;
+
+ auto event_type = kGpuEventTypeStrToEnum.find(type[1]);
+ auto event_info = kGpuEventInfoStrToEnum.find(info[1]);
+ if (event_type == kGpuEventTypeStrToEnum.end() || event_info == kGpuEventInfoStrToEnum.end())
+ return;
+
+ VendorAtom event = {.reverseDomainName = "",
+ .atomId = PixelAtoms::Atom::kGpuEvent,
+ .values = {event_type->second, event_info->second}};
+ const ndk::ScopedAStatus ret = stats_client->reportVendorAtom(event);
+ if (!ret.isOk())
+ ALOGE("Unable to report GPU event.");
+}
+
bool UeventListener::ProcessUevent() {
char msg[UEVENT_MSG_LEN + 2];
char *cp;
@@ -278,6 +307,7 @@ bool UeventListener::ProcessUevent() {
const char *mic_break_status, *mic_degrade_status;
const char *devpath;
bool collect_partner_id = false;
+ const char *gpu_event_type = nullptr, *gpu_event_info = nullptr;
int n;
if (uevent_fd_ < 0) {
@@ -333,6 +363,10 @@ bool UeventListener::ProcessUevent() {
subsystem = cp;
} else if (!strncmp(cp, kTypeCPartnerUevent.c_str(), kTypeCPartnerUevent.size())) {
collect_partner_id = true;
+ } else if (!strncmp(cp, "GPU_UEVENT_TYPE=", strlen("GPU_UEVENT_TYPE="))) {
+ gpu_event_type = cp;
+ } else if (!strncmp(cp, "GPU_UEVENT_INFO=", strlen("GPU_UEVENT_INFO="))) {
+ gpu_event_info = cp;
}
/* advance to after the next \0 */
while (*cp++) {
@@ -352,6 +386,7 @@ bool UeventListener::ProcessUevent() {
if (collect_partner_id) {
ReportTypeCPartnerId(stats_client);
}
+ ReportGpuEvent(stats_client, driver, gpu_event_type, gpu_event_info);
}
if (log_fd_ > 0) {
diff --git a/pixelstats/include/pixelstats/DisplayStatsReporter.h b/pixelstats/include/pixelstats/DisplayStatsReporter.h
new file mode 100644
index 00000000..35435583
--- /dev/null
+++ b/pixelstats/include/pixelstats/DisplayStatsReporter.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 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 HARDWARE_GOOGLE_PIXEL_PIXELSTATS_DISPLAYSTATSREPORTER_H
+#define HARDWARE_GOOGLE_PIXEL_PIXELSTATS_DISPLAYSTATSREPORTER_H
+
+#include <aidl/android/frameworks/stats/IStats.h>
+#include <hardware/google/pixel/pixelstats/pixelatoms.pb.h>
+
+#include <string>
+
+namespace android {
+namespace hardware {
+namespace google {
+namespace pixel {
+
+using aidl::android::frameworks::stats::IStats;
+using aidl::android::frameworks::stats::VendorAtomValue;
+
+/**
+ * A class to upload Pixel Display Stats metrics
+ */
+class DisplayStatsReporter {
+ public:
+ DisplayStatsReporter();
+ void logDisplayStats(const std::shared_ptr<IStats> &stats_client,
+ const std::vector<std::string> &display_stats_paths);
+
+ private:
+ struct DisplayPanelErrorStats {
+ int64_t primary_error_count_te;
+ int64_t primary_error_count_unknown;
+ int64_t secondary_error_count_te;
+ int64_t secondary_error_count_unknown;
+ };
+
+ // Proto messages are 1-indexed and VendorAtom field numbers start at 2, so
+ // store everything in the values array at the index of the field number
+ // -2.
+ const int kVendorAtomOffset = 2;
+ const int kNumOfDisplayPanelErrorStats = 4;
+ struct DisplayPanelErrorStats prev_data_;
+
+ void logDisplayPanelErrorStats(const std::shared_ptr<IStats> &stats_client,
+ const std::vector<std::string> &display_stats_paths);
+ bool captureDisplayPanelErrorStats(const std::vector<std::string> &display_stats_paths,
+ struct DisplayPanelErrorStats *cur_data);
+ bool readDisplayPanelErrorCount(const std::string &path, int64_t *val);
+};
+
+} // namespace pixel
+} // namespace google
+} // namespace hardware
+} // namespace android
+
+#endif // HARDWARE_GOOGLE_PIXEL_PIXELSTATS_DISPLAYSTATSREPORTER_H
diff --git a/pixelstats/include/pixelstats/MitigationDurationReporter.h b/pixelstats/include/pixelstats/MitigationDurationReporter.h
new file mode 100644
index 00000000..44a6bc0e
--- /dev/null
+++ b/pixelstats/include/pixelstats/MitigationDurationReporter.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2023 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 HARDWARE_GOOGLE_PIXEL_PIXELSTATS_MITIGATIONDURATIONREPORTER_H
+#define HARDWARE_GOOGLE_PIXEL_PIXELSTATS_MITIGATIONDURATIONREPORTER_H
+
+#include <aidl/android/frameworks/stats/IStats.h>
+#include <hardware/google/pixel/pixelstats/pixelatoms.pb.h>
+
+#include <map>
+#include <string>
+
+namespace android {
+namespace hardware {
+namespace google {
+namespace pixel {
+
+using aidl::android::frameworks::stats::IStats;
+using aidl::android::frameworks::stats::VendorAtomValue;
+
+#define MITIGATION_DURATION_MAIN_COUNT 12
+#define MITIGATION_DURATION_SUB_COUNT 12
+
+/**
+ * A class to upload Pixel Mitigation Duration metrics
+ */
+class MitigationDurationReporter {
+ public:
+ MitigationDurationReporter();
+ void logMitigationDuration(const std::shared_ptr<IStats> &stats_client,
+ const std::string &path);
+
+ private:
+ struct IrqDurationCounts {
+ int uvlo1_none;
+ int uvlo1_mmwave;
+ int uvlo1_rffe;
+ int uvlo2_none;
+ int uvlo2_mmwave;
+ int uvlo2_rffe;
+ int batoilo_none;
+ int batoilo_mmwave;
+ int batoilo_rffe;
+ int main[MITIGATION_DURATION_MAIN_COUNT];
+ int sub[MITIGATION_DURATION_SUB_COUNT];
+ };
+
+ // Proto messages are 1-indexed and VendorAtom field numbers start at 2, so
+ // store everything in the values array at the index of the field number
+ // -2.
+ const int kVendorAtomOffset = 2;
+ const int kExpectedNumberOfLines = 33;
+ const std::string kGreaterThanTenMsSysfsNode = "/greater_than_10ms_count";
+
+ void valueAssignmentHelper(std::vector<VendorAtomValue> *values, int *val, int fieldNumber);
+
+ int updateStat(const std::string *line, int *val);
+
+ bool getIrqDurationCountHelper(const std::string kMitigationDurationFile,
+ struct IrqDurationCounts *counts);
+ bool getStatFromLine(const std::string *line, int *val);
+};
+
+} // namespace pixel
+} // namespace google
+} // namespace hardware
+} // namespace android
+
+#endif // HARDWARE_GOOGLE_PIXEL_PIXELSTATS_MITIGATIONDURATIONREPORTER_H
diff --git a/pixelstats/include/pixelstats/SysfsCollector.h b/pixelstats/include/pixelstats/SysfsCollector.h
index 1054cc54..494acd71 100644
--- a/pixelstats/include/pixelstats/SysfsCollector.h
+++ b/pixelstats/include/pixelstats/SysfsCollector.h
@@ -23,6 +23,8 @@
#include "BatteryEEPROMReporter.h"
#include "BatteryHealthReporter.h"
#include "BrownoutDetectedReporter.h"
+#include "DisplayStatsReporter.h"
+#include "MitigationDurationReporter.h"
#include "MitigationStatsReporter.h"
#include "MmMetricsReporter.h"
#include "TempResidencyReporter.h"
@@ -59,6 +61,7 @@ class SysfsCollector {
const char *const ZramBdStatPath;
const char *const EEPROMPath;
const char *const MitigationPath;
+ const char *const MitigationDurationPath;
const char *const BrownoutLogPath;
const char *const BrownoutReasonProp;
const char *const SpeakerTemperaturePath;
@@ -68,12 +71,22 @@ class SysfsCollector {
const int BlockStatsLength;
const char *const AmsRatePath;
const std::vector<std::string> ThermalStatsPaths;
+ const std::vector<std::string> DisplayStatsPaths;
const char *const CCARatePath;
const std::vector<std::pair<std::string, std::string>> TempResidencyAndResetPaths;
const char *const LongIRQMetricsPath;
+ const char *const StormIRQMetricsPath;
+ const char *const IRQStatsResetPath;
const char *const ResumeLatencyMetricsPath;
const char *const ModemPcieLinkStatsPath;
const char *const WifiPcieLinkStatsPath;
+ const char *const PDMStatePath;
+ const char *const WavesPath;
+ const char *const AdaptedInfoCountPath;
+ const char *const AdaptedInfoDurationPath;
+ const char *const PcmLatencyPath;
+ const char *const PcmCountPath;
+ const char *const TotalCallCountPath;
};
SysfsCollector(const struct SysfsPaths &paths);
@@ -109,6 +122,9 @@ class SysfsCollector {
void logSpeakerHealthStats(const std::shared_ptr<IStats> &stats_client);
void logF2fsSmartIdleMaintEnabled(const std::shared_ptr<IStats> &stats_client);
void logThermalStats(const std::shared_ptr<IStats> &stats_client);
+ void logMitigationDurationCounts(const std::shared_ptr<IStats> &stats_client);
+ void logDisplayStats(const std::shared_ptr<IStats> &stats_client);
+ void logVendorAudioPdmStatsReported(const std::shared_ptr<IStats> &stats_client);
void reportSlowIoFromFile(const std::shared_ptr<IStats> &stats_client, const char *path,
const VendorSlowIo::IoOperation &operation_s);
@@ -121,6 +137,9 @@ class SysfsCollector {
void logVendorResumeLatencyStats(const std::shared_ptr<IStats> &stats_client);
void logPartitionUsedSpace(const std::shared_ptr<IStats> &stats_client);
void logPcieLinkStats(const std::shared_ptr<IStats> &stats_client);
+ void logWavesStats(const std::shared_ptr<IStats> &stats_client);
+ void logAdaptedInfoStats(const std::shared_ptr<IStats> &stats_client);
+ void logPcmUsageStats(const std::shared_ptr<IStats> &stats_client);
const char *const kSlowioReadCntPath;
const char *const kSlowioWriteCntPath;
@@ -143,6 +162,7 @@ class SysfsCollector {
const char *const kBrownoutLogPath;
const char *const kBrownoutReasonProp;
const char *const kPowerMitigationStatsPath;
+ const char *const kPowerMitigationDurationPath;
const char *const kSpeakerTemperaturePath;
const char *const kSpeakerExcursionPath;
const char *const kSpeakerHeartbeatPath;
@@ -153,15 +173,27 @@ class SysfsCollector {
const char *const kCCARatePath;
const std::vector<std::pair<std::string, std::string>> kTempResidencyAndResetPaths;
const char *const kLongIRQMetricsPath;
+ const char *const kStormIRQMetricsPath;
+ const char *const kIRQStatsResetPath;
const char *const kResumeLatencyMetricsPath;
const char *const kModemPcieLinkStatsPath;
const char *const kWifiPcieLinkStatsPath;
+ const std::vector<std::string> kDisplayStatsPaths;
+ const char *const kPDMStatePath;
+ const char *const kWavesPath;
+ const char *const kAdaptedInfoCountPath;
+ const char *const kAdaptedInfoDurationPath;
+ const char *const kPcmLatencyPath;
+ const char *const kPcmCountPath;
+ const char *const kTotalCallCountPath;
BatteryEEPROMReporter battery_EEPROM_reporter_;
MmMetricsReporter mm_metrics_reporter_;
MitigationStatsReporter mitigation_stats_reporter_;
+ MitigationDurationReporter mitigation_duration_reporter_;
BrownoutDetectedReporter brownout_detected_reporter_;
ThermalStatsReporter thermal_stats_reporter_;
+ DisplayStatsReporter display_stats_reporter_;
BatteryHealthReporter battery_health_reporter_;
TempResidencyReporter temp_residency_reporter_;
// Proto messages are 1-indexed and VendorAtom field numbers start at 2, so
@@ -173,8 +205,6 @@ class SysfsCollector {
int64_t prev_huge_pages_since_boot_ = -1;
struct perf_metrics_data {
- int64_t softirq_count;
- int64_t irq_count;
uint64_t resume_latency_sum_ms;
int64_t resume_count;
std::vector<int64_t> resume_latency_buckets;
diff --git a/pixelstats/include/pixelstats/UeventListener.h b/pixelstats/include/pixelstats/UeventListener.h
index 5316afaa..352beb88 100644
--- a/pixelstats/include/pixelstats/UeventListener.h
+++ b/pixelstats/include/pixelstats/UeventListener.h
@@ -88,6 +88,8 @@ class UeventListener {
void ReportBatteryCapacityFGEvent(const std::shared_ptr<IStats> &stats_client,
const char *subsystem);
void ReportTypeCPartnerId(const std::shared_ptr<IStats> &stats_client);
+ void ReportGpuEvent(const std::shared_ptr<IStats> &stats_client, const char *driver,
+ const char *gpu_event_type, const char *gpu_event_info);
const std::string kAudioUevent;
const std::string kBatterySSOCPath;
@@ -97,6 +99,47 @@ class UeventListener {
const std::string kTypeCPartnerVidPath;
const std::string kTypeCPartnerPidPath;
+ const std::unordered_map<std::string, PixelAtoms::GpuEvent::GpuEventType>
+ kGpuEventTypeStrToEnum{
+ {"KMD_ERROR",
+ PixelAtoms::GpuEvent::GpuEventType::GpuEvent_GpuEventType_MALI_KMD_ERROR},
+ {"GPU_RESET",
+ PixelAtoms::GpuEvent::GpuEventType::GpuEvent_GpuEventType_MALI_GPU_RESET}};
+
+ const std::unordered_map<std::string, PixelAtoms::GpuEvent::GpuEventInfo>
+ kGpuEventInfoStrToEnum{
+ {"CSG_REQ_STATUS_UPDATE",
+ PixelAtoms::GpuEvent::GpuEventInfo::
+ GpuEvent_GpuEventInfo_MALI_CSG_REQ_STATUS_UPDATE},
+ {"CSG_SUSPEND",
+ PixelAtoms::GpuEvent::GpuEventInfo::GpuEvent_GpuEventInfo_MALI_CSG_SUSPEND},
+ {"CSG_SLOTS_SUSPEND", PixelAtoms::GpuEvent::GpuEventInfo::
+ GpuEvent_GpuEventInfo_MALI_CSG_SLOTS_SUSPEND},
+ {"CSG_GROUP_SUSPEND", PixelAtoms::GpuEvent::GpuEventInfo::
+ GpuEvent_GpuEventInfo_MALI_CSG_GROUP_SUSPEND},
+ {"CSG_EP_CFG",
+ PixelAtoms::GpuEvent::GpuEventInfo::GpuEvent_GpuEventInfo_MALI_CSG_EP_CFG},
+ {"CSG_SLOTS_START", PixelAtoms::GpuEvent::GpuEventInfo::
+ GpuEvent_GpuEventInfo_MALI_CSG_SLOTS_START},
+ {"GROUP_TERM",
+ PixelAtoms::GpuEvent::GpuEventInfo::GpuEvent_GpuEventInfo_MALI_GROUP_TERM},
+ {"QUEUE_START",
+ PixelAtoms::GpuEvent::GpuEventInfo::GpuEvent_GpuEventInfo_MALI_QUEUE_START},
+ {"QUEUE_STOP",
+ PixelAtoms::GpuEvent::GpuEventInfo::GpuEvent_GpuEventInfo_MALI_QUEUE_STOP},
+ {"QUEUE_STOP_ACK",
+ PixelAtoms::GpuEvent::GpuEventInfo::GpuEvent_GpuEventInfo_MALI_QUEUE_STOP_ACK},
+ {"CSG_SLOT_READY",
+ PixelAtoms::GpuEvent::GpuEventInfo::GpuEvent_GpuEventInfo_MALI_CSG_SLOT_READY},
+ {"L2_PM_TIMEOUT",
+ PixelAtoms::GpuEvent::GpuEventInfo::GpuEvent_GpuEventInfo_MALI_L2_PM_TIMEOUT},
+ {"PM_TIMEOUT",
+ PixelAtoms::GpuEvent::GpuEventInfo::GpuEvent_GpuEventInfo_MALI_PM_TIMEOUT},
+ {"CSF_RESET_OK",
+ PixelAtoms::GpuEvent::GpuEventInfo::GpuEvent_GpuEventInfo_MALI_CSF_RESET_OK},
+ {"CSF_RESET_FAILED", PixelAtoms::GpuEvent::GpuEventInfo::
+ GpuEvent_GpuEventInfo_MALI_CSF_RESET_FAILED}};
+
BatteryCapacityReporter battery_capacity_reporter_;
ChargeStatsReporter charge_stats_reporter_;
diff --git a/pixelstats/pixelatoms.proto b/pixelstats/pixelatoms.proto
index 05421fc5..3f5e76f4 100644
--- a/pixelstats/pixelatoms.proto
+++ b/pixelstats/pixelatoms.proto
@@ -103,9 +103,15 @@ message Atom {
VibratorPlaycountReported vibrator_playcount_reported = 105049;
VibratorLatencyReported vibrator_latency_reported = 105050;
VibratorErrorsReported vibrator_errors_reported = 105051;
-
F2fsAtomicWriteInfo f2fs_atomic_write_info = 105052;
PartitionsUsedSpaceReported partition_used_space_reported = 105053;
+ PowerMitigationDurationCounts mitigation_duration = 105054; // moved from atoms.proto
+ DisplayPanelErrorStats display_panel_error_stats = 105055;
+ VendorAudioPdmStatsReported vendor_audio_pdm_stats_reported = 105056;
+ VendorAudioThirdPartyEffectStatsReported vendor_audio_third_party_effect_stats_reported = 105057;
+ VendorAudioAdaptedInfoStatsReported vendor_audio_adapted_info_stats_reported = 105058;
+ GpuEvent gpu_event = 105059;
+ VendorAudioPcmStatsReported vendor_audio_pcm_stats_reported = 105060;
}
// AOSP atom ID range ends at 109999
reserved 109997; // reserved for VtsVendorAtomJavaTest test atom
@@ -152,6 +158,8 @@ message ChargeStats {
ADAPTER_TYPE_EXT1 = 27;
ADAPTER_TYPE_EXT2 = 28;
ADAPTER_TYPE_EXT_UNKNOWN = 29;
+ ADAPTER_TYPE_USB_UNKNOWN = 30;
+ ADAPTER_TYPE_WLC_UNKNOWN = 31;
}
optional string reverse_domain_name = 1;
/* Type of charge adapter, enumerated above. */
@@ -949,6 +957,21 @@ message ThermalDfsStats {
}
/**
+ * Log Display Panel error statistics.
+ */
+message DisplayPanelErrorStats {
+ optional string reverse_domain_name = 1;
+ // The error count due to Tear Effect on primary display panel.
+ optional int32 primary_error_count_te = 2;
+ // The error count due to unknown reason on primary display panel.
+ optional int32 primary_error_count_unknown = 3;
+ // The error count due to Tear Effect on primary display panel.
+ optional int32 secondary_error_count_te = 4;
+ // The error count due to unknown reason on secondary display panel.
+ optional int32 secondary_error_count_unknown = 5;
+}
+
+/**
* Log how many segments have been reclaimed in a specific GC mode.
*/
message F2fsGcSegmentInfo {
@@ -1290,23 +1313,51 @@ message BlockStatsReported {
*/
message VendorAudioHardwareStatsReported {
optional string reverse_domain_name = 1;
- /* The percentage of calls in a day where auto-mic-switch triggered.
- * It represented as a fixed-point integer with three decimal place.
- * E.g.:12.345% is repsented by 12345.
+ /* The number of calls in a day where CCA is active.
+ * CCA can only be applied under some radio bands.
*/
optional int32 milli_rate_of_ams_per_day = 2;
- /* The percentage of calls in a day where CCA is active.
- * It represented as a fixed-point and rounded integer.
- * E.g.:12.345% is represented by 12.
- * CCA can only be applied under some radio bands.
- */
+ // cca_active: obsoleted UI enable & algorithm is active (C1)
+ // replaced by cca_active_count_per_day
+ optional int32 rate_of_cca_active_per_day = 3 [deprecated = true];
+
+ // cca_enable: obsoleted UI enable & algorithm is inactive field (C2)
+ // replaced by cca_enable_count_per_day
+ optional int32 rate_of_cca_enable_per_day = 4 [deprecated = true];
+
+ enum Source {
+ VOIP = 0;
+ VOICE = 1;
+ }
+
+ /* source: identify whether this atom is for voice or voip case. */
+ optional Source source = 5;
+
+ /* total_call_count_per_day: count total number of call per day. */
+ optional int32 total_call_count_per_day = 6;
+
+ /* cca_active: UI enable & algorithm is active (C1 or C3) */
+ optional int32 cca_active_count_per_day = 7;
+
+ /* cca_enable: UI enable & algorithm is inactive (C2 or C4) */
+ optional int32 cca_enable_count_per_day = 8;
+}
+
+/**
+ * Logs the reported vendor audio PDM stats.
+ * PDM stats are used to show background noise level during voice/voip calling.
+ * Each of the atom will show only one type of background noises. There are at most 4 types.
+ * Thus, this atoms will be reported at most 4 times to show all types.
+ */
+message VendorAudioPdmStatsReported {
+ optional string reverse_domain_name = 1;
- /* cca_active: UI enable & algorithm is active (C1) */
- optional int32 rate_of_cca_active_per_day = 3;
+ /* index of the pdm to report. There are 4 pdm instances. So, the value is in the range 1-4 */
+ optional int32 pdm_index = 2;
- /* cca_enable: UI enable & algorithm is inactive. (C2) */
- optional int32 rate_of_cca_enable_per_day = 4;
+ /* State of the pdm to report. There is only two value 1 for good and 0 for bad. */
+ optional int32 state = 3;
}
/*
@@ -1346,6 +1397,17 @@ message VendorLongIRQStatsReported {
optional int64 top4_irq_latency_us = 21;
optional int64 top5_irq_num = 22;
optional int64 top5_irq_latency_us = 23;
+
+ optional int64 storm_irq_top1_num = 24;
+ optional int64 storm_irq_top1_count = 25;
+ optional int64 storm_irq_top2_num = 26;
+ optional int64 storm_irq_top2_count = 27;
+ optional int64 storm_irq_top3_num = 28;
+ optional int64 storm_irq_top3_count = 29;
+ optional int64 storm_irq_top4_num = 30;
+ optional int64 storm_irq_top4_count = 31;
+ optional int64 storm_irq_top5_num= 32;
+ optional int64 storm_irq_top5_count = 33;
}
/**
@@ -1561,7 +1623,7 @@ message BrownoutDetected {
// Triggered DVFS State: Channel 6
optional int32 dvfs_channel6 = 37;
// brownout reason
- optional int32 brownout_reason = 38;
+ optional BrownoutReason brownout_reason = 38;
}
/*
@@ -1734,4 +1796,197 @@ message PartitionsUsedSpaceReported {
optional Directory directory = 2;
optional int64 free_bytes = 3;
optional int64 total_bytes = 4;
-} \ No newline at end of file
+}
+
+message GpuEvent {
+ enum GpuEventType {
+ MALI_TYPE_NONE = 0;
+ MALI_KMD_ERROR = 1;
+ MALI_GPU_RESET = 2;
+ }
+ enum GpuEventInfo {
+ MALI_INFO_NONE = 0;
+ MALI_CSG_REQ_STATUS_UPDATE = 1;
+ MALI_CSG_SUSPEND = 2;
+ MALI_CSG_SLOTS_SUSPEND = 3;
+ MALI_CSG_GROUP_SUSPEND = 4;
+ MALI_CSG_EP_CFG = 5;
+ MALI_CSG_SLOTS_START = 6;
+ MALI_GROUP_TERM = 7;
+ MALI_QUEUE_START = 8;
+ MALI_QUEUE_STOP = 9;
+ MALI_QUEUE_STOP_ACK = 10;
+ MALI_CSG_SLOT_READY = 11;
+ MALI_L2_PM_TIMEOUT = 12;
+ MALI_PM_TIMEOUT = 13;
+ MALI_CSF_RESET_OK = 14;
+ MALI_CSF_RESET_FAILED = 15;
+ }
+
+ /* Vendor reverse domain name (expecting "com.google.pixel"). */
+ optional string reverse_domain_name = 1;
+ /*
+ * Type of the GPU event. Possible values depend on the platform GPU.
+ * Eg, MALI_KMD_ERROR, MALI_GPU_RESET.
+ */
+ optional GpuEventType gpu_event_type = 2;
+ /*
+ * Additional information about the GPU event. Possible values depend
+ * on the platform GPU.
+ * Eg, MALI_PM_TIMEOUT, MALI_CSF_RESET_OK.
+ */
+ optional GpuEventInfo gpu_event_info = 3;
+}
+/**
+ * Log mitigation duration.
+ */
+message PowerMitigationDurationCounts {
+ optional string reverse_domain_name = 1;
+ // Count of UVLO1 greater than threshold without any other concurrent IRQs.
+ optional int32 greater_than_thresh_uvlo1_none = 2;
+ // Count of UVLO1 IRQ + MMWAVE IRQ with duration greater than threshold.
+ optional int32 greater_than_thresh_uvlo1_mmwave = 3;
+ // Count of UVLO1 IRQ + RFFE IRQ with duration greater than threshold.
+ optional int32 greater_than_thresh_uvlo1_rffe = 4;
+ // Count of UVLO2 greater than threshold without any other concurrent IRQs.
+ optional int32 greater_than_thresh_uvlo2_none = 5;
+ // Count of UVLO2 IRQ + MMWAVE IRQ with duration greater than threshold.
+ optional int32 greater_than_thresh_uvlo2_mmwave = 6;
+ // Count of UVLO2 IRQ + RFFE IRQ with duration greater than threshold.
+ optional int32 greater_than_thresh_uvlo2_rffe = 7;
+ // Count of BATOILO greater than threshold without any other concurrent IRQs.
+ optional int32 greater_than_thresh_batoilo_none = 8;
+ // Count of BATOILO IRQ + MMWAVE IRQ with duration greater than threshold.
+ optional int32 greater_than_thresh_batoilo_mmwave = 9;
+ // Count of BATOILO IRQ + RFFE IRQ with duration greater than threshold.
+ optional int32 greater_than_thresh_batoilo_rffe = 10;
+
+ // IRQ duration of main regulator indices 0-11 greater than threshold.
+ optional int32 greater_than_thresh_main_0 = 11;
+ optional int32 greater_than_thresh_main_1 = 12;
+ optional int32 greater_than_thresh_main_2 = 13;
+ optional int32 greater_than_thresh_main_3 = 14;
+ optional int32 greater_than_thresh_main_4 = 15;
+ optional int32 greater_than_thresh_main_5 = 16;
+ optional int32 greater_than_thresh_main_6 = 17;
+ optional int32 greater_than_thresh_main_7 = 18;
+ optional int32 greater_than_thresh_main_8 = 19;
+ optional int32 greater_than_thresh_main_9 = 20;
+ optional int32 greater_than_thresh_main_10 = 21;
+ optional int32 greater_than_thresh_main_11 = 22;
+
+ // IRQ duration of sub regulator indices 0-11 greater than threshold.
+ optional int32 greater_than_thresh_sub_0 = 23;
+ optional int32 greater_than_thresh_sub_1 = 24;
+ optional int32 greater_than_thresh_sub_2 = 25;
+ optional int32 greater_than_thresh_sub_3 = 26;
+ optional int32 greater_than_thresh_sub_4 = 27;
+ optional int32 greater_than_thresh_sub_5 = 28;
+ optional int32 greater_than_thresh_sub_6 = 29;
+ optional int32 greater_than_thresh_sub_7 = 30;
+ optional int32 greater_than_thresh_sub_8 = 31;
+ optional int32 greater_than_thresh_sub_9 = 32;
+ optional int32 greater_than_thresh_sub_10 = 33;
+ optional int32 greater_than_thresh_sub_11 = 34;
+}
+
+/*
+ * Logs the third party audio effects stats.
+ * Third party audio effects stats includes duration in milliseconds for each
+ * instance of the effects (speaker, USB, etc.).
+ */
+message VendorAudioThirdPartyEffectStatsReported {
+ /* Vendor reverse domain name (expecting "com.google.pixel"). */
+ optional string reverse_domain_name = 1;
+
+ enum InstanceId {
+ OTHER = 0;
+ SPEAKER = 1;
+ USB = 2;
+ BT_A2DP = 3;
+ BT_LE = 4;
+ }
+ /* Instance of the effect. */
+ optional InstanceId instance = 2;
+ /* Active duration in milliseconds per day for volume range 0. */
+ optional int32 volume_range_0_active_ms_per_day = 3;
+ /* Active duration in milliseconds per day for volume range 1. */
+ optional int32 volume_range_1_active_ms_per_day = 4;
+ /* Active duration in milliseconds per day for volume range 2. */
+ optional int32 volume_range_2_active_ms_per_day = 5;
+ /* Active duration in milliseconds per day for volume range 3. */
+ optional int32 volume_range_3_active_ms_per_day = 6;
+ /* Active duration in milliseconds per day for volume range 4. */
+ optional int32 volume_range_4_active_ms_per_day = 7;
+ /* Active duration in milliseconds per day for volume range 5. */
+ optional int32 volume_range_5_active_ms_per_day = 8;
+ /* Active duration in milliseconds per day for volume range 6. */
+ optional int32 volume_range_6_active_ms_per_day = 9;
+ /* Active duration in milliseconds per day for volume range 7. */
+ optional int32 volume_range_7_active_ms_per_day = 10;
+ /* Active duration in milliseconds per day for volume range 8. */
+ optional int32 volume_range_8_active_ms_per_day = 11;
+ /* Active duration in milliseconds per day for volume range 9. */
+ optional int32 volume_range_9_active_ms_per_day = 12;
+}
+
+/*
+ * Logs the Audio Adapted information stats.
+ * Two stats are recorded, count and duration (in ms) per features.
+ */
+message VendorAudioAdaptedInfoStatsReported {
+ /* Vendor reverse domain name */
+ optional string reverse_domain_name = 1;
+
+ enum AdaptedInfoFeature {
+ UNKNOWN = 0;
+ BATTERY_ADAPTED_AUDIO_CONTROL = 1;
+ MEDIA_PLAYBACK_THERMAL_THROTTLE = 2;
+ TELEPHONY_THERMAL_THROTTLE = 3;
+ ACOUSTIC_SHOCK = 4;
+ SPATIAL_AUDIO = 5;
+ };
+ /* Feature to record the stats */
+ optional AdaptedInfoFeature feature_id = 2;
+ /* Number of time the feature is active */
+ optional int32 active_counts_per_day = 3;
+ /* Duration the feature is active in milliseconds */
+ optional int32 active_duration_ms_per_day = 4;
+}
+
+/*
+ * Logs the audio PCM usage stats.
+ * PCM usage includes average latency and total active count per day.
+ */
+message VendorAudioPcmStatsReported {
+ /* Vendor reverse domain name */
+ optional string reverse_domain_name = 1;
+
+ enum HalPcmType {
+ UNKNOWN = 0;
+ DEEPBUFFER = 1;
+ LOWLATENCY = 2;
+ MMAP_PLAY = 3;
+ RAW_PLAY = 4;
+ IMMERSIVE = 5;
+ HAPTIC = 6;
+ COMPRESS = 7;
+ MMAP_REC = 8;
+ RAW_REC = 9;
+ AUDIO_REC = 10;
+ HIFI_RX = 11;
+ HIFI_TX = 12;
+ IMMUTABLE_RX = 13;
+ CUSTOM_PCM_1 = 14;
+ CUSTOM_PCM_2 = 15;
+ CUSTOM_PCM_3 = 16;
+ CUSTOM_PCM_4 = 17;
+ CUSTOM_PCM_5 = 18;
+ };
+ /* Type of PCM */
+ optional HalPcmType type = 2;
+ /* Average latency in millisecond of the pcm type per day. */
+ optional int32 pcm_open_latency_avg_ms_per_day = 3;
+ /* Total active count of the pcm type per day. */
+ optional int32 pcm_active_counts_per_day = 4;
+}
diff --git a/power-libperfmgr/aidl/PowerSessionManager.cpp b/power-libperfmgr/aidl/PowerSessionManager.cpp
index e66ff5f3..2d2aad25 100644
--- a/power-libperfmgr/aidl/PowerSessionManager.cpp
+++ b/power-libperfmgr/aidl/PowerSessionManager.cpp
@@ -72,7 +72,11 @@ static void set_uclamp_min(int tid, int min) {
int ret = sched_setattr(tid, &attr, 0);
if (ret) {
- ALOGW("sched_setattr failed for thread %d, err=%d", tid, errno);
+ if (errno == ESRCH) {
+ ALOGV("sched_setattr failed for thread %d, err=%d", tid, errno);
+ } else {
+ ALOGW("sched_setattr failed for thread %d, err=%d", tid, errno);
+ }
}
}
} // namespace
diff --git a/power-libperfmgr/libperfmgr/FileNode.cc b/power-libperfmgr/libperfmgr/FileNode.cc
index 88417848..05f0746d 100644
--- a/power-libperfmgr/libperfmgr/FileNode.cc
+++ b/power-libperfmgr/libperfmgr/FileNode.cc
@@ -31,11 +31,12 @@ namespace android {
namespace perfmgr {
FileNode::FileNode(std::string name, std::string node_path, std::vector<RequestGroup> req_sorted,
- std::size_t default_val_index, bool reset_on_init, bool truncate, bool hold_fd)
+ std::size_t default_val_index, bool reset_on_init, bool truncate, bool hold_fd, bool write_only)
: Node(std::move(name), std::move(node_path), std::move(req_sorted), default_val_index,
reset_on_init),
hold_fd_(hold_fd),
truncate_(truncate),
+ write_only_(write_only),
warn_timeout_(android::base::GetBoolProperty("ro.debuggable", false) ? 5ms : 50ms) {}
std::chrono::milliseconds FileNode::Update(bool log_error) {
@@ -110,7 +111,7 @@ bool FileNode::GetTruncate() const {
void FileNode::DumpToFd(int fd) const {
std::string node_value;
- if (!android::base::ReadFileToString(node_path_, &node_value)) {
+ if (!write_only_ && !android::base::ReadFileToString(node_path_, &node_value)) {
LOG(ERROR) << "Failed to read node path: " << node_path_;
}
node_value = android::base::Trim(node_value);
diff --git a/power-libperfmgr/libperfmgr/HintManager.cc b/power-libperfmgr/libperfmgr/HintManager.cc
index 8c84c685..dd313ef5 100644
--- a/power-libperfmgr/libperfmgr/HintManager.cc
+++ b/power-libperfmgr/libperfmgr/HintManager.cc
@@ -495,9 +495,19 @@ std::vector<std::unique_ptr<Node>> HintManager::ParseNodes(
LOG(VERBOSE) << "Node[" << i << "]'s HoldFd: " << std::boolalpha
<< hold_fd << std::noboolalpha;
+ bool write_only = false;
+ if (nodes[i]["WriteOnly"].empty() || !nodes[i]["WriteOnly"].isBool()) {
+ LOG(INFO) << "Failed to read Node[" << i
+ << "]'s WriteOnly, set to 'false'";
+ } else {
+ write_only = nodes[i]["WriteOnly"].asBool();
+ }
+ LOG(VERBOSE) << "Node[" << i << "]'s WriteOnly: " << std::boolalpha
+ << write_only << std::noboolalpha;
+
nodes_parsed.emplace_back(std::make_unique<FileNode>(
name, path, values_parsed, static_cast<std::size_t>(default_index), reset,
- truncate, hold_fd));
+ truncate, hold_fd, write_only));
} else {
nodes_parsed.emplace_back(std::make_unique<PropertyNode>(
name, path, values_parsed,
diff --git a/power-libperfmgr/libperfmgr/include/perfmgr/FileNode.h b/power-libperfmgr/libperfmgr/include/perfmgr/FileNode.h
index 5e97d276..bb8a2a79 100644
--- a/power-libperfmgr/libperfmgr/include/perfmgr/FileNode.h
+++ b/power-libperfmgr/libperfmgr/include/perfmgr/FileNode.h
@@ -33,7 +33,7 @@ class FileNode : public Node {
public:
FileNode(std::string name, std::string node_path, std::vector<RequestGroup> req_sorted,
std::size_t default_val_index, bool reset_on_init, bool truncate,
- bool hold_fd = false);
+ bool hold_fd = false, bool write_only = false);
std::chrono::milliseconds Update(bool log_error) override;
@@ -48,6 +48,8 @@ class FileNode : public Node {
const bool hold_fd_;
const bool truncate_;
+ // node will be read in DumpToFd
+ const bool write_only_;
const std::chrono::milliseconds warn_timeout_;
android::base::unique_fd fd_;
};
diff --git a/power-libperfmgr/libperfmgr/tests/RequestGroupTest.cc b/power-libperfmgr/libperfmgr/tests/RequestGroupTest.cc
index 8021a7e8..c23c8211 100644
--- a/power-libperfmgr/libperfmgr/tests/RequestGroupTest.cc
+++ b/power-libperfmgr/libperfmgr/tests/RequestGroupTest.cc
@@ -63,7 +63,7 @@ TEST(RequestGroupTest, AddRequestNoExpireTest) {
ReqTime::max() - std::chrono::steady_clock::now());
EXPECT_NEAR(expect.count(), expire_time.count(), kTIMING_TOLERANCE_MS);
// expire time is greater than 1 year
- EXPECT_LE(365 * 24 * 60 * 60 * 1000, expire_time.count());
+ EXPECT_LE(365ll * 24 * 60 * 60 * 1000, expire_time.count());
EXPECT_EQ(true, active);
}
diff --git a/thermal/Android.bp b/thermal/Android.bp
index 86f6cb69..61403b31 100644
--- a/thermal/Android.bp
+++ b/thermal/Android.bp
@@ -3,80 +3,119 @@ package {
}
cc_binary {
- name: "android.hardware.thermal-service.pixel",
- srcs: [
- "service.cpp",
- "Thermal.cpp",
- "thermal-helper.cpp",
- "utils/thermal_throttling.cpp",
- "utils/thermal_info.cpp",
- "utils/thermal_files.cpp",
- "utils/power_files.cpp",
- "utils/powerhal_helper.cpp",
- "utils/thermal_stats_helper.cpp",
- "utils/thermal_watcher.cpp",
- ],
- vendor: true,
- relative_install_path: "hw",
- vintf_fragments: [
- "android.hardware.thermal-service.pixel.xml"
- ],
- init_rc: [
- "android.hardware.thermal-service.pixel.rc",
- ],
- shared_libs: [
- "libbase",
- "libcutils",
- "libjsoncpp",
- "libutils",
- "libnl",
- "libbinder_ndk",
- "android.frameworks.stats-V1-ndk",
- "android.hardware.power-V1-ndk",
- "android.hardware.thermal-V1-ndk",
- "pixel-power-ext-V1-ndk",
- "pixelatoms-cpp",
- ],
- static_libs: [
- "libpixelstats",
- ],
- export_shared_lib_headers: [
- "android.frameworks.stats-V1-ndk",
- "pixelatoms-cpp",
- ],
- cflags: [
- "-Wall",
- "-Werror",
- "-Wextra",
- "-Wunused",
- ],
- tidy: true,
- tidy_checks: [
- "android-*",
- "cert-*",
- "clang-analyzer-security*",
- ],
- tidy_checks_as_errors: [
- "android-*",
- "clang-analyzer-security*",
- "cert-*",
- ],
+ name: "android.hardware.thermal-service.pixel",
+ srcs: [
+ "service.cpp",
+ "Thermal.cpp",
+ "thermal-helper.cpp",
+ "utils/thermal_throttling.cpp",
+ "utils/thermal_info.cpp",
+ "utils/thermal_files.cpp",
+ "utils/power_files.cpp",
+ "utils/powerhal_helper.cpp",
+ "utils/thermal_stats_helper.cpp",
+ "utils/thermal_watcher.cpp",
+ ],
+ vendor: true,
+ relative_install_path: "hw",
+ vintf_fragments: [
+ "android.hardware.thermal-service.pixel.xml",
+ ],
+ init_rc: [
+ "android.hardware.thermal-service.pixel.rc",
+ ],
+ shared_libs: [
+ "libbase",
+ "libcutils",
+ "libjsoncpp",
+ "libutils",
+ "libnl",
+ "libbinder_ndk",
+ "android.frameworks.stats-V1-ndk",
+ "android.hardware.power-V1-ndk",
+ "android.hardware.thermal-V1-ndk",
+ "pixel-power-ext-V1-ndk",
+ "pixelatoms-cpp",
+ ],
+ static_libs: [
+ "libpixelstats",
+ ],
+ export_shared_lib_headers: [
+ "android.frameworks.stats-V1-ndk",
+ "pixelatoms-cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ "-Wunused",
+ ],
+ tidy: true,
+ tidy_checks: [
+ "android-*",
+ "cert-*",
+ "clang-analyzer-security*",
+ ],
+ tidy_checks_as_errors: [
+ "android-*",
+ "clang-analyzer-security*",
+ "cert-*",
+ ],
+}
+
+cc_test {
+ name: "libthermaltest",
+ vendor: true,
+ srcs: [
+ "service.cpp",
+ "Thermal.cpp",
+ "thermal-helper.cpp",
+ "utils/thermal_throttling.cpp",
+ "utils/thermal_info.cpp",
+ "utils/thermal_files.cpp",
+ "utils/power_files.cpp",
+ "utils/powerhal_helper.cpp",
+ "utils/thermal_stats_helper.cpp",
+ "utils/thermal_watcher.cpp",
+ "tests/mock_thermal_helper.cpp",
+ "tests/thermal_looper_test.cpp",
+ ],
+ shared_libs: [
+ "libbase",
+ "libcutils",
+ "libjsoncpp",
+ "libutils",
+ "libnl",
+ "liblog",
+ "libbinder_ndk",
+ "android.frameworks.stats-V1-ndk",
+ "android.hardware.power-V1-ndk",
+ "android.hardware.thermal-V1-ndk",
+ "pixel-power-ext-V1-ndk",
+ "pixelatoms-cpp",
+ ],
+ static_libs: [
+ "libgmock",
+ "libpixelstats",
+ ],
+ test_suites: ["device-tests"],
+ require_root: true,
}
sh_binary {
- name: "thermal_logd",
- src: "init.thermal.logging.sh",
- vendor: true,
- init_rc: [
- "pixel-thermal-logd.rc",
- ],
+ name: "thermal_logd",
+ src: "init.thermal.logging.sh",
+ vendor: true,
+ init_rc: [
+ "pixel-thermal-logd.rc",
+ ],
}
sh_binary {
- name: "thermal_symlinks",
- src: "init.thermal.symlinks.sh",
- vendor: true,
- init_rc: [
- "pixel-thermal-symlinks.rc",
- ],
+ name: "thermal_symlinks",
+ src: "init.thermal.symlinks.sh",
+ vendor: true,
+ init_rc: [
+ "pixel-thermal-symlinks.rc",
+ ],
}
diff --git a/thermal/Thermal.cpp b/thermal/Thermal.cpp
index e653f0b6..4b55ab96 100644
--- a/thermal/Thermal.cpp
+++ b/thermal/Thermal.cpp
@@ -50,9 +50,14 @@ bool interfacesEqual(const std::shared_ptr<::ndk::ICInterface> left,
} // namespace
-Thermal::Thermal()
- : thermal_helper_(
- std::bind(&Thermal::sendThermalChangedCallback, this, std::placeholders::_1)) {}
+Thermal::Thermal() {
+ thermal_helper_ = std::make_shared<ThermalHelperImpl>(
+ std::bind(&Thermal::sendThermalChangedCallback, this, std::placeholders::_1));
+}
+
+Thermal::Thermal(const std::shared_ptr<ThermalHelper> &helper) {
+ thermal_helper_ = helper;
+}
ndk::ScopedAStatus Thermal::getTemperatures(std::vector<Temperature> *_aidl_return) {
return getFilteredTemperatures(false, TemperatureType::UNKNOWN, _aidl_return);
@@ -66,10 +71,10 @@ ndk::ScopedAStatus Thermal::getTemperaturesWithType(TemperatureType type,
ndk::ScopedAStatus Thermal::getFilteredTemperatures(bool filterType, TemperatureType type,
std::vector<Temperature> *_aidl_return) {
*_aidl_return = {};
- if (!thermal_helper_.isInitializedOk()) {
+ if (!thermal_helper_->isInitializedOk()) {
return initErrorStatus();
}
- if (!thermal_helper_.fillCurrentTemperatures(filterType, false, type, _aidl_return)) {
+ if (!thermal_helper_->fillCurrentTemperatures(filterType, false, type, _aidl_return)) {
return readErrorStatus();
}
return ndk::ScopedAStatus::ok();
@@ -87,10 +92,10 @@ ndk::ScopedAStatus Thermal::getCoolingDevicesWithType(CoolingType type,
ndk::ScopedAStatus Thermal::getFilteredCoolingDevices(bool filterType, CoolingType type,
std::vector<CoolingDevice> *_aidl_return) {
*_aidl_return = {};
- if (!thermal_helper_.isInitializedOk()) {
+ if (!thermal_helper_->isInitializedOk()) {
return initErrorStatus();
}
- if (!thermal_helper_.fillCurrentCoolingDevices(filterType, type, _aidl_return)) {
+ if (!thermal_helper_->fillCurrentCoolingDevices(filterType, type, _aidl_return)) {
return readErrorStatus();
}
return ndk::ScopedAStatus::ok();
@@ -110,10 +115,10 @@ ndk::ScopedAStatus Thermal::getTemperatureThresholdsWithType(
ndk::ScopedAStatus Thermal::getFilteredTemperatureThresholds(
bool filterType, TemperatureType type, std::vector<TemperatureThreshold> *_aidl_return) {
*_aidl_return = {};
- if (!thermal_helper_.isInitializedOk()) {
+ if (!thermal_helper_->isInitializedOk()) {
return initErrorStatus();
}
- if (!thermal_helper_.fillTemperatureThresholds(filterType, type, _aidl_return)) {
+ if (!thermal_helper_->fillTemperatureThresholds(filterType, type, _aidl_return)) {
return readErrorStatus();
}
return ndk::ScopedAStatus::ok();
@@ -168,7 +173,7 @@ ndk::ScopedAStatus Thermal::registerThermalChangedCallback(
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
"Invalid nullptr callback");
}
- if (!thermal_helper_.isInitializedOk()) {
+ if (!thermal_helper_->isInitializedOk()) {
return initErrorStatus();
}
std::lock_guard<std::mutex> _lock(thermal_callback_mutex_);
@@ -184,14 +189,25 @@ ndk::ScopedAStatus Thermal::registerThermalChangedCallback(
// Send notification right away after successful thermal callback registration
std::function<void()> handler = [this, c, filterType, type]() {
std::vector<Temperature> temperatures;
- if (thermal_helper_.fillCurrentTemperatures(filterType, true, type, &temperatures)) {
- for (const auto &t : temperatures) {
- if (!filterType || t.type == type) {
- LOG(INFO) << "Sending notification: "
- << " Type: " << toString(t.type) << " Name: " << t.name
- << " CurrentValue: " << t.value
- << " ThrottlingStatus: " << toString(t.throttlingStatus);
- c.callback->notifyThrottling(t);
+ if (thermal_helper_->fillCurrentTemperatures(filterType, true, type, &temperatures)) {
+ std::lock_guard<std::mutex> _lock(thermal_callback_mutex_);
+ auto it = std::find_if(callbacks_.begin(), callbacks_.end(),
+ [&](const CallbackSetting &cc) {
+ return interfacesEqual(c.callback, cc.callback);
+ });
+ if (it != callbacks_.end()) {
+ if (AIBinder_isAlive(c.callback->asBinder().get())) {
+ for (const auto &t : temperatures) {
+ if (!filterType || t.type == type) {
+ LOG(INFO) << "Sending notification: "
+ << " Type: " << toString(t.type) << " Name: " << t.name
+ << " CurrentValue: " << t.value
+ << " ThrottlingStatus: " << toString(t.throttlingStatus);
+ c.callback->notifyThrottling(t);
+ }
+ }
+ } else {
+ callbacks_.erase(it);
}
}
}
@@ -227,7 +243,7 @@ void Thermal::sendThermalChangedCallback(const Temperature &t) {
void Thermal::dumpVirtualSensorInfo(std::ostringstream *dump_buf) {
*dump_buf << "getVirtualSensorInfo:" << std::endl;
- const auto &map = thermal_helper_.GetSensorInfoMap();
+ const auto &map = thermal_helper_->GetSensorInfoMap();
for (const auto &sensor_info_pair : map) {
if (sensor_info_pair.second.virtual_sensor_info != nullptr) {
*dump_buf << " Name: " << sensor_info_pair.first << std::endl;
@@ -282,8 +298,8 @@ void Thermal::dumpVirtualSensorInfo(std::ostringstream *dump_buf) {
void Thermal::dumpThrottlingInfo(std::ostringstream *dump_buf) {
*dump_buf << "getThrottlingInfo:" << std::endl;
- const auto &map = thermal_helper_.GetSensorInfoMap();
- const auto &thermal_throttling_status_map = thermal_helper_.GetThermalThrottlingStatusMap();
+ const auto &map = thermal_helper_->GetSensorInfoMap();
+ const auto &thermal_throttling_status_map = thermal_helper_->GetThermalThrottlingStatusMap();
for (const auto &name_info_pair : map) {
if (name_info_pair.second.throttling_info == nullptr) {
continue;
@@ -343,9 +359,14 @@ void Thermal::dumpThrottlingInfo(std::ostringstream *dump_buf) {
}
*dump_buf << "]" << std::endl;
}
- *dump_buf << " Binded CDEV Info:" << std::endl;
+ const auto &profile = thermal_throttling_status_map.at(name_info_pair.first).profile;
+ *dump_buf << " Binded CDEV Info:" << (profile.empty() ? "default" : profile)
+ << std::endl;
+
for (const auto &binded_cdev_info_pair :
- name_info_pair.second.throttling_info->binded_cdev_info_map) {
+ name_info_pair.second.throttling_info->profile_map.count(profile)
+ ? name_info_pair.second.throttling_info->profile_map.at(profile)
+ : name_info_pair.second.throttling_info->binded_cdev_info_map) {
*dump_buf << " Cooling device name: " << binded_cdev_info_pair.first << std::endl;
if (thermal_throttling_status_map.at(name_info_pair.first)
.pid_power_budget_map.size()) {
@@ -411,7 +432,7 @@ void Thermal::dumpThrottlingInfo(std::ostringstream *dump_buf) {
}
void Thermal::dumpThrottlingRequestStatus(std::ostringstream *dump_buf) {
- const auto &thermal_throttling_status_map = thermal_helper_.GetThermalThrottlingStatusMap();
+ const auto &thermal_throttling_status_map = thermal_helper_->GetThermalThrottlingStatusMap();
if (!thermal_throttling_status_map.size()) {
return;
}
@@ -461,8 +482,8 @@ void Thermal::dumpThrottlingRequestStatus(std::ostringstream *dump_buf) {
}
void Thermal::dumpPowerRailInfo(std::ostringstream *dump_buf) {
- const auto &power_rail_info_map = thermal_helper_.GetPowerRailInfoMap();
- const auto &power_status_map = thermal_helper_.GetPowerStatusMap();
+ const auto &power_rail_info_map = thermal_helper_->GetPowerRailInfoMap();
+ const auto &power_status_map = thermal_helper_->GetPowerStatusMap();
*dump_buf << "getPowerRailInfo:" << std::endl;
for (const auto &power_rail_pair : power_rail_info_map) {
@@ -540,7 +561,7 @@ void Thermal::dumpStatsRecord(std::ostringstream *dump_buf, const StatsRecord &s
void Thermal::dumpThermalStats(std::ostringstream *dump_buf) {
*dump_buf << "getThermalStatsInfo:" << std::endl;
*dump_buf << " Sensor Temp Stats Info:" << std::endl;
- const auto &sensor_temp_stats_map_ = thermal_helper_.GetSensorTempStatsSnapshot();
+ const auto &sensor_temp_stats_map_ = thermal_helper_->GetSensorTempStatsSnapshot();
const std::string sensor_temp_stats_line_prefix(" ");
for (const auto &sensor_temp_stats_pair : sensor_temp_stats_map_) {
*dump_buf << " Sensor Name: " << sensor_temp_stats_pair.first << std::endl;
@@ -571,7 +592,7 @@ void Thermal::dumpThermalStats(std::ostringstream *dump_buf) {
}
*dump_buf << " Sensor Cdev Request Stats Info:" << std::endl;
const auto &sensor_cdev_request_stats_map_ =
- thermal_helper_.GetSensorCoolingDeviceRequestStatsSnapshot();
+ thermal_helper_->GetSensorCoolingDeviceRequestStatsSnapshot();
const std::string sensor_cdev_request_stats_line_prefix(" ");
for (const auto &sensor_cdev_request_stats_pair : sensor_cdev_request_stats_map_) {
*dump_buf << " Sensor Name: " << sensor_cdev_request_stats_pair.first << std::endl;
@@ -603,10 +624,10 @@ void Thermal::dumpThermalStats(std::ostringstream *dump_buf) {
void Thermal::dumpThermalData(int fd) {
std::ostringstream dump_buf;
- if (!thermal_helper_.isInitializedOk()) {
+ if (!thermal_helper_->isInitializedOk()) {
dump_buf << "ThermalHAL not initialized properly." << std::endl;
} else {
- const auto &sensor_status_map = thermal_helper_.GetSensorStatusMap();
+ const auto &sensor_status_map = thermal_helper_->GetSensorStatusMap();
{
dump_buf << "getCachedTemperatures:" << std::endl;
boot_clock::time_point now = boot_clock::now();
@@ -637,11 +658,11 @@ void Thermal::dumpThermalData(int fd) {
}
}
{
- const auto &map = thermal_helper_.GetSensorInfoMap();
+ const auto &map = thermal_helper_->GetSensorInfoMap();
dump_buf << "getCurrentTemperatures:" << std::endl;
Temperature temp_2_0;
for (const auto &name_info_pair : map) {
- thermal_helper_.readTemperature(name_info_pair.first, &temp_2_0, nullptr, true);
+ thermal_helper_->readTemperature(name_info_pair.first, &temp_2_0, nullptr, true);
dump_buf << " Type: " << toString(temp_2_0.type)
<< " Name: " << name_info_pair.first << " CurrentValue: " << temp_2_0.value
<< " ThrottlingStatus: " << toString(temp_2_0.throttlingStatus)
@@ -685,8 +706,8 @@ void Thermal::dumpThermalData(int fd) {
{
dump_buf << "getCurrentCoolingDevices:" << std::endl;
std::vector<CoolingDevice> cooling_devices;
- if (!thermal_helper_.fillCurrentCoolingDevices(false, CoolingType::CPU,
- &cooling_devices)) {
+ if (!thermal_helper_->fillCurrentCoolingDevices(false, CoolingType::CPU,
+ &cooling_devices)) {
dump_buf << " Failed to getCurrentCoolingDevices." << std::endl;
}
@@ -706,7 +727,7 @@ void Thermal::dumpThermalData(int fd) {
{
dump_buf << "sendCallback:" << std::endl;
dump_buf << " Enabled List: ";
- const auto &map = thermal_helper_.GetSensorInfoMap();
+ const auto &map = thermal_helper_->GetSensorInfoMap();
for (const auto &name_info_pair : map) {
if (name_info_pair.second.send_cb) {
dump_buf << name_info_pair.first << " ";
@@ -717,7 +738,7 @@ void Thermal::dumpThermalData(int fd) {
{
dump_buf << "sendPowerHint:" << std::endl;
dump_buf << " Enabled List: ";
- const auto &map = thermal_helper_.GetSensorInfoMap();
+ const auto &map = thermal_helper_->GetSensorInfoMap();
for (const auto &name_info_pair : map) {
if (name_info_pair.second.send_powerhint) {
dump_buf << name_info_pair.first << " ";
@@ -732,12 +753,12 @@ void Thermal::dumpThermalData(int fd) {
dumpThermalStats(&dump_buf);
{
dump_buf << "getAIDLPowerHalInfo:" << std::endl;
- dump_buf << " Exist: " << std::boolalpha << thermal_helper_.isAidlPowerHalExist()
+ dump_buf << " Exist: " << std::boolalpha << thermal_helper_->isAidlPowerHalExist()
<< std::endl;
- dump_buf << " Connected: " << std::boolalpha << thermal_helper_.isPowerHalConnected()
+ dump_buf << " Connected: " << std::boolalpha << thermal_helper_->isPowerHalConnected()
<< std::endl;
dump_buf << " Ext connected: " << std::boolalpha
- << thermal_helper_.isPowerHalExtConnected() << std::endl;
+ << thermal_helper_->isPowerHalExtConnected() << std::endl;
}
}
std::string buf = dump_buf.str();
@@ -755,18 +776,19 @@ binder_status_t Thermal::dump(int fd, const char **args, uint32_t numArgs) {
if (std::string(args[0]) == "emul_temp") {
return (numArgs != 3 ||
- !thermal_helper_.emulTemp(std::string(args[1]), std::strtod(args[2], nullptr)))
+ !thermal_helper_->emulTemp(std::string(args[1]), std::strtod(args[2], nullptr)))
? STATUS_BAD_VALUE
: STATUS_OK;
} else if (std::string(args[0]) == "emul_severity") {
return (numArgs != 3 ||
- !thermal_helper_.emulSeverity(std::string(args[1]),
- static_cast<int>(std::strtol(args[2], nullptr, 10))))
+ !thermal_helper_->emulSeverity(std::string(args[1]),
+ static_cast<int>(std::strtol(args[2], nullptr, 10))))
? STATUS_BAD_VALUE
: STATUS_OK;
} else if (std::string(args[0]) == "emul_clear") {
- return (numArgs != 2 || !thermal_helper_.emulClear(std::string(args[1]))) ? STATUS_BAD_VALUE
- : STATUS_OK;
+ return (numArgs != 2 || !thermal_helper_->emulClear(std::string(args[1])))
+ ? STATUS_BAD_VALUE
+ : STATUS_OK;
}
return STATUS_BAD_VALUE;
}
@@ -777,14 +799,25 @@ void Thermal::Looper::addEvent(const Thermal::Looper::Event &e) {
cv_.notify_all();
}
+Thermal::Looper::~Looper() {
+ {
+ std::unique_lock<std::mutex> lock(mutex_);
+ aborted_ = true;
+ }
+ cv_.notify_one();
+ thread_.join();
+}
+
void Thermal::Looper::loop() {
- while (true) {
+ while (!aborted_) {
std::unique_lock<std::mutex> lock(mutex_);
- cv_.wait(lock, [&] { return !events_.empty(); });
- Event event = events_.front();
- events_.pop();
- lock.unlock();
- event.handler();
+ cv_.wait(lock, [&] { return aborted_ || !events_.empty(); });
+ if (!aborted_ && !events_.empty()) {
+ Event event = events_.front();
+ events_.pop();
+ lock.unlock();
+ event.handler();
+ }
}
}
diff --git a/thermal/Thermal.h b/thermal/Thermal.h
index 74449c4e..f8f9c63a 100644
--- a/thermal/Thermal.h
+++ b/thermal/Thermal.h
@@ -41,6 +41,7 @@ struct CallbackSetting {
class Thermal : public BnThermal {
public:
Thermal();
+ explicit Thermal(const std::shared_ptr<ThermalHelper> &helper);
~Thermal() = default;
ndk::ScopedAStatus getTemperatures(std::vector<Temperature> *_aidl_return) override;
ndk::ScopedAStatus getTemperaturesWithType(TemperatureType type,
@@ -77,6 +78,8 @@ class Thermal : public BnThermal {
Looper() {
thread_ = std::thread([&] { loop(); });
}
+ ~Looper();
+
void addEvent(const Event &e);
private:
@@ -84,11 +87,12 @@ class Thermal : public BnThermal {
std::queue<Event> events_;
std::mutex mutex_;
std::thread thread_;
+ bool aborted_;
void loop();
};
- ThermalHelper thermal_helper_;
+ std::shared_ptr<ThermalHelper> thermal_helper_;
std::mutex thermal_callback_mutex_;
std::vector<CallbackSetting> callbacks_;
Looper looper_;
diff --git a/thermal/tests/mock_thermal_helper.cpp b/thermal/tests/mock_thermal_helper.cpp
new file mode 100644
index 00000000..358371d4
--- /dev/null
+++ b/thermal/tests/mock_thermal_helper.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 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 "mock_thermal_helper.h"
+
+namespace aidl::android::hardware::thermal::implementation {
+
+MockThermalHelper::MockThermalHelper() = default;
+MockThermalHelper::~MockThermalHelper() = default;
+
+} // namespace aidl::android::hardware::thermal::implementation
diff --git a/thermal/tests/mock_thermal_helper.h b/thermal/tests/mock_thermal_helper.h
new file mode 100644
index 00000000..43ff3286
--- /dev/null
+++ b/thermal/tests/mock_thermal_helper.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/thermal/IThermal.h>
+#include <gmock/gmock.h>
+#include <log/log.h>
+
+#include <unordered_map>
+
+#include "thermal-helper.h"
+
+namespace aidl::android::hardware::thermal::implementation {
+
+class MockThermalHelper : public ThermalHelper {
+ public:
+ MockThermalHelper();
+ ~MockThermalHelper() override;
+ MOCK_METHOD(bool, fillCurrentTemperatures,
+ (bool, bool, TemperatureType, std::vector<Temperature> *), (override));
+ MOCK_METHOD(bool, fillTemperatureThresholds,
+ (bool, TemperatureType, std::vector<TemperatureThreshold> *), (const, override));
+ MOCK_METHOD(bool, fillCurrentCoolingDevices, (bool, CoolingType, std::vector<CoolingDevice> *),
+ (const, override));
+ MOCK_METHOD(bool, emulTemp, (std::string_view, const float), (override));
+ MOCK_METHOD(bool, emulSeverity, (std::string_view, const int), (override));
+ MOCK_METHOD(bool, emulClear, (std::string_view), (override));
+ MOCK_METHOD(bool, isInitializedOk, (), (const, override));
+ MOCK_METHOD(bool, readTemperature,
+ (std::string_view, Temperature *out,
+ (std::pair<ThrottlingSeverity, ThrottlingSeverity> *), const bool),
+ (override));
+ MOCK_METHOD(bool, readTemperatureThreshold, (std::string_view, TemperatureThreshold *),
+ (const, override));
+ MOCK_METHOD(bool, readCoolingDevice, (std::string_view, CoolingDevice *), (const, override));
+ MOCK_METHOD((const std::unordered_map<std::string, SensorInfo> &), GetSensorInfoMap, (),
+ (const, override));
+ MOCK_METHOD((const std::unordered_map<std::string, CdevInfo> &), GetCdevInfoMap, (),
+ (const, override));
+ MOCK_METHOD((const std::unordered_map<std::string, SensorStatus> &), GetSensorStatusMap, (),
+ (const, override));
+ MOCK_METHOD((const std::unordered_map<std::string, ThermalThrottlingStatus> &),
+ GetThermalThrottlingStatusMap, (), (const, override));
+ MOCK_METHOD((const std::unordered_map<std::string, PowerRailInfo> &), GetPowerRailInfoMap, (),
+ (const, override));
+ MOCK_METHOD((const std::unordered_map<std::string, PowerStatus> &), GetPowerStatusMap, (),
+ (const, override));
+ MOCK_METHOD((const std::unordered_map<std::string, SensorTempStats>),
+ GetSensorTempStatsSnapshot, (), (override));
+ MOCK_METHOD((const std::unordered_map<std::string,
+ std::unordered_map<std::string, ThermalStats<int>>>),
+ GetSensorCoolingDeviceRequestStatsSnapshot, (), (override));
+ MOCK_METHOD(bool, isAidlPowerHalExist, (), (override));
+ MOCK_METHOD(bool, isPowerHalConnected, (), (override));
+ MOCK_METHOD(bool, isPowerHalExtConnected, (), (override));
+};
+
+} // namespace aidl::android::hardware::thermal::implementation
diff --git a/thermal/tests/thermal_looper_test.cpp b/thermal/tests/thermal_looper_test.cpp
new file mode 100644
index 00000000..65f13d13
--- /dev/null
+++ b/thermal/tests/thermal_looper_test.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2023 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 <aidl/android/hardware/thermal/BnThermalChangedCallback.h>
+#include <log/log.h>
+
+#include "Thermal.h"
+#include "mock_thermal_helper.h"
+
+namespace aidl::android::hardware::thermal::implementation {
+
+class ThermalLooperTest : public testing::Test {
+ protected:
+ void SetUp() override {
+ ON_CALL(*helper, isInitializedOk).WillByDefault(testing::Return(true));
+ }
+
+ std::shared_ptr<testing::NiceMock<MockThermalHelper>> helper =
+ std::make_shared<testing::NiceMock<MockThermalHelper>>();
+ std::shared_ptr<Thermal> thermal = ndk::SharedRefBase::make<Thermal>(helper);
+};
+
+class TestCallback : public BnThermalChangedCallback {
+ public:
+ ndk::ScopedAStatus notifyThrottling(const Temperature &t) override {
+ std::lock_guard<std::mutex> lock_guard(mMutex);
+ mTemperatures.emplace_back(t);
+ return ndk::ScopedAStatus::ok();
+ }
+
+ std::vector<Temperature> getTemperatures() {
+ std::lock_guard<std::mutex> lock_guard(mMutex);
+ return mTemperatures;
+ }
+
+ void clear() {
+ std::lock_guard<std::mutex> lock_guard(mMutex);
+ mTemperatures.clear();
+ }
+
+ private:
+ std::vector<Temperature> mTemperatures;
+ std::mutex mMutex;
+};
+
+TEST_F(ThermalLooperTest, AsyncCallbackTest) {
+ Temperature t1;
+ t1.type = TemperatureType::SKIN;
+ Temperature t2;
+ t2.type = TemperatureType::UNKNOWN;
+ ON_CALL(*helper, fillCurrentTemperatures)
+ .WillByDefault([this, t1, t2](bool, bool, TemperatureType,
+ std::vector<Temperature> *temperatures) {
+ std::vector<Temperature> ret = {t1, t2};
+ *temperatures = ret;
+ sleep(1);
+ return true;
+ });
+ std::shared_ptr<TestCallback> callback = ndk::SharedRefBase::make<TestCallback>();
+ std::shared_ptr<TestCallback> callbackWithType = ndk::SharedRefBase::make<TestCallback>();
+
+ // if callback immediately unregistered, no async callback should be scheduled
+ ASSERT_TRUE(thermal->registerThermalChangedCallback(callback).isOk());
+ ASSERT_TRUE(
+ thermal->registerThermalChangedCallbackWithType(callbackWithType, TemperatureType::SKIN)
+ .isOk());
+ ASSERT_TRUE(thermal->unregisterThermalChangedCallback(callback).isOk());
+ ASSERT_TRUE(thermal->unregisterThermalChangedCallback(callbackWithType).isOk());
+ sleep(3);
+ ASSERT_TRUE(callback->getTemperatures().empty());
+ ASSERT_TRUE(callbackWithType->getTemperatures().empty());
+
+ // otherwise, async callback should be scheduled if registered
+ ASSERT_TRUE(thermal->registerThermalChangedCallback(callback).isOk());
+ ASSERT_TRUE(
+ thermal->registerThermalChangedCallbackWithType(callbackWithType, TemperatureType::SKIN)
+ .isOk());
+ sleep(3);
+ ASSERT_THAT(callback->getTemperatures(), testing::UnorderedElementsAreArray({t1, t2}));
+ ASSERT_THAT(callbackWithType->getTemperatures(), testing::UnorderedElementsAreArray({t1}));
+}
+
+} // namespace aidl::android::hardware::thermal::implementation
diff --git a/thermal/thermal-helper.cpp b/thermal/thermal-helper.cpp
index d7411bc3..dc4a599c 100644
--- a/thermal/thermal-helper.cpp
+++ b/thermal/thermal-helper.cpp
@@ -92,14 +92,31 @@ std::unordered_map<std::string, std::string> parseThermalPathMap(std::string_vie
} // namespace
+// If the cdev_ceiling is higher than CDEV max_state, cap the cdev_ceiling to max_state.
+void ThermalHelperImpl::maxCoolingRequestCheck(
+ std::unordered_map<std::string, BindedCdevInfo> *binded_cdev_info_map) {
+ for (auto &binded_cdev_info_pair : *binded_cdev_info_map) {
+ const auto &cdev_info = cooling_device_info_map_.at(binded_cdev_info_pair.first);
+ for (auto &cdev_ceiling : binded_cdev_info_pair.second.cdev_ceiling) {
+ if (cdev_ceiling > cdev_info.max_state) {
+ if (cdev_ceiling != std::numeric_limits<int>::max()) {
+ LOG(ERROR) << binded_cdev_info_pair.first << " cdev_ceiling:" << cdev_ceiling
+ << " is higher than max state:" << cdev_info.max_state;
+ }
+ cdev_ceiling = cdev_info.max_state;
+ }
+ }
+ }
+}
+
/*
* Populate the sensor_name_to_file_map_ map by walking through the file tree,
* reading the type file and assigning the temp file path to the map. If we do
* not succeed, abort.
*/
-ThermalHelper::ThermalHelper(const NotificationCallback &cb)
- : thermal_watcher_(new ThermalWatcher(
- std::bind(&ThermalHelper::thermalWatcherCallbackFunc, this, std::placeholders::_1))),
+ThermalHelperImpl::ThermalHelperImpl(const NotificationCallback &cb)
+ : thermal_watcher_(new ThermalWatcher(std::bind(&ThermalHelperImpl::thermalWatcherCallbackFunc,
+ this, std::placeholders::_1))),
cb_(cb) {
const std::string config_path =
"/vendor/etc/" +
@@ -145,12 +162,11 @@ ThermalHelper::ThermalHelper(const NotificationCallback &cb)
LOG(FATAL) << "Failed to initialize thermal stats";
}
- for (auto const &name_status_pair : sensor_info_map_) {
+ for (auto &name_status_pair : sensor_info_map_) {
sensor_status_map_[name_status_pair.first] = {
.severity = ThrottlingSeverity::NONE,
.prev_hot_severity = ThrottlingSeverity::NONE,
.prev_cold_severity = ThrottlingSeverity::NONE,
- .prev_hint_severity = ThrottlingSeverity::NONE,
.last_update_time = boot_clock::time_point::min(),
.thermal_cached = {NAN, boot_clock::time_point::min()},
.emul_setting = nullptr,
@@ -165,22 +181,13 @@ ThermalHelper::ThermalHelper(const NotificationCallback &cb)
break;
}
- // Update cooling device max state
- for (auto &binded_cdev_info_pair :
- name_status_pair.second.throttling_info->binded_cdev_info_map) {
- const auto &cdev_info = cooling_device_info_map_.at(binded_cdev_info_pair.first);
-
- for (auto &cdev_ceiling : binded_cdev_info_pair.second.cdev_ceiling) {
- if (cdev_ceiling > cdev_info.max_state) {
- if (cdev_ceiling != std::numeric_limits<int>::max()) {
- LOG(WARNING) << "Sensor " << name_status_pair.first << "'s "
- << binded_cdev_info_pair.first
- << " cdev_ceiling:" << cdev_ceiling
- << " is higher than max state:" << cdev_info.max_state;
- }
- cdev_ceiling = cdev_info.max_state;
- }
- }
+ // Update cooling device max state for default mode
+ maxCoolingRequestCheck(&name_status_pair.second.throttling_info->binded_cdev_info_map);
+
+ // Update cooling device max state for each profile mode
+ for (auto &cdev_throttling_profile_pair :
+ name_status_pair.second.throttling_info->profile_map) {
+ maxCoolingRequestCheck(&cdev_throttling_profile_pair.second);
}
}
// Check the virtual sensor settings are valid
@@ -222,10 +229,10 @@ ThermalHelper::ThermalHelper(const NotificationCallback &cb)
}
}
- if (!connectToPowerHal()) {
+ if (!power_hal_service_.connect()) {
LOG(ERROR) << "Fail to connect to Power Hal";
} else {
- updateSupportedPowerHints();
+ power_hal_service_.updateSupportedPowerHints(sensor_info_map_);
}
if (thermal_throttling_disabled) {
@@ -260,12 +267,6 @@ ThermalHelper::ThermalHelper(const NotificationCallback &cb)
if (!is_initialized_) {
LOG(FATAL) << "ThermalHAL could not start watching thread properly.";
}
-
- if (!connectToPowerHal()) {
- LOG(ERROR) << "Fail to connect to Power Hal";
- } else {
- updateSupportedPowerHints();
- }
}
bool getThermalZoneTypeById(int tz_id, std::string *type) {
@@ -285,7 +286,7 @@ bool getThermalZoneTypeById(int tz_id, std::string *type) {
return true;
}
-bool ThermalHelper::emulTemp(std::string_view target_sensor, const float value) {
+bool ThermalHelperImpl::emulTemp(std::string_view target_sensor, const float value) {
LOG(INFO) << "Set " << target_sensor.data() << " emul_temp "
<< "to " << value;
@@ -303,7 +304,7 @@ bool ThermalHelper::emulTemp(std::string_view target_sensor, const float value)
return true;
}
-bool ThermalHelper::emulSeverity(std::string_view target_sensor, const int severity) {
+bool ThermalHelperImpl::emulSeverity(std::string_view target_sensor, const int severity) {
LOG(INFO) << "Set " << target_sensor.data() << " emul_severity "
<< "to " << severity;
@@ -326,7 +327,7 @@ bool ThermalHelper::emulSeverity(std::string_view target_sensor, const int sever
return true;
}
-bool ThermalHelper::emulClear(std::string_view target_sensor) {
+bool ThermalHelperImpl::emulClear(std::string_view target_sensor) {
LOG(INFO) << "Clear " << target_sensor.data() << " emulation settings";
std::lock_guard<std::shared_mutex> _lock(sensor_status_map_mutex_);
@@ -347,7 +348,8 @@ bool ThermalHelper::emulClear(std::string_view target_sensor) {
return true;
}
-bool ThermalHelper::readCoolingDevice(std::string_view cooling_device, CoolingDevice *out) const {
+bool ThermalHelperImpl::readCoolingDevice(std::string_view cooling_device,
+ CoolingDevice *out) const {
// Read the file. If the file can't be read temp will be empty string.
std::string data;
@@ -366,7 +368,7 @@ bool ThermalHelper::readCoolingDevice(std::string_view cooling_device, CoolingDe
return true;
}
-bool ThermalHelper::readTemperature(
+bool ThermalHelperImpl::readTemperature(
std::string_view sensor_name, Temperature *out,
std::pair<ThrottlingSeverity, ThrottlingSeverity> *throttling_status,
const bool force_no_cache) {
@@ -375,8 +377,8 @@ bool ThermalHelper::readTemperature(
std::map<std::string, float> sensor_log_map;
auto &sensor_status = sensor_status_map_.at(sensor_name.data());
- if (!readThermalSensor(sensor_name, &temp, force_no_cache, &sensor_log_map)) {
- LOG(ERROR) << "readTemperature: failed to read sensor: " << sensor_name;
+ if (!readThermalSensor(sensor_name, &temp, force_no_cache, &sensor_log_map) ||
+ std::isnan(temp)) {
return false;
}
@@ -428,8 +430,8 @@ bool ThermalHelper::readTemperature(
return true;
}
-bool ThermalHelper::readTemperatureThreshold(std::string_view sensor_name,
- TemperatureThreshold *out) const {
+bool ThermalHelperImpl::readTemperatureThreshold(std::string_view sensor_name,
+ TemperatureThreshold *out) const {
// Read the file. If the file can't be read temp will be empty string.
std::string temp;
std::string path;
@@ -450,7 +452,7 @@ bool ThermalHelper::readTemperatureThreshold(std::string_view sensor_name,
return true;
}
-void ThermalHelper::updateCoolingDevices(const std::vector<std::string> &updated_cdev) {
+void ThermalHelperImpl::updateCoolingDevices(const std::vector<std::string> &updated_cdev) {
int max_state;
for (const auto &target_cdev : updated_cdev) {
@@ -466,7 +468,7 @@ void ThermalHelper::updateCoolingDevices(const std::vector<std::string> &updated
}
}
-std::pair<ThrottlingSeverity, ThrottlingSeverity> ThermalHelper::getSeverityFromThresholds(
+std::pair<ThrottlingSeverity, ThrottlingSeverity> ThermalHelperImpl::getSeverityFromThresholds(
const ThrottlingArray &hot_thresholds, const ThrottlingArray &cold_thresholds,
const ThrottlingArray &hot_hysteresis, const ThrottlingArray &cold_hysteresis,
ThrottlingSeverity prev_hot_severity, ThrottlingSeverity prev_cold_severity,
@@ -507,8 +509,8 @@ std::pair<ThrottlingSeverity, ThrottlingSeverity> ThermalHelper::getSeverityFrom
return std::make_pair(ret_hot, ret_cold);
}
-bool ThermalHelper::isSubSensorValid(std::string_view sensor_data,
- const SensorFusionType sensor_fusion_type) {
+bool ThermalHelperImpl::isSubSensorValid(std::string_view sensor_data,
+ const SensorFusionType sensor_fusion_type) {
switch (sensor_fusion_type) {
case SensorFusionType::SENSOR:
if (!sensor_info_map_.count(sensor_data.data())) {
@@ -528,7 +530,7 @@ bool ThermalHelper::isSubSensorValid(std::string_view sensor_data,
return true;
}
-void ThermalHelper::clearAllThrottling(void) {
+void ThermalHelperImpl::clearAllThrottling(void) {
// Clear the CDEV request
for (const auto &cdev_info_pair : cooling_device_info_map_) {
cooling_devices_.writeCdevFile(cdev_info_pair.first, "0");
@@ -558,7 +560,7 @@ void ThermalHelper::clearAllThrottling(void) {
}
}
-bool ThermalHelper::initializeSensorMap(
+bool ThermalHelperImpl::initializeSensorMap(
const std::unordered_map<std::string, std::string> &path_map) {
for (const auto &sensor_info_pair : sensor_info_map_) {
std::string_view sensor_name = sensor_info_pair.first;
@@ -586,7 +588,7 @@ bool ThermalHelper::initializeSensorMap(
return true;
}
-bool ThermalHelper::initializeCoolingDevices(
+bool ThermalHelperImpl::initializeCoolingDevices(
const std::unordered_map<std::string, std::string> &path_map) {
for (auto &cooling_device_info_pair : cooling_device_info_map_) {
std::string cooling_device_name = cooling_device_info_pair.first;
@@ -674,14 +676,14 @@ bool ThermalHelper::initializeCoolingDevices(
return true;
}
-void ThermalHelper::setMinTimeout(SensorInfo *sensor_info) {
+void ThermalHelperImpl::setMinTimeout(SensorInfo *sensor_info) {
sensor_info->polling_delay = kMinPollIntervalMs;
sensor_info->passive_delay = kMinPollIntervalMs;
}
-void ThermalHelper::initializeTrip(const std::unordered_map<std::string, std::string> &path_map,
- std::set<std::string> *monitored_sensors,
- bool thermal_genl_enabled) {
+void ThermalHelperImpl::initializeTrip(const std::unordered_map<std::string, std::string> &path_map,
+ std::set<std::string> *monitored_sensors,
+ bool thermal_genl_enabled) {
for (auto &sensor_info : sensor_info_map_) {
if (!sensor_info.second.is_watch || (sensor_info.second.virtual_sensor_info != nullptr)) {
continue;
@@ -754,9 +756,9 @@ void ThermalHelper::initializeTrip(const std::unordered_map<std::string, std::st
}
}
-bool ThermalHelper::fillCurrentTemperatures(bool filterType, bool filterCallback,
- TemperatureType type,
- std::vector<Temperature> *temperatures) {
+bool ThermalHelperImpl::fillCurrentTemperatures(bool filterType, bool filterCallback,
+ TemperatureType type,
+ std::vector<Temperature> *temperatures) {
std::vector<Temperature> ret;
for (const auto &name_info_pair : sensor_info_map_) {
Temperature temp;
@@ -780,8 +782,9 @@ bool ThermalHelper::fillCurrentTemperatures(bool filterType, bool filterCallback
return ret.size() > 0;
}
-bool ThermalHelper::fillTemperatureThresholds(bool filterType, TemperatureType type,
- std::vector<TemperatureThreshold> *thresholds) const {
+bool ThermalHelperImpl::fillTemperatureThresholds(
+ bool filterType, TemperatureType type,
+ std::vector<TemperatureThreshold> *thresholds) const {
std::vector<TemperatureThreshold> ret;
for (const auto &name_info_pair : sensor_info_map_) {
TemperatureThreshold temp;
@@ -803,8 +806,8 @@ bool ThermalHelper::fillTemperatureThresholds(bool filterType, TemperatureType t
return ret.size() > 0;
}
-bool ThermalHelper::fillCurrentCoolingDevices(bool filterType, CoolingType type,
- std::vector<CoolingDevice> *cooling_devices) const {
+bool ThermalHelperImpl::fillCurrentCoolingDevices(
+ bool filterType, CoolingType type, std::vector<CoolingDevice> *cooling_devices) const {
std::vector<CoolingDevice> ret;
for (const auto &name_info_pair : cooling_device_info_map_) {
CoolingDevice value;
@@ -822,9 +825,9 @@ bool ThermalHelper::fillCurrentCoolingDevices(bool filterType, CoolingType type,
return ret.size() > 0;
}
-bool ThermalHelper::readDataByType(std::string_view sensor_data, float *reading_value,
- const SensorFusionType type, const bool force_no_cache,
- std::map<std::string, float> *sensor_log_map) {
+bool ThermalHelperImpl::readDataByType(std::string_view sensor_data, float *reading_value,
+ const SensorFusionType type, const bool force_no_cache,
+ std::map<std::string, float> *sensor_log_map) {
switch (type) {
case SensorFusionType::SENSOR:
if (!readThermalSensor(sensor_data.data(), reading_value, force_no_cache,
@@ -837,19 +840,24 @@ bool ThermalHelper::readDataByType(std::string_view sensor_data, float *reading_
*reading_value = GetPowerStatusMap().at(sensor_data.data()).last_updated_avg_power;
if (std::isnan(*reading_value)) {
LOG(INFO) << "Power data " << sensor_data.data() << " is under collecting";
- return false;
+ return true;
}
(*sensor_log_map)[sensor_data.data()] = *reading_value;
break;
+ case SensorFusionType::CONSTANT:
+ *reading_value = std::atof(sensor_data.data());
+ break;
default:
break;
}
return true;
}
-bool ThermalHelper::readThermalSensor(std::string_view sensor_name, float *temp,
- const bool force_no_cache,
- std::map<std::string, float> *sensor_log_map) {
+constexpr int kTranTimeoutParam = 2;
+
+bool ThermalHelperImpl::readThermalSensor(std::string_view sensor_name, float *temp,
+ const bool force_no_cache,
+ std::map<std::string, float> *sensor_log_map) {
float temp_val = 0.0;
std::string file_reading;
boot_clock::time_point now = boot_clock::now();
@@ -872,11 +880,13 @@ bool ThermalHelper::readThermalSensor(std::string_view sensor_name, float *temp,
}
}
+ const auto since_last_update = std::chrono::duration_cast<std::chrono::milliseconds>(
+ now - sensor_status.thermal_cached.timestamp);
+
// Check if thermal data need to be read from cache
if (!force_no_cache &&
(sensor_status.thermal_cached.timestamp != boot_clock::time_point::min()) &&
- (std::chrono::duration_cast<std::chrono::milliseconds>(
- now - sensor_status.thermal_cached.timestamp) < sensor_info.time_resolution) &&
+ (since_last_update < sensor_info.time_resolution) &&
!isnan(sensor_status.thermal_cached.temp)) {
*temp = sensor_status.thermal_cached.temp;
(*sensor_log_map)[sensor_name.data()] = *temp;
@@ -886,11 +896,8 @@ bool ThermalHelper::readThermalSensor(std::string_view sensor_name, float *temp,
// Reading thermal sensor according to it's composition
if (sensor_info.virtual_sensor_info == nullptr) {
- if (!thermal_sensors_.readThermalFile(sensor_name.data(), &file_reading)) {
- return false;
- }
-
- if (file_reading.empty()) {
+ if (!thermal_sensors_.readThermalFile(sensor_name.data(), &file_reading) ||
+ file_reading.empty()) {
LOG(ERROR) << "failed to read sensor: " << sensor_name;
return false;
}
@@ -904,11 +911,23 @@ bool ThermalHelper::readThermalSensor(std::string_view sensor_name, float *temp,
force_no_cache, sensor_log_map)) {
LOG(ERROR) << "Failed to read " << sensor_name.data() << "'s linked sensor "
<< sensor_info.virtual_sensor_info->linked_sensors[i];
+ return false;
}
- if (std::isnan(sensor_info.virtual_sensor_info->coefficients[i])) {
+
+ float coefficient = 0.0;
+ if (!readDataByType(sensor_info.virtual_sensor_info->coefficients[i], &coefficient,
+ sensor_info.virtual_sensor_info->coefficients_type[i],
+ force_no_cache, sensor_log_map)) {
+ LOG(ERROR) << "Failed to read " << sensor_name.data() << "'s coefficient "
+ << sensor_info.virtual_sensor_info->coefficients[i];
return false;
}
- float coefficient = sensor_info.virtual_sensor_info->coefficients[i];
+
+ if (std::isnan(sensor_reading) || std::isnan(coefficient)) {
+ LOG(INFO) << sensor_name << " data is under collecting";
+ return true;
+ }
+
switch (sensor_info.virtual_sensor_info->formula) {
case FormulaOption::COUNT_THRESHOLD:
if ((coefficient < 0 && sensor_reading < -coefficient) ||
@@ -936,6 +955,13 @@ bool ThermalHelper::readThermalSensor(std::string_view sensor_name, float *temp,
}
*temp = (temp_val + sensor_info.virtual_sensor_info->offset);
}
+
+ if (!isnan(sensor_info.step_ratio) && !isnan(sensor_status.thermal_cached.temp) &&
+ since_last_update < sensor_info.passive_delay * kTranTimeoutParam) {
+ *temp = (sensor_info.step_ratio * *temp +
+ (1 - sensor_info.step_ratio) * sensor_status.thermal_cached.temp);
+ }
+
(*sensor_log_map)[sensor_name.data()] = *temp;
ATRACE_INT(sensor_name.data(), static_cast<int>(*temp));
@@ -951,7 +977,7 @@ bool ThermalHelper::readThermalSensor(std::string_view sensor_name, float *temp,
// This is called in the different thread context and will update sensor_status
// uevent_sensors is the set of sensors which trigger uevent from thermal core driver.
-std::chrono::milliseconds ThermalHelper::thermalWatcherCallbackFunc(
+std::chrono::milliseconds ThermalHelperImpl::thermalWatcherCallbackFunc(
const std::set<std::string> &uevent_sensors) {
std::vector<Temperature> temps;
std::vector<std::string> cooling_devices_to_update;
@@ -1109,8 +1135,8 @@ std::chrono::milliseconds ThermalHelper::thermalWatcherCallbackFunc(
cb_(t);
}
- if (sensor_info_map_.at(t.name).send_powerhint && isAidlPowerHalExist()) {
- sendPowerExtHint(t);
+ if (sensor_info_map_.at(t.name).send_powerhint) {
+ power_hal_service_.sendPowerExtHint(t);
}
}
}
@@ -1120,59 +1146,15 @@ std::chrono::milliseconds ThermalHelper::thermalWatcherCallbackFunc(
LOG(ERROR) << "Failed to report " << count_failed_reporting << " thermal stats";
}
- return min_sleep_ms;
-}
-
-bool ThermalHelper::connectToPowerHal() {
- return power_hal_service_.connect();
-}
-
-void ThermalHelper::updateSupportedPowerHints() {
- for (auto const &name_status_pair : sensor_info_map_) {
- if (!(name_status_pair.second.send_powerhint)) {
- continue;
- }
- ThrottlingSeverity current_severity = ThrottlingSeverity::NONE;
- for (const auto &severity : ::ndk::enum_range<ThrottlingSeverity>()) {
- if (severity == ThrottlingSeverity::NONE) {
- supported_powerhint_map_[name_status_pair.first][ThrottlingSeverity::NONE] =
- ThrottlingSeverity::NONE;
- continue;
- }
-
- bool isSupported = false;
- ndk::ScopedAStatus isSupportedResult;
-
- if (power_hal_service_.isPowerHalExtConnected()) {
- isSupported = power_hal_service_.isModeSupported(name_status_pair.first, severity);
- }
- if (isSupported)
- current_severity = severity;
- supported_powerhint_map_[name_status_pair.first][severity] = current_severity;
- }
- }
-}
-
-void ThermalHelper::sendPowerExtHint(const Temperature &t) {
- ATRACE_CALL();
- std::lock_guard<std::shared_mutex> lock(sensor_status_map_mutex_);
- ThrottlingSeverity prev_hint_severity;
- prev_hint_severity = sensor_status_map_.at(t.name).prev_hint_severity;
- ThrottlingSeverity current_hint_severity = supported_powerhint_map_[t.name][t.throttlingStatus];
-
- if (prev_hint_severity == current_hint_severity)
- return;
-
- if (prev_hint_severity != ThrottlingSeverity::NONE) {
- power_hal_service_.setMode(t.name, prev_hint_severity, false);
- }
-
- if (current_hint_severity != ThrottlingSeverity::NONE) {
- power_hal_service_.setMode(t.name, current_hint_severity, true);
+ const auto since_last_power_log_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
+ now - power_files_.GetPrevPowerLogTime());
+ if (since_last_power_log_ms >= kPowerLogIntervalMs) {
+ power_files_.logPowerStatus(now);
}
- sensor_status_map_[t.name].prev_hint_severity = current_hint_severity;
+ return min_sleep_ms;
}
+
} // namespace implementation
} // namespace thermal
} // namespace hardware
diff --git a/thermal/thermal-helper.h b/thermal/thermal-helper.h
index 3b790e3e..6ae13c43 100644
--- a/thermal/thermal-helper.h
+++ b/thermal/thermal-helper.h
@@ -65,7 +65,6 @@ struct SensorStatus {
ThrottlingSeverity severity;
ThrottlingSeverity prev_hot_severity;
ThrottlingSeverity prev_cold_severity;
- ThrottlingSeverity prev_hint_severity;
boot_clock::time_point last_update_time;
ThermalSample thermal_cached;
std::unique_ptr<EmulSetting> emul_setting;
@@ -73,77 +72,112 @@ struct SensorStatus {
class ThermalHelper {
public:
- explicit ThermalHelper(const NotificationCallback &cb);
- ~ThermalHelper() = default;
+ virtual ~ThermalHelper() = default;
+ virtual bool fillCurrentTemperatures(bool filterType, bool filterCallback, TemperatureType type,
+ std::vector<Temperature> *temperatures) = 0;
+ virtual bool fillTemperatureThresholds(bool filterType, TemperatureType type,
+ std::vector<TemperatureThreshold> *thresholds) const = 0;
+ virtual bool fillCurrentCoolingDevices(bool filterType, CoolingType type,
+ std::vector<CoolingDevice> *coolingdevices) const = 0;
+ virtual bool emulTemp(std::string_view target_sensor, const float temp) = 0;
+ virtual bool emulSeverity(std::string_view target_sensor, const int severity) = 0;
+ virtual bool emulClear(std::string_view target_sensor) = 0;
+ virtual bool isInitializedOk() const = 0;
+ virtual bool readTemperature(
+ std::string_view sensor_name, Temperature *out,
+ std::pair<ThrottlingSeverity, ThrottlingSeverity> *throtting_status = nullptr,
+ const bool force_sysfs = false) = 0;
+ virtual bool readTemperatureThreshold(std::string_view sensor_name,
+ TemperatureThreshold *out) const = 0;
+ virtual bool readCoolingDevice(std::string_view cooling_device, CoolingDevice *out) const = 0;
+ virtual const std::unordered_map<std::string, SensorInfo> &GetSensorInfoMap() const = 0;
+ virtual const std::unordered_map<std::string, CdevInfo> &GetCdevInfoMap() const = 0;
+ virtual const std::unordered_map<std::string, SensorStatus> &GetSensorStatusMap() const = 0;
+ virtual const std::unordered_map<std::string, ThermalThrottlingStatus> &
+ GetThermalThrottlingStatusMap() const = 0;
+ virtual const std::unordered_map<std::string, PowerRailInfo> &GetPowerRailInfoMap() const = 0;
+ virtual const std::unordered_map<std::string, PowerStatus> &GetPowerStatusMap() const = 0;
+ virtual const std::unordered_map<std::string, SensorTempStats> GetSensorTempStatsSnapshot() = 0;
+ virtual const std::unordered_map<std::string,
+ std::unordered_map<std::string, ThermalStats<int>>>
+ GetSensorCoolingDeviceRequestStatsSnapshot() = 0;
+ virtual bool isAidlPowerHalExist() = 0;
+ virtual bool isPowerHalConnected() = 0;
+ virtual bool isPowerHalExtConnected() = 0;
+};
+
+class ThermalHelperImpl : public ThermalHelper {
+ public:
+ explicit ThermalHelperImpl(const NotificationCallback &cb);
+ ~ThermalHelperImpl() override = default;
bool fillCurrentTemperatures(bool filterType, bool filterCallback, TemperatureType type,
- std::vector<Temperature> *temperatures);
+ std::vector<Temperature> *temperatures) override;
bool fillTemperatureThresholds(bool filterType, TemperatureType type,
- std::vector<TemperatureThreshold> *thresholds) const;
+ std::vector<TemperatureThreshold> *thresholds) const override;
bool fillCurrentCoolingDevices(bool filterType, CoolingType type,
- std::vector<CoolingDevice> *coolingdevices) const;
- bool emulTemp(std::string_view target_sensor, const float temp);
- bool emulSeverity(std::string_view target_sensor, const int severity);
- bool emulClear(std::string_view target_sensor);
+ std::vector<CoolingDevice> *coolingdevices) const override;
+ bool emulTemp(std::string_view target_sensor, const float temp) override;
+ bool emulSeverity(std::string_view target_sensor, const int severity) override;
+ bool emulClear(std::string_view target_sensor) override;
// Disallow copy and assign.
- ThermalHelper(const ThermalHelper &) = delete;
- void operator=(const ThermalHelper &) = delete;
+ ThermalHelperImpl(const ThermalHelperImpl &) = delete;
+ void operator=(const ThermalHelperImpl &) = delete;
- bool isInitializedOk() const { return is_initialized_; }
+ bool isInitializedOk() const override { return is_initialized_; }
// Read the temperature of a single sensor.
- bool readTemperature(std::string_view sensor_name, Temperature *out);
bool readTemperature(
std::string_view sensor_name, Temperature *out,
std::pair<ThrottlingSeverity, ThrottlingSeverity> *throtting_status = nullptr,
- const bool force_sysfs = false);
+ const bool force_sysfs = false) override;
- bool readTemperatureThreshold(std::string_view sensor_name, TemperatureThreshold *out) const;
+ bool readTemperatureThreshold(std::string_view sensor_name,
+ TemperatureThreshold *out) const override;
// Read the value of a single cooling device.
- bool readCoolingDevice(std::string_view cooling_device, CoolingDevice *out) const;
+ bool readCoolingDevice(std::string_view cooling_device, CoolingDevice *out) const override;
// Get SensorInfo Map
- const std::unordered_map<std::string, SensorInfo> &GetSensorInfoMap() const {
+ const std::unordered_map<std::string, SensorInfo> &GetSensorInfoMap() const override {
return sensor_info_map_;
}
// Get CdevInfo Map
- const std::unordered_map<std::string, CdevInfo> &GetCdevInfoMap() const {
+ const std::unordered_map<std::string, CdevInfo> &GetCdevInfoMap() const override {
return cooling_device_info_map_;
}
// Get SensorStatus Map
- const std::unordered_map<std::string, SensorStatus> &GetSensorStatusMap() const {
+ const std::unordered_map<std::string, SensorStatus> &GetSensorStatusMap() const override {
std::shared_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
return sensor_status_map_;
}
// Get ThermalThrottling Map
const std::unordered_map<std::string, ThermalThrottlingStatus> &GetThermalThrottlingStatusMap()
- const {
+ const override {
return thermal_throttling_.GetThermalThrottlingStatusMap();
}
// Get PowerRailInfo Map
- const std::unordered_map<std::string, PowerRailInfo> &GetPowerRailInfoMap() const {
+ const std::unordered_map<std::string, PowerRailInfo> &GetPowerRailInfoMap() const override {
return power_files_.GetPowerRailInfoMap();
}
// Get PowerStatus Map
- const std::unordered_map<std::string, PowerStatus> &GetPowerStatusMap() const {
+ const std::unordered_map<std::string, PowerStatus> &GetPowerStatusMap() const override {
return power_files_.GetPowerStatusMap();
}
// Get Thermal Stats Sensor Map
- const std::unordered_map<std::string, SensorTempStats> GetSensorTempStatsSnapshot() {
+ const std::unordered_map<std::string, SensorTempStats> GetSensorTempStatsSnapshot() override {
return thermal_stats_helper_.GetSensorTempStatsSnapshot();
}
// Get Thermal Stats Sensor, Binded Cdev State Request Map
const std::unordered_map<std::string, std::unordered_map<std::string, ThermalStats<int>>>
- GetSensorCoolingDeviceRequestStatsSnapshot() {
+ GetSensorCoolingDeviceRequestStatsSnapshot() override {
return thermal_stats_helper_.GetSensorCoolingDeviceRequestStatsSnapshot();
}
- void sendPowerExtHint(const Temperature &t);
- bool isAidlPowerHalExist() { return power_hal_service_.isAidlPowerHalExist(); }
- bool isPowerHalConnected() { return power_hal_service_.isPowerHalConnected(); }
- bool isPowerHalExtConnected() { return power_hal_service_.isPowerHalExtConnected(); }
+ bool isAidlPowerHalExist() override { return power_hal_service_.isAidlPowerHalExist(); }
+ bool isPowerHalConnected() override { return power_hal_service_.isPowerHalConnected(); }
+ bool isPowerHalExtConnected() override { return power_hal_service_.isPowerHalExtConnected(); }
private:
bool initializeSensorMap(const std::unordered_map<std::string, std::string> &path_map);
@@ -169,9 +203,10 @@ class ThermalHelper {
// Read temperature data according to thermal sensor's info
bool readThermalSensor(std::string_view sensor_name, float *temp, const bool force_sysfs,
std::map<std::string, float> *sensor_log_map);
- bool connectToPowerHal();
- void updateSupportedPowerHints();
void updateCoolingDevices(const std::vector<std::string> &cooling_devices_to_update);
+ // Check the max CDEV state for cdev_ceiling
+ void maxCoolingRequestCheck(
+ std::unordered_map<std::string, BindedCdevInfo> *binded_cdev_info_map);
sp<ThermalWatcher> thermal_watcher_;
PowerFiles power_files_;
ThermalFiles thermal_sensors_;
diff --git a/thermal/utils/power_files.cpp b/thermal/utils/power_files.cpp
index 50cc5b62..767f434b 100644
--- a/thermal/utils/power_files.cpp
+++ b/thermal/utils/power_files.cpp
@@ -39,6 +39,28 @@ constexpr std::string_view kEnergyValueNode("energy_value");
using ::android::base::ReadFileToString;
using ::android::base::StringPrintf;
+namespace {
+bool calculateAvgPower(std::string_view power_rail, const PowerSample &last_sample,
+ const PowerSample &curr_sample, float *avg_power) {
+ *avg_power = NAN;
+ const auto duration = curr_sample.duration - last_sample.duration;
+ const auto deltaEnergy = curr_sample.energy_counter - last_sample.energy_counter;
+ if (!last_sample.duration) {
+ LOG(VERBOSE) << "Power rail " << power_rail.data()
+ << ": all power samples have not been collected yet";
+ } else if (duration <= 0 || deltaEnergy < 0) {
+ LOG(ERROR) << "Power rail " << power_rail.data() << " is invalid: duration = " << duration
+ << ", deltaEnergy = " << deltaEnergy;
+ return false;
+ } else {
+ *avg_power = static_cast<float>(deltaEnergy) / static_cast<float>(duration);
+ LOG(VERBOSE) << "Power rail " << power_rail.data() << ", avg power = " << *avg_power
+ << ", duration = " << duration << ", deltaEnergy = " << deltaEnergy;
+ }
+ return true;
+}
+} // namespace
+
bool PowerFiles::registerPowerRailsToWatch(const Json::Value &config) {
if (!ParsePowerRailInfo(config, &power_rail_info_map_)) {
LOG(ERROR) << "Failed to parse power rail info config";
@@ -113,6 +135,9 @@ bool PowerFiles::registerPowerRailsToWatch(const Json::Value &config) {
}
LOG(INFO) << "Successfully to register power rail " << power_rail_info_pair.first;
}
+
+ power_status_log_ = {.prev_log_time = boot_clock::now(),
+ .prev_energy_info_map = energy_info_map_};
return true;
}
@@ -212,33 +237,16 @@ bool PowerFiles::updateEnergyValues(void) {
float PowerFiles::updateAveragePower(std::string_view power_rail,
std::queue<PowerSample> *power_history) {
float avg_power = NAN;
-
if (!energy_info_map_.count(power_rail.data())) {
LOG(ERROR) << " Could not find power rail " << power_rail.data();
return avg_power;
}
const auto last_sample = power_history->front();
const auto curr_sample = energy_info_map_.at(power_rail.data());
- const auto duration = curr_sample.duration - last_sample.duration;
- const auto deltaEnergy = curr_sample.energy_counter - last_sample.energy_counter;
-
- if (!last_sample.duration) {
- LOG(VERBOSE) << "Power rail " << power_rail.data()
- << ": all power samples have not been collected yet";
- } else if (duration <= 0 || deltaEnergy < 0) {
- LOG(ERROR) << "Power rail " << power_rail.data() << " is invalid: duration = " << duration
- << ", deltaEnergy = " << deltaEnergy;
-
- return avg_power;
- } else {
- avg_power = static_cast<float>(deltaEnergy) / static_cast<float>(duration);
- LOG(VERBOSE) << "Power rail " << power_rail.data() << ", avg power = " << avg_power
- << ", duration = " << duration << ", deltaEnergy = " << deltaEnergy;
+ if (calculateAvgPower(power_rail, last_sample, curr_sample, &avg_power)) {
+ power_history->pop();
+ power_history->push(curr_sample);
}
-
- power_history->pop();
- power_history->push(curr_sample);
-
return avg_power;
}
@@ -335,6 +343,43 @@ bool PowerFiles::refreshPowerStatus(void) {
return true;
}
+void PowerFiles::logPowerStatus(const boot_clock::time_point &now) {
+ // calculate energy and print
+ uint8_t power_rail_log_cnt = 0;
+ uint64_t max_duration = 0;
+ float tot_power = 0.0;
+ std::string out;
+ for (const auto &energy_info_pair : energy_info_map_) {
+ const auto &rail = energy_info_pair.first;
+ if (!power_status_log_.prev_energy_info_map.count(rail)) {
+ continue;
+ }
+ const auto &last_sample = power_status_log_.prev_energy_info_map.at(rail);
+ const auto &curr_sample = energy_info_pair.second;
+ float avg_power = NAN;
+ if (calculateAvgPower(rail, last_sample, curr_sample, &avg_power) && avg_power != NAN) {
+ // start of new line
+ if (power_rail_log_cnt % kMaxPowerLogPerLine == 0) {
+ if (power_rail_log_cnt != 0) {
+ out.append("\n");
+ }
+ out.append("Power rails ");
+ }
+ out.append(StringPrintf("[%s: %0.2f mW] ", rail.c_str(), avg_power));
+ power_rail_log_cnt++;
+ tot_power += avg_power;
+ max_duration = std::max(max_duration, curr_sample.duration - last_sample.duration);
+ }
+ }
+
+ if (power_rail_log_cnt) {
+ LOG(INFO) << StringPrintf("Power rails total power: %0.2f mW for %" PRId64 " ms", tot_power,
+ max_duration);
+ LOG(INFO) << out;
+ }
+ power_status_log_ = {.prev_log_time = now, .prev_energy_info_map = energy_info_map_};
+}
+
} // namespace implementation
} // namespace thermal
} // namespace hardware
diff --git a/thermal/utils/power_files.h b/thermal/utils/power_files.h
index bcf8e820..0b00604f 100644
--- a/thermal/utils/power_files.h
+++ b/thermal/utils/power_files.h
@@ -47,6 +47,12 @@ struct PowerStatus {
float last_updated_avg_power;
};
+struct PowerStatusLog {
+ boot_clock::time_point prev_log_time;
+ // energy sample at last logging
+ std::unordered_map<std::string, PowerSample> prev_energy_info_map;
+};
+
// A helper class for monitoring power rails.
class PowerFiles {
public:
@@ -58,6 +64,12 @@ class PowerFiles {
bool registerPowerRailsToWatch(const Json::Value &config);
// Update the power data from ODPM sysfs
bool refreshPowerStatus(void);
+ // Log the power data for the duration
+ void logPowerStatus(const boot_clock::time_point &now);
+ // Get previous power log time_point
+ const boot_clock::time_point &GetPrevPowerLogTime() const {
+ return power_status_log_.prev_log_time;
+ }
// Get power status map
const std::unordered_map<std::string, PowerStatus> &GetPowerStatusMap() const {
std::shared_lock<std::shared_mutex> _lock(power_status_map_mutex_);
@@ -86,6 +98,7 @@ class PowerFiles {
std::unordered_map<std::string, PowerRailInfo> power_rail_info_map_;
// The set to store the energy source paths
std::unordered_set<std::string> energy_path_set_;
+ PowerStatusLog power_status_log_;
};
} // namespace implementation
diff --git a/thermal/utils/powerhal_helper.cpp b/thermal/utils/powerhal_helper.cpp
index c40d2629..f8ac7d0b 100644
--- a/thermal/utils/powerhal_helper.cpp
+++ b/thermal/utils/powerhal_helper.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define ATRACE_TAG (ATRACE_TAG_THERMAL | ATRACE_TAG_HAL)
+
#include "powerhal_helper.h"
#include <android-base/file.h>
@@ -29,7 +31,6 @@
#include <thread>
#include <vector>
-#include "thermal_info.h"
#include "thermal_throttling.h"
namespace aidl {
@@ -87,9 +88,103 @@ bool PowerHalService::connect() {
power_hal_aidl_exist_ = false;
}
+ if (power_hal_ext_aidl_death_recipient_.get() == nullptr) {
+ power_hal_ext_aidl_death_recipient_ = ndk::ScopedAIBinder_DeathRecipient(
+ AIBinder_DeathRecipient_new(onPowerHalExtAidlBinderDied));
+ }
+
+ auto linked = AIBinder_linkToDeath(power_hal_ext_aidl_->asBinder().get(),
+ power_hal_ext_aidl_death_recipient_.get(), this);
+
+ if (linked != STATUS_OK) {
+ LOG(ERROR) << "Failed to register power_hal_ext death recipient";
+ }
+
return true;
}
+void PowerHalService::reconnect() {
+ ATRACE_CALL();
+ if (!connect()) {
+ LOG(ERROR) << " Failed to reconnect power_hal_ext";
+ return;
+ }
+
+ LOG(INFO) << "Resend the power hints when power_hal_ext is reconnected";
+ std::lock_guard<std::shared_mutex> _lock(powerhint_status_mutex_);
+ for (const auto &[sensor_name, supported_powerhint] : supported_powerhint_map_) {
+ std::stringstream log_buf;
+ for (const auto &severity : ::ndk::enum_range<ThrottlingSeverity>()) {
+ bool mode = severity <= supported_powerhint.prev_hint_severity;
+ setMode(sensor_name, severity, mode);
+ log_buf << toString(severity).c_str() << ":" << mode << " ";
+ }
+
+ LOG(INFO) << sensor_name << " send powerhint: " << log_buf.str();
+ log_buf.clear();
+ }
+ return;
+}
+
+void PowerHalService::updateSupportedPowerHints(
+ const std::unordered_map<std::string, SensorInfo> &sensor_info_map_) {
+ for (auto const &name_status_pair : sensor_info_map_) {
+ if (!(name_status_pair.second.send_powerhint)) {
+ continue;
+ }
+ ThrottlingSeverity current_severity = ThrottlingSeverity::NONE;
+ for (const auto &severity : ::ndk::enum_range<ThrottlingSeverity>()) {
+ if (severity == ThrottlingSeverity::NONE) {
+ supported_powerhint_map_[name_status_pair.first]
+ .hint_severity_map[ThrottlingSeverity::NONE] = ThrottlingSeverity::NONE;
+ continue;
+ }
+
+ bool isSupported = false;
+ ndk::ScopedAStatus isSupportedResult;
+
+ if (power_hal_ext_aidl_ != nullptr) {
+ isSupported = isModeSupported(name_status_pair.first, severity);
+ }
+ if (isSupported)
+ current_severity = severity;
+ supported_powerhint_map_[name_status_pair.first].hint_severity_map[severity] =
+ current_severity;
+ }
+ }
+}
+
+void PowerHalService::sendPowerExtHint(const Temperature &t) {
+ ATRACE_CALL();
+ std::lock_guard<std::shared_mutex> _lock(powerhint_status_mutex_);
+ ThrottlingSeverity prev_hint_severity = supported_powerhint_map_[t.name].prev_hint_severity;
+ ThrottlingSeverity current_hint_severity =
+ supported_powerhint_map_[t.name].hint_severity_map[t.throttlingStatus];
+ std::stringstream log_buf;
+
+ if (!power_hal_aidl_exist_) {
+ LOG(ERROR) << "power_hal_aidl is not exist";
+ return;
+ }
+
+ if (prev_hint_severity == current_hint_severity) {
+ return;
+ }
+
+ for (const auto &severity : ::ndk::enum_range<ThrottlingSeverity>()) {
+ if (severity != supported_powerhint_map_[t.name].hint_severity_map[severity]) {
+ continue;
+ }
+ bool mode = severity <= current_hint_severity;
+ setMode(t.name, severity, mode);
+ log_buf << toString(severity).c_str() << ":" << mode << " ";
+ }
+
+ LOG(INFO) << t.name << " send powerhint: " << log_buf.str();
+
+ supported_powerhint_map_[t.name].prev_hint_severity = current_hint_severity;
+}
+
bool PowerHalService::isModeSupported(const std::string &type, const ThrottlingSeverity &t) {
bool isSupported = false;
if (!connect()) {
@@ -115,8 +210,6 @@ void PowerHalService::setMode(const std::string &type, const ThrottlingSeverity
}
std::string power_hint = StringPrintf("THERMAL_%s_%s", type.c_str(), toString(t).c_str());
- LOG(INFO) << (error_on_exit ? "Resend Hint " : "Send Hint ") << power_hint
- << " Enable: " << std::boolalpha << enable;
lock_.lock();
if (!power_hal_ext_aidl_->setMode(power_hint, enable).isOk()) {
LOG(ERROR) << "Fail to set mode, Hint: " << power_hint;
diff --git a/thermal/utils/powerhal_helper.h b/thermal/utils/powerhal_helper.h
index 0769aa23..ac3d8b5e 100644
--- a/thermal/utils/powerhal_helper.h
+++ b/thermal/utils/powerhal_helper.h
@@ -17,8 +17,10 @@
#pragma once
#include <aidl/android/hardware/power/IPower.h>
+#include <aidl/android/hardware/thermal/IThermal.h>
#include <aidl/android/hardware/thermal/ThrottlingSeverity.h>
#include <aidl/google/hardware/power/extension/pixel/IPowerExt.h>
+#include <utils/Trace.h>
#include <queue>
#include <shared_mutex>
@@ -26,6 +28,8 @@
#include <unordered_map>
#include <unordered_set>
+#include "thermal_info.h"
+
namespace aidl {
namespace android {
namespace hardware {
@@ -37,23 +41,47 @@ using ::aidl::google::hardware::power::extension::pixel::IPowerExt;
using CdevRequestStatus = std::unordered_map<std::string, int>;
+struct PowerHintstatus {
+ std::unordered_map<ThrottlingSeverity, ThrottlingSeverity> hint_severity_map;
+ ThrottlingSeverity prev_hint_severity;
+};
+
class PowerHalService {
public:
PowerHalService();
~PowerHalService() = default;
bool connect();
+ void reconnect();
bool isAidlPowerHalExist() { return power_hal_aidl_exist_; }
bool isModeSupported(const std::string &type, const ThrottlingSeverity &t);
bool isPowerHalConnected() { return power_hal_aidl_ != nullptr; }
bool isPowerHalExtConnected() { return power_hal_ext_aidl_ != nullptr; }
void setMode(const std::string &type, const ThrottlingSeverity &t, const bool &enable,
const bool error_on_exit = false);
+ void updateSupportedPowerHints(
+ const std::unordered_map<std::string, SensorInfo> &sensor_info_map_);
+ void sendPowerExtHint(const Temperature &t);
private:
+ ndk::ScopedAIBinder_DeathRecipient power_hal_ext_aidl_death_recipient_;
+ static void onPowerHalExtAidlBinderDied(void *cookie) {
+ if (cookie) {
+ auto *e = static_cast<PowerHalService *>(cookie);
+ {
+ std::lock_guard<std::mutex> lock(e->lock_);
+ e->power_hal_aidl_ = nullptr;
+ e->power_hal_ext_aidl_ = nullptr;
+ }
+ e->reconnect();
+ }
+ }
+
bool power_hal_aidl_exist_;
std::shared_ptr<IPower> power_hal_aidl_;
std::shared_ptr<IPowerExt> power_hal_ext_aidl_;
std::mutex lock_;
+ std::unordered_map<std::string, PowerHintstatus> supported_powerhint_map_;
+ mutable std::shared_mutex powerhint_status_mutex_;
};
} // namespace implementation
diff --git a/thermal/utils/thermal_files.cpp b/thermal/utils/thermal_files.cpp
index 26aaf450..c42fa1c3 100644
--- a/thermal/utils/thermal_files.cpp
+++ b/thermal/utils/thermal_files.cpp
@@ -63,6 +63,11 @@ bool ThermalFiles::readThermalFile(std::string_view thermal_name, std::string *d
return false;
}
+ if (sensor_reading.size() <= 1) {
+ LOG(ERROR) << thermal_name << "'s return size:" << sensor_reading.size() << " is invalid";
+ return false;
+ }
+
// Strip the newline.
*data = ::android::base::Trim(sensor_reading);
return true;
diff --git a/thermal/utils/thermal_info.cpp b/thermal/utils/thermal_info.cpp
index c00bf63e..c5535c5f 100644
--- a/thermal/utils/thermal_info.cpp
+++ b/thermal/utils/thermal_info.cpp
@@ -162,7 +162,8 @@ bool ParseVirtualSensorInfo(const std::string_view name, const Json::Value &sens
std::vector<std::string> linked_sensors;
std::vector<SensorFusionType> linked_sensors_type;
std::vector<std::string> trigger_sensors;
- std::vector<float> coefficients;
+ std::vector<std::string> coefficients;
+ std::vector<SensorFusionType> coefficients_type;
FormulaOption formula = FormulaOption::COUNT_THRESHOLD;
Json::Value values = sensor["Combination"];
@@ -192,6 +193,8 @@ bool ParseVirtualSensorInfo(const std::string_view name, const Json::Value &sens
linked_sensors_type.emplace_back(SensorFusionType::SENSOR);
} else if (values[j].asString().compare("ODPM") == 0) {
linked_sensors_type.emplace_back(SensorFusionType::ODPM);
+ } else if (values[j].asString().compare("CONSTANT") == 0) {
+ linked_sensors_type.emplace_back(SensorFusionType::CONSTANT);
} else {
LOG(ERROR) << "Sensor[" << name << "] has invalid CombinationType settings "
<< values[j].asString();
@@ -206,7 +209,7 @@ bool ParseVirtualSensorInfo(const std::string_view name, const Json::Value &sens
if (values.size()) {
coefficients.reserve(values.size());
for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
- coefficients.emplace_back(getFloatFromValue(values[j]));
+ coefficients.emplace_back(values[j].asString());
LOG(INFO) << "Sensor[" << name << "]'s coefficient[" << j << "]: " << coefficients[j];
}
} else {
@@ -217,6 +220,40 @@ bool ParseVirtualSensorInfo(const std::string_view name, const Json::Value &sens
LOG(ERROR) << "Sensor[" << name << "] has invalid Coefficient size";
return false;
}
+
+ values = sensor["CoefficientType"];
+ if (!values.size()) {
+ coefficients_type.reserve(linked_sensors.size());
+ for (size_t j = 0; j < linked_sensors.size(); ++j) {
+ coefficients_type.emplace_back(SensorFusionType::CONSTANT);
+ }
+ } else if (values.size() != coefficients.size()) {
+ LOG(ERROR) << "Sensor[" << name << "] has invalid coefficient type size";
+ return false;
+ } else {
+ for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
+ if (values[j].asString().compare("CONSTANT") == 0) {
+ coefficients_type.emplace_back(SensorFusionType::CONSTANT);
+ } else if (values[j].asString().compare("SENSOR") == 0) {
+ coefficients_type.emplace_back(SensorFusionType::SENSOR);
+ } else if (values[j].asString().compare("ODPM") == 0) {
+ coefficients_type.emplace_back(SensorFusionType::ODPM);
+ } else {
+ LOG(ERROR) << "Sensor[" << name << "] has invalid coefficient options "
+ << values[j].asString();
+ return false;
+ }
+ LOG(INFO) << "Sensor[" << name << "]'s coefficient type[" << j
+ << "]: " << coefficients_type[j];
+ }
+ }
+
+ if (linked_sensors.size() != coefficients_type.size()) {
+ LOG(ERROR) << "Sensor[" << name
+ << "]'s combination size is not matched with coefficient type size";
+ return false;
+ }
+
if (!sensor["Offset"].empty()) {
offset = sensor["Offset"].asFloat();
}
@@ -255,8 +292,9 @@ bool ParseVirtualSensorInfo(const std::string_view name, const Json::Value &sens
LOG(ERROR) << "Sensor[" << name << "]'s Formula is invalid";
return false;
}
- virtual_sensor_info->reset(new VirtualSensorInfo{
- linked_sensors, linked_sensors_type, coefficients, offset, trigger_sensors, formula});
+ virtual_sensor_info->reset(new VirtualSensorInfo{linked_sensors, linked_sensors_type,
+ coefficients, coefficients_type, offset,
+ trigger_sensors, formula});
return true;
}
@@ -332,6 +370,7 @@ bool ParseBindedCdevInfo(const Json::Value &values,
std::string power_rail;
bool high_power_check = false;
bool throttling_with_power_link = false;
+ bool enabled = true;
CdevArray cdev_floor_with_power_link;
cdev_floor_with_power_link.fill(0);
@@ -387,6 +426,9 @@ bool ParseBindedCdevInfo(const Json::Value &values,
}
}
}
+ if (values[j]["Disabled"].asBool()) {
+ enabled = false;
+ }
(*binded_cdev_info_map)[cdev_name] = {
.limit_info = limit_info,
@@ -400,6 +442,7 @@ bool ParseBindedCdevInfo(const Json::Value &values,
.max_throttle_step = max_throttle_step,
.cdev_floor_with_power_link = cdev_floor_with_power_link,
.power_rail = power_rail,
+ .enabled = enabled,
};
}
return true;
@@ -531,9 +574,48 @@ bool ParseSensorThrottlingInfo(const std::string_view name, const Json::Value &s
LOG(ERROR) << "Sensor[" << name << "]: failed to parse BindedCdevInfo";
return false;
}
+ Json::Value values;
+ ProfileMap profile_map;
+
+ values = sensor["Profile"];
+ for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
+ Json::Value sub_values;
+ const std::string &mode = values[j]["Mode"].asString();
+ std::unordered_map<std::string, BindedCdevInfo> binded_cdev_info_map_profile;
+ if (!ParseBindedCdevInfo(values[j]["BindedCdevInfo"], &binded_cdev_info_map_profile,
+ support_pid, &support_hard_limit)) {
+ LOG(ERROR) << "Sensor[" << name << " failed to parse BindedCdevInfo profile";
+ }
+ // Check if the binded_cdev_info_map_profile is valid
+ if (binded_cdev_info_map.size() != binded_cdev_info_map_profile.size()) {
+ LOG(ERROR) << "Sensor[" << name << "]:'s profile map size should not be changed";
+ return false;
+ } else {
+ for (const auto &binded_cdev_info_pair : binded_cdev_info_map_profile) {
+ if (binded_cdev_info_map.count(binded_cdev_info_pair.first)) {
+ if (binded_cdev_info_pair.second.power_rail !=
+ binded_cdev_info_map.at(binded_cdev_info_pair.first).power_rail) {
+ LOG(ERROR) << "Sensor[" << name << "]:'s profile " << mode << " binded "
+ << binded_cdev_info_pair.first
+ << "'s power rail is not included in default rules";
+ return false;
+ } else {
+ LOG(INFO) << "Sensor[" << name << "]:'s profile " << mode
+ << " is parsed successfully";
+ }
+ } else {
+ LOG(ERROR) << "Sensor[" << name << "]'s profile " << mode << " binded "
+ << binded_cdev_info_pair.first
+ << " is not included in default rules";
+ return false;
+ }
+ }
+ }
+ profile_map[mode] = binded_cdev_info_map_profile;
+ }
std::unordered_map<std::string, ThrottlingArray> excluded_power_info_map;
- Json::Value values = sensor["ExcludedPowerInfo"];
+ values = sensor["ExcludedPowerInfo"];
for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
Json::Value sub_values;
const std::string &power_rail = values[j]["PowerRail"].asString();
@@ -555,7 +637,7 @@ bool ParseSensorThrottlingInfo(const std::string_view name, const Json::Value &s
}
throttling_info->reset(new ThrottlingInfo{
k_po, k_pu, k_i, k_d, i_max, max_alloc_power, min_alloc_power, s_power, i_cutoff,
- i_default, tran_cycle, excluded_power_info_map, binded_cdev_info_map});
+ i_default, tran_cycle, excluded_power_info_map, binded_cdev_info_map, profile_map});
*support_throttling = support_pid | support_hard_limit;
return true;
}
@@ -797,6 +879,16 @@ bool ParseSensorInfo(const Json::Value &config,
}
LOG(INFO) << "Sensor[" << name << "]'s Time resolution: " << time_resolution.count();
+ float step_ratio = NAN;
+ if (!sensors[i]["StepRatio"].empty()) {
+ step_ratio = sensors[i]["StepRatio"].asFloat();
+ if (step_ratio < 0 || step_ratio > 1) {
+ LOG(ERROR) << "Sensor[" << name << "]'s StepRatio should be set 0 ~ 1";
+ sensors_parsed->clear();
+ return false;
+ }
+ }
+
if (is_hidden && send_cb) {
LOG(ERROR) << "is_hidden and send_cb cannot be enabled together";
sensors_parsed->clear();
@@ -833,6 +925,7 @@ bool ParseSensorInfo(const Json::Value &config,
.polling_delay = polling_delay,
.passive_delay = passive_delay,
.time_resolution = time_resolution,
+ .step_ratio = step_ratio,
.send_cb = send_cb,
.send_powerhint = send_powerhint,
.is_watch = is_watch,
@@ -939,7 +1032,7 @@ bool ParsePowerRailInfo(const Json::Value &config,
LOG(INFO) << "PowerRail[" << i << "]'s Rail: " << rail;
std::vector<std::string> linked_power_rails;
- std::vector<float> coefficients;
+ std::vector<float> coefficient;
float offset = 0;
FormulaOption formula = FormulaOption::COUNT_THRESHOLD;
bool is_virtual_power_rail = false;
@@ -969,11 +1062,11 @@ bool ParsePowerRailInfo(const Json::Value &config,
values = power_rails[i]["Coefficient"];
if (values.size()) {
- coefficients.reserve(values.size());
+ coefficient.reserve(values.size());
for (Json::Value::ArrayIndex j = 0; j < values.size(); ++j) {
- coefficients.emplace_back(getFloatFromValue(values[j]));
+ coefficient.emplace_back(getFloatFromValue(values[j]));
LOG(INFO) << "PowerRail[" << name << "]'s coefficient[" << j
- << "]: " << coefficients[j];
+ << "]: " << coefficient[j];
}
} else {
LOG(ERROR) << "PowerRails[" << name << "] has no coefficient for VirtualRail";
@@ -981,7 +1074,7 @@ bool ParsePowerRailInfo(const Json::Value &config,
return false;
}
- if (linked_power_rails.size() != coefficients.size()) {
+ if (linked_power_rails.size() != coefficient.size()) {
LOG(ERROR) << "PowerRails[" << name
<< "]'s combination size is not matched with coefficient size";
power_rails_parsed->clear();
@@ -992,7 +1085,7 @@ bool ParsePowerRailInfo(const Json::Value &config,
offset = power_rails[i]["Offset"].asFloat();
}
- if (linked_power_rails.size() != coefficients.size()) {
+ if (linked_power_rails.size() != coefficient.size()) {
LOG(ERROR) << "PowerRails[" << name
<< "]'s combination size is not matched with coefficient size";
power_rails_parsed->clear();
@@ -1017,7 +1110,7 @@ bool ParsePowerRailInfo(const Json::Value &config,
std::unique_ptr<VirtualPowerRailInfo> virtual_power_rail_info;
if (is_virtual_power_rail) {
virtual_power_rail_info.reset(
- new VirtualPowerRailInfo{linked_power_rails, coefficients, offset, formula});
+ new VirtualPowerRailInfo{linked_power_rails, coefficient, offset, formula});
}
power_sample_count = power_rails[i]["PowerSampleCount"].asInt();
diff --git a/thermal/utils/thermal_info.h b/thermal/utils/thermal_info.h
index 5b2e8b80..12997f26 100644
--- a/thermal/utils/thermal_info.h
+++ b/thermal/utils/thermal_info.h
@@ -40,6 +40,9 @@ using ThrottlingArray = std::array<float, static_cast<size_t>(kThrottlingSeverit
using CdevArray = std::array<int, static_cast<size_t>(kThrottlingSeverityCount)>;
constexpr std::chrono::milliseconds kMinPollIntervalMs = std::chrono::milliseconds(2000);
constexpr std::chrono::milliseconds kUeventPollTimeoutMs = std::chrono::milliseconds(300000);
+// TODO(b/292044404): Add debug config to make them easily configurable
+constexpr std::chrono::milliseconds kPowerLogIntervalMs = std::chrono::milliseconds(60000);
+constexpr int kMaxPowerLogPerLine = 6;
// Max number of time_in_state buckets is 20 in atoms
// VendorSensorCoolingDeviceStats, VendorTempResidencyStats
constexpr int kMaxStatsResidencyCount = 20;
@@ -93,12 +96,15 @@ struct StatsConfig {
enum SensorFusionType : uint32_t {
SENSOR = 0,
ODPM,
+ CONSTANT,
};
struct VirtualSensorInfo {
std::vector<std::string> linked_sensors;
std::vector<SensorFusionType> linked_sensors_type;
- std::vector<float> coefficients;
+ std::vector<std::string> coefficients;
+ std::vector<SensorFusionType> coefficients_type;
+
float offset;
std::vector<std::string> trigger_sensors;
FormulaOption formula;
@@ -134,8 +140,12 @@ struct BindedCdevInfo {
bool high_power_check;
// The flag for only triggering throttling until all power samples are collected
bool throttling_with_power_link;
+ bool enabled;
};
+// The map to store the CDEV throttling info for each profile
+using ProfileMap = std::unordered_map<std::string, std::unordered_map<std::string, BindedCdevInfo>>;
+
struct ThrottlingInfo {
ThrottlingArray k_po;
ThrottlingArray k_pu;
@@ -150,6 +160,7 @@ struct ThrottlingInfo {
int tran_cycle;
std::unordered_map<std::string, ThrottlingArray> excluded_power_info_map;
std::unordered_map<std::string, BindedCdevInfo> binded_cdev_info_map;
+ ProfileMap profile_map;
};
struct SensorInfo {
@@ -164,6 +175,9 @@ struct SensorInfo {
std::chrono::milliseconds polling_delay;
std::chrono::milliseconds passive_delay;
std::chrono::milliseconds time_resolution;
+ // The StepRatio value which is used for smoothing transient w/ the equation:
+ // Temp = CurrentTemp * StepRatio + LastTemp * (1 - StepRatio)
+ float step_ratio;
bool send_cb;
bool send_powerhint;
bool is_watch;
diff --git a/thermal/utils/thermal_stats_helper.cpp b/thermal/utils/thermal_stats_helper.cpp
index daaaf1c6..bbd99542 100644
--- a/thermal/utils/thermal_stats_helper.cpp
+++ b/thermal/utils/thermal_stats_helper.cpp
@@ -313,6 +313,9 @@ int ThermalStatsHelper::reportAllSensorTempStats(const std::shared_ptr<IStats> &
count_failed_reporting++;
}
}
+ // Reset temp stats after reporting
+ temp_stats.max_temp = std::numeric_limits<float>::min();
+ temp_stats.min_temp = std::numeric_limits<float>::max();
}
return count_failed_reporting;
}
diff --git a/thermal/utils/thermal_throttling.cpp b/thermal/utils/thermal_throttling.cpp
index 8aac95d4..57dca169 100644
--- a/thermal/utils/thermal_throttling.cpp
+++ b/thermal/utils/thermal_throttling.cpp
@@ -58,6 +58,28 @@ size_t getTargetStateOfPID(const SensorInfo &sensor_info, const ThrottlingSeveri
return target_state;
}
+void ThermalThrottling::parseProfileProperty(std::string_view sensor_name,
+ const SensorInfo &sensor_info) {
+ if (sensor_info.throttling_info == nullptr) {
+ return;
+ }
+
+ const std::string profile = ::android::base::GetProperty(
+ StringPrintf("vendor.thermal.%s.profile", sensor_name.data()), "");
+
+ if (profile.empty() || sensor_info.throttling_info->profile_map.count(profile)) {
+ if (profile != thermal_throttling_status_map_[sensor_name.data()].profile) {
+ LOG(INFO) << sensor_name.data() << ": throttling profile change to "
+ << ((profile.empty()) ? "default" : profile);
+ thermal_throttling_status_map_[sensor_name.data()].profile = profile;
+ }
+ } else {
+ LOG(ERROR) << sensor_name.data() << ": set profile to default because " << profile
+ << " is invalid";
+ thermal_throttling_status_map_[sensor_name.data()].profile = "";
+ }
+}
+
void ThermalThrottling::clearThrottlingData(std::string_view sensor_name,
const SensorInfo &sensor_info) {
if (!thermal_throttling_status_map_.count(sensor_name.data())) {
@@ -115,6 +137,7 @@ bool ThermalThrottling::registerThermalThrottling(
static_cast<size_t>(ThrottlingSeverity::NONE);
thermal_throttling_status_map_[sensor_name.data()].prev_power_budget = NAN;
thermal_throttling_status_map_[sensor_name.data()].tran_cycle = 0;
+ thermal_throttling_status_map_[sensor_name.data()].profile = "";
for (auto &binded_cdev_pair : throttling_info->binded_cdev_info_map) {
if (!cooling_device_info_map.count(binded_cdev_pair.first)) {
@@ -247,10 +270,12 @@ float ThermalThrottling::updatePowerBudget(const Temperature &temp, const Sensor
ATRACE_INT((sensor_name + std::string("-target_state")).c_str(),
static_cast<int>(target_state));
- ATRACE_INT((sensor_name + std::string("-err")).c_str(), static_cast<int>(err / sensor_info.multiplier));
+ ATRACE_INT((sensor_name + std::string("-err")).c_str(),
+ static_cast<int>(err / sensor_info.multiplier));
ATRACE_INT((sensor_name + std::string("-p")).c_str(), static_cast<int>(p));
ATRACE_INT((sensor_name + std::string("-d")).c_str(), static_cast<int>(d));
- ATRACE_INT((sensor_name + std::string("-temp")).c_str(), static_cast<int>(temp.value / sensor_info.multiplier));
+ ATRACE_INT((sensor_name + std::string("-temp")).c_str(),
+ static_cast<int>(temp.value / sensor_info.multiplier));
throttling_status.prev_power_budget = power_budget;
@@ -305,6 +330,7 @@ bool ThermalThrottling::allocatePowerToCdev(
std::unique_lock<std::shared_mutex> _lock(thermal_throttling_status_map_mutex_);
auto total_power_budget = updatePowerBudget(temp, sensor_info, time_elapsed_ms, curr_severity);
+ const auto &profile = thermal_throttling_status_map_[temp.name].profile;
if (sensor_info.throttling_info->excluded_power_info_map.size()) {
total_power_budget -= computeExcludedPower(sensor_info, curr_severity, power_status_map,
@@ -317,10 +343,15 @@ bool ThermalThrottling::allocatePowerToCdev(
}
// Compute total cdev weight
- for (const auto &binded_cdev_info_pair : sensor_info.throttling_info->binded_cdev_info_map) {
+ for (const auto &binded_cdev_info_pair :
+ (sensor_info.throttling_info->profile_map.count(profile)
+ ? sensor_info.throttling_info->profile_map.at(profile)
+ : sensor_info.throttling_info->binded_cdev_info_map)) {
const auto cdev_weight = binded_cdev_info_pair.second
.cdev_weight_for_pid[static_cast<size_t>(curr_severity)];
- if (std::isnan(cdev_weight) || cdev_weight == 0) {
+ if (!binded_cdev_info_pair.second.enabled) {
+ continue;
+ } else if (std::isnan(cdev_weight) || cdev_weight == 0) {
allocated_cdev.insert(binded_cdev_info_pair.first);
continue;
}
@@ -329,7 +360,9 @@ bool ThermalThrottling::allocatePowerToCdev(
while (!is_budget_allocated) {
for (const auto &binded_cdev_info_pair :
- sensor_info.throttling_info->binded_cdev_info_map) {
+ (sensor_info.throttling_info->profile_map.count(profile)
+ ? sensor_info.throttling_info->profile_map.at(profile)
+ : sensor_info.throttling_info->binded_cdev_info_map)) {
float cdev_power_adjustment = 0;
const auto cdev_weight =
binded_cdev_info_pair.second
@@ -338,10 +371,6 @@ bool ThermalThrottling::allocatePowerToCdev(
if (allocated_cdev.count(binded_cdev_info_pair.first)) {
continue;
}
- if (std::isnan(cdev_weight) || !cdev_weight) {
- allocated_cdev.insert(binded_cdev_info_pair.first);
- continue;
- }
// Get the power data
if (!power_data_invalid) {
@@ -403,7 +432,9 @@ bool ThermalThrottling::allocatePowerToCdev(
continue;
}
- if (!power_data_invalid && binded_cdev_info_pair.second.power_rail != "") {
+ if (!binded_cdev_info_pair.second.enabled) {
+ cdev_power_budget = cdev_info.state2power[0];
+ } else if (!power_data_invalid && binded_cdev_info_pair.second.power_rail != "") {
auto cdev_curr_power_budget =
thermal_throttling_status_map_[temp.name].pid_power_budget_map.at(
binded_cdev_info_pair.first);
@@ -516,10 +547,22 @@ void ThermalThrottling::updateCdevRequestBySeverity(std::string_view sensor_name
const SensorInfo &sensor_info,
ThrottlingSeverity curr_severity) {
std::unique_lock<std::shared_mutex> _lock(thermal_throttling_status_map_mutex_);
- for (auto const &binded_cdev_info_pair : sensor_info.throttling_info->binded_cdev_info_map) {
+ const auto &profile = thermal_throttling_status_map_[sensor_name.data()].profile;
+
+ for (const auto &binded_cdev_info_pair :
+ (sensor_info.throttling_info->profile_map.count(profile)
+ ? sensor_info.throttling_info->profile_map.at(profile)
+ : sensor_info.throttling_info->binded_cdev_info_map)) {
+ if (!thermal_throttling_status_map_[sensor_name.data()].hardlimit_cdev_request_map.count(
+ binded_cdev_info_pair.first)) {
+ continue;
+ }
thermal_throttling_status_map_[sensor_name.data()].hardlimit_cdev_request_map.at(
binded_cdev_info_pair.first) =
- binded_cdev_info_pair.second.limit_info[static_cast<size_t>(curr_severity)];
+ (binded_cdev_info_pair.second.enabled)
+ ? binded_cdev_info_pair.second
+ .limit_info[static_cast<size_t>(curr_severity)]
+ : 0;
LOG(VERBOSE) << "Hard Limit: Sensor " << sensor_name.data() << " update cdev "
<< binded_cdev_info_pair.first << " to "
<< thermal_throttling_status_map_[sensor_name.data()]
@@ -633,6 +676,10 @@ void ThermalThrottling::thermalThrottlingUpdate(
return;
}
+ if (sensor_info.throttling_info->profile_map.size()) {
+ parseProfileProperty(temp.name.c_str(), sensor_info);
+ }
+
if (thermal_throttling_status_map_[temp.name].pid_power_budget_map.size()) {
if (!allocatePowerToCdev(temp, sensor_info, curr_severity, time_elapsed_ms,
power_status_map, cooling_device_info_map)) {
@@ -670,12 +717,17 @@ void ThermalThrottling::computeCoolingDevicesRequest(
auto &thermal_throttling_status = thermal_throttling_status_map_.at(sensor_name.data());
const auto &cdev_release_map = thermal_throttling_status.throttling_release_map;
+ const auto &profile = thermal_throttling_status_map_[sensor_name.data()].profile;
+ const auto &binded_cdev_info_map =
+ sensor_info.throttling_info->profile_map.count(profile)
+ ? sensor_info.throttling_info->profile_map.at(profile)
+ : sensor_info.throttling_info->binded_cdev_info_map;
+
for (auto &cdev_request_pair : thermal_throttling_status.cdev_status_map) {
int pid_cdev_request = 0;
int hardlimit_cdev_request = 0;
const auto &cdev_name = cdev_request_pair.first;
- const auto &binded_cdev_info =
- sensor_info.throttling_info->binded_cdev_info_map.at(cdev_name);
+ const auto &binded_cdev_info = binded_cdev_info_map.at(cdev_name);
const auto cdev_ceiling = binded_cdev_info.cdev_ceiling[static_cast<size_t>(curr_severity)];
const auto cdev_floor =
binded_cdev_info.cdev_floor_with_power_link[static_cast<size_t>(curr_severity)];
diff --git a/thermal/utils/thermal_throttling.h b/thermal/utils/thermal_throttling.h
index e83ee06a..76c41e0f 100644
--- a/thermal/utils/thermal_throttling.h
+++ b/thermal/utils/thermal_throttling.h
@@ -47,6 +47,7 @@ struct ThermalThrottlingStatus {
float prev_power_budget;
float budget_transient;
int tran_cycle;
+ std::string profile;
};
// Return the control temp target of PID algorithm
@@ -61,6 +62,8 @@ class ThermalThrottling {
ThermalThrottling(const ThermalThrottling &) = delete;
void operator=(const ThermalThrottling &) = delete;
+ // Check if the thermal throttling profile need to be switched
+ void parseProfileProperty(std::string_view sensor_name, const SensorInfo &sensor_info);
// Clear throttling data
void clearThrottlingData(std::string_view sensor_name, const SensorInfo &sensor_info);
// Register map for throttling algo
diff --git a/vibrator/cs40l26/Hardware.h b/vibrator/cs40l26/Hardware.h
index d5230fee..50e2cb66 100644
--- a/vibrator/cs40l26/Hardware.h
+++ b/vibrator/cs40l26/Hardware.h
@@ -144,11 +144,21 @@ class HwApi : public Vibrator::HwApi, private HwApiBase {
if (ioctl(fd, EVIOCGBIT(0, sizeof(val)), &val) > 0 && (val & (1 << EV_FF)) &&
ioctl(fd, EVIOCGNAME(sizeof(str)), &str) > 0 &&
strcmp(str, INPUT_EVENT_NAME.c_str()) == 0) {
+ // Get fd ready for input event ioctl().
mInputFd.reset(fd); // mInputFd.ok() becomes true.
ALOGI("Control %s through %s", INPUT_EVENT_NAME.c_str(), g.gl_pathv[i]);
- // Construct the sysfs device path.
std::string path = g.gl_pathv[i];
+ // Get fstream ready for input event write().
+ saveName(path, &mInputIoStream);
+ mInputIoStream.open(
+ path, std::fstream::out | std::fstream::in | std::fstream::binary);
+ if (!mInputIoStream) {
+ ALOGE("Failed to open %s (%d): %s", path.c_str(), errno,
+ strerror(errno));
+ }
+
+ // Construct the sysfs device path.
path = "/sys/class/input/" +
path.substr(path.find("event"), std::string::npos) + "/../../../";
updatePathPrefix(path);
@@ -185,9 +195,13 @@ class HwApi : public Vibrator::HwApi, private HwApiBase {
ALOGE("Invalid gain");
return false;
}
- if (write(mInputFd, (const void *)&gain, sizeof(gain)) != sizeof(gain)) {
+ mInputIoStream.write((const char *)&gain, sizeof(gain));
+ mInputIoStream.flush();
+ if (mInputIoStream.fail()) {
+ ALOGE("setFFGain fail");
return false;
}
+ HWAPI_RECORD(StringPrintf("%d%%", value), &mInputIoStream);
return true;
}
bool setFFEffect(struct ff_effect *effect, uint16_t timeoutMs) override {
@@ -199,9 +213,10 @@ class HwApi : public Vibrator::HwApi, private HwApiBase {
if (((*effect).replay.length != timeoutMs) || (ioctl(mInputFd, EVIOCSFF, effect) < 0)) {
ALOGE("setFFEffect fail");
return false;
- } else {
- return true;
}
+ HWAPI_RECORD(StringPrintf("#%d: %dms", (*effect).id, (*effect).replay.length),
+ &mInputIoStream);
+ return true;
}
bool setFFPlay(int8_t index, bool value) override {
ATRACE_NAME(StringPrintf("%s index:%d %s", __func__, index, value ? "on" : "off").c_str());
@@ -210,11 +225,14 @@ class HwApi : public Vibrator::HwApi, private HwApiBase {
.code = static_cast<uint16_t>(index),
.value = value,
};
- if (write(mInputFd, (const void *)&play, sizeof(play)) != sizeof(play)) {
+ mInputIoStream.write((const char *)&play, sizeof(play));
+ mInputIoStream.flush();
+ if (mInputIoStream.fail()) {
+ ALOGE("setFFPlay fail");
return false;
- } else {
- return true;
}
+ HWAPI_RECORD(StringPrintf("#%d: %b", index, value), &mInputIoStream);
+ return true;
}
bool getHapticAlsaDevice(int *card, int *device) override {
ATRACE_NAME(__func__);
@@ -227,6 +245,7 @@ class HwApi : public Vibrator::HwApi, private HwApiBase {
std::string currentToken;
std::getline(ss, currentToken, ':');
sscanf(currentToken.c_str(), "%d-%d", card, device);
+ saveName(StringPrintf("/dev/snd/pcmC%uD%up", *card, *device), &mPcmStream);
return true;
}
}
@@ -246,23 +265,27 @@ class HwApi : public Vibrator::HwApi, private HwApiBase {
ALOGE("cannot open pcm_out driver: %s", pcm_get_error(*haptic_pcm));
goto fail;
}
+ HWAPI_RECORD(std::string("pcm_open"), &mPcmStream);
ret = pcm_prepare(*haptic_pcm);
if (ret < 0) {
ALOGE("cannot prepare haptic_pcm: %s", pcm_get_error(*haptic_pcm));
goto fail;
}
+ HWAPI_RECORD(std::string("pcm_prepare"), &mPcmStream);
ret = pcm_start(*haptic_pcm);
if (ret < 0) {
ALOGE("cannot start haptic_pcm: %s", pcm_get_error(*haptic_pcm));
goto fail;
}
+ HWAPI_RECORD(std::string("pcm_start"), &mPcmStream);
return true;
} else {
if (*haptic_pcm) {
pcm_close(*haptic_pcm);
+ HWAPI_RECORD(std::string("pcm_close"), &mPcmStream);
*haptic_pcm = NULL;
}
return true;
@@ -270,6 +293,7 @@ class HwApi : public Vibrator::HwApi, private HwApiBase {
fail:
pcm_close(*haptic_pcm);
+ HWAPI_RECORD(std::string("pcm_close"), &mPcmStream);
*haptic_pcm = NULL;
return false;
}
@@ -308,6 +332,7 @@ class HwApi : public Vibrator::HwApi, private HwApiBase {
}
*outEffectIndex = (*effect).id;
*status = 0;
+ HWAPI_RECORD(StringPrintf("#%d: %dB", *outEffectIndex, numBytes), &mInputIoStream);
return true;
}
bool eraseOwtEffect(int8_t effectIndex, std::vector<ff_effect> *effect) override {
@@ -334,12 +359,14 @@ class HwApi : public Vibrator::HwApi, private HwApiBase {
break;
}
}
+ HWAPI_RECORD(StringPrintf("#%d", effectIndex), &mInputIoStream);
} else {
/* Flush all non-prestored effects of ff-core and driver. */
getEffectCount(&effectCountBefore);
for (i = WAVEFORM_MAX_PHYSICAL_INDEX; i < FF_MAX_EFFECTS; i++) {
if (ioctl(mInputFd, EVIOCRMFF, i) >= 0) {
successFlush++;
+ HWAPI_RECORD(StringPrintf("#%d", i), &mInputIoStream);
}
}
getEffectCount(&effectCountAfter);
@@ -352,10 +379,57 @@ class HwApi : public Vibrator::HwApi, private HwApiBase {
}
return true;
}
+ bool isDbcSupported() override {
+ ATRACE_NAME(__func__);
+ return utils::getProperty("ro.vendor.vibrator.hal.dbc.enable", false);
+ }
+
+ bool enableDbc() override {
+ ATRACE_NAME(__func__);
+ if (isDbcSupported()) {
+ open("dbc/dbc_env_rel_coef", &mDbcEnvRelCoef);
+ open("dbc/dbc_rise_headroom", &mDbcRiseHeadroom);
+ open("dbc/dbc_fall_headroom", &mDbcFallHeadroom);
+ open("dbc/dbc_tx_lvl_thresh_fs", &mDbcTxLvlThreshFs);
+ open("dbc/dbc_tx_lvl_hold_off_ms", &mDbcTxLvlHoldOffMs);
+ open("default/pm_active_timeout_ms", &mPmActiveTimeoutMs);
+ open("dbc/dbc_enable", &mDbcEnable);
+
+ // Set values from config. Default if not found.
+ set(utils::getProperty("ro.vendor.vibrator.hal.dbc.envrelcoef", kDbcDefaultEnvRelCoef),
+ &mDbcEnvRelCoef);
+ set(utils::getProperty("ro.vendor.vibrator.hal.dbc.riseheadroom",
+ kDbcDefaultRiseHeadroom),
+ &mDbcRiseHeadroom);
+ set(utils::getProperty("ro.vendor.vibrator.hal.dbc.fallheadroom",
+ kDbcDefaultFallHeadroom),
+ &mDbcFallHeadroom);
+ set(utils::getProperty("ro.vendor.vibrator.hal.dbc.txlvlthreshfs",
+ kDbcDefaultTxLvlThreshFs),
+ &mDbcTxLvlThreshFs);
+ set(utils::getProperty("ro.vendor.vibrator.hal.dbc.txlvlholdoffms",
+ kDbcDefaultTxLvlHoldOffMs),
+ &mDbcTxLvlHoldOffMs);
+ set(utils::getProperty("ro.vendor.vibrator.hal.pm.activetimeout",
+ kDefaultPmActiveTimeoutMs),
+ &mPmActiveTimeoutMs);
+ set(kDbcEnable, &mDbcEnable);
+ return true;
+ }
+ return false;
+ }
void debug(int fd) override { HwApiBase::debug(fd); }
private:
+ static constexpr uint32_t kDbcDefaultEnvRelCoef = 8353728;
+ static constexpr uint32_t kDbcDefaultRiseHeadroom = 1909602;
+ static constexpr uint32_t kDbcDefaultFallHeadroom = 1909602;
+ static constexpr uint32_t kDbcDefaultTxLvlThreshFs = 2516583;
+ static constexpr uint32_t kDbcDefaultTxLvlHoldOffMs = 0;
+ static constexpr uint32_t kDefaultPmActiveTimeoutMs = 5;
+ static constexpr uint32_t kDbcEnable = 1;
+
std::ofstream mF0;
std::ofstream mF0Offset;
std::ofstream mRedc;
@@ -366,7 +440,18 @@ class HwApi : public Vibrator::HwApi, private HwApiBase {
std::ofstream mF0CompEnable;
std::ofstream mRedcCompEnable;
std::ofstream mMinOnOffInterval;
+ std::ofstream mInputIoStream;
+ std::ofstream mPcmStream;
::android::base::unique_fd mInputFd;
+
+ // DBC Parameters
+ std::ofstream mDbcEnvRelCoef;
+ std::ofstream mDbcRiseHeadroom;
+ std::ofstream mDbcFallHeadroom;
+ std::ofstream mDbcTxLvlThreshFs;
+ std::ofstream mDbcTxLvlHoldOffMs;
+ std::ofstream mDbcEnable;
+ std::ofstream mPmActiveTimeoutMs;
};
class HwCal : public Vibrator::HwCal, private HwCalBase {
@@ -445,7 +530,7 @@ class HwCal : public Vibrator::HwCal, private HwCalBase {
}
bool isRedcCompEnabled() override {
bool value;
- getProperty("redc.comp.enabled", &value, true);
+ getProperty("redc.comp.enabled", &value, false);
return value;
}
void debug(int fd) override { HwCalBase::debug(fd); }
diff --git a/vibrator/cs40l26/Vibrator.cpp b/vibrator/cs40l26/Vibrator.cpp
index ccc2fa68..8c303ffd 100644
--- a/vibrator/cs40l26/Vibrator.cpp
+++ b/vibrator/cs40l26/Vibrator.cpp
@@ -22,6 +22,7 @@
#include <log/log.h>
#include <utils/Trace.h>
+#include <chrono>
#include <cinttypes>
#include <cmath>
#include <fstream>
@@ -63,7 +64,7 @@ static constexpr int8_t MAX_PAUSE_TIMING_ERROR_MS = 1; // ALERT Irq Handling
static constexpr uint32_t MAX_TIME_MS = UINT16_MAX;
static constexpr auto ASYNC_COMPLETION_TIMEOUT = std::chrono::milliseconds(100);
-static constexpr auto POLLING_TIMEOUT = 20;
+static constexpr auto POLLING_TIMEOUT = 50; // POLLING_TIMEOUT < ASYNC_COMPLETION_TIMEOUT
static constexpr int32_t COMPOSE_DELAY_MAX_MS = 10000;
/* nsections is 8 bits. Need to preserve 1 section for the first delay before the first effect. */
@@ -518,14 +519,11 @@ Vibrator::Vibrator(std::unique_ptr<HwApi> hwapi, std::unique_ptr<HwCal> hwcal,
createPwleMaxLevelLimitMap();
createBandwidthAmplitudeMap();
+ // We need to do this until it's supported through WISCE
+ mHwApi->enableDbc();
+
#ifdef ADAPTIVE_HAPTICS_V1
- mContextListener = CapoDetector::start();
- if (mContextListener == nullptr) {
- ALOGE("%s, CapoDetector failed to start", __func__);
- } else {
- ALOGD("%s, CapoDetector started successfully! NanoAppID: 0x%x", __func__,
- (uint32_t)mContextListener->getNanoppAppId());
- }
+ updateContext();
#endif /*ADAPTIVE_HAPTICS_V1*/
}
@@ -558,6 +556,20 @@ ndk::ScopedAStatus Vibrator::off() {
bool ret{true};
const std::scoped_lock<std::mutex> lock(mActiveId_mutex);
+ const auto startTime = std::chrono::system_clock::now();
+ const auto endTime = startTime + std::chrono::milliseconds(POLLING_TIMEOUT);
+ auto now = startTime;
+ while (halState == ISSUED && now <= endTime) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
+ now = std::chrono::system_clock::now();
+ }
+ if (halState == ISSUED && now > endTime) {
+ ALOGE("Timeout waiting for the actuator activation! (%d ms)", POLLING_TIMEOUT);
+ } else if (halState == PLAYING) {
+ ALOGD("Took %lld ms to wait for the actuator activation.",
+ std::chrono::duration_cast<std::chrono::milliseconds>(now - startTime).count());
+ }
+
if (mActiveId >= 0) {
/* Stop the active effect. */
if (!mHwApi->setFFPlay(mActiveId, false)) {
@@ -565,6 +577,7 @@ ndk::ScopedAStatus Vibrator::off() {
ALOGE("Failed to stop effect %d (%d): %s", mActiveId, errno, strerror(errno));
ret = false;
}
+ halState = STOPPED;
if ((mActiveId >= WAVEFORM_MAX_PHYSICAL_INDEX) &&
(!mHwApi->eraseOwtEffect(mActiveId, &mFfEffects))) {
@@ -581,6 +594,7 @@ ndk::ScopedAStatus Vibrator::off() {
if (mF0Offset) {
mHwApi->setF0Offset(0);
}
+ halState = RESTORED;
if (ret) {
return ndk::ScopedAStatus::ok();
@@ -877,6 +891,7 @@ ndk::ScopedAStatus Vibrator::on(uint32_t timeoutMs, uint32_t effectIndex, const
ALOGE("Failed to play effect %d (%d): %s", effectIndex, errno, strerror(errno));
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
+ halState = ISSUED;
mAsyncHandle = std::async(&Vibrator::waitForComplete, this, callback);
return ndk::ScopedAStatus::ok();
@@ -894,7 +909,7 @@ uint16_t Vibrator::amplitudeToScale(float amplitude, float maximum, bool scalabl
ratio = 100;
#ifdef ADAPTIVE_HAPTICS_V1
- if (scalable && mContextEnable) {
+ if (scalable && mContextEnable && mContextListener) {
uint32_t now = CapoDetector::getCurrentTimeInMs();
uint32_t last_played = mLastEffectPlayedTime;
uint32_t lastFaceUpTime = 0;
@@ -947,10 +962,24 @@ uint16_t Vibrator::amplitudeToScale(float amplitude, float maximum, bool scalabl
void Vibrator::updateContext() {
mContextEnable = mHwApi->getContextEnable();
- mFadeEnable = mHwApi->getContextFadeEnable();
- mScalingFactor = mHwApi->getContextScale();
- mScaleTime = mHwApi->getContextSettlingTime();
- mScaleCooldown = mHwApi->getContextCooldownTime();
+ if (mContextEnable && !mContextEnabledPreviously) {
+ mContextListener = CapoDetector::start();
+ if (mContextListener == nullptr) {
+ ALOGE("%s, CapoDetector failed to start", __func__);
+ } else {
+ mFadeEnable = mHwApi->getContextFadeEnable();
+ mScalingFactor = mHwApi->getContextScale();
+ mScaleTime = mHwApi->getContextSettlingTime();
+ mScaleCooldown = mHwApi->getContextCooldownTime();
+ ALOGD("%s, CapoDetector started successfully! NanoAppID: 0x%x, Scaling Factor: %d, "
+ "Scaling Time: %d, Cooldown Time: %d",
+ __func__, (uint32_t)mContextListener->getNanoppAppId(), mScalingFactor,
+ mScaleTime, mScaleCooldown);
+
+ /* We no longer need to use this path */
+ mContextEnabledPreviously = true;
+ }
+ }
}
ndk::ScopedAStatus Vibrator::setEffectAmplitude(float amplitude, float maximum, bool scalable) {
@@ -959,9 +988,7 @@ ndk::ScopedAStatus Vibrator::setEffectAmplitude(float amplitude, float maximum,
uint16_t scale;
#ifdef ADAPTIVE_HAPTICS_V1
- if (scalable) {
- updateContext();
- }
+ updateContext();
#endif /*ADAPTIVE_HAPTICS_V1*/
scale = amplitudeToScale(amplitude, maximum, scalable);
@@ -1443,7 +1470,12 @@ binder_status_t Vibrator::dump(int fd, const char **args, uint32_t numArgs) {
dprintf(fd, "AIDL:\n");
+ dprintf(fd, " Global Gain: %0.2f\n", mLongEffectScale);
+ dprintf(fd, " Active Effect ID: %" PRId32 "\n", mActiveId);
+ dprintf(fd, " F0: %.02f\n", mResonantFrequency);
dprintf(fd, " F0 Offset: %" PRIu32 "\n", mF0Offset);
+ dprintf(fd, " Redc: %.02f\n", mRedc);
+ dprintf(fd, " HAL State: %" PRIu32 "\n", halState);
dprintf(fd, " Voltage Levels:\n");
dprintf(fd, " Tick Effect Min: %" PRIu32 " Max: %" PRIu32 "\n", mTickEffectVol[0],
@@ -1453,15 +1485,15 @@ binder_status_t Vibrator::dump(int fd, const char **args, uint32_t numArgs) {
dprintf(fd, " Long Effect Min: %" PRIu32 " Max: %" PRIu32 "\n", mLongEffectVol[0],
mLongEffectVol[1]);
- dprintf(fd, " FF effect:\n");
- dprintf(fd, " Physical waveform:\n");
+ dprintf(fd, " FF Effect:\n");
+ dprintf(fd, " Physical Waveform:\n");
dprintf(fd, "\tId\tIndex\tt ->\tt'\n");
for (uint8_t effectId = 0; effectId < WAVEFORM_MAX_PHYSICAL_INDEX; effectId++) {
dprintf(fd, "\t%d\t%d\t%d\t%d\n", mFfEffects[effectId].id,
mFfEffects[effectId].u.periodic.custom_data[1], mEffectDurations[effectId],
mFfEffects[effectId].replay.length);
}
- dprintf(fd, " OWT waveform:\n");
+ dprintf(fd, " OWT Waveform:\n");
dprintf(fd, "\tId\tBytes\tData\n");
for (uint8_t effectId = WAVEFORM_MAX_PHYSICAL_INDEX; effectId < WAVEFORM_MAX_INDEX;
effectId++) {
@@ -1479,6 +1511,65 @@ binder_status_t Vibrator::dump(int fd, const char **args, uint32_t numArgs) {
}
dprintf(fd, "\n");
+
+ dprintf(fd, "Versions:\n");
+ std::ifstream verFile;
+ const auto verBinFileMode = std::ifstream::in | std::ifstream::binary;
+ std::string ver;
+ verFile.open("/sys/module/cs40l26_core/version");
+ if (verFile.is_open()) {
+ getline(verFile, ver);
+ dprintf(fd, " Haptics Driver: %s\n", ver.c_str());
+ verFile.close();
+ }
+ verFile.open("/sys/module/cl_dsp_core/version");
+ if (verFile.is_open()) {
+ getline(verFile, ver);
+ dprintf(fd, " DSP Driver: %s\n", ver.c_str());
+ verFile.close();
+ }
+ verFile.open("/vendor/firmware/cs40l26.wmfw", verBinFileMode);
+ if (verFile.is_open()) {
+ verFile.seekg(113);
+ dprintf(fd, " cs40l26.wmfw: %d.%d.%d\n", verFile.get(), verFile.get(), verFile.get());
+ verFile.close();
+ }
+ verFile.open("/vendor/firmware/cs40l26-calib.wmfw", verBinFileMode);
+ if (verFile.is_open()) {
+ verFile.seekg(113);
+ dprintf(fd, " cs40l26-calib.wmfw: %d.%d.%d\n", verFile.get(), verFile.get(),
+ verFile.get());
+ verFile.close();
+ }
+ verFile.open("/vendor/firmware/cs40l26.bin", verBinFileMode);
+ if (verFile.is_open()) {
+ while (getline(verFile, ver)) {
+ auto pos = ver.find("Date: ");
+ if (pos != std::string::npos) {
+ ver = ver.substr(pos + 6, pos + 15);
+ dprintf(fd, " cs40l26.bin: %s\n", ver.c_str());
+ break;
+ }
+ }
+ verFile.close();
+ }
+ verFile.open("/vendor/firmware/cs40l26-svc.bin", verBinFileMode);
+ if (verFile.is_open()) {
+ verFile.seekg(36);
+ getline(verFile, ver);
+ ver = ver.substr(ver.rfind('\\') + 1);
+ dprintf(fd, " cs40l26-svc.bin: %s\n", ver.c_str());
+ verFile.close();
+ }
+ verFile.open("/vendor/firmware/cs40l26-calib.bin", verBinFileMode);
+ if (verFile.is_open()) {
+ verFile.seekg(36);
+ getline(verFile, ver);
+ ver = ver.substr(ver.rfind('\\') + 1);
+ dprintf(fd, " cs40l26-calib.bin: %s\n", ver.c_str());
+ verFile.close();
+ }
+
dprintf(fd, "\n");
mHwApi->debug(fd);
@@ -1487,14 +1578,23 @@ binder_status_t Vibrator::dump(int fd, const char **args, uint32_t numArgs) {
mHwCal->debug(fd);
- dprintf(fd, "Capo Info\n");
+ dprintf(fd, "\n");
+
+ dprintf(fd, "Capo Info:\n");
+ dprintf(fd, "Capo Enabled: %d\n", mContextEnable);
if (mContextListener) {
dprintf(fd, "Capo ID: 0x%x\n", (uint32_t)(mContextListener->getNanoppAppId()));
dprintf(fd, "Capo State: %d\n", mContextListener->getCarriedPosition());
}
+ dprintf(fd, "\n");
+
mStatsApi->debug(fd);
+ if (mHwApi->isDbcSupported()) {
+ dprintf(fd, "\nDBC Enabled\n");
+ }
+
fsync(fd);
return STATUS_OK;
}
@@ -1729,9 +1829,11 @@ void Vibrator::waitForComplete(std::shared_ptr<IVibratorCallback> &&callback) {
if (!mHwApi->pollVibeState(VIBE_STATE_HAPTIC, POLLING_TIMEOUT)) {
ALOGW("Failed to get state \"Haptic\"");
}
+ halState = PLAYING;
ATRACE_BEGIN("Vibrating");
mHwApi->pollVibeState(VIBE_STATE_STOPPED);
ATRACE_END();
+ halState = STOPPED;
const std::scoped_lock<std::mutex> lock(mActiveId_mutex);
uint32_t effectCount = WAVEFORM_MAX_PHYSICAL_INDEX;
@@ -1751,6 +1853,7 @@ void Vibrator::waitForComplete(std::shared_ptr<IVibratorCallback> &&callback) {
}
mActiveId = -1;
+ halState = RESTORED;
if (callback) {
auto ret = callback->onComplete();
diff --git a/vibrator/cs40l26/Vibrator.h b/vibrator/cs40l26/Vibrator.h
index 0c540682..c4a992ff 100644
--- a/vibrator/cs40l26/Vibrator.h
+++ b/vibrator/cs40l26/Vibrator.h
@@ -106,6 +106,11 @@ class Vibrator : public BnVibrator {
int *status) = 0;
// Erase OWT waveform
virtual bool eraseOwtEffect(int8_t effectIndex, std::vector<ff_effect> *effect) = 0;
+ // Checks to see if DBC (Dynamic Boost Control) feature is supported
+ // by the target device.
+ virtual bool isDbcSupported() = 0;
+ // Configures and enables the DBC feature and all associated parameters
+ virtual bool enableDbc() = 0;
// Emit diagnostic information to the given file.
virtual void debug(int fd) = 0;
};
@@ -266,9 +271,19 @@ class Vibrator : public BnVibrator {
uint32_t mScalingFactor;
uint32_t mScaleCooldown;
bool mContextEnable;
+ bool mContextEnabledPreviously{false};
uint32_t mLastEffectPlayedTime = 0;
float mLastPlayedScale = 0;
sp<CapoDetector> mContextListener;
+ enum hal_state {
+ IDLE,
+ PREPARING,
+ ISSUED,
+ PLAYING,
+ STOPPED,
+ RESTORED,
+ };
+ hal_state halState = IDLE;
};
} // namespace vibrator
diff --git a/vibrator/cs40l26/android.hardware.vibrator-service.cs40l26-dual.rc b/vibrator/cs40l26/android.hardware.vibrator-service.cs40l26-dual.rc
index a2d4706b..6ea9d3b9 100644
--- a/vibrator/cs40l26/android.hardware.vibrator-service.cs40l26-dual.rc
+++ b/vibrator/cs40l26/android.hardware.vibrator-service.cs40l26-dual.rc
@@ -18,6 +18,13 @@ service vendor.vibrator.cs40l26-dual /vendor/bin/hw/android.hardware.vibrator-se
default/f0_comp_enable
default/redc_comp_enable
default/delay_before_stop_playback_us
+ dbc/dbc_env_rel_coef
+ dbc/dbc_rise_headroom
+ dbc/dbc_fall_headroom
+ dbc/dbc_tx_lvl_thresh_fs
+ dbc/dbc_tx_lvl_hold_off_ms
+ default/pm_active_timeout_ms
+ dbc/dbc_enable
"
setenv STATS_INSTANCE default
diff --git a/vibrator/cs40l26/android.hardware.vibrator-service.cs40l26.rc b/vibrator/cs40l26/android.hardware.vibrator-service.cs40l26.rc
index 8c9e2c2d..9a46abce 100644
--- a/vibrator/cs40l26/android.hardware.vibrator-service.cs40l26.rc
+++ b/vibrator/cs40l26/android.hardware.vibrator-service.cs40l26.rc
@@ -18,6 +18,13 @@ service vendor.vibrator.cs40l26 /vendor/bin/hw/android.hardware.vibrator-service
default/f0_comp_enable
default/redc_comp_enable
default/delay_before_stop_playback_us
+ dbc/dbc_env_rel_coef
+ dbc/dbc_rise_headroom
+ dbc/dbc_fall_headroom
+ dbc/dbc_tx_lvl_thresh_fs
+ dbc/dbc_tx_lvl_hold_off_ms
+ default/pm_active_timeout_ms
+ dbc/dbc_enable
"
setenv STATS_INSTANCE default
diff --git a/vibrator/cs40l26/apex/Android.bp b/vibrator/cs40l26/apex/Android.bp
deleted file mode 100644
index dea90ed6..00000000
--- a/vibrator/cs40l26/apex/Android.bp
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2022 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.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-apex_key {
- name: "com.google.pixel.vibrator.hal.key",
- public_key: "com.google.pixel.vibrator.hal.avbpubkey",
- private_key: "com.google.pixel.vibrator.hal.pem",
-}
-
-android_app_certificate {
- name: "com.google.pixel.vibrator.hal.certificate",
- certificate: "com.google.pixel.vibrator.hal",
-}
-
-genrule {
- name: "gen-android.hardware.vibrator-service.cs40l26.rc",
- srcs: [":android.hardware.vibrator-service.cs40l26.rc"],
- out: ["android.hardware.vibrator-service.cs40l26.rc"],
- cmd: "sed -E 's/\\/vendor\\/bin/\\/apex\\/com.google.pixel.vibrator.hal\\/bin/' $(in) > $(out)",
-}
-
-prebuilt_etc {
- name: "apex-android.hardware.vibrator-service.cs40l26.rc",
- src: ":gen-android.hardware.vibrator-service.cs40l26.rc",
- installable: false,
-}
-
-apex {
- name: "com.google.pixel.vibrator.hal",
- manifest: "apex_manifest.json",
- file_contexts: "file_contexts", // Default, please edit, see go/android-apex-howto
- key: "com.google.pixel.vibrator.hal.key",
- certificate: ":com.google.pixel.vibrator.hal.certificate",
- vintf_fragments: [
- ":android.hardware.vibrator-service.cs40l26.xml",
- ],
- use_vndk_as_stable: true,
- // Install the apex in /vendor/apex
- soc_specific: true,
- updatable: false,
- binaries: [
- "android.hardware.vibrator-service.cs40l26",
- ],
- prebuilts: [
- "apex-android.hardware.vibrator-service.cs40l26.rc",
- ],
- overrides: ["android.hardware.vibrator-service.cs40l26"],
-}
diff --git a/vibrator/cs40l26/apex/apex_manifest.json b/vibrator/cs40l26/apex/apex_manifest.json
deleted file mode 100644
index cbdc876c..00000000
--- a/vibrator/cs40l26/apex/apex_manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.google.pixel.vibrator.hal",
- "version": 1
-}
diff --git a/vibrator/cs40l26/apex/com.google.pixel.vibrator.hal.avbpubkey b/vibrator/cs40l26/apex/com.google.pixel.vibrator.hal.avbpubkey
deleted file mode 100644
index 46b6769f..00000000
--- a/vibrator/cs40l26/apex/com.google.pixel.vibrator.hal.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/vibrator/cs40l26/apex/com.google.pixel.vibrator.hal.pem b/vibrator/cs40l26/apex/com.google.pixel.vibrator.hal.pem
deleted file mode 100644
index 595322ac..00000000
--- a/vibrator/cs40l26/apex/com.google.pixel.vibrator.hal.pem
+++ /dev/null
@@ -1,52 +0,0 @@
------BEGIN PRIVATE KEY-----
-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
-vgJDLYQ0TdEWpv6trpA3s3hgFOx16g==
------END PRIVATE KEY-----
diff --git a/vibrator/cs40l26/apex/com.google.pixel.vibrator.hal.pk8 b/vibrator/cs40l26/apex/com.google.pixel.vibrator.hal.pk8
deleted file mode 100644
index 8a5c5de2..00000000
--- a/vibrator/cs40l26/apex/com.google.pixel.vibrator.hal.pk8
+++ /dev/null
Binary files differ
diff --git a/vibrator/cs40l26/apex/com.google.pixel.vibrator.hal.x509.pem b/vibrator/cs40l26/apex/com.google.pixel.vibrator.hal.x509.pem
deleted file mode 100644
index f1c4b481..00000000
--- a/vibrator/cs40l26/apex/com.google.pixel.vibrator.hal.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF3zCCA8cCFG61gvRZ1Gc1PG7iECvnY7zKSCaEMA0GCSqGSIb3DQEBCwUAMIGq
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEmMCQGA1UEAwwdY29t
-Lmdvb2dsZS5waXhlbC52aWJyYXRvci5oYWwwIBcNMjIwODA1MTc1NTU4WhgPNDc2
-MDA3MDExNzU1NThaMIGqMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5p
-YTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4G
-A1UECwwHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNv
-bTEmMCQGA1UEAwwdY29tLmdvb2dsZS5waXhlbC52aWJyYXRvci5oYWwwggIiMA0G
-CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCVoc9F0h6gf3M/Sm5K9rt8W1ZmB/Lu
-fMlkMAZXqMWRbCYVPDg0hQkICLNEOEM76oFvMBCSS2HsZwdXgAguwy3IBhpuMC+t
-mNkA9+6gAXXE3nBwQ/PjphS9vPPIQ+cvbEBiwaAFpAWCx9nb5VLBrkNBIFDuzE+t
-He6sj8kD8vVWKqSEwHHwFdzvXLkSQvYKhrWFltcuUmkpxnHtfVJAH/iO7Vb/jR+s
-H1YVqJcS35OjnjYzjDfQTr7aqV09K/3X9Srai5o0BiWRpcpytmK5MEIqEPJvewRz
-e76Uw7kMO68f5OS6NV1iXqCI4l/k5v+Q0jlxecqJdWANWSegR5cli3eUS/zEDmZb
-2OlrNACsr4hpGu5M2EuVwxg89SbKlUU2ughE6+c/56c45WRalyailaWltN5SF9zK
-RaW1iGS3GDBXeVFqavydJLs9NDdEd0x9wAEdvN8rhrChkhjq18L9ls4d6JIC629V
-n/GT63AHfulpklt5ueGOT1vQZdg6Z8LipcwAzIpTUZJEyVGbGp/o3jf80yYdfftU
-AT51+i89xiJwKDBnCS0FDT54NFpp9yCKTZtLIGa+GweW4kVya2AG6iFdf0/GXPGz
-khOPxhIyC8IfvK+Ozryn2X1ied44gHy6dKA8QXa5nRRxVPnOjJTzQp+vRty+dvzz
-imdJENRezYdKXQIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQA/0IUBeq+xyG7Q8Alb
-4x6cNgLhyxqyn1JQ856YsrGZrdRXLz3pVv21hKOW5g4ol7kXMnGcpnympgk8bgux
-4YFUNxGtM+2SR2ev3bmh+I0UTEom85k6FIYI22cje7cPJUq2E1V/IUWOSPGZ5A8O
-HaW0CKOO9aspyYFXZyWqf9pdzygaqSB1BH2yxr8Hqwdhi7YDRE81RYZHC7KMsq7E
-f2KkI/Lw+Q4vKGCcXNXiJrkUNkRWiuS8mbUtrNf4ub2i07zkB+pJ6Z5NhqnPV8v8
-nNVqdPmRnDcW1eRedV2Zx8/kUF8xqDjAYAv6i+D4Qmz2wjh63/EkUXqoyn/yrDBL
-DGzQWfZvLsXKYPFcEIvGTIkZnKSaLbI5ReO+hZ4i4BgCs/dYvVX27mfTGkwsj11j
-w4SmQuMxqMA26HQDhL7TPkBmfzvD53YC57wbioLhAUgQM5pwi3utx8oj+zcoqNxl
-x6PiaWCWR0pVjGyI4UTMn2wyf8NlqEa7fJI74S035ZK6eqfP2wfZlzV5zpIOnmR1
-GK7oIjbG2NNVINiOSEhPD9CMYxX6UXh+C3vD37QMdRbcLahvjlFVkPCVi1lPf/Js
-Rjj9ZCh2BT/ks2KMIHzR7oFQZzMOiz8MP9HrsS1QLyKMxco2jyI2jL8y/j3VOsZz
-3ZkM2dl0vADvHBwHZH3/v/InMA==
------END CERTIFICATE-----
diff --git a/vibrator/cs40l26/apex/file_contexts b/vibrator/cs40l26/apex/file_contexts
deleted file mode 100644
index 5795d2b5..00000000
--- a/vibrator/cs40l26/apex/file_contexts
+++ /dev/null
@@ -1,3 +0,0 @@
-(/.*)? u:object_r:vendor_file:s0
-/bin/hw/android\.hardware\.vibrator-service\.cs40l26 u:object_r:hal_vibrator_default_exec:s0
-
diff --git a/vibrator/cs40l26/device.mk b/vibrator/cs40l26/device.mk
index 24d68d2c..b83f3bb7 100644
--- a/vibrator/cs40l26/device.mk
+++ b/vibrator/cs40l26/device.mk
@@ -1,8 +1,4 @@
-ifeq ($(LOCAL_PREFER_VENDOR_APEX),true)
-PRODUCT_PACKAGES += com.google.pixel.vibrator.hal
-else
PRODUCT_PACKAGES += android.hardware.vibrator-service.cs40l26
-endif
BOARD_SEPOLICY_DIRS += \
hardware/google/pixel-sepolicy/vibrator/common \
diff --git a/vibrator/cs40l26/tests/mocks.h b/vibrator/cs40l26/tests/mocks.h
index dda31f24..53c9a045 100644
--- a/vibrator/cs40l26/tests/mocks.h
+++ b/vibrator/cs40l26/tests/mocks.h
@@ -49,6 +49,8 @@ class MockApi : public ::aidl::android::hardware::vibrator::Vibrator::HwApi {
bool(const uint8_t *owtData, const uint32_t numBytes, struct ff_effect *effect,
uint32_t *outEffectIndex, int *status));
MOCK_METHOD2(eraseOwtEffect, bool(int8_t effectIndex, std::vector<ff_effect> *effect));
+ MOCK_METHOD0(isDbcSupported, bool());
+ MOCK_METHOD0(enableDbc, bool());
MOCK_METHOD1(debug, void(int fd));
~MockApi() override { destructor(); };
diff --git a/vibrator/cs40l26/tests/test-vibrator.cpp b/vibrator/cs40l26/tests/test-vibrator.cpp
index ce9808bd..254a6bdb 100644
--- a/vibrator/cs40l26/tests/test-vibrator.cpp
+++ b/vibrator/cs40l26/tests/test-vibrator.cpp
@@ -88,7 +88,7 @@ static const std::map<Effect, EffectIndex> EFFECT_INDEX{
static constexpr uint32_t MIN_ON_OFF_INTERVAL_US = 8500;
static constexpr uint8_t VOLTAGE_SCALE_MAX = 100;
static constexpr int8_t MAX_COLD_START_LATENCY_MS = 6; // I2C Transaction + DSP Return-From-Standby
-static constexpr auto POLLING_TIMEOUT = 20;
+static constexpr auto POLLING_TIMEOUT = 50; // POLLING_TIMEOUT < ASYNC_COMPLETION_TIMEOUT
enum WaveformIndex : uint16_t {
/* Physical waveform */
WAVEFORM_LONG_VIBRATION_EFFECT_INDEX = 0,
@@ -303,6 +303,7 @@ class VibratorTest : public Test {
EXPECT_CALL(*mMockApi, setMinOnOffInterval(_)).Times(times);
EXPECT_CALL(*mMockApi, getHapticAlsaDevice(_, _)).Times(times);
EXPECT_CALL(*mMockApi, setHapticPcmAmp(_, _, _, _)).Times(times);
+ EXPECT_CALL(*mMockApi, enableDbc()).Times(times);
EXPECT_CALL(*mMockApi, debug(_)).Times(times);
@@ -396,6 +397,7 @@ TEST_F(VibratorTest, Constructor) {
EXPECT_CALL(*mMockApi, getContextSettlingTime()).WillRepeatedly(Return(0));
EXPECT_CALL(*mMockApi, getContextCooldownTime()).WillRepeatedly(Return(0));
EXPECT_CALL(*mMockApi, getContextFadeEnable()).WillRepeatedly(Return(false));
+ EXPECT_CALL(*mMockApi, enableDbc()).WillOnce(Return(true));
createVibrator(std::move(mockapi), std::move(mockcal), std::move(mockstats), false);
}
diff --git a/vibrator/drv2624/apex/Android.bp b/vibrator/drv2624/apex/Android.bp
deleted file mode 100644
index 016a7935..00000000
--- a/vibrator/drv2624/apex/Android.bp
+++ /dev/null
@@ -1,59 +0,0 @@
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-apex {
- name: "com.android.vibrator.drv2624",
- manifest: "apex_manifest.json",
- key: "com.android.vibrator.drv2624.key",
- certificate: ":com.android.vibrator.drv2624.certificate",
- file_contexts: "file_contexts",
- use_vndk_as_stable: true,
- updatable: false,
-
- // install the apex in /vendor/apex
- proprietary: true,
-
- // BEGIN of apex payloads
- // /bin
- binaries: [
- "android.hardware.vibrator-service.drv2624",
- ],
- // /etc
- prebuilts: [
- "com.android.vibrator.drv2624.rc",
- ],
- // END of apex payloads
-
- // BEGIN of companion files to be installed if this module is installed
- // init script, which is installed in /vendor/etc.
- // Note that init scripts in an apex can contain only "service" sections.
- // The following init script contains "on" section to enable the service.
- init_rc: [
- "com.android.vibrator.drv2624.enable.rc",
- ],
-
- // vintf manifest fragments, which is installed in /vendor/etc/vintf.
- // TODO(b/130058564): should we put vintf framgments within the apex?
- vintf_fragments: [
- "com.android.vibrator.drv2624.xml",
- ],
- // END of companion filse
-}
-
-apex_key {
- name: "com.android.vibrator.drv2624.key",
- public_key: "com.android.vibrator.drv2624.pubkey",
- private_key: "com.android.vibrator.drv2624.pem",
-}
-
-android_app_certificate {
- name: "com.android.vibrator.drv2624.certificate",
- certificate: "com.android.vibrator.drv2624",
-}
-
-prebuilt_etc {
- name: "com.android.vibrator.drv2624.rc",
- src: "com.android.vibrator.drv2624.rc",
- installable: false,
-}
diff --git a/vibrator/drv2624/apex/apex_manifest.json b/vibrator/drv2624/apex/apex_manifest.json
deleted file mode 100644
index ac8af3a4..00000000
--- a/vibrator/drv2624/apex/apex_manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.vibrator.drv2624",
- "version": 1
-}
diff --git a/vibrator/drv2624/apex/com.android.vibrator.drv2624.enable.rc b/vibrator/drv2624/apex/com.android.vibrator.drv2624.enable.rc
deleted file mode 100644
index d9b79f08..00000000
--- a/vibrator/drv2624/apex/com.android.vibrator.drv2624.enable.rc
+++ /dev/null
@@ -1,29 +0,0 @@
-on boot
- wait /sys/class/leds/vibrator/device
-
- mkdir /mnt/vendor/persist/haptics 0770 system system
- chmod 770 /mnt/vendor/persist/haptics
- chmod 440 /mnt/vendor/persist/haptics/drv2624.cal
- chown system system /mnt/vendor/persist/haptics
- chown system system /mnt/vendor/persist/haptics/drv2624.cal
-
- write /sys/class/leds/vibrator/trigger transient
- chown system system /sys/class/leds/vibrator/activate
- chown system system /sys/class/leds/vibrator/brightness
- chown system system /sys/class/leds/vibrator/duration
- chown system system /sys/class/leds/vibrator/state
-
- chown system system /sys/class/leds/vibrator/device/autocal
- chown system system /sys/class/leds/vibrator/device/autocal_result
- chown system system /sys/class/leds/vibrator/device/ctrl_loop
- chown system system /sys/class/leds/vibrator/device/lp_trigger_effect
- chown system system /sys/class/leds/vibrator/device/lp_trigger_scale
- chown system system /sys/class/leds/vibrator/device/lra_wave_shape
- chown system system /sys/class/leds/vibrator/device/mode
- chown system system /sys/class/leds/vibrator/device/od_clamp
- chown system system /sys/class/leds/vibrator/device/ol_lra_period
- chown system system /sys/class/leds/vibrator/device/rtp_input
- chown system system /sys/class/leds/vibrator/device/scale
- chown system system /sys/class/leds/vibrator/device/set_sequencer
-
- enable vendor.vibrator.drv2624
diff --git a/vibrator/drv2624/apex/com.android.vibrator.drv2624.pem b/vibrator/drv2624/apex/com.android.vibrator.drv2624.pem
deleted file mode 100644
index 012ed8fc..00000000
--- a/vibrator/drv2624/apex/com.android.vibrator.drv2624.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-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
------END RSA PRIVATE KEY-----
diff --git a/vibrator/drv2624/apex/com.android.vibrator.drv2624.pk8 b/vibrator/drv2624/apex/com.android.vibrator.drv2624.pk8
deleted file mode 100644
index 1e941879..00000000
--- a/vibrator/drv2624/apex/com.android.vibrator.drv2624.pk8
+++ /dev/null
Binary files differ
diff --git a/vibrator/drv2624/apex/com.android.vibrator.drv2624.pubkey b/vibrator/drv2624/apex/com.android.vibrator.drv2624.pubkey
deleted file mode 100644
index 479a8686..00000000
--- a/vibrator/drv2624/apex/com.android.vibrator.drv2624.pubkey
+++ /dev/null
Binary files differ
diff --git a/vibrator/drv2624/apex/com.android.vibrator.drv2624.rc b/vibrator/drv2624/apex/com.android.vibrator.drv2624.rc
deleted file mode 100644
index df4e3e95..00000000
--- a/vibrator/drv2624/apex/com.android.vibrator.drv2624.rc
+++ /dev/null
@@ -1,18 +0,0 @@
-service vendor.vibrator.drv2624 /apex/com.android.vibrator.drv2624/bin/hw/android.hardware.vibrator-service.drv2624
- class hal
- user system
- group system
-
- setenv PROPERTY_PREFIX ro.vendor.vibrator.hal.
- setenv CALIBRATION_FILEPATH /persist/haptics/drv2624.cal
-
- setenv HWAPI_PATH_PREFIX /sys/class/leds/vibrator/
- setenv HWAPI_DEBUG_PATHS "
- device/autocal
- device/lp_trigger_effect
- device/lp_trigger_scale
- device/ol_lra_period
- state
- "
-
- disabled
diff --git a/vibrator/drv2624/apex/com.android.vibrator.drv2624.x509.pem b/vibrator/drv2624/apex/com.android.vibrator.drv2624.x509.pem
deleted file mode 100644
index e1d9cac2..00000000
--- a/vibrator/drv2624/apex/com.android.vibrator.drv2624.x509.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-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
-8rWXShiHxat5sB1c3ON8X4ZukajREniUSOXhzic=
------END CERTIFICATE-----
diff --git a/vibrator/drv2624/apex/com.android.vibrator.drv2624.xml b/vibrator/drv2624/apex/com.android.vibrator.drv2624.xml
deleted file mode 100644
index 4db8f8c5..00000000
--- a/vibrator/drv2624/apex/com.android.vibrator.drv2624.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<manifest version="1.0" type="device">
- <hal format="aidl">
- <name>android.hardware.vibrator</name>
- <version>2</version>
- <fqname>IVibrator/default</fqname>
- </hal>
-</manifest>
diff --git a/vibrator/drv2624/apex/file_contexts b/vibrator/drv2624/apex/file_contexts
deleted file mode 100644
index 5be98ec7..00000000
--- a/vibrator/drv2624/apex/file_contexts
+++ /dev/null
@@ -1,2 +0,0 @@
-(/.*)? u:object_r:vendor_file:s0
-/bin/hw/android\.hardware\.vibrator-service\.drv2624 u:object_r:hal_vibrator_default_exec:s0 \ No newline at end of file
diff --git a/vibrator/drv2624/apex/key.pem b/vibrator/drv2624/apex/key.pem
deleted file mode 100644
index b582099c..00000000
--- a/vibrator/drv2624/apex/key.pem
+++ /dev/null
@@ -1,52 +0,0 @@
------BEGIN PRIVATE KEY-----
-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
-zCK8JO9WGOwvH9n0F+pgYXEo4OtjMA==
------END PRIVATE KEY-----