Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 423c1b36 authored by Matt Buckley's avatar Matt Buckley
Browse files

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: atest cts/tests/tests/os/src/android/os/cts/PerformanceHintManagerTest.java
Test: atest HintManagerServiceTest
Change-Id: Ia1349e1bd8c4c85276788892b69897b5ef267c03
parent 4660c49c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -33662,6 +33662,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);
  }
+1 −0
Original line number Diff line number Diff line
@@ -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);
}
+35 −27
Original line number Diff line number Diff line
@@ -50,6 +50,15 @@ public final class PerformanceHintManager {
        mNativeManagerPtr = nativeManagerPtr;
    }

    /**
     * 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.
@@ -77,36 +86,23 @@ public final class PerformanceHintManager {
        return new Session(nativeSessionPtr);
    }

    /**
     * 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) {
@@ -229,6 +225,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.
@@ -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);
}
+24 −8
Original line number Diff line number Diff line
@@ -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) {
+9 −0
Original line number Diff line number Diff line
@@ -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);
    }
}
Loading