diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 05:11:42 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 05:11:42 +0000 |
commit | becceed833bea7e9ebc2b6b681d11de748727a3f (patch) | |
tree | a6f442eba168310a88707d45fb20952ad3f9ec73 /battery_mitigation | |
parent | f68db2b9637283a61107060b660c8ff865c60337 (diff) | |
parent | c7f3e0ba3acb455437abc7c931aae1afafcb57f2 (diff) | |
download | pixel-4b28dd14e303b2def8170c07502efa6b7a527083.tar.gz |
Snap for 10453563 from c7f3e0ba3acb455437abc7c931aae1afafcb57f2 to mainline-permission-releaseaml_per_341711000aml_per_341614000aml_per_341510010aml_per_341410020aml_per_341311000aml_per_341110020aml_per_341110010aml_per_341011100aml_per_341011020aml_per_340916010android14-mainline-permission-release
Change-Id: Idc023fbdc5b38a577e99f595ff2046edfbdb15ff
Diffstat (limited to 'battery_mitigation')
-rw-r--r-- | battery_mitigation/Android.bp | 46 | ||||
-rw-r--r-- | battery_mitigation/BatteryMitigation.cpp | 67 | ||||
-rw-r--r-- | battery_mitigation/MitigationThermalManager.cpp | 189 | ||||
-rw-r--r-- | battery_mitigation/OWNERS | 2 | ||||
-rw-r--r-- | battery_mitigation/include/battery_mitigation/BatteryMitigation.h | 44 | ||||
-rw-r--r-- | battery_mitigation/include/battery_mitigation/MitigationConfig.h | 50 | ||||
-rw-r--r-- | battery_mitigation/include/battery_mitigation/MitigationThermalManager.h | 121 |
7 files changed, 519 insertions, 0 deletions
diff --git a/battery_mitigation/Android.bp b/battery_mitigation/Android.bp new file mode 100644 index 00000000..1a5d6c6e --- /dev/null +++ b/battery_mitigation/Android.bp @@ -0,0 +1,46 @@ +// +// 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"], +} + +cc_library { + name: "libpixelmitigation", + export_include_dirs: ["include"], + vendor_available: true, + srcs: [ + "BatteryMitigation.cpp", + "MitigationThermalManager.cpp", + ], + static_libs: [ + "libmath", + ], + + shared_libs: [ + "libbase", + "libbinder_ndk", + "libcutils", + "libhardware", + "liblog", + "libutils", + "android.hardware.thermal-V1-ndk" + ], + cflags: [ + "-Wall", + "-Werror", + ], +} diff --git a/battery_mitigation/BatteryMitigation.cpp b/battery_mitigation/BatteryMitigation.cpp new file mode 100644 index 00000000..98419fc5 --- /dev/null +++ b/battery_mitigation/BatteryMitigation.cpp @@ -0,0 +1,67 @@ +/* + * 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. + */ + +#include <battery_mitigation/BatteryMitigation.h> + +#include <sstream> + +#define MAX_BROWNOUT_DATA_AGE_SECONDS 300 + +namespace android { +namespace hardware { +namespace google { +namespace pixel { + +BatteryMitigation::BatteryMitigation(const struct MitigationConfig::Config &cfg) { + mThermalMgr = &MitigationThermalManager::getInstance(); + mThermalMgr->updateConfig(cfg); +} + +bool BatteryMitigation::isMitigationLogTimeValid(std::chrono::system_clock::time_point startTime, + const char *const logFilePath, + const char *const timestampFormat, + const std::regex pattern) { + std::string logFile; + if (!android::base::ReadFileToString(logFilePath, &logFile)) { + return false; + } + std::istringstream content(logFile); + std::string line; + int counter = 0; + std::smatch pattern_match; + while (std::getline(content, line)) { + if (std::regex_match(line, pattern_match, pattern)) { + std::tm triggeredTimestamp = {}; + 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)) { + return true; + } + } + counter += 1; + if (counter > 5) { + break; + } + } + return false; +} + +} // namespace pixel +} // namespace google +} // namespace hardware +} // namespace android diff --git a/battery_mitigation/MitigationThermalManager.cpp b/battery_mitigation/MitigationThermalManager.cpp new file mode 100644 index 00000000..42e6e3cb --- /dev/null +++ b/battery_mitigation/MitigationThermalManager.cpp @@ -0,0 +1,189 @@ +/* + * 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. + */ +#define LOG_TAG "mitigation-logger" + +#include <android-base/chrono_utils.h> +#include <android-base/file.h> +#include <android-base/logging.h> +#include <android/binder_manager.h> +#include <android/binder_process.h> +#include <battery_mitigation/MitigationThermalManager.h> +#include <errno.h> +#include <utils/Log.h> + +#include <chrono> +#include <ctime> +#include <iomanip> +#include <iostream> +#include <string> +#include <thread> + +#define NUM_OF_SAMPLES 20 +#define CAPTURE_INTERVAL_S 2 /* 2 seconds between new capture */ + +namespace android { +namespace hardware { +namespace google { +namespace pixel { + +MitigationThermalManager &MitigationThermalManager::getInstance() { + static MitigationThermalManager mitigationThermalManager; + return mitigationThermalManager; +} + +void MitigationThermalManager::remove() { + const std::lock_guard<std::mutex> lock(thermal_hal_mutex_); + if (!thermal) { + return; + } + if (callback) { + auto ret = thermal->unregisterThermalChangedCallback(callback); + if (!ret.isOk()) { + LOG(ERROR) << "Failed to release thermal callback! " << ret.getMessage(); + } + } +} + +MitigationThermalManager::MitigationThermalManager() { + if (!ABinderProcess_isThreadPoolStarted()) { + // if no thread pool then the thermal callback will not work, so abort + LOG(ERROR) << "The user of MitigationThermalManager did not start a thread pool!"; + return; + } + if (!connectThermalHal()) { + remove(); + } +} + +MitigationThermalManager::~MitigationThermalManager() { + remove(); +} + +void MitigationThermalManager::updateConfig(const struct MitigationConfig::Config &cfg) { + kLogFilePath = std::string(cfg.LogFilePath); + kSystemPath = cfg.SystemPath; + kSystemName = cfg.SystemName; + kFilteredZones = cfg.FilteredZones; + kTimestampFormat = cfg.TimestampFormat; +} + +bool MitigationThermalManager::connectThermalHal() { + const std::string thermal_instance_name = + std::string(::aidl::android::hardware::thermal::IThermal::descriptor) + "/default"; + std::shared_ptr<aidl::android::hardware::thermal::IThermal> thermal_aidl_service; + const std::lock_guard<std::mutex> lock(thermal_hal_mutex_); + if (AServiceManager_isDeclared(thermal_instance_name.c_str())) { + thermal = ::aidl::android::hardware::thermal::IThermal::fromBinder( + ndk::SpAIBinder(AServiceManager_waitForService(thermal_instance_name.c_str()))); + lastCapturedTime = ::android::base::boot_clock::now(); + return registerCallback(); + } else { + LOG(ERROR) << "Thermal AIDL service is not declared"; + } + return false; +} + +bool MitigationThermalManager::isMitigationTemperature(const Temperature &temperature) { + if (std::find(kFilteredZones.begin(), kFilteredZones.end(), temperature.name) != + kFilteredZones.end()) { + return true; + } + return false; +} + +void MitigationThermalManager::thermalCb(const Temperature &temperature) { + if ((temperature.throttlingStatus == ThrottlingSeverity::NONE) || + (!isMitigationTemperature(temperature))) { + return; + } + auto currentTime = ::android::base::boot_clock::now(); + auto delta = + std::chrono::duration_cast<std::chrono::seconds>(currentTime - lastCapturedTime); + if (delta.count() < CAPTURE_INTERVAL_S) { + /* Do not log if delta is within 2 seconds */ + return; + } + int flag = O_WRONLY | O_CREAT | O_NOFOLLOW | O_CLOEXEC | O_APPEND | O_TRUNC; + android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(kLogFilePath.c_str(), flag, 0644))); + lastCapturedTime = currentTime; + std::stringstream oss; + oss << temperature.name << " triggered at " << temperature.value << std::endl << std::flush; + android::base::WriteStringToFd(oss.str(), fd); + fsync(fd); + + for (int i = 0; i < NUM_OF_SAMPLES; i++) { + auto now = std::chrono::system_clock::now(); + auto time_sec = std::chrono::system_clock::to_time_t(now); + auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) - + std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()); + struct tm now_tm; + localtime_r(&time_sec, &now_tm); + oss << std::put_time(&now_tm, kTimestampFormat.c_str()) << "." << std::setw(3) + << std::setfill('0') << ms.count() << std::endl + << std::flush; + android::base::WriteStringToFd(oss.str(), fd); + fsync(fd); + oss.str(""); + /* log System info */ + for (int j = 0; j < kSystemName.size(); j++) { + std::string value; + bool result = android::base::ReadFileToString(kSystemPath[j], &value); + if (!result) { + LOG(ERROR) << "Could not read: " << kSystemName[j]; + } + android::base::WriteStringToFd(kSystemName[j] + ":" + value, fd); + } + } + fsync(fd); +} + +bool MitigationThermalManager::registerCallback() { + if (!thermal) { + LOG(ERROR) << "Unable to connect Thermal AIDL service"; + return false; + } + // Create thermal callback recipient object. + if (callback == nullptr) { + callback = + ndk::SharedRefBase::make<ThermalCallback>([this](const Temperature &temperature) { + std::lock_guard api_lock(thermal_callback_mutex_); + thermalCb(temperature); + }); + } + // Register thermal callback to thermal hal to cover all. Cannot register twice. + auto ret_callback = thermal->registerThermalChangedCallback(callback); + if (!ret_callback.isOk()) { + LOG(ERROR) << "Failed to register thermal callback! " << ret_callback.getMessage(); + return false; + } + + // Create AIDL thermal death recipient object. + if (aidlDeathRecipient.get() == nullptr) { + aidlDeathRecipient = ndk::ScopedAIBinder_DeathRecipient( + AIBinder_DeathRecipient_new(onThermalAidlBinderDied)); + } + auto linked = AIBinder_linkToDeath(thermal->asBinder().get(), aidlDeathRecipient.get(), this); + if (linked != STATUS_OK) { + // should we continue if the death recipient is not registered? + LOG(ERROR) << "Failed to register AIDL thermal death notification"; + } + return true; +} + +} // namespace pixel +} // namespace google +} // namespace hardware +} // namespace android diff --git a/battery_mitigation/OWNERS b/battery_mitigation/OWNERS new file mode 100644 index 00000000..363efac2 --- /dev/null +++ b/battery_mitigation/OWNERS @@ -0,0 +1,2 @@ +geolee@google.com +wvw@google.com diff --git a/battery_mitigation/include/battery_mitigation/BatteryMitigation.h b/battery_mitigation/include/battery_mitigation/BatteryMitigation.h new file mode 100644 index 00000000..d3ce433d --- /dev/null +++ b/battery_mitigation/include/battery_mitigation/BatteryMitigation.h @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#pragma once + +#include <utils/RefBase.h> + +#include "MitigationThermalManager.h" + +namespace android { +namespace hardware { +namespace google { +namespace pixel { + +using ::android::sp; + +class BatteryMitigation : public RefBase { + public: + BatteryMitigation(const struct MitigationConfig::Config &cfg); + bool isMitigationLogTimeValid(std::chrono::system_clock::time_point startTime, + const char *const logFilePath, const char *const timestampFormat, + const std::regex pattern); + + private: + MitigationThermalManager *mThermalMgr; +}; + +} // namespace pixel +} // namespace google +} // namespace hardware +} // namespace android diff --git a/battery_mitigation/include/battery_mitigation/MitigationConfig.h b/battery_mitigation/include/battery_mitigation/MitigationConfig.h new file mode 100644 index 00000000..825e30c6 --- /dev/null +++ b/battery_mitigation/include/battery_mitigation/MitigationConfig.h @@ -0,0 +1,50 @@ +/* + * 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. + */ + +#ifndef HARDWARE_GOOGLE_PIXEL_BATTERY_MITIGATION_CONFIG_H +#define HARDWARE_GOOGLE_PIXEL_BATTERY_MITIGATION_CONFIG_H + +namespace android { +namespace hardware { +namespace google { +namespace pixel { + +class MitigationConfig { + public: + struct Config { + const std::vector<std::string> SystemPath; + const std::vector<std::string> FilteredZones; + const std::vector<std::string> SystemName; + const char *const LogFilePath; + const char *const TimestampFormat; + }; + + MitigationConfig(const struct Config &cfg); + + private: + const std::vector<std::string> kSystemPath; + const std::vector<std::string> kFilteredZones; + const std::vector<std::string> kSystemName; + const char *const kLogFilePath; + const char *const kTimestampFormat; +}; + +} // namespace pixel +} // namespace google +} // namespace hardware +} // namespace android + +#endif // HARDWARE_GOOGLE_PIXEL_BATTERY_MITIGATION_CONFIG_H diff --git a/battery_mitigation/include/battery_mitigation/MitigationThermalManager.h b/battery_mitigation/include/battery_mitigation/MitigationThermalManager.h new file mode 100644 index 00000000..5b5a3f0a --- /dev/null +++ b/battery_mitigation/include/battery_mitigation/MitigationThermalManager.h @@ -0,0 +1,121 @@ +/* + * 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. + */ + +#pragma once + +#ifndef MITIGATION_THERMAL_MANAGER_H_ +#define MITIGATION_THERMAL_MANAGER_H_ + +#include <aidl/android/hardware/thermal/BnThermalChangedCallback.h> +#include <aidl/android/hardware/thermal/IThermal.h> +#include <android-base/chrono_utils.h> +#include <android-base/file.h> +#include <android-base/logging.h> +#include <android-base/parseint.h> +#include <android-base/properties.h> +#include <android-base/strings.h> +#include <android/binder_auto_utils.h> +#include <unistd.h> +#include <utils/Mutex.h> + +#include <fstream> +#include <iostream> +#include <regex> + +#include "MitigationConfig.h" + +namespace android { +namespace hardware { +namespace google { +namespace pixel { + +using ::aidl::android::hardware::thermal::BnThermalChangedCallback; +using ::aidl::android::hardware::thermal::IThermal; +using ::aidl::android::hardware::thermal::Temperature; +using ::aidl::android::hardware::thermal::TemperatureType; +using ::aidl::android::hardware::thermal::ThrottlingSeverity; +using android::hardware::google::pixel::MitigationConfig; + +class MitigationThermalManager { + public: + static MitigationThermalManager &getInstance(); + + // delete copy and move constructors and assign operators + MitigationThermalManager(MitigationThermalManager const &) = delete; + MitigationThermalManager(MitigationThermalManager &&) = delete; + MitigationThermalManager &operator=(MitigationThermalManager const &) = delete; + MitigationThermalManager &operator=(MitigationThermalManager &&) = delete; + + private: + // ThermalCallback implements the HIDL thermal changed callback + // interface, IThermalChangedCallback. + void thermalCb(const Temperature &temperature); + android::base::boot_clock::time_point lastCapturedTime; + + class ThermalCallback : public BnThermalChangedCallback { + public: + ThermalCallback(std::function<void(const Temperature &)> notify_function) + : notifyFunction(notify_function) {} + + // Callback function. thermal service will call this. + ndk::ScopedAStatus notifyThrottling(const Temperature &temperature) override { + if ((temperature.type == TemperatureType::BCL_VOLTAGE) || + (temperature.type == TemperatureType::BCL_CURRENT)) { + notifyFunction(temperature); + } + return ndk::ScopedAStatus::ok(); + } + + private: + std::function<void(const Temperature &)> notifyFunction; + }; + + static void onThermalAidlBinderDied(void *) { + LOG(ERROR) << "Thermal AIDL service died, trying to reconnect"; + MitigationThermalManager::getInstance().connectThermalHal(); + } + + public: + MitigationThermalManager(); + ~MitigationThermalManager(); + bool connectThermalHal(); + bool isMitigationTemperature(const Temperature &temperature); + bool registerCallback(); + void remove(); + void updateConfig(const struct MitigationConfig::Config &cfg); + + + private: + std::mutex thermal_callback_mutex_; + std::mutex thermal_hal_mutex_; + // Thermal hal interface. + std::shared_ptr<IThermal> thermal; + // Thermal hal callback object. + std::shared_ptr<ThermalCallback> callback; + // Receiver when AIDL thermal hal restart. + ndk::ScopedAIBinder_DeathRecipient aidlDeathRecipient; + std::vector<std::string> kSystemPath; + std::vector<std::string> kFilteredZones; + std::vector<std::string> kSystemName; + std::string kLogFilePath; + std::string kTimestampFormat; +}; + +} // namespace pixel +} // namespace google +} // namespace hardware +} // namespace android +#endif |