diff options
| -rw-r--r-- | core/api/current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/os/IHintSession.aidl | 1 | ||||
| -rw-r--r-- | core/java/android/os/PerformanceHintManager.java | 62 | ||||
| -rw-r--r-- | core/jni/android_os_PerformanceHintManager.cpp | 32 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/os/PerformanceHintManagerTest.java | 9 | ||||
| -rw-r--r-- | native/android/Android.bp | 6 | ||||
| -rw-r--r-- | native/android/libandroid.map.txt | 1 | ||||
| -rw-r--r-- | native/android/performance_hint.cpp | 19 | ||||
| -rw-r--r-- | native/android/tests/performance_hint/PerformanceHintNativeTest.cpp | 51 | ||||
| -rw-r--r-- | services/core/Android.bp | 8 | ||||
| -rw-r--r-- | services/core/java/com/android/server/power/hint/HintManagerService.java | 34 | ||||
| -rw-r--r-- | services/core/jni/Android.bp | 6 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_hint_HintManagerService.cpp | 32 | ||||
| -rw-r--r-- | services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java | 43 |
14 files changed, 243 insertions, 62 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index d1b51543d248..363e9d4a29bb 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -33668,6 +33668,7 @@ package android.os { public static class PerformanceHintManager.Session implements java.io.Closeable { method public void close(); method public void reportActualWorkDuration(long); + method public void setPreferPowerEfficiency(boolean); method public void setThreads(@NonNull int[]); method public void updateTargetWorkDuration(long); } diff --git a/core/java/android/os/IHintSession.aidl b/core/java/android/os/IHintSession.aidl index 0d1dde105c09..6b43e73d10e7 100644 --- a/core/java/android/os/IHintSession.aidl +++ b/core/java/android/os/IHintSession.aidl @@ -23,4 +23,5 @@ oneway interface IHintSession { void reportActualWorkDuration(in long[] actualDurationNanos, in long[] timeStampNanos); void close(); void sendHint(int hint); + void setMode(int mode, boolean enabled); } diff --git a/core/java/android/os/PerformanceHintManager.java b/core/java/android/os/PerformanceHintManager.java index bcea7978a804..cbc921391155 100644 --- a/core/java/android/os/PerformanceHintManager.java +++ b/core/java/android/os/PerformanceHintManager.java @@ -51,6 +51,15 @@ public final class PerformanceHintManager { } /** + * Get preferred update rate information for this device. + * + * @return the preferred update rate supported by device software + */ + public long getPreferredUpdateRateNanos() { + return nativeGetPreferredUpdateRateNanos(mNativeManagerPtr); + } + + /** * Creates a {@link Session} for the given set of threads and sets their initial target work * duration. * @@ -78,35 +87,22 @@ public final class PerformanceHintManager { } /** - * Get preferred update rate information for this device. - * - * @return the preferred update rate supported by device software - */ - public long getPreferredUpdateRateNanos() { - return nativeGetPreferredUpdateRateNanos(mNativeManagerPtr); - } - - /** * A Session represents a group of threads with an inter-related workload such that hints for * their performance should be considered as a unit. The threads in a given session should be - * long-life and not created or destroyed dynamically. - * - * <p>Each session is expected to have a periodic workload with a target duration for each - * cycle. The cycle duration is likely greater than the target work duration to allow other - * parts of the pipeline to run within the available budget. For example, a renderer thread may - * work at 60hz in order to produce frames at the display's frame but have a target work - * duration of only 6ms.</p> + * long-lived and not created or destroyed dynamically. * - * <p>Any call in this class will change its internal data, so you must do your own thread - * safety to protect from racing.</p> + * The work duration API can be used with periodic workloads to dynamically adjust thread + * performance and keep the work on schedule while optimizing the available power budget. + * When using the work duration API, the starting target duration should be specified + * while creating the session, but can later be adjusted with + * {@link #updateTargetWorkDuration(long)}. While using the work duration API, the client is be + * expected to call {@link #reportActualWorkDuration(long)} each cycle to report the actual + * time taken to complete to the system. * - * <p>Note that the target work duration can be {@link #updateTargetWorkDuration(long) updated} - * if workloads change.</p> + * Any call in this class will change its internal data, so you must do your own thread + * safety to protect from racing. * - * <p>After each cycle of work, the client is expected to - * {@link #reportActualWorkDuration(long) report} the actual time taken to complete.</p> - * - * <p>All timings should be in {@link SystemClock#elapsedRealtimeNanos()}.</p> + * All timings should be in {@link SystemClock#elapsedRealtimeNanos()}. */ public static class Session implements Closeable { private long mNativeSessionPtr; @@ -186,9 +182,9 @@ public final class PerformanceHintManager { /** * Reports the actual duration for the last cycle of work. * - * <p>The system will attempt to adjust the core placement of the threads within the thread + * The system will attempt to adjust the core placement of the threads within the thread * group and/or the frequency of the core on which they are run to bring the actual duration - * close to the target duration.</p> + * close to the target duration. * * @param actualDurationNanos how long the thread group took to complete its last task in * nanoseconds @@ -202,7 +198,7 @@ public final class PerformanceHintManager { /** * Ends the current hint session. * - * <p>Once called, you should not call anything else on this object.</p> + * Once called, you should not call anything else on this object. */ public void close() { if (mNativeSessionPtr != 0) { @@ -230,6 +226,16 @@ public final class PerformanceHintManager { } /** + * This tells the session that these threads can be + * safely scheduled to prefer power efficiency over performance. + * + * @param enabled The flag that sets whether this session uses power-efficient scheduling. + */ + public void setPreferPowerEfficiency(boolean enabled) { + nativeSetPreferPowerEfficiency(mNativeSessionPtr, enabled); + } + + /** * Set a list of threads to the performance hint session. This operation will replace * the current list of threads with the given list of threads. * Note that this is not an oneway method. @@ -275,4 +281,6 @@ public final class PerformanceHintManager { private static native void nativeCloseSession(long nativeSessionPtr); private static native void nativeSendHint(long nativeSessionPtr, int hint); private static native void nativeSetThreads(long nativeSessionPtr, int[] tids); + private static native void nativeSetPreferPowerEfficiency(long nativeSessionPtr, + boolean enabled); } diff --git a/core/jni/android_os_PerformanceHintManager.cpp b/core/jni/android_os_PerformanceHintManager.cpp index ffe844d39f27..27c4cd4d2cd1 100644 --- a/core/jni/android_os_PerformanceHintManager.cpp +++ b/core/jni/android_os_PerformanceHintManager.cpp @@ -34,26 +34,28 @@ struct APerformanceHintManager; struct APerformanceHintSession; typedef APerformanceHintManager* (*APH_getManager)(); +typedef int64_t (*APH_getPreferredUpdateRateNanos)(APerformanceHintManager* manager); typedef APerformanceHintSession* (*APH_createSession)(APerformanceHintManager*, const int32_t*, size_t, int64_t); -typedef int64_t (*APH_getPreferredUpdateRateNanos)(APerformanceHintManager* manager); typedef void (*APH_updateTargetWorkDuration)(APerformanceHintSession*, int64_t); typedef void (*APH_reportActualWorkDuration)(APerformanceHintSession*, int64_t); typedef void (*APH_closeSession)(APerformanceHintSession* session); typedef void (*APH_sendHint)(APerformanceHintSession*, int32_t); typedef int (*APH_setThreads)(APerformanceHintSession*, const pid_t*, size_t); typedef void (*APH_getThreadIds)(APerformanceHintSession*, int32_t* const, size_t* const); +typedef void (*APH_setPreferPowerEfficiency)(APerformanceHintSession*, bool); bool gAPerformanceHintBindingInitialized = false; APH_getManager gAPH_getManagerFn = nullptr; -APH_createSession gAPH_createSessionFn = nullptr; APH_getPreferredUpdateRateNanos gAPH_getPreferredUpdateRateNanosFn = nullptr; +APH_createSession gAPH_createSessionFn = nullptr; APH_updateTargetWorkDuration gAPH_updateTargetWorkDurationFn = nullptr; APH_reportActualWorkDuration gAPH_reportActualWorkDurationFn = nullptr; APH_closeSession gAPH_closeSessionFn = nullptr; APH_sendHint gAPH_sendHintFn = nullptr; APH_setThreads gAPH_setThreadsFn = nullptr; APH_getThreadIds gAPH_getThreadIdsFn = nullptr; +APH_setPreferPowerEfficiency gAPH_setPreferPowerEfficiencyFn = nullptr; void ensureAPerformanceHintBindingInitialized() { if (gAPerformanceHintBindingInitialized) return; @@ -65,10 +67,6 @@ void ensureAPerformanceHintBindingInitialized() { LOG_ALWAYS_FATAL_IF(gAPH_getManagerFn == nullptr, "Failed to find required symbol APerformanceHint_getManager!"); - gAPH_createSessionFn = (APH_createSession)dlsym(handle_, "APerformanceHint_createSession"); - LOG_ALWAYS_FATAL_IF(gAPH_createSessionFn == nullptr, - "Failed to find required symbol APerformanceHint_createSession!"); - gAPH_getPreferredUpdateRateNanosFn = (APH_getPreferredUpdateRateNanos)dlsym(handle_, "APerformanceHint_getPreferredUpdateRateNanos"); @@ -76,6 +74,10 @@ void ensureAPerformanceHintBindingInitialized() { "Failed to find required symbol " "APerformanceHint_getPreferredUpdateRateNanos!"); + gAPH_createSessionFn = (APH_createSession)dlsym(handle_, "APerformanceHint_createSession"); + LOG_ALWAYS_FATAL_IF(gAPH_createSessionFn == nullptr, + "Failed to find required symbol APerformanceHint_createSession!"); + gAPH_updateTargetWorkDurationFn = (APH_updateTargetWorkDuration)dlsym(handle_, "APerformanceHint_updateTargetWorkDuration"); @@ -96,8 +98,7 @@ void ensureAPerformanceHintBindingInitialized() { gAPH_sendHintFn = (APH_sendHint)dlsym(handle_, "APerformanceHint_sendHint"); LOG_ALWAYS_FATAL_IF(gAPH_sendHintFn == nullptr, - "Failed to find required symbol " - "APerformanceHint_sendHint!"); + "Failed to find required symbol APerformanceHint_sendHint!"); gAPH_setThreadsFn = (APH_setThreads)dlsym(handle_, "APerformanceHint_setThreads"); LOG_ALWAYS_FATAL_IF(gAPH_setThreadsFn == nullptr, @@ -107,6 +108,13 @@ void ensureAPerformanceHintBindingInitialized() { LOG_ALWAYS_FATAL_IF(gAPH_getThreadIdsFn == nullptr, "Failed to find required symbol APerformanceHint_getThreadIds!"); + gAPH_setPreferPowerEfficiencyFn = + (APH_setPreferPowerEfficiency)dlsym(handle_, + "APerformanceHint_setPreferPowerEfficiency"); + LOG_ALWAYS_FATAL_IF(gAPH_setPreferPowerEfficiencyFn == nullptr, + "Failed to find required symbol" + "APerformanceHint_setPreferPowerEfficiency!"); + gAPerformanceHintBindingInitialized = true; } @@ -223,6 +231,13 @@ static jintArray nativeGetThreadIds(JNIEnv* env, jclass clazz, jlong nativeSessi return jintArr; } +static void nativeSetPreferPowerEfficiency(JNIEnv* env, jclass clazz, jlong nativeSessionPtr, + jboolean enabled) { + ensureAPerformanceHintBindingInitialized(); + gAPH_setPreferPowerEfficiencyFn(reinterpret_cast<APerformanceHintSession*>(nativeSessionPtr), + enabled); +} + static const JNINativeMethod gPerformanceHintMethods[] = { {"nativeAcquireManager", "()J", (void*)nativeAcquireManager}, {"nativeGetPreferredUpdateRateNanos", "(J)J", (void*)nativeGetPreferredUpdateRateNanos}, @@ -233,6 +248,7 @@ static const JNINativeMethod gPerformanceHintMethods[] = { {"nativeSendHint", "(JI)V", (void*)nativeSendHint}, {"nativeSetThreads", "(J[I)V", (void*)nativeSetThreads}, {"nativeGetThreadIds", "(J)[I", (void*)nativeGetThreadIds}, + {"nativeSetPreferPowerEfficiency", "(JZ)V", (void*)nativeSetPreferPowerEfficiency}, }; int register_android_os_PerformanceHintManager(JNIEnv* env) { diff --git a/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java b/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java index b0826ab77035..20ba4270e6fc 100644 --- a/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java +++ b/core/tests/coretests/src/android/os/PerformanceHintManagerTest.java @@ -173,4 +173,13 @@ public class PerformanceHintManagerTest { session.setThreads(new int[]{-1}); }); } + + @Test + public void testSetPreferPowerEfficiency() { + Session s = createSession(); + assumeNotNull(s); + s.setPreferPowerEfficiency(false); + s.setPreferPowerEfficiency(true); + s.setPreferPowerEfficiency(true); + } } diff --git a/native/android/Android.bp b/native/android/Android.bp index 254eb4494ed8..7f3792d06795 100644 --- a/native/android/Android.bp +++ b/native/android/Android.bp @@ -46,7 +46,10 @@ cc_defaults { cc_library_shared { name: "libandroid", - defaults: ["libandroid_defaults"], + defaults: [ + "libandroid_defaults", + "android.hardware.power-ndk_shared", + ], srcs: [ "activity_manager.cpp", @@ -95,7 +98,6 @@ cc_library_shared { "libpowermanager", "android.hardware.configstore@1.0", "android.hardware.configstore-utils", - "android.hardware.power-V4-ndk", "libnativedisplay", ], diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt index d74f9b7bb659..b0af09c19b7e 100644 --- a/native/android/libandroid.map.txt +++ b/native/android/libandroid.map.txt @@ -334,6 +334,7 @@ LIBANDROID { APerformanceHint_reportActualWorkDuration; # introduced=Tiramisu APerformanceHint_closeSession; # introduced=Tiramisu APerformanceHint_setThreads; # introduced=UpsideDownCake + APerformanceHint_setPreferPowerEfficiency; # introduced=VanillaIceCream local: *; }; diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp index 6198f40bfcd1..c25df6e08fd0 100644 --- a/native/android/performance_hint.cpp +++ b/native/android/performance_hint.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "perf_hint" #include <aidl/android/hardware/power/SessionHint.h> +#include <aidl/android/hardware/power/SessionMode.h> #include <android/os/IHintManager.h> #include <android/os/IHintSession.h> #include <android/performance_hint.h> @@ -36,6 +37,7 @@ using namespace android::os; using namespace std::chrono_literals; using AidlSessionHint = aidl::android::hardware::power::SessionHint; +using AidlSessionMode = aidl::android::hardware::power::SessionMode; struct APerformanceHintSession; @@ -72,6 +74,7 @@ public: int sendHint(SessionHint hint); int setThreads(const int32_t* threadIds, size_t size); int getThreadIds(int32_t* const threadIds, size_t* size); + int setPreferPowerEfficiency(bool enabled); private: friend struct APerformanceHintManager; @@ -307,6 +310,18 @@ int APerformanceHintSession::getThreadIds(int32_t* const threadIds, size_t* size return 0; } +int APerformanceHintSession::setPreferPowerEfficiency(bool enabled) { + binder::Status ret = + mHintSession->setMode(static_cast<int32_t>(AidlSessionMode::POWER_EFFICIENCY), enabled); + + if (!ret.isOk()) { + ALOGE("%s: HintSession setPreferPowerEfficiency failed: %s", __FUNCTION__, + ret.exceptionMessage().c_str()); + return EPIPE; + } + return OK; +} + // ===================================== C API APerformanceHintManager* APerformanceHint_getManager() { return APerformanceHintManager::getInstance(); @@ -357,6 +372,10 @@ int APerformanceHint_getThreadIds(void* aPerformanceHintSession, int32_t* const ->getThreadIds(threadIds, size); } +int APerformanceHint_setPreferPowerEfficiency(APerformanceHintSession* session, bool enabled) { + return session->setPreferPowerEfficiency(enabled); +} + void APerformanceHint_setIHintManagerForTesting(void* iManager) { delete gHintManagerForTesting; gHintManagerForTesting = nullptr; diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp index 6f7562b93a30..22d33b139ccf 100644 --- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp +++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp @@ -56,7 +56,8 @@ public: (const ::std::vector<int64_t>& actualDurationNanos, const ::std::vector<int64_t>& timeStampNanos), (override)); - MOCK_METHOD(Status, sendHint, (int32_t hints), (override)); + MOCK_METHOD(Status, sendHint, (int32_t hint), (override)); + MOCK_METHOD(Status, setMode, (int32_t mode, bool enabled), (override)); MOCK_METHOD(Status, close, (), (override)); MOCK_METHOD(IBinder*, onAsBinder, (), (override)); }; @@ -190,3 +191,51 @@ TEST_F(PerformanceHintTest, SetThreads) { result = APerformanceHint_setThreads(session, invalidTids.data(), invalidTids.size()); EXPECT_EQ(EPERM, result); } + +TEST_F(PerformanceHintTest, SetPowerEfficient) { + APerformanceHintManager* manager = createManager(); + + std::vector<int32_t> tids; + tids.push_back(1); + tids.push_back(2); + int64_t targetDuration = 56789L; + + StrictMock<MockIHintSession>* iSession = new StrictMock<MockIHintSession>(); + sp<IHintSession> session_sp(iSession); + + EXPECT_CALL(*mMockIHintManager, createHintSession(_, Eq(tids), Eq(targetDuration), _)) + .Times(Exactly(1)) + .WillRepeatedly(DoAll(SetArgPointee<3>(std::move(session_sp)), Return(Status()))); + + APerformanceHintSession* session = + APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration); + ASSERT_TRUE(session); + + EXPECT_CALL(*iSession, setMode(_, Eq(true))).Times(Exactly(1)); + int result = APerformanceHint_setPreferPowerEfficiency(session, true); + EXPECT_EQ(0, result); + + EXPECT_CALL(*iSession, setMode(_, Eq(false))).Times(Exactly(1)); + result = APerformanceHint_setPreferPowerEfficiency(session, false); + EXPECT_EQ(0, result); +} + +TEST_F(PerformanceHintTest, CreateZeroTargetDurationSession) { + APerformanceHintManager* manager = createManager(); + + std::vector<int32_t> tids; + tids.push_back(1); + tids.push_back(2); + int64_t targetDuration = 0; + + StrictMock<MockIHintSession>* iSession = new StrictMock<MockIHintSession>(); + sp<IHintSession> session_sp(iSession); + + EXPECT_CALL(*mMockIHintManager, createHintSession(_, Eq(tids), Eq(targetDuration), _)) + .Times(Exactly(1)) + .WillRepeatedly(DoAll(SetArgPointee<3>(std::move(session_sp)), Return(Status()))); + + APerformanceHintSession* session = + APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration); + ASSERT_TRUE(session); +}
\ No newline at end of file diff --git a/services/core/Android.bp b/services/core/Android.bp index 9f263c842965..c2774e5c4400 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -98,7 +98,10 @@ genrule { java_library_static { name: "services.core.unboosted", - defaults: ["platform_service_defaults"], + defaults: [ + "platform_service_defaults", + "android.hardware.power-java_static", + ], srcs: [ ":android.hardware.biometrics.face-V3-java-source", ":android.hardware.tv.hdmi.connection-V1-java-source", @@ -152,7 +155,7 @@ java_library_static { "android.hardware.boot-V1.0-java", // HIDL "android.hardware.boot-V1.1-java", // HIDL "android.hardware.boot-V1.2-java", // HIDL - "android.hardware.boot-V1-java", // AIDL + "android.hardware.boot-V1-java", // AIDL "android.hardware.broadcastradio-V2.0-java", // HIDL "android.hardware.broadcastradio-V1-java", // AIDL "android.hardware.health-V1.0-java", // HIDL @@ -176,7 +179,6 @@ java_library_static { "android.hardware.ir-V1-java", "android.hardware.rebootescrow-V1-java", "android.hardware.power.stats-V2-java", - "android.hardware.power-V4-java", "android.hidl.manager-V1.2-java", "cbor-java", "icu4j_calendar_astronomer", diff --git a/services/core/java/com/android/server/power/hint/HintManagerService.java b/services/core/java/com/android/server/power/hint/HintManagerService.java index 8dcf3e06330f..33bed3d42e50 100644 --- a/services/core/java/com/android/server/power/hint/HintManagerService.java +++ b/services/core/java/com/android/server/power/hint/HintManagerService.java @@ -171,6 +171,8 @@ public final class HintManagerService extends SystemService { public static class NativeWrapper { private native void nativeInit(); + private static native long nativeGetHintSessionPreferredRate(); + private static native long nativeCreateHintSession(int tgid, int uid, int[] tids, long durationNanos); @@ -190,13 +192,18 @@ public final class HintManagerService extends SystemService { private static native void nativeSetThreads(long halPtr, int[] tids); - private static native long nativeGetHintSessionPreferredRate(); + private static native void nativeSetMode(long halPtr, int mode, boolean enabled); /** Wrapper for HintManager.nativeInit */ public void halInit() { nativeInit(); } + /** Wrapper for HintManager.nativeGetHintSessionPreferredRate */ + public long halGetHintSessionPreferredRate() { + return nativeGetHintSessionPreferredRate(); + } + /** Wrapper for HintManager.nativeCreateHintSession */ public long halCreateHintSession(int tgid, int uid, int[] tids, long durationNanos) { return nativeCreateHintSession(tgid, uid, tids, durationNanos); @@ -234,15 +241,16 @@ public final class HintManagerService extends SystemService { nativeSendHint(halPtr, hint); } - /** Wrapper for HintManager.nativeGetHintSessionPreferredRate */ - public long halGetHintSessionPreferredRate() { - return nativeGetHintSessionPreferredRate(); - } - /** Wrapper for HintManager.nativeSetThreads */ public void halSetThreads(long halPtr, int[] tids) { nativeSetThreads(halPtr, tids); } + + /** Wrapper for HintManager.setMode */ + public void halSetMode(long halPtr, int mode, boolean enabled) { + nativeSetMode(halPtr, mode, enabled); + } + } @VisibleForTesting @@ -552,7 +560,7 @@ public final class HintManagerService extends SystemService { if (mHalSessionPtr == 0 || !updateHintAllowed()) { return; } - Preconditions.checkArgument(hint >= 0, "the hint ID the hint value should be" + Preconditions.checkArgument(hint >= 0, "the hint ID value should be" + " greater than zero."); mNativeWrapper.halSendHint(mHalSessionPtr, hint); } @@ -593,6 +601,18 @@ public final class HintManagerService extends SystemService { return mThreadIds; } + @Override + public void setMode(int mode, boolean enabled) { + synchronized (mLock) { + if (mHalSessionPtr == 0 || !updateHintAllowed()) { + return; + } + Preconditions.checkArgument(mode >= 0, "the mode Id value should be" + + " greater than zero."); + mNativeWrapper.halSetMode(mHalSessionPtr, mode, enabled); + } + } + private void onProcStateChanged() { updateHintAllowed(); } diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 101af4d36162..405b133a6de1 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -94,7 +94,10 @@ cc_library_static { cc_defaults { name: "libservices.core-libs", - defaults: ["android.hardware.graphics.common-ndk_shared"], + defaults: [ + "android.hardware.graphics.common-ndk_shared", + "android.hardware.power-ndk_shared", + ], shared_libs: [ "libadb_pairing_server", "libadb_pairing_connection", @@ -177,7 +180,6 @@ cc_defaults { "android.hardware.power@1.1", "android.hardware.power@1.2", "android.hardware.power@1.3", - "android.hardware.power-V4-ndk", "android.hardware.power.stats@1.0", "android.hardware.power.stats-V1-ndk", "android.hardware.thermal@1.0", diff --git a/services/core/jni/com_android_server_hint_HintManagerService.cpp b/services/core/jni/com_android_server_hint_HintManagerService.cpp index e148b94bb0a5..7edf445d7604 100644 --- a/services/core/jni/com_android_server_hint_HintManagerService.cpp +++ b/services/core/jni/com_android_server_hint_HintManagerService.cpp @@ -31,6 +31,7 @@ using aidl::android::hardware::power::IPowerHintSession; using aidl::android::hardware::power::SessionHint; +using aidl::android::hardware::power::SessionMode; using aidl::android::hardware::power::WorkDuration; using android::base::StringPrintf; @@ -41,6 +42,15 @@ static power::PowerHalController gPowerHalController; static std::unordered_map<jlong, std::shared_ptr<IPowerHintSession>> gSessionMap; static std::mutex gSessionMapLock; +static int64_t getHintSessionPreferredRate() { + int64_t rate = -1; + auto result = gPowerHalController.getHintSessionPreferredRate(); + if (result.isOk()) { + rate = result.value(); + } + return rate; +} + static jlong createHintSession(JNIEnv* env, int32_t tgid, int32_t uid, std::vector<int32_t> threadIds, int64_t durationNanos) { auto result = gPowerHalController.createHintSession(tgid, uid, threadIds, durationNanos); @@ -93,13 +103,9 @@ static void setThreads(int64_t session_ptr, const std::vector<int32_t>& threadId appSession->setThreads(threadIds); } -static int64_t getHintSessionPreferredRate() { - int64_t rate = -1; - auto result = gPowerHalController.getHintSessionPreferredRate(); - if (result.isOk()) { - rate = result.value(); - } - return rate; +static void setMode(int64_t session_ptr, SessionMode mode, bool enabled) { + auto appSession = reinterpret_cast<IPowerHintSession*>(session_ptr); + appSession->setMode(mode, enabled); } // ---------------------------------------------------------------------------- @@ -107,6 +113,10 @@ static void nativeInit(JNIEnv* env, jobject obj) { gPowerHalController.init(); } +static jlong nativeGetHintSessionPreferredRate(JNIEnv* /* env */, jclass /* clazz */) { + return static_cast<jlong>(getHintSessionPreferredRate()); +} + static jlong nativeCreateHintSession(JNIEnv* env, jclass /* clazz */, jint tgid, jint uid, jintArray tids, jlong durationNanos) { ScopedIntArrayRO tidArray(env, tids); @@ -165,14 +175,16 @@ static void nativeSetThreads(JNIEnv* env, jclass /* clazz */, jlong session_ptr, setThreads(session_ptr, threadIds); } -static jlong nativeGetHintSessionPreferredRate(JNIEnv* /* env */, jclass /* clazz */) { - return static_cast<jlong>(getHintSessionPreferredRate()); +static void nativeSetMode(JNIEnv* env, jclass /* clazz */, jlong session_ptr, jint mode, + jboolean enabled) { + setMode(session_ptr, static_cast<SessionMode>(mode), enabled); } // ---------------------------------------------------------------------------- static const JNINativeMethod sHintManagerServiceMethods[] = { /* name, signature, funcPtr */ {"nativeInit", "()V", (void*)nativeInit}, + {"nativeGetHintSessionPreferredRate", "()J", (void*)nativeGetHintSessionPreferredRate}, {"nativeCreateHintSession", "(II[IJ)J", (void*)nativeCreateHintSession}, {"nativePauseHintSession", "(J)V", (void*)nativePauseHintSession}, {"nativeResumeHintSession", "(J)V", (void*)nativeResumeHintSession}, @@ -181,7 +193,7 @@ static const JNINativeMethod sHintManagerServiceMethods[] = { {"nativeReportActualWorkDuration", "(J[J[J)V", (void*)nativeReportActualWorkDuration}, {"nativeSendHint", "(JI)V", (void*)nativeSendHint}, {"nativeSetThreads", "(J[I)V", (void*)nativeSetThreads}, - {"nativeGetHintSessionPreferredRate", "()J", (void*)nativeGetHintSessionPreferredRate}, + {"nativeSetMode", "(JIZ)V", (void*)nativeSetMode}, }; int register_android_server_HintManagerService(JNIEnv* env) { diff --git a/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java index 726a4e285d68..9fca513e50b9 100644 --- a/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/hint/HintManagerServiceTest.java @@ -27,10 +27,11 @@ import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeFalse; import static org.junit.Assume.assumeTrue; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyBoolean; +import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyLong; +import static org.mockito.Mockito.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; @@ -73,6 +74,7 @@ public class HintManagerServiceTest { private static final int TGID = Process.getThreadGroupLeader(TID); private static final int[] SESSION_TIDS_A = new int[] {TID}; private static final int[] SESSION_TIDS_B = new int[] {TID}; + private static final int[] SESSION_TIDS_C = new int[] {TID}; private static final long[] DURATIONS_THREE = new long[] {1L, 100L, 1000L}; private static final long[] TIMESTAMPS_THREE = new long[] {1L, 2L, 3L}; private static final long[] DURATIONS_ZERO = new long[] {}; @@ -94,6 +96,8 @@ public class HintManagerServiceTest { eq(DEFAULT_TARGET_DURATION))).thenReturn(1L); when(mNativeWrapperMock.halCreateHintSession(eq(TGID), eq(UID), eq(SESSION_TIDS_B), eq(DEFAULT_TARGET_DURATION))).thenReturn(2L); + when(mNativeWrapperMock.halCreateHintSession(eq(TGID), eq(UID), eq(SESSION_TIDS_C), + eq(0L))).thenReturn(1L); when(mAmInternalMock.getIsolatedProcesses(anyInt())).thenReturn(null); LocalServices.removeServiceForTest(ActivityManagerInternal.class); LocalServices.addService(ActivityManagerInternal.class, mAmInternalMock); @@ -138,6 +142,10 @@ public class HintManagerServiceTest { IHintSession b = service.getBinderServiceInstance().createHintSession(token, SESSION_TIDS_B, DEFAULT_TARGET_DURATION); assertNotEquals(a, b); + + IHintSession c = service.getBinderServiceInstance().createHintSession(token, + SESSION_TIDS_C, 0L); + assertNotNull(c); } @Test @@ -338,4 +346,35 @@ public class HintManagerServiceTest { a.setThreads(SESSION_TIDS_A); verify(mNativeWrapperMock, never()).halSetThreads(anyLong(), any()); } + + @Test + public void testSetMode() throws Exception { + HintManagerService service = createService(); + IBinder token = new Binder(); + + AppHintSession a = (AppHintSession) service.getBinderServiceInstance() + .createHintSession(token, SESSION_TIDS_A, DEFAULT_TARGET_DURATION); + + a.setMode(0, true); + verify(mNativeWrapperMock, times(1)).halSetMode(anyLong(), + eq(0), eq(true)); + + a.setMode(0, false); + verify(mNativeWrapperMock, times(1)).halSetMode(anyLong(), + eq(0), eq(false)); + + assertThrows(IllegalArgumentException.class, () -> { + a.setMode(-1, true); + }); + + reset(mNativeWrapperMock); + // Set session to background, then the duration would not be updated. + service.mUidObserver.onUidStateChanged( + a.mUid, ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 0, 0); + FgThread.getHandler().runWithScissors(() -> { }, 500); + assertFalse(a.updateHintAllowed()); + a.setMode(0, true); + verify(mNativeWrapperMock, never()).halSetMode(anyLong(), anyInt(), anyBoolean()); + } + } |