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

Commit 754e0659 authored by Peiyong Lin's avatar Peiyong Lin Committed by Android (Google) Code Review
Browse files

Merge "[Reland] Add API support for GPU work duration report in ADPF." into main

parents c882d013 81780c4a
Loading
Loading
Loading
Loading
+114 −12
Original line number Diff line number Diff line
@@ -60,6 +60,27 @@ __BEGIN_DECLS

struct APerformanceHintManager;
struct APerformanceHintSession;
struct AWorkDuration;

/**
 * {@link AWorkDuration} is an opaque type that represents the breakdown of the
 * actual workload duration in each component internally.
 *
 * A new {@link AWorkDuration} can be obtained using
 * {@link AWorkDuration_create()}, when the client finishes using
 * {@link AWorkDuration}, {@link AWorkDuration_release()} must be
 * called to destroy and free up the resources associated with
 * {@link AWorkDuration}.
 *
 * This file provides a set of functions to allow clients to set the measured
 * work duration of each component on {@link AWorkDuration}.
 *
 * - AWorkDuration_setWorkPeriodStartTimestampNanos()
 * - AWorkDuration_setActualTotalDurationNanos()
 * - AWorkDuration_setActualCpuDurationNanos()
 * - AWorkDuration_setActualGpuDurationNanos()
 */
typedef struct AWorkDuration AWorkDuration;

/**
 * An opaque type representing a handle to a performance hint manager.
@@ -102,7 +123,7 @@ typedef struct APerformanceHintSession APerformanceHintSession;
  *
  * @return APerformanceHintManager instance on success, nullptr on failure.
  */
APerformanceHintManager* APerformanceHint_getManager() __INTRODUCED_IN(__ANDROID_API_T__);
APerformanceHintManager* _Nullable APerformanceHint_getManager() __INTRODUCED_IN(__ANDROID_API_T__);

/**
 * Creates a session for the given set of threads and sets their initial target work
@@ -116,9 +137,9 @@ APerformanceHintManager* APerformanceHint_getManager() __INTRODUCED_IN(__ANDROID
 *     This must be positive if using the work duration API, or 0 otherwise.
 * @return APerformanceHintManager instance on success, nullptr on failure.
 */
APerformanceHintSession* APerformanceHint_createSession(
        APerformanceHintManager* manager,
        const int32_t* threadIds, size_t size,
APerformanceHintSession* _Nullable APerformanceHint_createSession(
        APerformanceHintManager* _Nonnull manager,
        const int32_t* _Nonnull threadIds, size_t size,
        int64_t initialTargetWorkDurationNanos) __INTRODUCED_IN(__ANDROID_API_T__);

/**
@@ -128,7 +149,7 @@ APerformanceHintSession* APerformanceHint_createSession(
 * @return the preferred update rate supported by device software.
 */
int64_t APerformanceHint_getPreferredUpdateRateNanos(
        APerformanceHintManager* manager) __INTRODUCED_IN(__ANDROID_API_T__);
        APerformanceHintManager* _Nonnull manager) __INTRODUCED_IN(__ANDROID_API_T__);

/**
 * Updates this session's target duration for each cycle of work.
@@ -140,7 +161,7 @@ int64_t APerformanceHint_getPreferredUpdateRateNanos(
 *         EPIPE if communication with the system service has failed.
 */
int APerformanceHint_updateTargetWorkDuration(
        APerformanceHintSession* session,
        APerformanceHintSession* _Nonnull session,
        int64_t targetDurationNanos) __INTRODUCED_IN(__ANDROID_API_T__);

/**
@@ -157,7 +178,7 @@ int APerformanceHint_updateTargetWorkDuration(
 *         EPIPE if communication with the system service has failed.
 */
int APerformanceHint_reportActualWorkDuration(
        APerformanceHintSession* session,
        APerformanceHintSession* _Nonnull session,
        int64_t actualDurationNanos) __INTRODUCED_IN(__ANDROID_API_T__);

/**
@@ -167,7 +188,7 @@ int APerformanceHint_reportActualWorkDuration(
 * @param session The performance hint session instance to release.
 */
void APerformanceHint_closeSession(
        APerformanceHintSession* session) __INTRODUCED_IN(__ANDROID_API_T__);
        APerformanceHintSession* _Nonnull session) __INTRODUCED_IN(__ANDROID_API_T__);

/**
 * Set a list of threads to the performance hint session. This operation will replace
@@ -184,8 +205,8 @@ void APerformanceHint_closeSession(
 *         EPERM if any thread id doesn't belong to the application.
 */
int APerformanceHint_setThreads(
        APerformanceHintSession* session,
        const pid_t* threadIds,
        APerformanceHintSession* _Nonnull session,
        const pid_t* _Nonnull threadIds,
        size_t size) __INTRODUCED_IN(__ANDROID_API_U__);

/**
@@ -198,9 +219,90 @@ int APerformanceHint_setThreads(
 *         EPIPE if communication with the system service has failed.
 */
int APerformanceHint_setPreferPowerEfficiency(
        APerformanceHintSession* session,
        APerformanceHintSession* _Nonnull session,
        bool enabled) __INTRODUCED_IN(__ANDROID_API_V__);

/**
 * Reports the durations for the last cycle of work.
 *
 * The system will attempt to adjust the scheduling and performance of the
 * threads within the thread group to bring the actual duration close to the target duration.
 *
 * @param session The {@link APerformanceHintSession} instance to update.
 * @param workDuration The {@link AWorkDuration} structure of times the thread group took to
 *     complete its last task in nanoseconds breaking down into different components.
 *
 *     The work period start timestamp, actual total duration and actual CPU duration must be
 *     positive.
 *
 *     The actual GPU duration must be non-negative. If the actual GPU duration is 0, it means
 *     the actual GPU duration is not measured.
 *
 * @return 0 on success.
 *         EINVAL if session is nullptr or any duration is an invalid number.
 *         EPIPE if communication with the system service has failed.
 */
int APerformanceHint_reportActualWorkDuration2(
        APerformanceHintSession* _Nonnull session,
        AWorkDuration* _Nonnull workDuration) __INTRODUCED_IN(__ANDROID_API_V__);

/**
 * Creates a new AWorkDuration. When the client finishes using {@link AWorkDuration}, it should
 * call {@link AWorkDuration_release()} to destroy {@link AWorkDuration} and release all resources
 * associated with it.
 *
 * @return AWorkDuration on success and nullptr otherwise.
 */
AWorkDuration* _Nonnull AWorkDuration_create() __INTRODUCED_IN(__ANDROID_API_V__);

/**
 * Destroys {@link AWorkDuration} and free all resources associated to it.
 *
 * @param aWorkDuration The {@link AWorkDuration} created by calling {@link AWorkDuration_create()}
 */
void AWorkDuration_release(AWorkDuration* _Nonnull WorkDuration) __INTRODUCED_IN(__ANDROID_API_V__);

/**
 * Sets the work period start timestamp in nanoseconds.
 *
 * @param aWorkDuration The {@link AWorkDuration} created by calling {@link AWorkDuration_create()}
 * @param workPeriodStartTimestampNanos The work period start timestamp in nanoseconds based on
 *        CLOCK_MONOTONIC about when the work starts, the timestamp must be positive.
 */
void AWorkDuration_setWorkPeriodStartTimestampNanos(AWorkDuration* _Nonnull aWorkDuration,
        int64_t workPeriodStartTimestampNanos) __INTRODUCED_IN(__ANDROID_API_V__);

/**
 * Sets the actual total work duration in nanoseconds.
 *
 * @param aWorkDuration The {@link AWorkDuration} created by calling {@link AWorkDuration_create()}
 * @param actualTotalDurationNanos The actual total work duration in nanoseconds, the number must be
 *        positive.
 */
void AWorkDuration_setActualTotalDurationNanos(AWorkDuration* _Nonnull aWorkDuration,
        int64_t actualTotalDurationNanos) __INTRODUCED_IN(__ANDROID_API_V__);

/**
 * Sets the actual CPU work duration in nanoseconds.
 *
 * @param aWorkDuration The {@link AWorkDuration} created by calling {@link AWorkDuration_create()}
 * @param actualCpuDurationNanos The actual CPU work duration in nanoseconds, the number must be
 *        positive.
 */
void AWorkDuration_setActualCpuDurationNanos(AWorkDuration* _Nonnull aWorkDuration,
        int64_t actualCpuDurationNanos) __INTRODUCED_IN(__ANDROID_API_V__);

/**
 * Sets the actual GPU work duration in nanoseconds.
 *
 * @param aWorkDuration The {@link AWorkDuration} created by calling {@link AWorkDuration_create()}.
 * @param actualGpuDurationNanos The actual GPU work duration in nanoseconds, the number must be
 *        non-negative. If the actual GPU duration is 0, it means the actual GPU duration is
 *        measured.
 */
void AWorkDuration_setActualGpuDurationNanos(AWorkDuration* _Nonnull aWorkDuration,
        int64_t actualGpuDurationNanos) __INTRODUCED_IN(__ANDROID_API_V__);

__END_DECLS

#endif // ANDROID_NATIVE_PERFORMANCE_HINT_H
+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ cc_library_shared {
        "PowerHalWrapper.cpp",
        "PowerSaveState.cpp",
        "Temperature.cpp",
        "WorkDuration.cpp",
        "WorkSource.cpp",
        ":libpowermanager_aidl",
    ],
+51 −0
Original line number Diff line number Diff line
/**
 * 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.
 */

#define LOG_TAG "WorkDuration"

#include <android/WorkDuration.h>
#include <android/performance_hint.h>
#include <binder/Parcel.h>
#include <utils/Log.h>

namespace android::os {

WorkDuration::WorkDuration(int64_t startTimestampNanos, int64_t totalDurationNanos,
                           int64_t cpuDurationNanos, int64_t gpuDurationNanos)
      : workPeriodStartTimestampNanos(startTimestampNanos),
        actualTotalDurationNanos(totalDurationNanos),
        actualCpuDurationNanos(cpuDurationNanos),
        actualGpuDurationNanos(gpuDurationNanos) {}

status_t WorkDuration::writeToParcel(Parcel* parcel) const {
    if (parcel == nullptr) {
        ALOGE("%s: Null parcel", __func__);
        return BAD_VALUE;
    }

    parcel->writeInt64(workPeriodStartTimestampNanos);
    parcel->writeInt64(actualTotalDurationNanos);
    parcel->writeInt64(actualCpuDurationNanos);
    parcel->writeInt64(actualGpuDurationNanos);
    parcel->writeInt64(timestampNanos);
    return OK;
}

status_t WorkDuration::readFromParcel(const Parcel*) {
    return INVALID_OPERATION;
}

} // namespace android::os
+71 −0
Original line number Diff line number Diff line
/**
 * 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.
 */

#pragma once

#include <binder/Parcelable.h>
#include <math.h>

struct AWorkDuration {};

namespace android::os {

/**
 * C++ Parcelable version of {@link PerformanceHintManager.WorkDuration} that can be used in
 * binder calls.
 * This file needs to be kept in sync with the WorkDuration in
 * frameworks/base/core/java/android/os/WorkDuration.java
 */
struct WorkDuration : AWorkDuration, android::Parcelable {
    WorkDuration() = default;
    ~WorkDuration() = default;

    WorkDuration(int64_t workPeriodStartTimestampNanos, int64_t actualTotalDurationNanos,
                 int64_t actualCpuDurationNanos, int64_t actualGpuDurationNanos);
    status_t writeToParcel(Parcel* parcel) const override;
    status_t readFromParcel(const Parcel* parcel) override;

    inline bool equalsWithoutTimestamp(const WorkDuration& other) const {
        return workPeriodStartTimestampNanos == other.workPeriodStartTimestampNanos &&
                actualTotalDurationNanos == other.actualTotalDurationNanos &&
                actualCpuDurationNanos == other.actualCpuDurationNanos &&
                actualGpuDurationNanos == other.actualGpuDurationNanos;
    }

    bool operator==(const WorkDuration& other) const {
        return timestampNanos == other.timestampNanos && equalsWithoutTimestamp(other);
    }

    bool operator!=(const WorkDuration& other) const { return !(*this == other); }

    friend std::ostream& operator<<(std::ostream& os, const WorkDuration& workDuration) {
        os << "{"
           << "workPeriodStartTimestampNanos: " << workDuration.workPeriodStartTimestampNanos
           << ", actualTotalDurationNanos: " << workDuration.actualTotalDurationNanos
           << ", actualCpuDurationNanos: " << workDuration.actualCpuDurationNanos
           << ", actualGpuDurationNanos: " << workDuration.actualGpuDurationNanos
           << ", timestampNanos: " << workDuration.timestampNanos << "}";
        return os;
    }

    int64_t workPeriodStartTimestampNanos;
    int64_t actualTotalDurationNanos;
    int64_t actualCpuDurationNanos;
    int64_t actualGpuDurationNanos;
    int64_t timestampNanos;
};

} // namespace android::os
+5 −0
Original line number Diff line number Diff line
@@ -251,7 +251,12 @@ void PowerAdvisor::reportActualWorkDuration() {
    actualDuration = std::make_optional(*actualDuration + sTargetSafetyMargin);
    mActualDuration = actualDuration;
    WorkDuration duration;
    duration.workPeriodStartTimestampNanos = mCommitStartTimes[0].ns();
    // TODO(b/284324521): Correctly calculate total duration.
    duration.durationNanos = actualDuration->ns();
    duration.cpuDurationNanos = actualDuration->ns();
    // TODO(b/284324521): Calculate RenderEngine GPU time.
    duration.gpuDurationNanos = 0;
    duration.timeStampNanos = TimePoint::now().ns();
    mHintSessionQueue.push_back(duration);