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

Commit 020fcf01 authored by Matt Buckley's avatar Matt Buckley Committed by Android (Google) Code Review
Browse files

Merge "Refactor initial support check to use SupportInfo" into main

parents 79ea2bf9 3470f4f6
Loading
Loading
Loading
Loading
+23 −11
Original line number Original line Diff line number Diff line
@@ -21,11 +21,13 @@ import android.os.CpuHeadroomParamsInternal;
import android.os.GpuHeadroomParamsInternal;
import android.os.GpuHeadroomParamsInternal;
import android.os.IHintSession;
import android.os.IHintSession;
import android.os.SessionCreationConfig;
import android.os.SessionCreationConfig;
import android.hardware.power.CpuHeadroomResult;

import android.hardware.power.ChannelConfig;
import android.hardware.power.ChannelConfig;
import android.hardware.power.CpuHeadroomResult;
import android.hardware.power.GpuHeadroomResult;
import android.hardware.power.GpuHeadroomResult;
import android.hardware.power.SessionConfig;
import android.hardware.power.SessionConfig;
import android.hardware.power.SessionTag;
import android.hardware.power.SessionTag;
import android.hardware.power.SupportInfo;


/** {@hide} */
/** {@hide} */
interface IHintManager {
interface IHintManager {
@@ -40,11 +42,6 @@ interface IHintManager {
    IHintSession createHintSessionWithConfig(in IBinder token, in SessionTag tag,
    IHintSession createHintSessionWithConfig(in IBinder token, in SessionTag tag,
            in SessionCreationConfig creationConfig, out SessionConfig config);
            in SessionCreationConfig creationConfig, out SessionConfig config);


    /**
     * Get preferred rate limit in nanoseconds.
     */
    long getHintSessionPreferredRate();

    void setHintSessionThreads(in IHintSession hintSession, in int[] tids);
    void setHintSessionThreads(in IHintSession hintSession, in int[] tids);
    int[] getHintSessionThreadIds(in IHintSession hintSession);
    int[] getHintSessionThreadIds(in IHintSession hintSession);


@@ -60,14 +57,29 @@ interface IHintManager {
    @nullable GpuHeadroomResult getGpuHeadroom(in GpuHeadroomParamsInternal params);
    @nullable GpuHeadroomResult getGpuHeadroom(in GpuHeadroomParamsInternal params);
    long getGpuHeadroomMinIntervalMillis();
    long getGpuHeadroomMinIntervalMillis();


    /**
     * Get Maximum number of graphics pipeline threads allowed per-app.
     */
    int getMaxGraphicsPipelineThreadsCount();

    /**
    /**
     * Used by the JNI to pass an interface to the SessionManager;
     * Used by the JNI to pass an interface to the SessionManager;
     * for internal use only.
     * for internal use only.
     */
     */
    oneway void passSessionManagerBinder(in IBinder sessionManager);
    oneway void passSessionManagerBinder(in IBinder sessionManager);

    parcelable HintManagerClientData {
        int powerHalVersion;
        int maxGraphicsPipelineThreads;
        long preferredRateNanos;
        SupportInfo supportInfo;
    }

    interface IHintManagerClient {
        /**
        * Returns FMQ channel information for the caller, which it associates to the callback binder lifespan.
        */
        oneway void receiveChannelConfig(in ChannelConfig config);
    }

    /**
     * Set up an ADPF client, receiving a remote client binder interface and
     * passing back a bundle of support and configuration information.
     */
    HintManagerClientData registerClient(in IHintManagerClient client);
}
}
+72 −42
Original line number Original line Diff line number Diff line
@@ -22,6 +22,7 @@
#include <aidl/android/hardware/power/SessionHint.h>
#include <aidl/android/hardware/power/SessionHint.h>
#include <aidl/android/hardware/power/SessionMode.h>
#include <aidl/android/hardware/power/SessionMode.h>
#include <aidl/android/hardware/power/SessionTag.h>
#include <aidl/android/hardware/power/SessionTag.h>
#include <aidl/android/hardware/power/SupportInfo.h>
#include <aidl/android/hardware/power/WorkDuration.h>
#include <aidl/android/hardware/power/WorkDuration.h>
#include <aidl/android/hardware/power/WorkDurationFixedV1.h>
#include <aidl/android/hardware/power/WorkDurationFixedV1.h>
#include <aidl/android/os/IHintManager.h>
#include <aidl/android/os/IHintManager.h>
@@ -148,10 +149,36 @@ private:
    std::future<bool> mChannelCreationFinished;
    std::future<bool> mChannelCreationFinished;
};
};


class SupportInfoWrapper {
public:
    SupportInfoWrapper(hal::SupportInfo& info);
    bool isSessionModeSupported(hal::SessionMode mode);
    bool isSessionHintSupported(hal::SessionHint hint);

private:
    template <class T>
    bool getEnumSupportFromBitfield(T& enumValue, int64_t& supportBitfield) {
        // extract the bit corresponding to the enum by shifting the bitfield
        // over that much and cutting off any extra values
        return (supportBitfield >> static_cast<int>(enumValue)) % 2;
    }
    hal::SupportInfo mSupportInfo;
};

class HintManagerClient : public IHintManager::BnHintManagerClient {
public:
    // Currently a no-op that exists for FMQ init to call in the future
    ndk::ScopedAStatus receiveChannelConfig(const hal::ChannelConfig&) {
        return ndk::ScopedAStatus::ok();
    }
};

struct APerformanceHintManager {
struct APerformanceHintManager {
public:
public:
    static APerformanceHintManager* getInstance();
    static APerformanceHintManager* getInstance();
    APerformanceHintManager(std::shared_ptr<IHintManager>& service, int64_t preferredRateNanos);
    APerformanceHintManager(std::shared_ptr<IHintManager>& service,
                            IHintManager::HintManagerClientData&& clientData,
                            std::shared_ptr<HintManagerClient> callbackClient);
    APerformanceHintManager() = delete;
    APerformanceHintManager() = delete;
    ~APerformanceHintManager();
    ~APerformanceHintManager();


@@ -169,29 +196,21 @@ public:
    FMQWrapper& getFMQWrapper();
    FMQWrapper& getFMQWrapper();
    bool canSendLoadHints(std::vector<hal::SessionHint>& hints, int64_t now) REQUIRES(sHintMutex);
    bool canSendLoadHints(std::vector<hal::SessionHint>& hints, int64_t now) REQUIRES(sHintMutex);
    void initJava(JNIEnv* _Nonnull env);
    void initJava(JNIEnv* _Nonnull env);
    ndk::ScopedAIBinder_Weak x;
    template <class T>
    template <class T>
    static void layersFromNativeSurfaces(ANativeWindow** windows, int numWindows,
    static void layersFromNativeSurfaces(ANativeWindow** windows, int numWindows,
                                         ASurfaceControl** controls, int numSurfaceControls,
                                         ASurfaceControl** controls, int numSurfaceControls,
                                         std::vector<T>& out);
                                         std::vector<T>& out);
    ndk::SpAIBinder& getToken();
    SupportInfoWrapper& getSupportInfo();


private:
private:
    // Necessary to create an empty binder object
    static void* tokenStubOnCreate(void*) {
        return nullptr;
    }
    static void tokenStubOnDestroy(void*) {}
    static binder_status_t tokenStubOnTransact(AIBinder*, transaction_code_t, const AParcel*,
                                               AParcel*) {
        return STATUS_OK;
    }

    static APerformanceHintManager* create(std::shared_ptr<IHintManager> iHintManager);
    static APerformanceHintManager* create(std::shared_ptr<IHintManager> iHintManager);


    std::shared_ptr<IHintManager> mHintManager;
    std::shared_ptr<IHintManager> mHintManager;
    std::shared_ptr<HintManagerClient> mCallbackClient;
    IHintManager::HintManagerClientData mClientData;
    SupportInfoWrapper mSupportInfoWrapper;
    ndk::SpAIBinder mToken;
    ndk::SpAIBinder mToken;
    const int64_t mPreferredRateNanos;
    std::optional<int32_t> mMaxGraphicsPipelineThreadsCount;
    FMQWrapper mFMQWrapper;
    FMQWrapper mFMQWrapper;
    double mHintBudget = kMaxLoadHintsPerInterval;
    double mHintBudget = kMaxLoadHintsPerInterval;
    int64_t mLastBudgetReplenish = 0;
    int64_t mLastBudgetReplenish = 0;
@@ -273,14 +292,27 @@ static FMQWrapper& getFMQ() {
    return APerformanceHintManager::getInstance()->getFMQWrapper();
    return APerformanceHintManager::getInstance()->getFMQWrapper();
}
}


// ===================================== SupportInfoWrapper implementation

SupportInfoWrapper::SupportInfoWrapper(hal::SupportInfo& info) : mSupportInfo(info) {}

bool SupportInfoWrapper::isSessionHintSupported(hal::SessionHint hint) {
    return getEnumSupportFromBitfield(hint, mSupportInfo.sessionHints);
}

bool SupportInfoWrapper::isSessionModeSupported(hal::SessionMode mode) {
    return getEnumSupportFromBitfield(mode, mSupportInfo.sessionModes);
}

// ===================================== APerformanceHintManager implementation
// ===================================== APerformanceHintManager implementation
APerformanceHintManager::APerformanceHintManager(std::shared_ptr<IHintManager>& manager,
APerformanceHintManager::APerformanceHintManager(std::shared_ptr<IHintManager>& manager,
                                                 int64_t preferredRateNanos)
                                                 IHintManager::HintManagerClientData&& clientData,
      : mHintManager(std::move(manager)), mPreferredRateNanos(preferredRateNanos) {
                                                 std::shared_ptr<HintManagerClient> callbackClient)
    static AIBinder_Class* tokenBinderClass =
      : mHintManager(std::move(manager)),
            AIBinder_Class_define("phm_token", tokenStubOnCreate, tokenStubOnDestroy,
        mCallbackClient(callbackClient),
                                  tokenStubOnTransact);
        mClientData(clientData),
    mToken = ndk::SpAIBinder(AIBinder_new(tokenBinderClass, nullptr));
        mSupportInfoWrapper(clientData.supportInfo),
        mToken(callbackClient->asBinder()) {
    if (mFMQWrapper.isSupported()) {
    if (mFMQWrapper.isSupported()) {
        mFMQWrapper.setToken(mToken);
        mFMQWrapper.setToken(mToken);
        mFMQWrapper.startChannel(mHintManager.get());
        mFMQWrapper.startChannel(mHintManager.get());
@@ -315,16 +347,17 @@ APerformanceHintManager* APerformanceHintManager::create(std::shared_ptr<IHintMa
        ALOGE("%s: PerformanceHint service is not ready ", __FUNCTION__);
        ALOGE("%s: PerformanceHint service is not ready ", __FUNCTION__);
        return nullptr;
        return nullptr;
    }
    }
    int64_t preferredRateNanos = -1L;
    std::shared_ptr<HintManagerClient> client = ndk::SharedRefBase::make<HintManagerClient>();
    ndk::ScopedAStatus ret = manager->getHintSessionPreferredRate(&preferredRateNanos);
    IHintManager::HintManagerClientData clientData;
    ndk::ScopedAStatus ret = manager->registerClient(client, &clientData);
    if (!ret.isOk()) {
    if (!ret.isOk()) {
        ALOGE("%s: PerformanceHint cannot get preferred rate. %s", __FUNCTION__, ret.getMessage());
        ALOGE("%s: PerformanceHint is not supported. %s", __FUNCTION__, ret.getMessage());
        return nullptr;
        return nullptr;
    }
    }
    if (preferredRateNanos <= 0) {
    if (clientData.preferredRateNanos <= 0) {
        preferredRateNanos = -1L;
        clientData.preferredRateNanos = -1L;
    }
    }
    return new APerformanceHintManager(manager, preferredRateNanos);
    return new APerformanceHintManager(manager, std::move(clientData), client);
}
}


bool APerformanceHintManager::canSendLoadHints(std::vector<hal::SessionHint>& hints, int64_t now) {
bool APerformanceHintManager::canSendLoadHints(std::vector<hal::SessionHint>& hints, int64_t now) {
@@ -389,7 +422,9 @@ APerformanceHintSession* APerformanceHintManager::createSessionUsingConfig(
        ALOGE("%s: PerformanceHint cannot create session. %s", __FUNCTION__, ret.getMessage());
        ALOGE("%s: PerformanceHint cannot create session. %s", __FUNCTION__, ret.getMessage());
        return nullptr;
        return nullptr;
    }
    }
    auto out = new APerformanceHintSession(mHintManager, std::move(session), mPreferredRateNanos,

    auto out = new APerformanceHintSession(mHintManager, std::move(session),
                                           mClientData.preferredRateNanos,
                                           sessionCreationConfig->targetWorkDurationNanos, isJava,
                                           sessionCreationConfig->targetWorkDurationNanos, isJava,
                                           sessionConfig.id == -1
                                           sessionConfig.id == -1
                                                   ? std::nullopt
                                                   ? std::nullopt
@@ -416,24 +451,11 @@ APerformanceHintSession* APerformanceHintManager::getSessionFromJava(JNIEnv* env
}
}


int64_t APerformanceHintManager::getPreferredRateNanos() const {
int64_t APerformanceHintManager::getPreferredRateNanos() const {
    return mPreferredRateNanos;
    return mClientData.preferredRateNanos;
}
}


int32_t APerformanceHintManager::getMaxGraphicsPipelineThreadsCount() {
int32_t APerformanceHintManager::getMaxGraphicsPipelineThreadsCount() {
    if (!mMaxGraphicsPipelineThreadsCount.has_value()) {
    return mClientData.maxGraphicsPipelineThreads;
        int32_t threadsCount = -1;
        ndk::ScopedAStatus ret = mHintManager->getMaxGraphicsPipelineThreadsCount(&threadsCount);
        if (!ret.isOk()) {
            ALOGE("%s: PerformanceHint cannot get max graphics pipeline threads count. %s",
                  __FUNCTION__, ret.getMessage());
            return -1;
        }
        if (threadsCount <= 0) {
            threadsCount = -1;
        }
        mMaxGraphicsPipelineThreadsCount.emplace(threadsCount);
    }
    return mMaxGraphicsPipelineThreadsCount.value();
}
}


FMQWrapper& APerformanceHintManager::getFMQWrapper() {
FMQWrapper& APerformanceHintManager::getFMQWrapper() {
@@ -450,6 +472,14 @@ void APerformanceHintManager::initJava(JNIEnv* _Nonnull env) {
    mJavaInitialized = true;
    mJavaInitialized = true;
}
}


ndk::SpAIBinder& APerformanceHintManager::getToken() {
    return mToken;
}

SupportInfoWrapper& APerformanceHintManager::getSupportInfo() {
    return mSupportInfoWrapper;
}

// ===================================== APerformanceHintSession implementation
// ===================================== APerformanceHintSession implementation


constexpr int kNumEnums = enum_size<hal::SessionHint>();
constexpr int kNumEnums = enum_size<hal::SessionHint>();
+22 −13
Original line number Original line Diff line number Diff line
@@ -56,9 +56,6 @@ public:
                 const SessionCreationConfig& creationConfig, hal::SessionConfig* config,
                 const SessionCreationConfig& creationConfig, hal::SessionConfig* config,
                 std::shared_ptr<IHintSession>* _aidl_return),
                 std::shared_ptr<IHintSession>* _aidl_return),
                (override));
                (override));
    MOCK_METHOD(ScopedAStatus, getHintSessionPreferredRate, (int64_t * _aidl_return), (override));
    MOCK_METHOD(ScopedAStatus, getMaxGraphicsPipelineThreadsCount, (int32_t* _aidl_return),
                (override));
    MOCK_METHOD(ScopedAStatus, setHintSessionThreads,
    MOCK_METHOD(ScopedAStatus, setHintSessionThreads,
                (const std::shared_ptr<IHintSession>& hintSession,
                (const std::shared_ptr<IHintSession>& hintSession,
                 const ::std::vector<int32_t>& tids),
                 const ::std::vector<int32_t>& tids),
@@ -84,6 +81,11 @@ public:
    MOCK_METHOD(ScopedAStatus, getGpuHeadroomMinIntervalMillis, (int64_t* _aidl_return),
    MOCK_METHOD(ScopedAStatus, getGpuHeadroomMinIntervalMillis, (int64_t* _aidl_return),
                (override));
                (override));
    MOCK_METHOD(ScopedAStatus, passSessionManagerBinder, (const SpAIBinder& sessionManager));
    MOCK_METHOD(ScopedAStatus, passSessionManagerBinder, (const SpAIBinder& sessionManager));
    MOCK_METHOD(ScopedAStatus, registerClient,
                (const std::shared_ptr<::aidl::android::os::IHintManager::IHintManagerClient>&
                         clientDataIn,
                 ::aidl::android::os::IHintManager::HintManagerClientData* _aidl_return),
                (override));
    MOCK_METHOD(SpAIBinder, asBinder, (), (override));
    MOCK_METHOD(SpAIBinder, asBinder, (), (override));
    MOCK_METHOD(bool, isRemote, (), (override));
    MOCK_METHOD(bool, isRemote, (), (override));
};
};
@@ -125,10 +127,9 @@ public:


    APerformanceHintManager* createManager() {
    APerformanceHintManager* createManager() {
        APerformanceHint_setUseFMQForTesting(mUsingFMQ);
        APerformanceHint_setUseFMQForTesting(mUsingFMQ);
        ON_CALL(*mMockIHintManager, getHintSessionPreferredRate(_))
        ON_CALL(*mMockIHintManager, registerClient(_, _))
                .WillByDefault(DoAll(SetArgPointee<0>(123L), [] { return ScopedAStatus::ok(); }));
                .WillByDefault(
        ON_CALL(*mMockIHintManager, getMaxGraphicsPipelineThreadsCount(_))
                        DoAll(SetArgPointee<1>(mClientData), [] { return ScopedAStatus::ok(); }));
                .WillByDefault(DoAll(SetArgPointee<0>(5), [] { return ScopedAStatus::ok(); }));
        return APerformanceHint_getManager();
        return APerformanceHint_getManager();
    }
    }


@@ -238,6 +239,20 @@ public:
    int kMockQueueSize = 20;
    int kMockQueueSize = 20;
    bool mUsingFMQ = false;
    bool mUsingFMQ = false;


    IHintManager::HintManagerClientData mClientData{
            .powerHalVersion = 6,
            .maxGraphicsPipelineThreads = 5,
            .preferredRateNanos = 123L,
            .supportInfo{
                    .usesSessions = true,
                    .boosts = 0,
                    .modes = 0,
                    .sessionHints = -1,
                    .sessionModes = -1,
                    .sessionTags = -1,
            },
    };

    int32_t mMaxLoadHintsPerInterval;
    int32_t mMaxLoadHintsPerInterval;
    int64_t mLoadHintInterval;
    int64_t mLoadHintInterval;


@@ -256,12 +271,6 @@ bool equalsWithoutTimestamp(hal::WorkDuration lhs, hal::WorkDuration rhs) {
            lhs.gpuDurationNanos == rhs.gpuDurationNanos && lhs.durationNanos == rhs.durationNanos;
            lhs.gpuDurationNanos == rhs.gpuDurationNanos && lhs.durationNanos == rhs.durationNanos;
}
}


TEST_F(PerformanceHintTest, TestGetPreferredUpdateRateNanos) {
    APerformanceHintManager* manager = createManager();
    int64_t preferredUpdateRateNanos = APerformanceHint_getPreferredUpdateRateNanos(manager);
    EXPECT_EQ(123L, preferredUpdateRateNanos);
}

TEST_F(PerformanceHintTest, TestSession) {
TEST_F(PerformanceHintTest, TestSession) {
    APerformanceHintManager* manager = createManager();
    APerformanceHintManager* manager = createManager();
    APerformanceHintSession* session = createSession(manager);
    APerformanceHintSession* session = createSession(manager);
+49 −10
Original line number Original line Diff line number Diff line
@@ -296,7 +296,11 @@ public final class HintManagerService extends SystemService {
        mPowerHalVersion = 0;
        mPowerHalVersion = 0;
        mUsesFmq = false;
        mUsesFmq = false;
        if (mPowerHal != null) {
        if (mPowerHal != null) {
            try {
                mSupportInfo = getSupportInfo();
                mSupportInfo = getSupportInfo();
            } catch (RemoteException e) {
                throw new IllegalStateException("Could not contact PowerHAL!", e);
            }
        }
        }
        mDefaultCpuHeadroomCalculationWindowMillis =
        mDefaultCpuHeadroomCalculationWindowMillis =
                new CpuHeadroomParamsInternal().calculationWindowMillis;
                new CpuHeadroomParamsInternal().calculationWindowMillis;
@@ -314,7 +318,7 @@ public final class HintManagerService extends SystemService {
        }
        }
    }
    }


    SupportInfo getSupportInfo() {
    SupportInfo getSupportInfo() throws RemoteException {
        try {
        try {
            mPowerHalVersion = mPowerHal.getInterfaceVersion();
            mPowerHalVersion = mPowerHal.getInterfaceVersion();
            if (mPowerHalVersion >= 6) {
            if (mPowerHalVersion >= 6) {
@@ -325,9 +329,40 @@ public final class HintManagerService extends SystemService {
        }
        }


        SupportInfo supportInfo = new SupportInfo();
        SupportInfo supportInfo = new SupportInfo();
        supportInfo.usesSessions = isHintSessionSupported();
        // Global boosts & modes aren't currently relevant for HMS clients
        supportInfo.boosts = 0;
        supportInfo.modes = 0;
        supportInfo.sessionHints = 0;
        supportInfo.sessionModes = 0;
        supportInfo.sessionTags = 0;

        supportInfo.headroom = new SupportInfo.HeadroomSupportInfo();
        supportInfo.headroom = new SupportInfo.HeadroomSupportInfo();
        supportInfo.headroom.isCpuSupported = false;
        supportInfo.headroom.isCpuSupported = false;
        supportInfo.headroom.isGpuSupported = false;
        supportInfo.headroom.isGpuSupported = false;
        if (isHintSessionSupported()) {
            if (mPowerHalVersion == 4) {
                // Assume we support the V4 hints & modes unless specified
                // otherwise; this is to avoid breaking backwards compat
                // since we historically just assumed they were.
                supportInfo.sessionHints = 31; // first 5 bits are ones
            }
            if (mPowerHalVersion == 5) {
                // Assume we support the V5 hints & modes unless specified
                // otherwise; this is to avoid breaking backwards compat
                // since we historically just assumed they were.

                // Hal V5 has 8 modes, all of which it assumes are supported,
                // so we represent that by having the first 8 bits set
                supportInfo.sessionHints = 255; // first 8 bits are ones
                // Hal V5 has 1 mode which it assumes is supported, so we
                // represent that by having the first bit set
                supportInfo.sessionModes = 1;
                // Hal V5 has 5 tags, all of which it assumes are supported,
                // so we represent that by having the first 5 bits set
                supportInfo.sessionTags = 31;
            }
        }
        return supportInfo;
        return supportInfo;
    }
    }


@@ -1228,7 +1263,7 @@ public final class HintManagerService extends SystemService {
                    @SessionTag int tag, SessionCreationConfig creationConfig,
                    @SessionTag int tag, SessionCreationConfig creationConfig,
                    SessionConfig config) {
                    SessionConfig config) {
            if (!isHintSessionSupported()) {
            if (!isHintSessionSupported()) {
                throw new UnsupportedOperationException("PowerHAL is not supported!");
                throw new UnsupportedOperationException("PowerHintSessions are not supported!");
            }
            }


            java.util.Objects.requireNonNull(token);
            java.util.Objects.requireNonNull(token);
@@ -1424,12 +1459,6 @@ public final class HintManagerService extends SystemService {
            removeChannelItem(callingTgid, callingUid);
            removeChannelItem(callingTgid, callingUid);
        };
        };


        @Override
        public long getHintSessionPreferredRate() {
            return mHintSessionPreferredRate;
        }

        @Override
        public int getMaxGraphicsPipelineThreadsCount() {
        public int getMaxGraphicsPipelineThreadsCount() {
            return MAX_GRAPHICS_PIPELINE_THREADS_COUNT;
            return MAX_GRAPHICS_PIPELINE_THREADS_COUNT;
        }
        }
@@ -1561,6 +1590,16 @@ public final class HintManagerService extends SystemService {
            mSessionManager = ISessionManager.Stub.asInterface(sessionManager);
            mSessionManager = ISessionManager.Stub.asInterface(sessionManager);
        }
        }


        public IHintManager.HintManagerClientData
                registerClient(@NonNull IHintManager.IHintManagerClient clientBinder) {
            IHintManager.HintManagerClientData out = new IHintManager.HintManagerClientData();
            out.preferredRateNanos = mHintSessionPreferredRate;
            out.maxGraphicsPipelineThreads = getMaxGraphicsPipelineThreadsCount();
            out.powerHalVersion = mPowerHalVersion;
            out.supportInfo = mSupportInfo;
            return out;
        }

        @Override
        @Override
        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
            if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) {
            if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) {
@@ -1568,7 +1607,7 @@ public final class HintManagerService extends SystemService {
            }
            }
            pw.println("HintSessionPreferredRate: " + mHintSessionPreferredRate);
            pw.println("HintSessionPreferredRate: " + mHintSessionPreferredRate);
            pw.println("MaxGraphicsPipelineThreadsCount: " + MAX_GRAPHICS_PIPELINE_THREADS_COUNT);
            pw.println("MaxGraphicsPipelineThreadsCount: " + MAX_GRAPHICS_PIPELINE_THREADS_COUNT);
            pw.println("HAL Support: " + isHintSessionSupported());
            pw.println("Hint Session Support: " + isHintSessionSupported());
            pw.println("Active Sessions:");
            pw.println("Active Sessions:");
            synchronized (mLock) {
            synchronized (mLock) {
                for (int i = 0; i < mActiveSessions.size(); i++) {
                for (int i = 0; i < mActiveSessions.size(); i++) {
+90 −8
Original line number Original line Diff line number Diff line
@@ -64,6 +64,7 @@ import android.os.Binder;
import android.os.CpuHeadroomParamsInternal;
import android.os.CpuHeadroomParamsInternal;
import android.os.GpuHeadroomParamsInternal;
import android.os.GpuHeadroomParamsInternal;
import android.os.IBinder;
import android.os.IBinder;
import android.os.IHintManager;
import android.os.IHintSession;
import android.os.IHintSession;
import android.os.PerformanceHintManager;
import android.os.PerformanceHintManager;
import android.os.Process;
import android.os.Process;
@@ -154,6 +155,8 @@ public class HintManagerServiceTest {
    private ActivityManagerInternal mAmInternalMock;
    private ActivityManagerInternal mAmInternalMock;
    @Mock
    @Mock
    private PackageManager mMockPackageManager;
    private PackageManager mMockPackageManager;
    @Mock
    private IHintManager.IHintManagerClient mClientCallback;
    @Rule
    @Rule
    public final CheckFlagsRule mCheckFlagsRule =
    public final CheckFlagsRule mCheckFlagsRule =
            DeviceFlagsValueProvider.createCheckFlagsRule();
            DeviceFlagsValueProvider.createCheckFlagsRule();
@@ -171,6 +174,23 @@ public class HintManagerServiceTest {
        };
        };
    }
    }


    private SupportInfo makeDefaultSupportInfo() {
        mSupportInfo = new SupportInfo();
        mSupportInfo.usesSessions = true;
        // By default, mark everything as fully supported
        mSupportInfo.sessionHints = -1;
        mSupportInfo.sessionModes = -1;
        mSupportInfo.modes = -1;
        mSupportInfo.boosts = -1;
        mSupportInfo.sessionTags = -1;
        mSupportInfo.headroom = new SupportInfo.HeadroomSupportInfo();
        mSupportInfo.headroom.isCpuSupported = true;
        mSupportInfo.headroom.cpuMinIntervalMillis = 2000;
        mSupportInfo.headroom.isGpuSupported = true;
        mSupportInfo.headroom.gpuMinIntervalMillis = 2000;
        return mSupportInfo;
    }

    @Before
    @Before
    public void setUp() throws Exception {
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        MockitoAnnotations.initMocks(this);
@@ -181,12 +201,7 @@ public class HintManagerServiceTest {
        mConfig.eventFlagDescriptor = new MQDescriptor<Byte, Byte>();
        mConfig.eventFlagDescriptor = new MQDescriptor<Byte, Byte>();
        ApplicationInfo applicationInfo = new ApplicationInfo();
        ApplicationInfo applicationInfo = new ApplicationInfo();
        applicationInfo.category = ApplicationInfo.CATEGORY_GAME;
        applicationInfo.category = ApplicationInfo.CATEGORY_GAME;
        mSupportInfo = new SupportInfo();
        mSupportInfo = makeDefaultSupportInfo();
        mSupportInfo.headroom = new SupportInfo.HeadroomSupportInfo();
        mSupportInfo.headroom.isCpuSupported = true;
        mSupportInfo.headroom.cpuMinIntervalMillis = 2000;
        mSupportInfo.headroom.isGpuSupported = true;
        mSupportInfo.headroom.gpuMinIntervalMillis = 2000;
        when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
        when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
        when(mMockPackageManager.getNameForUid(anyInt())).thenReturn(TEST_APP_NAME);
        when(mMockPackageManager.getNameForUid(anyInt())).thenReturn(TEST_APP_NAME);
        when(mMockPackageManager.getApplicationInfo(eq(TEST_APP_NAME), anyInt()))
        when(mMockPackageManager.getApplicationInfo(eq(TEST_APP_NAME), anyInt()))
@@ -215,6 +230,7 @@ public class HintManagerServiceTest {
        when(mIPowerMock.getInterfaceVersion()).thenReturn(6);
        when(mIPowerMock.getInterfaceVersion()).thenReturn(6);
        when(mIPowerMock.getSupportInfo()).thenReturn(mSupportInfo);
        when(mIPowerMock.getSupportInfo()).thenReturn(mSupportInfo);
        when(mIPowerMock.getSessionChannel(anyInt(), anyInt())).thenReturn(mConfig);
        when(mIPowerMock.getSessionChannel(anyInt(), anyInt())).thenReturn(mConfig);
        when(mIPowerMock.getSupportInfo()).thenReturn(mSupportInfo);
        LocalServices.removeServiceForTest(ActivityManagerInternal.class);
        LocalServices.removeServiceForTest(ActivityManagerInternal.class);
        LocalServices.addService(ActivityManagerInternal.class, mAmInternalMock);
        LocalServices.addService(ActivityManagerInternal.class, mAmInternalMock);
    }
    }
@@ -409,8 +425,11 @@ public class HintManagerServiceTest {
        HintManagerService service = createService();
        HintManagerService service = createService();
        IBinder token = new Binder();
        IBinder token = new Binder();


        final int threadCount =
        IHintManager.HintManagerClientData data = service.getBinderServiceInstance()
                service.getBinderServiceInstance().getMaxGraphicsPipelineThreadsCount();
                .registerClient(mClientCallback);

        final int threadCount = data.maxGraphicsPipelineThreads;

        long sessionPtr1 = 1111L;
        long sessionPtr1 = 1111L;
        long sessionId1 = 11111L;
        long sessionId1 = 11111L;
        CountDownLatch stopLatch1 = new CountDownLatch(1);
        CountDownLatch stopLatch1 = new CountDownLatch(1);
@@ -1400,4 +1419,67 @@ public class HintManagerServiceTest {
        verify(mIPowerMock, times(1)).getGpuHeadroom(eq(halParams1));
        verify(mIPowerMock, times(1)).getGpuHeadroom(eq(halParams1));
        verify(mIPowerMock, times(1)).getGpuHeadroom(eq(halParams2));
        verify(mIPowerMock, times(1)).getGpuHeadroom(eq(halParams2));
    }
    }

    @Test
    public void testRegisteringClient() throws Exception {
        HintManagerService service = createService();
        IHintManager.HintManagerClientData data = service.getBinderServiceInstance()
                .registerClient(mClientCallback);
        assertNotNull(data);
        assertEquals(data.supportInfo, mSupportInfo);
    }

    @Test
    public void testRegisteringClientOnV4() throws Exception {
        when(mIPowerMock.getInterfaceVersion()).thenReturn(4);
        HintManagerService service = createService();
        IHintManager.HintManagerClientData data = service.getBinderServiceInstance()
                .registerClient(mClientCallback);
        assertNotNull(data);
        assertEquals(data.supportInfo.usesSessions, true);
        assertEquals(data.supportInfo.boosts, 0);
        assertEquals(data.supportInfo.modes, 0);
        assertEquals(data.supportInfo.sessionHints, 31);
        assertEquals(data.supportInfo.sessionModes, 0);
        assertEquals(data.supportInfo.sessionTags, 0);
        assertEquals(data.powerHalVersion, 4);
        assertEquals(data.preferredRateNanos, DEFAULT_HINT_PREFERRED_RATE);
    }

    @Test
    public void testRegisteringClientOnV5() throws Exception {
        when(mIPowerMock.getInterfaceVersion()).thenReturn(5);
        HintManagerService service = createService();
        IHintManager.HintManagerClientData data = service.getBinderServiceInstance()
                .registerClient(mClientCallback);
        assertNotNull(data);
        assertEquals(data.supportInfo.usesSessions, true);
        assertEquals(data.supportInfo.boosts, 0);
        assertEquals(data.supportInfo.modes, 0);
        assertEquals(data.supportInfo.sessionHints, 255);
        assertEquals(data.supportInfo.sessionModes, 1);
        assertEquals(data.supportInfo.sessionTags, 31);
        assertEquals(data.powerHalVersion, 5);
        assertEquals(data.preferredRateNanos, DEFAULT_HINT_PREFERRED_RATE);
    }

    @Test
    public void testSettingUpOldClientWhenUnsupported() throws Exception {
        when(mIPowerMock.getInterfaceVersion()).thenReturn(5);
        // Mock unsupported to modify the default support behavior
        when(mNativeWrapperMock.halGetHintSessionPreferredRate())
                .thenReturn(-1L);
        HintManagerService service = createService();
        IHintManager.HintManagerClientData data = service.getBinderServiceInstance()
                .registerClient(mClientCallback);
        assertNotNull(data);
        assertEquals(data.supportInfo.usesSessions, false);
        assertEquals(data.supportInfo.boosts, 0);
        assertEquals(data.supportInfo.modes, 0);
        assertEquals(data.supportInfo.sessionHints, 0);
        assertEquals(data.supportInfo.sessionModes, 0);
        assertEquals(data.supportInfo.sessionTags, 0);
        assertEquals(data.powerHalVersion, 5);
        assertEquals(data.preferredRateNanos, -1);
    }
}
}