Add plumbing for ADPF Power Efficiency hint

These patches introduce a new power efficiency mode for hint sessions
to the public API, and internally expose a new setMode API for hint
sessions that resembles the setMode API for iPower, to control
different session operating modes.

This set of patches:
 - Updates the PowerHAL AIDL to version 5, and updates relevant bp files
 - Exposes new setPreferPowerEfficiency(bool enabled) method from the
 SDK and NDK
 - Exposes new setMode(int mode, bool enabled) method from PowerHAL AIDL
 and HintManagerService
 - Adds support for new setMode call in PowerHAL

Bug: b/288117936
Test: manual
Change-Id: Id006341b5ab0ae6fadd975d740d2fcf89f0636e4
diff --git a/power/aidl/Android.bp b/power/aidl/Android.bp
index 082572d..7643926 100644
--- a/power/aidl/Android.bp
+++ b/power/aidl/Android.bp
@@ -55,6 +55,44 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 
 }
+
+cc_defaults {
+    name: "android.hardware.power-ndk_shared",
+    shared_libs: [
+        "android.hardware.power-V5-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "android.hardware.power-ndk_export_shared",
+    shared_libs: [
+        "android.hardware.power-V5-ndk",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.power-V5-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "android.hardware.power-ndk_static",
+    static_libs: [
+        "android.hardware.power-V5-ndk",
+    ],
+}
+
+java_defaults {
+    name: "android.hardware.power-java_shared",
+    libs: [
+        "android.hardware.power-V5-java",
+    ],
+}
+
+java_defaults {
+    name: "android.hardware.power-java_static",
+    static_libs: [
+        "android.hardware.power-V5-java",
+    ],
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl
index c792d4e..8ee15ef 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl
@@ -34,10 +34,10 @@
 package android.hardware.power;
 @Backing(type="int") @VintfStability
 enum Boost {
-  INTERACTION = 0,
-  DISPLAY_UPDATE_IMMINENT = 1,
-  ML_ACC = 2,
-  AUDIO_LAUNCH = 3,
-  CAMERA_LAUNCH = 4,
-  CAMERA_SHOT = 5,
+  INTERACTION,
+  DISPLAY_UPDATE_IMMINENT,
+  ML_ACC,
+  AUDIO_LAUNCH,
+  CAMERA_LAUNCH,
+  CAMERA_SHOT,
 }
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl
index e6809da..6bc663e 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl
@@ -41,4 +41,5 @@
   oneway void close();
   oneway void sendHint(android.hardware.power.SessionHint hint);
   void setThreads(in int[] threadIds);
+  oneway void setMode(android.hardware.power.SessionMode type, boolean enabled);
 }
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl
index f38426b..efbb300 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl
@@ -34,21 +34,21 @@
 package android.hardware.power;
 @Backing(type="int") @VintfStability
 enum Mode {
-  DOUBLE_TAP_TO_WAKE = 0,
-  LOW_POWER = 1,
-  SUSTAINED_PERFORMANCE = 2,
-  FIXED_PERFORMANCE = 3,
-  VR = 4,
-  LAUNCH = 5,
-  EXPENSIVE_RENDERING = 6,
-  INTERACTIVE = 7,
-  DEVICE_IDLE = 8,
-  DISPLAY_INACTIVE = 9,
-  AUDIO_STREAMING_LOW_LATENCY = 10,
-  CAMERA_STREAMING_SECURE = 11,
-  CAMERA_STREAMING_LOW = 12,
-  CAMERA_STREAMING_MID = 13,
-  CAMERA_STREAMING_HIGH = 14,
-  GAME = 15,
-  GAME_LOADING = 16,
+  DOUBLE_TAP_TO_WAKE,
+  LOW_POWER,
+  SUSTAINED_PERFORMANCE,
+  FIXED_PERFORMANCE,
+  VR,
+  LAUNCH,
+  EXPENSIVE_RENDERING,
+  INTERACTIVE,
+  DEVICE_IDLE,
+  DISPLAY_INACTIVE,
+  AUDIO_STREAMING_LOW_LATENCY,
+  CAMERA_STREAMING_SECURE,
+  CAMERA_STREAMING_LOW,
+  CAMERA_STREAMING_MID,
+  CAMERA_STREAMING_HIGH,
+  GAME,
+  GAME_LOADING,
 }
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionMode.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionMode.aidl
new file mode 100644
index 0000000..d0ae0ba
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionMode.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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;
+@Backing(type="int") @VintfStability
+enum SessionMode {
+  POWER_EFFICIENCY,
+}
diff --git a/power/aidl/android/hardware/power/IPowerHintSession.aidl b/power/aidl/android/hardware/power/IPowerHintSession.aidl
index 7db0ea1..62263c8 100644
--- a/power/aidl/android/hardware/power/IPowerHintSession.aidl
+++ b/power/aidl/android/hardware/power/IPowerHintSession.aidl
@@ -17,6 +17,7 @@
 package android.hardware.power;
 
 import android.hardware.power.SessionHint;
+import android.hardware.power.SessionMode;
 import android.hardware.power.WorkDuration;
 
 @VintfStability
@@ -81,4 +82,13 @@
      *    must be thrown.
      */
     void setThreads(in int[] threadIds);
+
+    /**
+     * Called to enable or disable special modes for the hint session, which may
+     * adjust the power or performance of the session.
+     *
+     * @param type The mode being set
+     * @param enabled True to enable the mode, false to disable it
+     */
+    oneway void setMode(SessionMode type, boolean enabled);
 }
diff --git a/power/aidl/android/hardware/power/SessionMode.aidl b/power/aidl/android/hardware/power/SessionMode.aidl
new file mode 100644
index 0000000..f1ee64e
--- /dev/null
+++ b/power/aidl/android/hardware/power/SessionMode.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+package android.hardware.power;
+
+@VintfStability
+@Backing(type="int")
+enum SessionMode {
+    /**
+     * This mode indicates that the work of this hint session is not
+     * critical to perceived performance, despite its CPU intensity,
+     * and can be safely scheduled to prefer power efficiency.
+     */
+    POWER_EFFICIENCY,
+}
diff --git a/power/aidl/default/Android.bp b/power/aidl/default/Android.bp
index da91ee6..c0bfbe8 100644
--- a/power/aidl/default/Android.bp
+++ b/power/aidl/default/Android.bp
@@ -23,6 +23,7 @@
 
 cc_binary {
     name: "android.hardware.power-service.example",
+    defaults: ["android.hardware.power-ndk_shared"],
     relative_install_path: "hw",
     init_rc: [":android.hardware.power.rc"],
     vintf_fragments: [":android.hardware.power.xml"],
@@ -30,7 +31,6 @@
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.power-V4-ndk",
     ],
     srcs: [
         "main.cpp",
diff --git a/power/aidl/default/PowerHintSession.cpp b/power/aidl/default/PowerHintSession.cpp
index f395800..452e435 100644
--- a/power/aidl/default/PowerHintSession.cpp
+++ b/power/aidl/default/PowerHintSession.cpp
@@ -59,4 +59,8 @@
     return ScopedAStatus::ok();
 }
 
+ScopedAStatus PowerHintSession::setMode(SessionMode /* mode */, bool /* enabled */) {
+    return ScopedAStatus::ok();
+}
+
 }  // namespace aidl::android::hardware::power::impl::example
diff --git a/power/aidl/default/PowerHintSession.h b/power/aidl/default/PowerHintSession.h
index 1d74716..b488bf1 100644
--- a/power/aidl/default/PowerHintSession.h
+++ b/power/aidl/default/PowerHintSession.h
@@ -18,6 +18,7 @@
 
 #include <aidl/android/hardware/power/BnPowerHintSession.h>
 #include <aidl/android/hardware/power/SessionHint.h>
+#include <aidl/android/hardware/power/SessionMode.h>
 #include <aidl/android/hardware/power/WorkDuration.h>
 
 namespace aidl::android::hardware::power::impl::example {
@@ -33,6 +34,7 @@
     ndk::ScopedAStatus close() override;
     ndk::ScopedAStatus sendHint(SessionHint hint) override;
     ndk::ScopedAStatus setThreads(const std::vector<int32_t>& threadIds) override;
+    ndk::ScopedAStatus setMode(SessionMode mode, bool enabled) override;
 };
 
 }  // namespace aidl::android::hardware::power::impl::example
diff --git a/power/aidl/default/power-default.xml b/power/aidl/default/power-default.xml
index f5dd6b9..418fb83 100644
--- a/power/aidl/default/power-default.xml
+++ b/power/aidl/default/power-default.xml
@@ -1,7 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.power</name>
-        <version>4</version>
+        <version>5</version>
         <fqname>IPower/default</fqname>
     </hal>
 </manifest>
diff --git a/power/aidl/vts/Android.bp b/power/aidl/vts/Android.bp
index 56c98bd..eb98b8b 100644
--- a/power/aidl/vts/Android.bp
+++ b/power/aidl/vts/Android.bp
@@ -26,14 +26,12 @@
     defaults: [
         "VtsHalTargetTestDefaults",
         "use_libaidlvintf_gtest_helper_static",
+        "android.hardware.power-ndk_static",
     ],
     srcs: ["VtsHalPowerTargetTest.cpp"],
     shared_libs: [
         "libbinder_ndk",
     ],
-    static_libs: [
-        "android.hardware.power-V4-ndk",
-    ],
     test_suites: [
         "general-tests",
         "vts",
diff --git a/power/aidl/vts/VtsHalPowerTargetTest.cpp b/power/aidl/vts/VtsHalPowerTargetTest.cpp
index 0976d18..96995a0 100644
--- a/power/aidl/vts/VtsHalPowerTargetTest.cpp
+++ b/power/aidl/vts/VtsHalPowerTargetTest.cpp
@@ -34,6 +34,7 @@
 using android::hardware::power::IPowerHintSession;
 using android::hardware::power::Mode;
 using android::hardware::power::SessionHint;
+using android::hardware::power::SessionMode;
 using android::hardware::power::WorkDuration;
 
 const std::vector<Boost> kBoosts{ndk::enum_range<Boost>().begin(), ndk::enum_range<Boost>().end()};
@@ -43,6 +44,9 @@
 const std::vector<SessionHint> kSessionHints{ndk::enum_range<SessionHint>().begin(),
                                              ndk::enum_range<SessionHint>().end()};
 
+const std::vector<SessionMode> kSessionModes{ndk::enum_range<SessionMode>().begin(),
+                                             ndk::enum_range<SessionMode>().end()};
+
 const std::vector<Boost> kInvalidBoosts = {
         static_cast<Boost>(static_cast<int32_t>(kBoosts.front()) - 1),
         static_cast<Boost>(static_cast<int32_t>(kBoosts.back()) + 1),
@@ -58,6 +62,11 @@
         static_cast<SessionHint>(static_cast<int32_t>(kSessionHints.back()) + 1),
 };
 
+const std::vector<SessionMode> kInvalidSessionModes = {
+        static_cast<SessionMode>(static_cast<int32_t>(kSessionModes.front()) - 1),
+        static_cast<SessionMode>(static_cast<int32_t>(kSessionModes.back()) + 1),
+};
+
 class DurationWrapper : public WorkDuration {
   public:
     DurationWrapper(int64_t dur, int64_t time) {
@@ -228,6 +237,21 @@
     ASSERT_TRUE(mSession->setThreads(kSelfTids).isOk());
 }
 
+TEST_P(HintSessionAidl, setSessionMode) {
+    if (mServiceVersion < 5) {
+        GTEST_SKIP() << "DEVICE not launching with Power V5 and beyond.";
+    }
+
+    for (const auto& sessionMode : kSessionModes) {
+        ASSERT_TRUE(mSession->setMode(sessionMode, true).isOk());
+        ASSERT_TRUE(mSession->setMode(sessionMode, false).isOk());
+    }
+    for (const auto& sessionMode : kInvalidSessionModes) {
+        ASSERT_TRUE(mSession->setMode(sessionMode, true).isOk());
+        ASSERT_TRUE(mSession->setMode(sessionMode, false).isOk());
+    }
+}
+
 // FIXED_PERFORMANCE mode is required for all devices which ship on Android 11
 // or later
 TEST_P(PowerAidl, hasFixedPerformance) {