thermal: notify perfmgr current thermal status

Bug: 72471476
Bug: 162791243
Test: build and using emul temp/running burn8 to verify it
Change-Id: If0fd7d5a877f172562eed406a0a39cfa120e6961
(cherry picked from commit 7c8556bf9a436ff0eaf4601ed74e86aa05f7afbf)
diff --git a/thermal/Android.bp b/thermal/Android.bp
index 7875ea4..a305521 100644
--- a/thermal/Android.bp
+++ b/thermal/Android.bp
@@ -23,8 +23,11 @@
     "libhidlbase",
     "libjsoncpp",
     "libutils",
+    "libbinder_ndk",
     "android.hardware.thermal@1.0",
     "android.hardware.thermal@2.0",
+    "android.hardware.power-ndk_platform",
+    "pixel-power-ext-ndk_platform"
   ],
   cflags: [
     "-Wall",
diff --git a/thermal/Thermal.cpp b/thermal/Thermal.cpp
index bd47f6e..ada526f 100644
--- a/thermal/Thermal.cpp
+++ b/thermal/Thermal.cpp
@@ -241,6 +241,8 @@
                   << " Type: " << android::hardware::thermal::V2_0::toString(t.type)
                   << " Name: " << t.name << " CurrentValue: " << t.value << " ThrottlingStatus: "
                   << android::hardware::thermal::V2_0::toString(t.throttlingStatus);
+
+        thermal_helper_.sendPowerExtHint(t);
         callbacks_.erase(
             std::remove_if(callbacks_.begin(), callbacks_.end(),
                            [&](const CallbackSetting &c) {
@@ -377,6 +379,24 @@
                              << std::noboolalpha << std::endl;
                 }
             }
+            {
+                dump_buf << "SendPowerHint:" << std::endl;
+                const auto &map = thermal_helper_.GetSensorInfoMap();
+                for (const auto &name_info_pair : map) {
+                    dump_buf << " Name: " << name_info_pair.first;
+                    dump_buf << " SendPowerHint: " << std::boolalpha
+                             << name_info_pair.second.send_powerhint << std::noboolalpha
+                             << std::endl;
+                }
+            }
+            {
+                dump_buf << "AIDL Power Hal exist: " << std::boolalpha
+                         << thermal_helper_.isAidlPowerHalExist() << std::endl;
+                dump_buf << "AIDL Power Hal connected: " << std::boolalpha
+                         << thermal_helper_.isPowerHalConnected() << std::endl;
+                dump_buf << "AIDL Power Hal Ext connected: " << std::boolalpha
+                         << thermal_helper_.isPowerHalExtConnected() << std::endl;
+            }
         }
         std::string buf = dump_buf.str();
         if (!android::base::WriteStringToFd(buf, fd)) {
diff --git a/thermal/thermal-helper.cpp b/thermal/thermal-helper.cpp
index 725578d..43f0d92 100644
--- a/thermal/thermal-helper.cpp
+++ b/thermal/thermal-helper.cpp
@@ -25,6 +25,7 @@
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
+#include <android/binder_manager.h>
 #include <hidl/HidlTransportSupport.h>
 
 #include "thermal-helper.h"
@@ -54,6 +55,7 @@
 
 namespace {
 using android::base::StringPrintf;
+using android::hardware::thermal::V2_0::toString;
 
 /*
  * Pixel don't offline CPU, so std::thread::hardware_concurrency(); should work.
@@ -167,6 +169,91 @@
 }
 
 }  // namespace
+PowerHalService::PowerHalService()
+    : power_hal_aidl_exist_(true), power_hal_aidl_(nullptr), power_hal_ext_aidl_(nullptr) {
+    connect();
+}
+
+bool PowerHalService::connect() {
+    std::lock_guard<std::mutex> lock(lock_);
+    if (!power_hal_aidl_exist_)
+        return false;
+
+    if (power_hal_aidl_ != nullptr)
+        return true;
+
+    const std::string kInstance = std::string(IPower::descriptor) + "/default";
+    ndk::SpAIBinder power_binder = ndk::SpAIBinder(AServiceManager_getService(kInstance.c_str()));
+    ndk::SpAIBinder ext_power_binder;
+
+    if (power_binder.get() == nullptr) {
+        LOG(ERROR) << "Cannot get Power Hal Binder";
+        power_hal_aidl_exist_ = false;
+        return false;
+    }
+
+    power_hal_aidl_ = IPower::fromBinder(power_binder);
+
+    if (power_hal_aidl_ == nullptr) {
+        power_hal_aidl_exist_ = false;
+        LOG(ERROR) << "Cannot get Power Hal AIDL" << kInstance.c_str();
+        return false;
+    }
+
+    if (STATUS_OK != AIBinder_getExtension(power_binder.get(), ext_power_binder.getR()) ||
+        ext_power_binder.get() == nullptr) {
+        LOG(ERROR) << "Cannot get Power Hal Extension Binder";
+        power_hal_aidl_exist_ = false;
+        return false;
+    }
+
+    power_hal_ext_aidl_ = IPowerExt::fromBinder(ext_power_binder);
+    if (power_hal_ext_aidl_ == nullptr) {
+        LOG(ERROR) << "Cannot get Power Hal Extension AIDL";
+        power_hal_aidl_exist_ = false;
+    }
+
+    return true;
+}
+
+bool PowerHalService::isModeSupported(const std::string &type, const ThrottlingSeverity &t) {
+    bool isSupported = false;
+    if (!isPowerHalConnected()) {
+        return false;
+    }
+    std::string power_hint = StringPrintf("THERMAL_%s_%s", type.c_str(), toString(t).c_str());
+    lock_.lock();
+    if (!power_hal_ext_aidl_->isModeSupported(power_hint, &isSupported).isOk()) {
+        LOG(ERROR) << "Fail to check supported mode, Hint: " << power_hint;
+        power_hal_aidl_exist_ = false;
+        power_hal_ext_aidl_ = nullptr;
+        power_hal_aidl_ = nullptr;
+        lock_.unlock();
+        return false;
+    }
+    lock_.unlock();
+    return isSupported;
+}
+
+void PowerHalService::setMode(const std::string &type, const ThrottlingSeverity &t,
+                              const bool &enable) {
+    if (!isPowerHalConnected()) {
+        return;
+    }
+
+    std::string power_hint = StringPrintf("THERMAL_%s_%s", type.c_str(), toString(t).c_str());
+    LOG(INFO) << "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;
+        power_hal_aidl_exist_ = false;
+        power_hal_ext_aidl_ = nullptr;
+        power_hal_aidl_ = nullptr;
+        lock_.unlock();
+        return;
+    }
+    lock_.unlock();
+}
 
 /*
  * Populate the sensor_name_to_file_map_ map by walking through the file tree,
@@ -188,6 +275,7 @@
             .severity = ThrottlingSeverity::NONE,
             .prev_hot_severity = ThrottlingSeverity::NONE,
             .prev_cold_severity = ThrottlingSeverity::NONE,
+            .prev_hint_severity = ThrottlingSeverity::NONE,
         };
     }
 
@@ -215,6 +303,12 @@
     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 ThermalHelper::readCoolingDevice(std::string_view cooling_device,
@@ -614,6 +708,64 @@
     return thermal_triggered;
 }
 
+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 : hidl_enum_range<ThrottlingSeverity>()) {
+            LOG(ERROR) << "sensor: " << name_status_pair.first
+                       << " current_severity :" << toString(current_severity) << " severity "
+                       << toString(severity);
+            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_2_0 &t) {
+    std::lock_guard<std::shared_mutex> lock(sensor_status_map_mutex_);
+    if (!isAidlPowerHalExist())
+        return;
+
+    if (!sensor_info_map_.at(t.name).send_powerhint)
+        return;
+
+    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);
+    }
+
+    sensor_status_map_[t.name].prev_hint_severity = current_hint_severity;
+}
 }  // namespace implementation
 }  // namespace V2_0
 }  // namespace thermal
diff --git a/thermal/thermal-helper.h b/thermal/thermal-helper.h
index 5eb389e..37a2dea 100644
--- a/thermal/thermal-helper.h
+++ b/thermal/thermal-helper.h
@@ -40,6 +40,8 @@
 #include <unordered_map>
 #include <vector>
 
+#include <aidl/android/hardware/power/IPower.h>
+#include <aidl/google/hardware/power/extension/pixel/IPowerExt.h>
 #include <android/hardware/thermal/2.0/IThermal.h>
 
 #include "utils/config_parser.h"
@@ -52,6 +54,8 @@
 namespace V2_0 {
 namespace implementation {
 
+using ::aidl::android::hardware::power::IPower;
+using ::aidl::google::hardware::power::extension::pixel::IPowerExt;
 using ::android::hardware::hidl_vec;
 using ::android::hardware::thermal::V1_0::CpuUsage;
 using ::android::hardware::thermal::V2_0::CoolingType;
@@ -72,6 +76,25 @@
     ThrottlingSeverity severity;
     ThrottlingSeverity prev_hot_severity;
     ThrottlingSeverity prev_cold_severity;
+    ThrottlingSeverity prev_hint_severity;
+};
+
+class PowerHalService {
+  public:
+    PowerHalService();
+    ~PowerHalService() = default;
+    bool connect();
+    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);
+
+  private:
+    bool power_hal_aidl_exist_;
+    std::shared_ptr<IPower> power_hal_aidl_;
+    std::shared_ptr<IPowerExt> power_hal_ext_aidl_;
+    std::mutex lock_;
 };
 
 class ThermalHelper {
@@ -105,6 +128,12 @@
     // Get SensorInfo Map
     const std::map<std::string, SensorInfo> &GetSensorInfoMap() const { return sensor_info_map_; }
 
+    void sendPowerExtHint(const Temperature_2_0 &t);
+
+    bool isAidlPowerHalExist() { return power_hal_service_.isAidlPowerHalExist(); }
+    bool isPowerHalConnected() { return power_hal_service_.isPowerHalConnected(); }
+    bool isPowerHalExtConnected() { return power_hal_service_.isPowerHalExtConnected(); }
+
   private:
     bool initializeSensorMap(const std::map<std::string, std::string> &path_map);
     bool initializeCoolingDevices(const std::map<std::string, std::string> &path_map);
@@ -119,6 +148,9 @@
         ThrottlingSeverity prev_hot_severity, ThrottlingSeverity prev_cold_severity,
         float value) const;
 
+    bool connectToPowerHal();
+    void updateSupportedPowerHints();
+
     sp<ThermalWatcher> thermal_watcher_;
     ThermalFiles thermal_sensors_;
     ThermalFiles cooling_devices_;
@@ -126,6 +158,9 @@
     const NotificationCallback cb_;
     const std::map<std::string, CoolingType> cooling_device_info_map_;
     const std::map<std::string, SensorInfo> sensor_info_map_;
+    std::map<std::string, std::map<ThrottlingSeverity, ThrottlingSeverity>>
+            supported_powerhint_map_;
+    PowerHalService power_hal_service_;
 
     mutable std::shared_mutex sensor_status_map_mutex_;
     std::map<std::string, SensorStatus> sensor_status_map_;
diff --git a/thermal/utils/config_parser.cpp b/thermal/utils/config_parser.cpp
index d74fd49..daba0ee 100644
--- a/thermal/utils/config_parser.cpp
+++ b/thermal/utils/config_parser.cpp
@@ -217,6 +217,15 @@
         LOG(INFO) << "Sensor[" << name << "]'s Monitor: " << std::boolalpha << is_monitor
                   << std::noboolalpha;
 
+        bool send_powerhint = false;
+        if (sensors[i]["SendPowerHint"].empty() || !sensors[i]["SendPowerHint"].isBool()) {
+            LOG(INFO) << "Failed to read Sensor[" << name << "]'s SendPowerHint, set to 'false'";
+        } else {
+            send_powerhint = sensors[i]["SendPowerHint"].asBool();
+        }
+        LOG(INFO) << "Sensor[" << name << "]'s SendPowerHint: " << std::boolalpha << send_powerhint
+                  << std::noboolalpha;
+
         sensors_parsed[name] = {
                 .type = sensor_type,
                 .hot_thresholds = hot_thresholds,
@@ -226,6 +235,7 @@
                 .vr_threshold = vr_threshold,
                 .multiplier = multiplier,
                 .is_monitor = is_monitor,
+                .send_powerhint = send_powerhint,
         };
         ++total_parsed;
     }
diff --git a/thermal/utils/config_parser.h b/thermal/utils/config_parser.h
index fe43594..399fef6 100644
--- a/thermal/utils/config_parser.h
+++ b/thermal/utils/config_parser.h
@@ -45,6 +45,7 @@
     float vr_threshold;
     float multiplier;
     bool is_monitor;
+    bool send_powerhint;
 };
 
 std::map<std::string, SensorInfo> ParseSensorInfo(std::string_view config_path);