Add CPU and GPU headroom HAL APIs

Bug: 346604998
Flag: EXEMPT HAL changes
Test: atest VtsHalPowerTargetTest
Change-Id: Ib6d6fd944238d37b33ace044c9a2d89c47861771
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CpuHeadroomParams.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CpuHeadroomParams.aidl
new file mode 100644
index 0000000..09a2ace
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/CpuHeadroomParams.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable CpuHeadroomParams {
+  android.hardware.power.CpuHeadroomParams.CalculationType calculationType;
+  android.hardware.power.CpuHeadroomParams.SelectionType selectionType;
+  int pid;
+  enum CalculationType {
+    MIN,
+    AVERAGE,
+  }
+  enum SelectionType {
+    ALL,
+    PER_CORE,
+  }
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/GpuHeadroomParams.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/GpuHeadroomParams.aidl
new file mode 100644
index 0000000..64bb4a4
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/GpuHeadroomParams.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable GpuHeadroomParams {
+  android.hardware.power.GpuHeadroomParams.CalculationType calculationType;
+  enum CalculationType {
+    MIN,
+    AVERAGE,
+  }
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl
index 8d8fb88..10456cb 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPower.aidl
@@ -44,4 +44,8 @@
   android.hardware.power.ChannelConfig getSessionChannel(in int tgid, in int uid);
   oneway void closeSessionChannel(in int tgid, in int uid);
   android.hardware.power.SupportInfo getSupportInfo();
+  float[] getCpuHeadroom(in android.hardware.power.CpuHeadroomParams params);
+  float getGpuHeadroom(in android.hardware.power.GpuHeadroomParams params);
+  long getCpuHeadroomMinIntervalMillis();
+  long getGpuHeadroomMinIntervalMillis();
 }
diff --git a/power/aidl/android/hardware/power/CpuHeadroomParams.aidl b/power/aidl/android/hardware/power/CpuHeadroomParams.aidl
new file mode 100644
index 0000000..cf71b67
--- /dev/null
+++ b/power/aidl/android/hardware/power/CpuHeadroomParams.aidl
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2024 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 android.hardware.power;
+
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable CpuHeadroomParams {
+    /**
+     * Defines how to calculate the headroom.
+     */
+    enum CalculationType {
+        // Default to return the minimum headroom in a window.
+        MIN,
+        // Returns the average headroom in a window.
+        AVERAGE,
+    }
+
+    /**
+     * The calculation type.
+     */
+    CalculationType calculationType;
+
+    /**
+     * Defines how to select the CPU.
+     */
+    enum SelectionType {
+        // Default to return a single value for all cores.
+        ALL,
+        // Returns per-core headroom in a list.
+        PER_CORE,
+    }
+
+    /**
+     * The CPU selection type.
+     */
+    SelectionType selectionType;
+
+    /**
+     * The caller thread's PID.
+     *
+     * If pid is positive, return the headroom only for cores that are available
+     * to the given pid, otherwise return the headroom(s) for all cores.
+     *
+     * This should handle all the cases including but not limited to thread core
+     * affinity and app cpuset that change the available CPU cores for the caller.
+     */
+    int pid;
+}
diff --git a/power/aidl/android/hardware/power/GpuHeadroomParams.aidl b/power/aidl/android/hardware/power/GpuHeadroomParams.aidl
new file mode 100644
index 0000000..972adbc
--- /dev/null
+++ b/power/aidl/android/hardware/power/GpuHeadroomParams.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 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 android.hardware.power;
+
+@VintfStability
+@JavaDerive(equals=true, toString=true)
+parcelable GpuHeadroomParams {
+    /**
+     * Defines how to calculate the headroom.
+     */
+    enum CalculationType {
+        // Default to return the minimum headroom in a window.
+        MIN,
+        // Returns the average headroom in a window.
+        AVERAGE,
+    }
+
+    /**
+     * The calculation type.
+     */
+    CalculationType calculationType;
+}
diff --git a/power/aidl/android/hardware/power/IPower.aidl b/power/aidl/android/hardware/power/IPower.aidl
index 2f15648..e2f121c 100644
--- a/power/aidl/android/hardware/power/IPower.aidl
+++ b/power/aidl/android/hardware/power/IPower.aidl
@@ -18,6 +18,8 @@
 
 import android.hardware.power.Boost;
 import android.hardware.power.ChannelConfig;
+import android.hardware.power.CpuHeadroomParams;
+import android.hardware.power.GpuHeadroomParams;
 import android.hardware.power.IPowerHintSession;
 import android.hardware.power.Mode;
 import android.hardware.power.SessionConfig;
@@ -155,4 +157,47 @@
      *          not supported.
      */
     SupportInfo getSupportInfo();
+
+    /**
+     * Provides an estimate of available CPU headroom the device based on past history.
+     * <p>
+     * @param params params to customize the CPU headroom calculation
+     * @return a single value or an array of values depending on selection type of params.
+     *         Each value is ranged from [0, 100], and 0 indicates no CPU resources were left
+     *         during the calculation interval and the app may expect low resources to be granted.
+     * @throws EX_UNSUPPORTED_OPERATION if the API is unsupported or the request params can't be
+     *         served.
+     */
+    float[] getCpuHeadroom(in CpuHeadroomParams params);
+
+    /**
+     * Provides an estimate of available GPU headroom the device based on past history.
+     * <p>
+     * @param params params to customize the GPU headroom calculation
+     * @return Value is ranged from [0, 100], and 0 indicates no GPU resources were left
+     *         during the calculation interval and the app may expect low resources to be granted.
+     * @throws EX_UNSUPPORTED_OPERATION if the API is unsupported or the request params can't be
+     *         served.
+     */
+    float getGpuHeadroom(in GpuHeadroomParams params);
+
+    /**
+     * Minimum polling interval for calling getCpuHeadroom in milliseconds.
+     *
+     * The getCpuHeadroom API may return cached result if called more frequent
+     * than the interval.
+     *
+     * @throws EX_UNSUPPORTED_OPERATION if the API is unsupported.
+     */
+    long getCpuHeadroomMinIntervalMillis();
+
+    /**
+     * Minimum polling interval for calling getGpuHeadroom in milliseconds.
+     *
+     * The getGpuHeadroom API may return cached result if called more frequent
+     * than the interval.
+     *
+     * @throws EX_UNSUPPORTED_OPERATION if the API is unsupported.
+     */
+    long getGpuHeadroomMinIntervalMillis();
 }
diff --git a/power/aidl/default/Power.cpp b/power/aidl/default/Power.cpp
index 36d0055..1fc0a0a 100644
--- a/power/aidl/default/Power.cpp
+++ b/power/aidl/default/Power.cpp
@@ -69,6 +69,27 @@
     return ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus Power::getCpuHeadroom(const CpuHeadroomParams& _,
+                                         std::vector<float>* _aidl_return) {
+    *_aidl_return = {0.5f};
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Power::getGpuHeadroom(const GpuHeadroomParams& _, float* _aidl_return) {
+    *_aidl_return = 0.5f;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Power::getCpuHeadroomMinIntervalMillis(int64_t* _aidl_return) {
+    *_aidl_return = 1000;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Power::getGpuHeadroomMinIntervalMillis(int64_t* _aidl_return) {
+    *_aidl_return = 1000;
+    return ndk::ScopedAStatus::ok();
+}
+
 ScopedAStatus Power::createHintSession(int32_t, int32_t, const std::vector<int32_t>& tids, int64_t,
                                        std::shared_ptr<IPowerHintSession>* _aidl_return) {
     if (tids.size() == 0) {
diff --git a/power/aidl/default/Power.h b/power/aidl/default/Power.h
index ef524e1..a77a514 100644
--- a/power/aidl/default/Power.h
+++ b/power/aidl/default/Power.h
@@ -45,6 +45,12 @@
                                          ChannelConfig* _aidl_return) override;
     ndk::ScopedAStatus closeSessionChannel(int32_t tgid, int32_t uid) override;
     ndk::ScopedAStatus getSupportInfo(SupportInfo* _aidl_return) override;
+    ndk::ScopedAStatus getCpuHeadroom(const CpuHeadroomParams& params,
+                                      std::vector<float>* _aidl_return) override;
+    ndk::ScopedAStatus getGpuHeadroom(const GpuHeadroomParams& params,
+                                      float* _aidl_return) override;
+    ndk::ScopedAStatus getCpuHeadroomMinIntervalMillis(int64_t* _aidl_return) override;
+    ndk::ScopedAStatus getGpuHeadroomMinIntervalMillis(int64_t* _aidl_return) override;
 
   private:
     std::vector<std::shared_ptr<IPowerHintSession>> mPowerHintSessions;
diff --git a/power/aidl/vts/VtsHalPowerTargetTest.cpp b/power/aidl/vts/VtsHalPowerTargetTest.cpp
index 9684c38..5e3ddd5 100644
--- a/power/aidl/vts/VtsHalPowerTargetTest.cpp
+++ b/power/aidl/vts/VtsHalPowerTargetTest.cpp
@@ -30,6 +30,8 @@
 #include <unistd.h>
 #include <cstdint>
 #include "aidl/android/hardware/common/fmq/SynchronizedReadWrite.h"
+#include "aidl/android/hardware/power/CpuHeadroomParams.h"
+#include "aidl/android/hardware/power/GpuHeadroomParams.h"
 
 namespace aidl::android::hardware::power {
 namespace {
@@ -40,6 +42,8 @@
 using android::hardware::power::Boost;
 using android::hardware::power::ChannelConfig;
 using android::hardware::power::ChannelMessage;
+using android::hardware::power::CpuHeadroomParams;
+using android::hardware::power::GpuHeadroomParams;
 using android::hardware::power::IPower;
 using android::hardware::power::IPowerHintSession;
 using android::hardware::power::Mode;
@@ -291,6 +295,43 @@
     ASSERT_NE(nullptr, session);
 }
 
+TEST_P(PowerAidl, getCpuHeadroom) {
+    if (mServiceVersion < 6) {
+        GTEST_SKIP() << "DEVICE not launching with Power V6 and beyond.";
+    }
+    CpuHeadroomParams params;
+    std::vector<float> headroom;
+    auto ret = power->getCpuHeadroom(params, &headroom);
+    if (ret.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+        GTEST_SKIP() << "power->getCpuHeadroom is not supported";
+    }
+    ASSERT_TRUE(ret.isOk());
+    int64_t minIntervalMillis;
+    ASSERT_TRUE(power->getCpuHeadroomMinIntervalMillis(&minIntervalMillis).isOk());
+    ASSERT_GE(minIntervalMillis, 0);
+    ASSERT_GE(headroom.size(), 1);
+    ASSERT_GE(headroom[0], 0.0f);
+    ASSERT_LE(headroom[0], 100.00f);
+}
+
+TEST_P(PowerAidl, getGpuHeadroom) {
+    if (mServiceVersion < 6) {
+        GTEST_SKIP() << "DEVICE not launching with Power V6 and beyond.";
+    }
+    GpuHeadroomParams params;
+    float headroom;
+    auto ret = power->getGpuHeadroom(params, &headroom);
+    if (ret.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+        GTEST_SKIP() << "power->getGpuHeadroom is not supported";
+    }
+    ASSERT_TRUE(ret.isOk());
+    int64_t minIntervalMillis;
+    ASSERT_TRUE(power->getGpuHeadroomMinIntervalMillis(&minIntervalMillis).isOk());
+    ASSERT_GE(minIntervalMillis, 0);
+    ASSERT_GE(headroom, 0.0f);
+    ASSERT_LE(headroom, 100.00f);
+}
+
 // FIXED_PERFORMANCE mode is required for all devices which ship on Android 11
 // or later
 TEST_P(PowerAidl, hasFixedPerformance) {