diff options
author | 2024-12-15 03:19:54 -0800 | |
---|---|---|
committer | 2024-12-20 12:35:54 -0800 | |
commit | 65254c0f96be32a36603bf7eb593b37c54784adf (patch) | |
tree | 173eec9ed098aa252f81be4e506735a550721bd1 | |
parent | a484d2365ac56bf83327713d5c61afefecdbfa2a (diff) |
Update performance_hint to follow NDK API guidance
This patch updates the performance_hint NDK in response to API guidance,
and updates the tests accordingly.
Additionally, this patch updates the documentation and ergonomics of a
few related methods to better accomodate these changes, and to downgrade
going over the graphics pipeline limit from a breakage to a very severe
warning.
Flag: EXEMPT NDK
Test: atest
cts/tests/tests/os/src/android/os/cts/PerformanceHintManagerTest.java
Test: atest PerformanceHintNativeTestCases
Test: atest HintManagerServiceTest
Bug: 380299912
Bug: 381269529
Change-Id: I31f1c1db4ee4846a8aca63243f61ac1672aac309
6 files changed, 516 insertions, 371 deletions
diff --git a/core/java/android/os/IHintManager.aidl b/core/java/android/os/IHintManager.aidl index 56a089aff78a..5128e9173358 100644 --- a/core/java/android/os/IHintManager.aidl +++ b/core/java/android/os/IHintManager.aidl @@ -39,12 +39,18 @@ interface IHintManager { * Throws UnsupportedOperationException if ADPF is not supported, and IllegalStateException * if creation is supported but fails. */ - IHintSession createHintSessionWithConfig(in IBinder token, in SessionTag tag, + SessionCreationReturn createHintSessionWithConfig(in IBinder token, in SessionTag tag, in SessionCreationConfig creationConfig, out SessionConfig config); void setHintSessionThreads(in IHintSession hintSession, in int[] tids); int[] getHintSessionThreadIds(in IHintSession hintSession); + parcelable SessionCreationReturn { + IHintSession session; + // True if the graphics pipeline thread limit is being exceeded + boolean pipelineThreadLimitExceeded = false; + } + /** * Returns FMQ channel information for the caller, which it associates to a binder token. * diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt index 1ccadf90c2a9..f629c8802aef 100644 --- a/native/android/libandroid.map.txt +++ b/native/android/libandroid.map.txt @@ -396,6 +396,7 @@ LIBANDROID { APerformanceHint_notifyWorkloadSpike; # introduced=36 APerformanceHint_borrowSessionFromJava; # introduced=36 APerformanceHint_setNativeSurfaces; # introduced=36 + APerformanceHint_isFeatureSupported; # introduced=36 AWorkDuration_create; # introduced=VanillaIceCream AWorkDuration_release; # introduced=VanillaIceCream AWorkDuration_setWorkPeriodStartTimestampNanos; # introduced=VanillaIceCream @@ -419,7 +420,6 @@ LIBANDROID_PLATFORM { AThermal_setIThermalServiceForTesting; APerformanceHint_setIHintManagerForTesting; APerformanceHint_sendHint; - APerformanceHint_setUseGraphicsPipelineForTesting; APerformanceHint_getThreadIds; APerformanceHint_createSessionInternal; APerformanceHint_createSessionUsingConfigInternal; diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp index 9257901bcd1f..7e655235732f 100644 --- a/native/android/performance_hint.cpp +++ b/native/android/performance_hint.cpp @@ -71,26 +71,31 @@ using android::base::StringPrintf; struct APerformanceHintSession; -constexpr int64_t SEND_HINT_TIMEOUT = std::chrono::nanoseconds(100ms).count(); struct AWorkDuration : public hal::WorkDuration {}; struct ASessionCreationConfig : public SessionCreationConfig { std::vector<wp<IBinder>> layers{}; - bool hasMode(hal::SessionMode&& mode) { + bool hasMode(hal::SessionMode mode) { return std::find(modesToEnable.begin(), modesToEnable.end(), mode) != modesToEnable.end(); } + void setMode(hal::SessionMode mode, bool enabled) { + if (hasMode(mode)) { + if (!enabled) { + std::erase(modesToEnable, mode); + } + } else if (enabled) { + modesToEnable.push_back(mode); + } + } }; -bool kForceGraphicsPipeline = false; - -bool useGraphicsPipeline() { - return android::os::adpf_graphics_pipeline() || kForceGraphicsPipeline; -} - // A pair of values that determine the behavior of the // load hint rate limiter, to only allow "X hints every Y seconds" -constexpr double kLoadHintInterval = std::chrono::nanoseconds(2s).count(); +constexpr int64_t kLoadHintInterval = std::chrono::nanoseconds(2s).count(); constexpr double kMaxLoadHintsPerInterval = 20; -constexpr double kReplenishRate = kMaxLoadHintsPerInterval / kLoadHintInterval; +// Replenish rate is used for new rate limiting behavior, it currently replenishes at a rate of +// 20 / 2s = 1 per 100us, which is the same limit as before, just enforced differently +constexpr double kReplenishRate = kMaxLoadHintsPerInterval / static_cast<double>(kLoadHintInterval); +constexpr int64_t kSendHintTimeout = kLoadHintInterval / kMaxLoadHintsPerInterval; bool kForceNewHintBehavior = false; template <class T> @@ -149,9 +154,7 @@ private: std::future<bool> mChannelCreationFinished; }; -class SupportInfoWrapper { -public: - SupportInfoWrapper(hal::SupportInfo& info); +struct SupportInfoWrapper : public hal::SupportInfo { bool isSessionModeSupported(hal::SessionMode mode); bool isSessionHintSupported(hal::SessionHint hint); @@ -162,7 +165,6 @@ private: // over that much and cutting off any extra values return (supportBitfield >> static_cast<int>(enumValue)) % 2; } - hal::SupportInfo mSupportInfo; }; class HintManagerClient : public IHintManager::BnHintManagerClient { @@ -188,9 +190,9 @@ public: bool isJava = false); APerformanceHintSession* getSessionFromJava(JNIEnv* _Nonnull env, jobject _Nonnull sessionObj); - APerformanceHintSession* createSessionUsingConfig(ASessionCreationConfig* sessionCreationConfig, - hal::SessionTag tag = hal::SessionTag::APP, - bool isJava = false); + int createSessionUsingConfig(ASessionCreationConfig* sessionCreationConfig, + APerformanceHintSession** sessionPtr, + hal::SessionTag tag = hal::SessionTag::APP, bool isJava = false); int64_t getPreferredRateNanos() const; int32_t getMaxGraphicsPipelineThreadsCount(); FMQWrapper& getFMQWrapper(); @@ -202,6 +204,7 @@ public: std::vector<T>& out); ndk::SpAIBinder& getToken(); SupportInfoWrapper& getSupportInfo(); + bool isFeatureSupported(APerformanceHintFeature feature); private: static APerformanceHintManager* create(std::shared_ptr<IHintManager> iHintManager); @@ -239,8 +242,8 @@ public: int setPreferPowerEfficiency(bool enabled); int reportActualWorkDuration(AWorkDuration* workDuration); bool isJava(); - status_t setNativeSurfaces(ANativeWindow** windows, int numWindows, ASurfaceControl** controls, - int numSurfaceControls); + status_t setNativeSurfaces(ANativeWindow** windows, size_t numWindows, + ASurfaceControl** controls, size_t numSurfaceControls); private: friend struct APerformanceHintManager; @@ -294,14 +297,12 @@ static FMQWrapper& getFMQ() { // ===================================== SupportInfoWrapper implementation -SupportInfoWrapper::SupportInfoWrapper(hal::SupportInfo& info) : mSupportInfo(info) {} - bool SupportInfoWrapper::isSessionHintSupported(hal::SessionHint hint) { - return getEnumSupportFromBitfield(hint, mSupportInfo.sessionHints); + return getEnumSupportFromBitfield(hint, sessionHints); } bool SupportInfoWrapper::isSessionModeSupported(hal::SessionMode mode) { - return getEnumSupportFromBitfield(mode, mSupportInfo.sessionModes); + return getEnumSupportFromBitfield(mode, sessionModes); } // ===================================== APerformanceHintManager implementation @@ -386,12 +387,14 @@ APerformanceHintSession* APerformanceHintManager::createSession( .targetWorkDurationNanos = initialTargetWorkDurationNanos, }}; - return APerformanceHintManager::createSessionUsingConfig(&creationConfig, tag, isJava); + APerformanceHintSession* sessionOut; + APerformanceHintManager::createSessionUsingConfig(&creationConfig, &sessionOut, tag, isJava); + return sessionOut; } -APerformanceHintSession* APerformanceHintManager::createSessionUsingConfig( - ASessionCreationConfig* sessionCreationConfig, hal::SessionTag tag, bool isJava) { - std::shared_ptr<IHintSession> session; +int APerformanceHintManager::createSessionUsingConfig(ASessionCreationConfig* sessionCreationConfig, + APerformanceHintSession** sessionOut, + hal::SessionTag tag, bool isJava) { hal::SessionConfig sessionConfig{.id = -1}; ndk::ScopedAStatus ret; @@ -411,31 +414,65 @@ APerformanceHintSession* APerformanceHintManager::createSessionUsingConfig( } } + bool autoCpu = sessionCreationConfig->hasMode(hal::SessionMode::AUTO_CPU); + bool autoGpu = sessionCreationConfig->hasMode(hal::SessionMode::AUTO_GPU); + + if (autoCpu || autoGpu) { + LOG_ALWAYS_FATAL_IF(!sessionCreationConfig->hasMode(hal::SessionMode::GRAPHICS_PIPELINE), + "Automatic session timing enabled without graphics pipeline mode"); + } + + if (autoCpu && !mSupportInfoWrapper.isSessionModeSupported(hal::SessionMode::AUTO_CPU)) { + ALOGE("Automatic CPU timing enabled but not supported"); + return ENOTSUP; + } + + if (autoGpu && !mSupportInfoWrapper.isSessionModeSupported(hal::SessionMode::AUTO_GPU)) { + ALOGE("Automatic GPU timing enabled but not supported"); + return ENOTSUP; + } + + IHintManager::SessionCreationReturn returnValue; ret = mHintManager->createHintSessionWithConfig(mToken, tag, *static_cast<SessionCreationConfig*>( sessionCreationConfig), - &sessionConfig, &session); + &sessionConfig, &returnValue); sessionCreationConfig->layerTokens.clear(); - if (!ret.isOk() || !session) { + if (!ret.isOk() || !returnValue.session) { ALOGE("%s: PerformanceHint cannot create session. %s", __FUNCTION__, ret.getMessage()); - return nullptr; + switch (ret.getExceptionCode()) { + case binder::Status::EX_UNSUPPORTED_OPERATION: + return ENOTSUP; + case binder::Status::EX_ILLEGAL_ARGUMENT: + return EINVAL; + default: + return EPIPE; + } } - auto out = new APerformanceHintSession(mHintManager, std::move(session), + auto out = new APerformanceHintSession(mHintManager, std::move(returnValue.session), mClientData.preferredRateNanos, sessionCreationConfig->targetWorkDurationNanos, isJava, sessionConfig.id == -1 ? std::nullopt : std::make_optional<hal::SessionConfig>( std::move(sessionConfig))); + + *sessionOut = out; + std::scoped_lock lock(sHintMutex); out->traceThreads(sessionCreationConfig->tids); out->traceTargetDuration(sessionCreationConfig->targetWorkDurationNanos); out->traceModes(sessionCreationConfig->modesToEnable); - return out; + if (returnValue.pipelineThreadLimitExceeded) { + ALOGE("Graphics pipeline session thread limit exceeded!"); + return EBUSY; + } + + return 0; } APerformanceHintSession* APerformanceHintManager::getSessionFromJava(JNIEnv* env, @@ -480,6 +517,25 @@ SupportInfoWrapper& APerformanceHintManager::getSupportInfo() { return mSupportInfoWrapper; } +bool APerformanceHintManager::isFeatureSupported(APerformanceHintFeature feature) { + switch (feature) { + case (APERF_HINT_SESSIONS): + return mSupportInfoWrapper.usesSessions; + case (APERF_HINT_POWER_EFFICIENCY): + return mSupportInfoWrapper.isSessionModeSupported(hal::SessionMode::POWER_EFFICIENCY); + case (APERF_HINT_SURFACE_BINDING): + return mSupportInfoWrapper.compositionData.isSupported; + case (APERF_HINT_GRAPHICS_PIPELINE): + return mSupportInfoWrapper.isSessionModeSupported(hal::SessionMode::GRAPHICS_PIPELINE); + case (APERF_HINT_AUTO_CPU): + return mSupportInfoWrapper.isSessionModeSupported(hal::SessionMode::AUTO_CPU); + case (APERF_HINT_AUTO_GPU): + return mSupportInfoWrapper.isSessionModeSupported(hal::SessionMode::AUTO_GPU); + default: + return false; + } +} + // ===================================== APerformanceHintSession implementation constexpr int kNumEnums = enum_size<hal::SessionHint>(); @@ -512,10 +568,6 @@ APerformanceHintSession::~APerformanceHintSession() { } int APerformanceHintSession::updateTargetWorkDuration(int64_t targetDurationNanos) { - if (targetDurationNanos <= 0) { - ALOGE("%s: targetDurationNanos must be positive", __FUNCTION__); - return EINVAL; - } std::scoped_lock lock(sHintMutex); if (mTargetDurationNanos == targetDurationNanos) { return 0; @@ -546,7 +598,6 @@ int APerformanceHintSession::reportActualWorkDuration(int64_t actualDurationNano .workPeriodStartTimestampNanos = 0, .cpuDurationNanos = actualDurationNanos, .gpuDurationNanos = 0}; - return reportActualWorkDurationInternal(static_cast<AWorkDuration*>(&workDuration)); } @@ -556,17 +607,24 @@ bool APerformanceHintSession::isJava() { int APerformanceHintSession::sendHints(std::vector<hal::SessionHint>& hints, int64_t now, const char*) { - std::scoped_lock lock(sHintMutex); + auto& supportInfo = APerformanceHintManager::getInstance()->getSupportInfo(); + + // Drop all unsupported hints, there's not much point reporting errors or warnings for this + std::erase_if(hints, + [&](hal::SessionHint hint) { return !supportInfo.isSessionHintSupported(hint); }); + if (hints.empty()) { - return EINVAL; + // We successfully sent all hints we were able to, technically + return 0; } + for (auto&& hint : hints) { - if (static_cast<int32_t>(hint) < 0 || static_cast<int32_t>(hint) >= kNumEnums) { - ALOGE("%s: invalid session hint %d", __FUNCTION__, hint); - return EINVAL; - } + LOG_ALWAYS_FATAL_IF(static_cast<int32_t>(hint) < 0 || + static_cast<int32_t>(hint) >= kNumEnums, + "%s: invalid session hint %d", __FUNCTION__, hint); } + std::scoped_lock lock(sHintMutex); if (useNewLoadHintBehavior()) { if (!APerformanceHintManager::getInstance()->canSendLoadHints(hints, now)) { return EBUSY; @@ -575,7 +633,7 @@ int APerformanceHintSession::sendHints(std::vector<hal::SessionHint>& hints, int // keep old rate limiter behavior for legacy flag else { for (auto&& hint : hints) { - if (now < (mLastHintSentTimestamp[static_cast<int32_t>(hint)] + SEND_HINT_TIMEOUT)) { + if (now < (mLastHintSentTimestamp[static_cast<int32_t>(hint)] + kSendHintTimeout)) { return EBUSY; } } @@ -651,7 +709,9 @@ int APerformanceHintSession::setThreads(const int32_t* threadIds, size_t size) { } std::vector<int32_t> tids(threadIds, threadIds + size); ndk::ScopedAStatus ret = mHintManager->setHintSessionThreads(mHintSession, tids); - if (!ret.isOk()) { + + // Illegal state means there were too many graphics pipeline threads + if (!ret.isOk() && ret.getExceptionCode() != EX_SERVICE_SPECIFIC) { ALOGE("%s: failed: %s", __FUNCTION__, ret.getMessage()); if (ret.getExceptionCode() == EX_ILLEGAL_ARGUMENT) { return EINVAL; @@ -663,8 +723,10 @@ int APerformanceHintSession::setThreads(const int32_t* threadIds, size_t size) { std::scoped_lock lock(sHintMutex); traceThreads(tids); + bool tooManyThreads = + ret.getExceptionCode() == EX_SERVICE_SPECIFIC && ret.getServiceSpecificError() == 5; - return 0; + return tooManyThreads ? EBUSY : 0; } int APerformanceHintSession::getThreadIds(int32_t* const threadIds, size_t* size) { @@ -711,10 +773,16 @@ int APerformanceHintSession::reportActualWorkDuration(AWorkDuration* workDuratio int APerformanceHintSession::reportActualWorkDurationInternal(AWorkDuration* workDuration) { int64_t actualTotalDurationNanos = workDuration->durationNanos; - traceActualDuration(workDuration->durationNanos); int64_t now = uptimeNanos(); workDuration->timeStampNanos = now; std::scoped_lock lock(sHintMutex); + + if (mTargetDurationNanos <= 0) { + ALOGE("Cannot report work durations if the target duration is not positive."); + return EINVAL; + } + + traceActualDuration(actualTotalDurationNanos); mActualWorkDurations.push_back(std::move(*workDuration)); if (actualTotalDurationNanos >= mTargetDurationNanos) { @@ -757,9 +825,9 @@ int APerformanceHintSession::reportActualWorkDurationInternal(AWorkDuration* wor return 0; } -status_t APerformanceHintSession::setNativeSurfaces(ANativeWindow** windows, int numWindows, +status_t APerformanceHintSession::setNativeSurfaces(ANativeWindow** windows, size_t numWindows, ASurfaceControl** controls, - int numSurfaceControls) { + size_t numSurfaceControls) { if (!mSessionConfig.has_value()) { return ENOTSUP; } @@ -774,7 +842,10 @@ status_t APerformanceHintSession::setNativeSurfaces(ANativeWindow** windows, int ndkLayerHandles.emplace_back(ndk::SpAIBinder(AIBinder_fromPlatformBinder(handle))); } - mHintSession->associateToLayers(ndkLayerHandles); + auto ret = mHintSession->associateToLayers(ndkLayerHandles); + if (!ret.isOk()) { + return EPIPE; + } return 0; } @@ -857,6 +928,11 @@ bool FMQWrapper::startChannel(IHintManager* manager) { } return true; }); + + // If we're unit testing the FMQ, we should block for it to finish completing + if (gForceFMQEnabled.has_value()) { + mChannelCreationFinished.wait(); + } } return isActive(); } @@ -1029,7 +1105,8 @@ void APerformanceHintSession::traceTargetDuration(int64_t targetDuration) { ATrace_setCounter((mSessionName + " target duration").c_str(), targetDuration); } -// ===================================== C API +// ===================================== Start of C API + APerformanceHintManager* APerformanceHint_getManager() { return APerformanceHintManager::getInstance(); } @@ -1037,10 +1114,16 @@ APerformanceHintManager* APerformanceHint_getManager() { #define VALIDATE_PTR(ptr) \ LOG_ALWAYS_FATAL_IF(ptr == nullptr, "%s: " #ptr " is nullptr", __FUNCTION__); +#define HARD_VALIDATE_INT(value, cmp) \ + LOG_ALWAYS_FATAL_IF(!(value cmp), \ + "%s: Invalid value. Check failed: (" #value " " #cmp \ + ") with value: %" PRIi64, \ + __FUNCTION__, static_cast<int64_t>(value)); + #define VALIDATE_INT(value, cmp) \ if (!(value cmp)) { \ ALOGE("%s: Invalid value. Check failed: (" #value " " #cmp ") with value: %" PRIi64, \ - __FUNCTION__, value); \ + __FUNCTION__, static_cast<int64_t>(value)); \ return EINVAL; \ } @@ -1058,19 +1141,27 @@ APerformanceHintSession* APerformanceHint_createSession(APerformanceHintManager* return manager->createSession(threadIds, size, initialTargetWorkDurationNanos); } -APerformanceHintSession* APerformanceHint_createSessionUsingConfig( - APerformanceHintManager* manager, ASessionCreationConfig* sessionCreationConfig) { +int APerformanceHint_createSessionUsingConfig(APerformanceHintManager* manager, + ASessionCreationConfig* sessionCreationConfig, + APerformanceHintSession** sessionOut) { VALIDATE_PTR(manager); VALIDATE_PTR(sessionCreationConfig); - return manager->createSessionUsingConfig(sessionCreationConfig); + VALIDATE_PTR(sessionOut); + *sessionOut = nullptr; + + return manager->createSessionUsingConfig(sessionCreationConfig, sessionOut); } -APerformanceHintSession* APerformanceHint_createSessionUsingConfigInternal( - APerformanceHintManager* manager, ASessionCreationConfig* sessionCreationConfig, - SessionTag tag) { +int APerformanceHint_createSessionUsingConfigInternal(APerformanceHintManager* manager, + ASessionCreationConfig* sessionCreationConfig, + APerformanceHintSession** sessionOut, + SessionTag tag) { VALIDATE_PTR(manager); VALIDATE_PTR(sessionCreationConfig); - return manager->createSessionUsingConfig(sessionCreationConfig, + VALIDATE_PTR(sessionOut); + *sessionOut = nullptr; + + return manager->createSessionUsingConfig(sessionCreationConfig, sessionOut, static_cast<hal::SessionTag>(tag)); } @@ -1111,6 +1202,7 @@ int APerformanceHint_getMaxGraphicsPipelineThreadsCount(APerformanceHintManager* int APerformanceHint_updateTargetWorkDuration(APerformanceHintSession* session, int64_t targetDurationNanos) { VALIDATE_PTR(session) + VALIDATE_INT(targetDurationNanos, >= 0) return session->updateTargetWorkDuration(targetDurationNanos); } @@ -1204,13 +1296,23 @@ int APerformanceHint_notifyWorkloadSpike(APerformanceHintSession* session, bool } int APerformanceHint_setNativeSurfaces(APerformanceHintSession* session, - ANativeWindow** nativeWindows, int nativeWindowsSize, - ASurfaceControl** surfaceControls, int surfaceControlsSize) { + ANativeWindow** nativeWindows, size_t nativeWindowsSize, + ASurfaceControl** surfaceControls, + size_t surfaceControlsSize) { VALIDATE_PTR(session) return session->setNativeSurfaces(nativeWindows, nativeWindowsSize, surfaceControls, surfaceControlsSize); } +bool APerformanceHint_isFeatureSupported(APerformanceHintFeature feature) { + APerformanceHintManager* manager = APerformanceHintManager::getInstance(); + if (manager == nullptr) { + // Clearly whatever it is isn't supported in this case + return false; + } + return manager->isFeatureSupported(feature); +} + AWorkDuration* AWorkDuration_create() { return new AWorkDuration(); } @@ -1265,78 +1367,32 @@ ASessionCreationConfig* ASessionCreationConfig_create() { void ASessionCreationConfig_release(ASessionCreationConfig* config) { VALIDATE_PTR(config) - delete config; } -int ASessionCreationConfig_setTids(ASessionCreationConfig* config, const pid_t* tids, size_t size) { +void ASessionCreationConfig_setTids(ASessionCreationConfig* config, const pid_t* tids, + size_t size) { VALIDATE_PTR(config) VALIDATE_PTR(tids) + HARD_VALIDATE_INT(size, > 0) - if (!useGraphicsPipeline()) { - return ENOTSUP; - } - - if (size <= 0) { - LOG_ALWAYS_FATAL_IF(size <= 0, - "%s: Invalid value. Thread id list size should be greater than zero.", - __FUNCTION__); - return EINVAL; - } config->tids = std::vector<int32_t>(tids, tids + size); - return 0; } -int ASessionCreationConfig_setTargetWorkDurationNanos(ASessionCreationConfig* config, - int64_t targetWorkDurationNanos) { +void ASessionCreationConfig_setTargetWorkDurationNanos(ASessionCreationConfig* config, + int64_t targetWorkDurationNanos) { VALIDATE_PTR(config) - VALIDATE_INT(targetWorkDurationNanos, >= 0) - - if (!useGraphicsPipeline()) { - return ENOTSUP; - } - config->targetWorkDurationNanos = targetWorkDurationNanos; - return 0; } -int ASessionCreationConfig_setPreferPowerEfficiency(ASessionCreationConfig* config, bool enabled) { +void ASessionCreationConfig_setPreferPowerEfficiency(ASessionCreationConfig* config, bool enabled) { VALIDATE_PTR(config) - - if (!useGraphicsPipeline()) { - return ENOTSUP; - } - - if (enabled) { - config->modesToEnable.push_back(hal::SessionMode::POWER_EFFICIENCY); - } else { - std::erase(config->modesToEnable, hal::SessionMode::POWER_EFFICIENCY); - } - return 0; + config->setMode(hal::SessionMode::POWER_EFFICIENCY, enabled); } -int ASessionCreationConfig_setGraphicsPipeline(ASessionCreationConfig* config, bool enabled) { +void ASessionCreationConfig_setGraphicsPipeline(ASessionCreationConfig* config, bool enabled) { VALIDATE_PTR(config) - - if (!useGraphicsPipeline()) { - return ENOTSUP; - } - - if (enabled) { - config->modesToEnable.push_back(hal::SessionMode::GRAPHICS_PIPELINE); - } else { - std::erase(config->modesToEnable, hal::SessionMode::GRAPHICS_PIPELINE); - - // Remove automatic timing modes if we turn off GRAPHICS_PIPELINE, - // as it is a strict pre-requisite for these to run - std::erase(config->modesToEnable, hal::SessionMode::AUTO_CPU); - std::erase(config->modesToEnable, hal::SessionMode::AUTO_GPU); - } - return 0; -} - -void APerformanceHint_setUseGraphicsPipelineForTesting(bool enabled) { - kForceGraphicsPipeline = enabled; + config->setMode(hal::SessionMode::GRAPHICS_PIPELINE, enabled); } void APerformanceHint_getRateLimiterPropertiesForTesting(int32_t* maxLoadHintsPerInterval, @@ -1349,47 +1405,21 @@ void APerformanceHint_setUseNewLoadHintBehaviorForTesting(bool newBehavior) { kForceNewHintBehavior = newBehavior; } -int ASessionCreationConfig_setNativeSurfaces(ASessionCreationConfig* config, - ANativeWindow** nativeWindows, int nativeWindowsSize, - ASurfaceControl** surfaceControls, - int surfaceControlsSize) { +void ASessionCreationConfig_setNativeSurfaces(ASessionCreationConfig* config, + ANativeWindow** nativeWindows, + size_t nativeWindowsSize, + ASurfaceControl** surfaceControls, + size_t surfaceControlsSize) { VALIDATE_PTR(config) - APerformanceHintManager::layersFromNativeSurfaces<wp<IBinder>>(nativeWindows, nativeWindowsSize, surfaceControls, surfaceControlsSize, config->layers); - - if (config->layers.empty()) { - return EINVAL; - } - - return 0; } -int ASessionCreationConfig_setUseAutoTiming(ASessionCreationConfig* _Nonnull config, bool cpu, - bool gpu) { +void ASessionCreationConfig_setUseAutoTiming(ASessionCreationConfig* _Nonnull config, bool cpu, + bool gpu) { VALIDATE_PTR(config) - if ((cpu || gpu) && !config->hasMode(hal::SessionMode::GRAPHICS_PIPELINE)) { - ALOGE("Automatic timing is not supported unless graphics pipeline mode is enabled first"); - return ENOTSUP; - } - - if (config->hasMode(hal::SessionMode::AUTO_CPU)) { - if (!cpu) { - std::erase(config->modesToEnable, hal::SessionMode::AUTO_CPU); - } - } else if (cpu) { - config->modesToEnable.push_back(static_cast<hal::SessionMode>(hal::SessionMode::AUTO_CPU)); - } - - if (config->hasMode(hal::SessionMode::AUTO_GPU)) { - if (!gpu) { - std::erase(config->modesToEnable, hal::SessionMode::AUTO_GPU); - } - } else if (gpu) { - config->modesToEnable.push_back(static_cast<hal::SessionMode>(hal::SessionMode::AUTO_GPU)); - } - - return 0; + config->setMode(hal::SessionMode::AUTO_CPU, cpu); + config->setMode(hal::SessionMode::AUTO_GPU, gpu); } diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp index e3c10f63abb4..f68fa1a89540 100644 --- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp +++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp @@ -49,12 +49,87 @@ using HalFlagQueue = ::android::AidlMessageQueue<int8_t, SynchronizedReadWrite>; using namespace android; using namespace testing; +constexpr int64_t DEFAULT_TARGET_NS = 16666666L; + +template <class T, void (*D)(T*)> +std::shared_ptr<T> wrapSP(T* incoming) { + return incoming == nullptr ? nullptr : std::shared_ptr<T>(incoming, [](T* ptr) { D(ptr); }); +} +constexpr auto&& wrapSession = wrapSP<APerformanceHintSession, APerformanceHint_closeSession>; +constexpr auto&& wrapConfig = wrapSP<ASessionCreationConfig, ASessionCreationConfig_release>; +constexpr auto&& wrapWorkDuration = wrapSP<AWorkDuration, AWorkDuration_release>; + +std::shared_ptr<ASessionCreationConfig> createConfig() { + return wrapConfig(ASessionCreationConfig_create()); +} + +struct ConfigCreator { + std::vector<int32_t> tids{1, 2}; + int64_t targetDuration = DEFAULT_TARGET_NS; + bool powerEfficient = false; + bool graphicsPipeline = false; + std::vector<ANativeWindow*> nativeWindows{}; + std::vector<ASurfaceControl*> surfaceControls{}; + bool autoCpu = false; + bool autoGpu = false; +}; + +struct SupportHelper { + bool hintSessions : 1; + bool powerEfficiency : 1; + bool bindToSurface : 1; + bool graphicsPipeline : 1; + bool autoCpu : 1; + bool autoGpu : 1; +}; + +SupportHelper getSupportHelper() { + return { + .hintSessions = APerformanceHint_isFeatureSupported(APERF_HINT_SESSIONS), + .powerEfficiency = APerformanceHint_isFeatureSupported(APERF_HINT_POWER_EFFICIENCY), + .bindToSurface = APerformanceHint_isFeatureSupported(APERF_HINT_SURFACE_BINDING), + .graphicsPipeline = APerformanceHint_isFeatureSupported(APERF_HINT_GRAPHICS_PIPELINE), + .autoCpu = APerformanceHint_isFeatureSupported(APERF_HINT_AUTO_CPU), + .autoGpu = APerformanceHint_isFeatureSupported(APERF_HINT_AUTO_GPU), + }; +} + +SupportHelper getFullySupportedSupportHelper() { + return { + .hintSessions = true, + .powerEfficiency = true, + .graphicsPipeline = true, + .autoCpu = true, + .autoGpu = true, + }; +} + +std::shared_ptr<ASessionCreationConfig> configFromCreator(ConfigCreator&& creator) { + auto config = createConfig(); + + ASessionCreationConfig_setTids(config.get(), creator.tids.data(), creator.tids.size()); + ASessionCreationConfig_setTargetWorkDurationNanos(config.get(), creator.targetDuration); + ASessionCreationConfig_setPreferPowerEfficiency(config.get(), creator.powerEfficient); + ASessionCreationConfig_setGraphicsPipeline(config.get(), creator.graphicsPipeline); + ASessionCreationConfig_setNativeSurfaces(config.get(), + creator.nativeWindows.size() > 0 + ? creator.nativeWindows.data() + : nullptr, + creator.nativeWindows.size(), + creator.surfaceControls.size() > 0 + ? creator.surfaceControls.data() + : nullptr, + creator.surfaceControls.size()); + ASessionCreationConfig_setUseAutoTiming(config.get(), creator.autoCpu, creator.autoGpu); + return config; +} + class MockIHintManager : public IHintManager { public: MOCK_METHOD(ScopedAStatus, createHintSessionWithConfig, (const SpAIBinder& token, hal::SessionTag tag, const SessionCreationConfig& creationConfig, hal::SessionConfig* config, - std::shared_ptr<IHintSession>* _aidl_return), + IHintManager::SessionCreationReturn* _aidl_return), (override)); MOCK_METHOD(ScopedAStatus, setHintSessionThreads, (const std::shared_ptr<IHintSession>& hintSession, @@ -115,8 +190,9 @@ public: APerformanceHint_getRateLimiterPropertiesForTesting(&mMaxLoadHintsPerInterval, &mLoadHintInterval); APerformanceHint_setIHintManagerForTesting(&mMockIHintManager); - APerformanceHint_setUseGraphicsPipelineForTesting(true); APerformanceHint_setUseNewLoadHintBehaviorForTesting(true); + mTids.push_back(1); + mTids.push_back(2); } void TearDown() override { @@ -130,20 +206,22 @@ public: ON_CALL(*mMockIHintManager, registerClient(_, _)) .WillByDefault( DoAll(SetArgPointee<1>(mClientData), [] { return ScopedAStatus::ok(); })); + ON_CALL(*mMockIHintManager, isRemote()).WillByDefault(Return(true)); return APerformanceHint_getManager(); } - APerformanceHintSession* createSession(APerformanceHintManager* manager, - int64_t targetDuration = 56789L, bool isHwui = false) { + void prepareSessionMock() { mMockSession = ndk::SharedRefBase::make<NiceMock<MockIHintSession>>(); const int64_t sessionId = 123; - std::vector<int32_t> tids; - tids.push_back(1); - tids.push_back(2); + + mSessionCreationReturn = IHintManager::SessionCreationReturn{ + .session = mMockSession, + .pipelineThreadLimitExceeded = false, + }; ON_CALL(*mMockIHintManager, createHintSessionWithConfig(_, _, _, _, _)) .WillByDefault(DoAll(SetArgPointee<3>(hal::SessionConfig({.id = sessionId})), - SetArgPointee<4>(std::shared_ptr<IHintSession>(mMockSession)), + SetArgPointee<4>(mSessionCreationReturn), [] { return ScopedAStatus::ok(); })); ON_CALL(*mMockIHintManager, setHintSessionThreads(_, _)).WillByDefault([] { @@ -161,48 +239,36 @@ public: ON_CALL(*mMockSession, reportActualWorkDuration2(_)).WillByDefault([] { return ScopedAStatus::ok(); }); + } + + std::shared_ptr<APerformanceHintSession> createSession(APerformanceHintManager* manager, + int64_t targetDuration = 56789L, + bool isHwui = false) { + prepareSessionMock(); if (isHwui) { - return APerformanceHint_createSessionInternal(manager, tids.data(), tids.size(), - targetDuration, SessionTag::HWUI); + return wrapSession(APerformanceHint_createSessionInternal(manager, mTids.data(), + mTids.size(), targetDuration, + SessionTag::HWUI)); } - return APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration); + return wrapSession(APerformanceHint_createSession(manager, mTids.data(), mTids.size(), + targetDuration)); } - APerformanceHintSession* createSessionUsingConfig(APerformanceHintManager* manager, - SessionCreationConfig config, - bool isHwui = false) { - mMockSession = ndk::SharedRefBase::make<NiceMock<MockIHintSession>>(); - const int64_t sessionId = 123; - - ON_CALL(*mMockIHintManager, createHintSessionWithConfig(_, _, _, _, _)) - .WillByDefault(DoAll(SetArgPointee<3>(hal::SessionConfig({.id = sessionId})), - SetArgPointee<4>(std::shared_ptr<IHintSession>(mMockSession)), - [] { return ScopedAStatus::ok(); })); - - ON_CALL(*mMockIHintManager, setHintSessionThreads(_, _)).WillByDefault([] { - return ScopedAStatus::ok(); - }); - ON_CALL(*mMockSession, sendHint(_)).WillByDefault([] { return ScopedAStatus::ok(); }); - ON_CALL(*mMockSession, setMode(_, true)).WillByDefault([] { return ScopedAStatus::ok(); }); - ON_CALL(*mMockSession, close()).WillByDefault([] { return ScopedAStatus::ok(); }); - ON_CALL(*mMockSession, updateTargetWorkDuration(_)).WillByDefault([] { - return ScopedAStatus::ok(); - }); - ON_CALL(*mMockSession, reportActualWorkDuration(_, _)).WillByDefault([] { - return ScopedAStatus::ok(); - }); - ON_CALL(*mMockSession, reportActualWorkDuration2(_)).WillByDefault([] { - return ScopedAStatus::ok(); - }); - + std::shared_ptr<APerformanceHintSession> createSessionUsingConfig( + APerformanceHintManager* manager, std::shared_ptr<ASessionCreationConfig>& config, + bool isHwui = false) { + prepareSessionMock(); + APerformanceHintSession* session; + int out = 0; if (isHwui) { - return APerformanceHint_createSessionUsingConfigInternal( - manager, reinterpret_cast<ASessionCreationConfig*>(&config), SessionTag::HWUI); + out = APerformanceHint_createSessionUsingConfigInternal(manager, config.get(), &session, + SessionTag::HWUI); } - return APerformanceHint_createSessionUsingConfig(manager, - reinterpret_cast<ASessionCreationConfig*>( - &config)); + out = APerformanceHint_createSessionUsingConfig(manager, config.get(), &session); + EXPECT_EQ(out, 0); + + return wrapSession(session); } void setFMQEnabled(bool enabled) { @@ -233,11 +299,13 @@ public: uint32_t mWriteBits = 0x00000002; std::shared_ptr<NiceMock<MockIHintManager>> mMockIHintManager = nullptr; std::shared_ptr<NiceMock<MockIHintSession>> mMockSession = nullptr; + IHintManager::SessionCreationReturn mSessionCreationReturn; std::shared_ptr<AidlMessageQueue<hal::ChannelMessage, SynchronizedReadWrite>> mMockFMQ; std::shared_ptr<AidlMessageQueue<int8_t, SynchronizedReadWrite>> mMockFlagQueue; hardware::EventFlag* mEventFlag; int kMockQueueSize = 20; bool mUsingFMQ = false; + std::vector<int> mTids; IHintManager::HintManagerClientData mClientData{ .powerHalVersion = 6, @@ -273,107 +341,109 @@ bool equalsWithoutTimestamp(hal::WorkDuration lhs, hal::WorkDuration rhs) { TEST_F(PerformanceHintTest, TestSession) { APerformanceHintManager* manager = createManager(); - APerformanceHintSession* session = createSession(manager); + auto&& session = createSession(manager); ASSERT_TRUE(session); int64_t targetDurationNanos = 10; EXPECT_CALL(*mMockSession, updateTargetWorkDuration(Eq(targetDurationNanos))).Times(Exactly(1)); - int result = APerformanceHint_updateTargetWorkDuration(session, targetDurationNanos); + int result = APerformanceHint_updateTargetWorkDuration(session.get(), targetDurationNanos); EXPECT_EQ(0, result); // subsequent call with same target should be ignored but return no error - result = APerformanceHint_updateTargetWorkDuration(session, targetDurationNanos); + result = APerformanceHint_updateTargetWorkDuration(session.get(), targetDurationNanos); EXPECT_EQ(0, result); + Mock::VerifyAndClearExpectations(mMockSession.get()); + usleep(2); // Sleep for longer than preferredUpdateRateNanos. int64_t actualDurationNanos = 20; std::vector<int64_t> actualDurations; actualDurations.push_back(20); EXPECT_CALL(*mMockSession, reportActualWorkDuration2(_)).Times(Exactly(1)); - result = APerformanceHint_reportActualWorkDuration(session, actualDurationNanos); + EXPECT_CALL(*mMockSession, updateTargetWorkDuration(_)).Times(Exactly(1)); + result = APerformanceHint_reportActualWorkDuration(session.get(), actualDurationNanos); EXPECT_EQ(0, result); - result = APerformanceHint_updateTargetWorkDuration(session, -1L); + result = APerformanceHint_reportActualWorkDuration(session.get(), -1L); EXPECT_EQ(EINVAL, result); - result = APerformanceHint_reportActualWorkDuration(session, -1L); + result = APerformanceHint_updateTargetWorkDuration(session.get(), 0); + EXPECT_EQ(0, result); + result = APerformanceHint_updateTargetWorkDuration(session.get(), -2); + EXPECT_EQ(EINVAL, result); + result = APerformanceHint_reportActualWorkDuration(session.get(), 12L); EXPECT_EQ(EINVAL, result); SessionHint hintId = SessionHint::CPU_LOAD_RESET; EXPECT_CALL(*mMockSession, sendHint(Eq(hintId))).Times(Exactly(1)); - result = APerformanceHint_sendHint(session, hintId); + result = APerformanceHint_sendHint(session.get(), hintId); EXPECT_EQ(0, result); EXPECT_CALL(*mMockSession, sendHint(Eq(SessionHint::CPU_LOAD_UP))).Times(Exactly(1)); - result = APerformanceHint_notifyWorkloadIncrease(session, true, false, "Test hint"); + result = APerformanceHint_notifyWorkloadIncrease(session.get(), true, false, "Test hint"); EXPECT_EQ(0, result); EXPECT_CALL(*mMockSession, sendHint(Eq(SessionHint::CPU_LOAD_RESET))).Times(Exactly(1)); EXPECT_CALL(*mMockSession, sendHint(Eq(SessionHint::GPU_LOAD_RESET))).Times(Exactly(1)); - result = APerformanceHint_notifyWorkloadReset(session, true, true, "Test hint"); + result = APerformanceHint_notifyWorkloadReset(session.get(), true, true, "Test hint"); EXPECT_EQ(0, result); EXPECT_CALL(*mMockSession, sendHint(Eq(SessionHint::CPU_LOAD_SPIKE))).Times(Exactly(1)); EXPECT_CALL(*mMockSession, sendHint(Eq(SessionHint::GPU_LOAD_SPIKE))).Times(Exactly(1)); - result = APerformanceHint_notifyWorkloadSpike(session, true, true, "Test hint"); + result = APerformanceHint_notifyWorkloadSpike(session.get(), true, true, "Test hint"); EXPECT_EQ(0, result); - result = APerformanceHint_sendHint(session, static_cast<SessionHint>(-1)); - EXPECT_EQ(EINVAL, result); + EXPECT_DEATH( + { APerformanceHint_sendHint(session.get(), static_cast<SessionHint>(-1)); }, + "invalid session hint"); Mock::VerifyAndClearExpectations(mMockSession.get()); for (int i = 0; i < mMaxLoadHintsPerInterval; ++i) { - APerformanceHint_sendHint(session, hintId); + APerformanceHint_sendHint(session.get(), hintId); } // Expect to get rate limited if we try to send faster than the limiter allows EXPECT_CALL(*mMockSession, sendHint(_)).Times(Exactly(0)); - result = APerformanceHint_notifyWorkloadIncrease(session, true, true, "Test hint"); + result = APerformanceHint_notifyWorkloadIncrease(session.get(), true, true, "Test hint"); EXPECT_EQ(result, EBUSY); EXPECT_CALL(*mMockSession, sendHint(_)).Times(Exactly(0)); - result = APerformanceHint_notifyWorkloadReset(session, true, true, "Test hint"); + result = APerformanceHint_notifyWorkloadReset(session.get(), true, true, "Test hint"); EXPECT_CALL(*mMockSession, close()).Times(Exactly(1)); - APerformanceHint_closeSession(session); } TEST_F(PerformanceHintTest, TestUpdatedSessionCreation) { EXPECT_CALL(*mMockIHintManager, createHintSessionWithConfig(_, _, _, _, _)).Times(1); APerformanceHintManager* manager = createManager(); - APerformanceHintSession* session = createSession(manager); + auto&& session = createSession(manager); ASSERT_TRUE(session); - APerformanceHint_closeSession(session); } TEST_F(PerformanceHintTest, TestSessionCreationUsingConfig) { EXPECT_CALL(*mMockIHintManager, createHintSessionWithConfig(_, _, _, _, _)).Times(1); - SessionCreationConfig config{.tids = std::vector<int32_t>(1, 2), - .targetWorkDurationNanos = 5678, - .modesToEnable = std::vector<hal::SessionMode>(0)}; + auto&& config = configFromCreator({.tids = mTids}); APerformanceHintManager* manager = createManager(); - APerformanceHintSession* session = createSessionUsingConfig(manager, config); + auto&& session = createSessionUsingConfig(manager, config); ASSERT_TRUE(session); - APerformanceHint_closeSession(session); } TEST_F(PerformanceHintTest, TestHwuiSessionCreation) { EXPECT_CALL(*mMockIHintManager, createHintSessionWithConfig(_, hal::SessionTag::HWUI, _, _, _)) .Times(1); APerformanceHintManager* manager = createManager(); - APerformanceHintSession* session = createSession(manager, 56789L, true); + auto&& session = createSession(manager, 56789L, true); ASSERT_TRUE(session); - APerformanceHint_closeSession(session); } TEST_F(PerformanceHintTest, SetThreads) { APerformanceHintManager* manager = createManager(); - APerformanceHintSession* session = createSession(manager); + auto&& session = createSession(manager); ASSERT_TRUE(session); int32_t emptyTids[2]; - int result = APerformanceHint_setThreads(session, emptyTids, 0); + int result = APerformanceHint_setThreads(session.get(), emptyTids, 0); EXPECT_EQ(EINVAL, result); std::vector<int32_t> newTids; newTids.push_back(1); newTids.push_back(3); EXPECT_CALL(*mMockIHintManager, setHintSessionThreads(_, Eq(newTids))).Times(Exactly(1)); - result = APerformanceHint_setThreads(session, newTids.data(), newTids.size()); + result = APerformanceHint_setThreads(session.get(), newTids.data(), newTids.size()); EXPECT_EQ(0, result); testing::Mock::VerifyAndClearExpectations(mMockIHintManager.get()); @@ -383,27 +453,27 @@ TEST_F(PerformanceHintTest, SetThreads) { EXPECT_CALL(*mMockIHintManager, setHintSessionThreads(_, Eq(invalidTids))) .Times(Exactly(1)) .WillOnce(Return(ByMove(ScopedAStatus::fromExceptionCode(EX_SECURITY)))); - result = APerformanceHint_setThreads(session, invalidTids.data(), invalidTids.size()); + result = APerformanceHint_setThreads(session.get(), invalidTids.data(), invalidTids.size()); EXPECT_EQ(EPERM, result); } TEST_F(PerformanceHintTest, SetPowerEfficient) { APerformanceHintManager* manager = createManager(); - APerformanceHintSession* session = createSession(manager); + auto&& session = createSession(manager); ASSERT_TRUE(session); EXPECT_CALL(*mMockSession, setMode(_, Eq(true))).Times(Exactly(1)); - int result = APerformanceHint_setPreferPowerEfficiency(session, true); + int result = APerformanceHint_setPreferPowerEfficiency(session.get(), true); EXPECT_EQ(0, result); EXPECT_CALL(*mMockSession, setMode(_, Eq(false))).Times(Exactly(1)); - result = APerformanceHint_setPreferPowerEfficiency(session, false); + result = APerformanceHint_setPreferPowerEfficiency(session.get(), false); EXPECT_EQ(0, result); } TEST_F(PerformanceHintTest, CreateZeroTargetDurationSession) { APerformanceHintManager* manager = createManager(); - APerformanceHintSession* session = createSession(manager, 0); + auto&& session = createSession(manager, 0); ASSERT_TRUE(session); } @@ -428,12 +498,12 @@ MATCHER_P(WorkDurationEq, expected, "") { TEST_F(PerformanceHintTest, TestAPerformanceHint_reportActualWorkDuration2) { APerformanceHintManager* manager = createManager(); - APerformanceHintSession* session = createSession(manager); + auto&& session = createSession(manager); ASSERT_TRUE(session); int64_t targetDurationNanos = 10; EXPECT_CALL(*mMockSession, updateTargetWorkDuration(Eq(targetDurationNanos))).Times(Exactly(1)); - int result = APerformanceHint_updateTargetWorkDuration(session, targetDurationNanos); + int result = APerformanceHint_updateTargetWorkDuration(session.get(), targetDurationNanos); EXPECT_EQ(0, result); usleep(2); // Sleep for longer than preferredUpdateRateNanos. @@ -452,54 +522,53 @@ TEST_F(PerformanceHintTest, TestAPerformanceHint_reportActualWorkDuration2) { EXPECT_CALL(*mMockSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations))) .Times(Exactly(pair.expectedResult == OK)); - result = APerformanceHint_reportActualWorkDuration2(session, + result = APerformanceHint_reportActualWorkDuration2(session.get(), reinterpret_cast<AWorkDuration*>( &pair.duration)); EXPECT_EQ(pair.expectedResult, result); } EXPECT_CALL(*mMockSession, close()).Times(Exactly(1)); - APerformanceHint_closeSession(session); } TEST_F(PerformanceHintTest, TestAWorkDuration) { - AWorkDuration* aWorkDuration = AWorkDuration_create(); + // AWorkDuration* aWorkDuration = AWorkDuration_create(); + auto&& aWorkDuration = wrapWorkDuration(AWorkDuration_create()); ASSERT_NE(aWorkDuration, nullptr); - AWorkDuration_setWorkPeriodStartTimestampNanos(aWorkDuration, 1); - AWorkDuration_setActualTotalDurationNanos(aWorkDuration, 20); - AWorkDuration_setActualCpuDurationNanos(aWorkDuration, 13); - AWorkDuration_setActualGpuDurationNanos(aWorkDuration, 8); - AWorkDuration_release(aWorkDuration); + AWorkDuration_setWorkPeriodStartTimestampNanos(aWorkDuration.get(), 1); + AWorkDuration_setActualTotalDurationNanos(aWorkDuration.get(), 20); + AWorkDuration_setActualCpuDurationNanos(aWorkDuration.get(), 13); + AWorkDuration_setActualGpuDurationNanos(aWorkDuration.get(), 8); } TEST_F(PerformanceHintTest, TestCreateUsingFMQ) { setFMQEnabled(true); APerformanceHintManager* manager = createManager(); - APerformanceHintSession* session = createSession(manager); + auto&& session = createSession(manager); ASSERT_TRUE(session); } TEST_F(PerformanceHintTest, TestUpdateTargetWorkDurationUsingFMQ) { setFMQEnabled(true); APerformanceHintManager* manager = createManager(); - APerformanceHintSession* session = createSession(manager); - APerformanceHint_updateTargetWorkDuration(session, 456); + auto&& session = createSession(manager); + APerformanceHint_updateTargetWorkDuration(session.get(), 456); expectToReadFromFmq<HalChannelMessageContents::Tag::targetDuration>(456); } TEST_F(PerformanceHintTest, TestSendHintUsingFMQ) { setFMQEnabled(true); APerformanceHintManager* manager = createManager(); - APerformanceHintSession* session = createSession(manager); - APerformanceHint_sendHint(session, SessionHint::CPU_LOAD_UP); + auto&& session = createSession(manager); + APerformanceHint_sendHint(session.get(), SessionHint::CPU_LOAD_UP); expectToReadFromFmq<HalChannelMessageContents::Tag::hint>(hal::SessionHint::CPU_LOAD_UP); } TEST_F(PerformanceHintTest, TestReportActualUsingFMQ) { setFMQEnabled(true); APerformanceHintManager* manager = createManager(); - APerformanceHintSession* session = createSession(manager); + auto&& session = createSession(manager); hal::WorkDuration duration{.timeStampNanos = 3, .durationNanos = 999999, .workPeriodStartTimestampNanos = 1, @@ -513,20 +582,91 @@ TEST_F(PerformanceHintTest, TestReportActualUsingFMQ) { .gpuDurationNanos = duration.gpuDurationNanos, }; - APerformanceHint_reportActualWorkDuration2(session, + APerformanceHint_reportActualWorkDuration2(session.get(), reinterpret_cast<AWorkDuration*>(&duration)); expectToReadFromFmq<HalChannelMessageContents::Tag::workDuration>(durationExpected); } TEST_F(PerformanceHintTest, TestASessionCreationConfig) { - ASessionCreationConfig* config = ASessionCreationConfig_create(); + auto&& config = configFromCreator({ + .tids = mTids, + .targetDuration = 20, + .powerEfficient = true, + .graphicsPipeline = true, + }); + + APerformanceHintManager* manager = createManager(); + auto&& session = createSessionUsingConfig(manager, config); + + ASSERT_NE(session, nullptr); ASSERT_NE(config, nullptr); +} + +TEST_F(PerformanceHintTest, TestSupportObject) { + // Disable GPU and Power Efficiency support to test partial enabling + mClientData.supportInfo.sessionModes &= ~(1 << (int)hal::SessionMode::AUTO_GPU); + mClientData.supportInfo.sessionHints &= ~(1 << (int)hal::SessionHint::GPU_LOAD_UP); + mClientData.supportInfo.sessionHints &= ~(1 << (int)hal::SessionHint::POWER_EFFICIENCY); + + APerformanceHintManager* manager = createManager(); + + union { + int expectedSupportInt; + SupportHelper expectedSupport; + }; + + union { + int actualSupportInt; + SupportHelper actualSupport; + }; + + expectedSupport = getFullySupportedSupportHelper(); + actualSupport = getSupportHelper(); + + expectedSupport.autoGpu = false; + + EXPECT_EQ(expectedSupportInt, actualSupportInt); +} + +TEST_F(PerformanceHintTest, TestCreatingAutoSession) { + // Disable GPU capability for testing + mClientData.supportInfo.sessionModes &= ~(1 << (int)hal::SessionMode::AUTO_GPU); + APerformanceHintManager* manager = createManager(); - const int32_t testTids[2] = {1, 2}; - const size_t size = 2; - EXPECT_EQ(ASessionCreationConfig_setTids(config, testTids, size), 0); - EXPECT_EQ(ASessionCreationConfig_setTargetWorkDurationNanos(config, 20), 0); - EXPECT_EQ(ASessionCreationConfig_setPreferPowerEfficiency(config, true), 0); - EXPECT_EQ(ASessionCreationConfig_setGraphicsPipeline(config, true), 0); - ASessionCreationConfig_release(config); + auto&& invalidConfig = configFromCreator({ + .tids = mTids, + .targetDuration = 20, + .graphicsPipeline = false, + .autoCpu = true, + .autoGpu = true, + }); + + EXPECT_DEATH({ createSessionUsingConfig(manager, invalidConfig); }, ""); + + auto&& unsupportedConfig = configFromCreator({ + .tids = mTids, + .targetDuration = 20, + .graphicsPipeline = true, + .autoCpu = true, + .autoGpu = true, + }); + + APerformanceHintSession* unsupportedSession = nullptr; + + // Creating a session with auto timing but no graphics pipeline should fail + int out = APerformanceHint_createSessionUsingConfig(manager, unsupportedConfig.get(), + &unsupportedSession); + EXPECT_EQ(out, ENOTSUP); + EXPECT_EQ(wrapSession(unsupportedSession), nullptr); + + auto&& validConfig = configFromCreator({ + .tids = mTids, + .targetDuration = 20, + .graphicsPipeline = true, + .autoCpu = true, + .autoGpu = false, + }); + + auto&& validSession = createSessionUsingConfig(manager, validConfig); + EXPECT_NE(validSession, nullptr); } 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 a0bc77e939d1..c4e4c422688d 100644 --- a/services/core/java/com/android/server/power/hint/HintManagerService.java +++ b/services/core/java/com/android/server/power/hint/HintManagerService.java @@ -42,6 +42,7 @@ import android.hardware.power.GpuHeadroomParams; import android.hardware.power.GpuHeadroomResult; import android.hardware.power.IPower; import android.hardware.power.SessionConfig; +import android.hardware.power.SessionMode; import android.hardware.power.SessionTag; import android.hardware.power.SupportInfo; import android.hardware.power.WorkDuration; @@ -58,6 +59,7 @@ import android.os.PerformanceHintManager; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.ServiceSpecificException; import android.os.SessionCreationConfig; import android.os.SystemProperties; import android.os.UserHandle; @@ -80,7 +82,6 @@ import com.android.server.FgThread; import com.android.server.LocalServices; import com.android.server.ServiceThread; import com.android.server.SystemService; -import com.android.server.power.hint.HintManagerService.AppHintSession.SessionModes; import com.android.server.utils.Slogf; import java.io.BufferedReader; @@ -409,6 +410,29 @@ public final class HintManagerService extends SystemService { mEnforceCpuHeadroomUserModeCpuTimeCheck = true; } + private boolean tooManyPipelineThreads(int uid) { + synchronized (mThreadsUsageObject) { + ArraySet<ThreadUsageTracker> threadsSet = mThreadsUsageMap.get(uid); + int graphicsPipelineThreadCount = 0; + if (threadsSet != null) { + // We count the graphics pipeline threads that are + // *not* in this session, since those in this session + // will be replaced. Then if the count plus the new tids + // is over max available graphics pipeline threads we raise + // an exception. + for (ThreadUsageTracker t : threadsSet) { + if (t.isGraphicsPipeline()) { + graphicsPipelineThreadCount++; + } + } + if (graphicsPipelineThreadCount > MAX_GRAPHICS_PIPELINE_THREADS_COUNT) { + return true; + } + } + return false; + } + } + private ServiceThread createCleanUpThread() { final ServiceThread handlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_LOWEST, true /*allowIo*/); @@ -1307,9 +1331,9 @@ public final class HintManagerService extends SystemService { @VisibleForTesting final class BinderService extends IHintManager.Stub { @Override - public IHintSession createHintSessionWithConfig(@NonNull IBinder token, - @SessionTag int tag, SessionCreationConfig creationConfig, - SessionConfig config) { + public IHintManager.SessionCreationReturn createHintSessionWithConfig( + @NonNull IBinder token, @SessionTag int tag, + SessionCreationConfig creationConfig, SessionConfig config) { if (!isHintSessionSupported()) { throw new UnsupportedOperationException("PowerHintSessions are not supported!"); } @@ -1327,8 +1351,24 @@ public final class HintManagerService extends SystemService { final long identity = Binder.clearCallingIdentity(); final long durationNanos = creationConfig.targetWorkDurationNanos; - Preconditions.checkArgument(checkGraphicsPipelineValid(creationConfig, callingUid), - "not enough of available graphics pipeline thread."); + boolean isGraphicsPipeline = false; + boolean isAutoTimed = false; + if (creationConfig.modesToEnable != null) { + for (int mode : creationConfig.modesToEnable) { + if (mode == SessionMode.GRAPHICS_PIPELINE) { + isGraphicsPipeline = true; + } + if (mode == SessionMode.AUTO_CPU || mode == SessionMode.AUTO_GPU) { + isAutoTimed = true; + } + } + } + + if (isAutoTimed) { + Preconditions.checkArgument(isGraphicsPipeline, + "graphics pipeline mode not enabled for an automatically timed session"); + } + try { final IntArray nonIsolated = powerhintThreadCleanup() ? new IntArray(tids.length) : null; @@ -1446,12 +1486,8 @@ public final class HintManagerService extends SystemService { } if (hs != null) { - boolean isGraphicsPipeline = false; if (creationConfig.modesToEnable != null) { for (int sessionMode : creationConfig.modesToEnable) { - if (sessionMode == SessionModes.GRAPHICS_PIPELINE.ordinal()) { - isGraphicsPipeline = true; - } hs.setMode(sessionMode, true); } } @@ -1470,7 +1506,10 @@ public final class HintManagerService extends SystemService { } } - return hs; + IHintManager.SessionCreationReturn out = new IHintManager.SessionCreationReturn(); + out.pipelineThreadLimitExceeded = tooManyPipelineThreads(callingUid); + out.session = hs; + return out; } finally { Binder.restoreCallingIdentity(identity); } @@ -1852,45 +1891,6 @@ public final class HintManagerService extends SystemService { throw new IllegalStateException("Can't find cpu line in " + filePath); } - private boolean checkGraphicsPipelineValid(SessionCreationConfig creationConfig, int uid) { - if (creationConfig.modesToEnable == null) { - return true; - } - boolean setGraphicsPipeline = false; - for (int modeToEnable : creationConfig.modesToEnable) { - if (modeToEnable == SessionModes.GRAPHICS_PIPELINE.ordinal()) { - setGraphicsPipeline = true; - } - } - if (!setGraphicsPipeline) { - return true; - } - - synchronized (mThreadsUsageObject) { - // count used graphics pipeline threads for the calling UID - // consider the case that new tids are overlapping with in session tids - ArraySet<ThreadUsageTracker> threadsSet = mThreadsUsageMap.get(uid); - if (threadsSet == null) { - return true; - } - - final int newThreadCount = creationConfig.tids.length; - int graphicsPipelineThreadCount = 0; - for (ThreadUsageTracker t : threadsSet) { - // count graphics pipeline threads in use - // and exclude overlapping ones - if (t.isGraphicsPipeline()) { - graphicsPipelineThreadCount++; - if (contains(creationConfig.tids, t.getTid())) { - graphicsPipelineThreadCount--; - } - } - } - return graphicsPipelineThreadCount + newThreadCount - <= MAX_GRAPHICS_PIPELINE_THREADS_COUNT; - } - } - private void logPerformanceHintSessionAtom(int uid, long sessionId, long targetDuration, int[] tids, @SessionTag int sessionTag) { FrameworkStatsLog.write(FrameworkStatsLog.PERFORMANCE_HINT_SESSION_REPORTED, uid, @@ -1928,11 +1928,6 @@ public final class HintManagerService extends SystemService { protected Integer mSessionId; protected boolean mTrackedBySF; - enum SessionModes { - POWER_EFFICIENCY, - GRAPHICS_PIPELINE, - }; - protected AppHintSession( int uid, int pid, int sessionTag, int[] threadIds, IBinder token, long halSessionPtr, long durationNanos, Integer sessionId) { @@ -1985,8 +1980,8 @@ public final class HintManagerService extends SystemService { if (!isHintAllowed()) { return; } - Preconditions.checkArgument(targetDurationNanos > 0, "Expected" - + " the target duration to be greater than 0."); + Preconditions.checkArgument(targetDurationNanos >= 0, "Expected" + + " the target duration to be greater than or equal to 0."); mNativeWrapper.halUpdateTargetWorkDuration(mHalSessionPtr, targetDurationNanos); mTargetDurationNanos = targetDurationNanos; } @@ -2149,6 +2144,11 @@ public final class HintManagerService extends SystemService { public void setThreads(@NonNull int[] tids) { setThreadsInternal(tids, true); + if (tooManyPipelineThreads(Binder.getCallingUid())) { + // This is technically a success but we are going to throw a fit anyway + throw new ServiceSpecificException(5, + "Not enough available graphics pipeline threads."); + } } private void setThreadsInternal(int[] tids, boolean checkTid) { @@ -2156,32 +2156,7 @@ public final class HintManagerService extends SystemService { throw new IllegalArgumentException("Thread id list can't be empty."); } - final int callingUid = Binder.getCallingUid(); - if (mGraphicsPipeline) { - synchronized (mThreadsUsageObject) { - // replace original tids with new tids - ArraySet<ThreadUsageTracker> threadsSet = mThreadsUsageMap.get(callingUid); - int graphicsPipelineThreadCount = 0; - if (threadsSet != null) { - // We count the graphics pipeline threads that are - // *not* in this session, since those in this session - // will be replaced. Then if the count plus the new tids - // is over max available graphics pipeline threads we raise - // an exception. - for (ThreadUsageTracker t : threadsSet) { - if (t.isGraphicsPipeline() && !contains(mThreadIds, t.getTid())) { - graphicsPipelineThreadCount++; - } - } - if (graphicsPipelineThreadCount + tids.length - > MAX_GRAPHICS_PIPELINE_THREADS_COUNT) { - throw new IllegalArgumentException( - "Not enough available graphics pipeline threads."); - } - } - } - } synchronized (this) { if (mHalSessionPtr == 0) { @@ -2315,15 +2290,15 @@ public final class HintManagerService extends SystemService { } Preconditions.checkArgument(mode >= 0, "the mode Id value should be" + " greater than zero."); - if (mode == SessionModes.POWER_EFFICIENCY.ordinal()) { + if (mode == SessionMode.POWER_EFFICIENCY) { mPowerEfficient = enabled; - } else if (mode == SessionModes.GRAPHICS_PIPELINE.ordinal()) { + } else if (mode == SessionMode.GRAPHICS_PIPELINE) { mGraphicsPipeline = enabled; } mNativeWrapper.halSetMode(mHalSessionPtr, mode, enabled); } if (enabled) { - if (mode == SessionModes.POWER_EFFICIENCY.ordinal()) { + if (mode == SessionMode.POWER_EFFICIENCY) { if (!mHasBeenPowerEfficient) { mHasBeenPowerEfficient = true; synchronized (mSessionSnapshotMapLock) { @@ -2342,7 +2317,7 @@ public final class HintManagerService extends SystemService { sessionSnapshot.logPowerEfficientSession(); } } - } else if (mode == SessionModes.GRAPHICS_PIPELINE.ordinal()) { + } else if (mode == SessionMode.GRAPHICS_PIPELINE) { if (!mHasBeenGraphicsPipeline) { mHasBeenGraphicsPipeline = true; synchronized (mSessionSnapshotMapLock) { diff --git a/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java b/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java index de6f9bd7527a..bd15bd058fcc 100644 --- a/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java +++ b/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java @@ -391,19 +391,19 @@ public class HintManagerServiceTest { makeSessionCreationConfig(SESSION_TIDS_A, DEFAULT_TARGET_DURATION); IHintSession a = service.getBinderServiceInstance().createHintSessionWithConfig(token, - SessionTag.OTHER, creationConfig, new SessionConfig()); + SessionTag.OTHER, creationConfig, new SessionConfig()).session; assertNotNull(a); creationConfig.tids = SESSION_TIDS_B; creationConfig.targetWorkDurationNanos = DOUBLED_TARGET_DURATION; IHintSession b = service.getBinderServiceInstance().createHintSessionWithConfig(token, - SessionTag.OTHER, creationConfig, new SessionConfig()); + SessionTag.OTHER, creationConfig, new SessionConfig()).session; assertNotEquals(a, b); creationConfig.tids = SESSION_TIDS_C; creationConfig.targetWorkDurationNanos = 0L; IHintSession c = service.getBinderServiceInstance().createHintSessionWithConfig(token, - SessionTag.OTHER, creationConfig, new SessionConfig()); + SessionTag.OTHER, creationConfig, new SessionConfig()).session; assertNotNull(c); verify(mNativeWrapperMock, times(3)).halCreateHintSession(anyInt(), anyInt(), any(int[].class), anyLong()); @@ -418,7 +418,7 @@ public class HintManagerServiceTest { SessionConfig config = new SessionConfig(); IHintSession a = service.getBinderServiceInstance().createHintSessionWithConfig(token, - SessionTag.OTHER, creationConfig, config); + SessionTag.OTHER, creationConfig, config).session; assertNotNull(a); assertEquals(SESSION_IDS[0], config.id); @@ -426,7 +426,7 @@ public class HintManagerServiceTest { creationConfig.tids = SESSION_TIDS_B; creationConfig.targetWorkDurationNanos = DOUBLED_TARGET_DURATION; IHintSession b = service.getBinderServiceInstance().createHintSessionWithConfig(token, - SessionTag.APP, creationConfig, config2); + SessionTag.APP, creationConfig, config2).session; assertNotEquals(a, b); assertEquals(SESSION_IDS[1], config2.id); @@ -434,7 +434,7 @@ public class HintManagerServiceTest { creationConfig.tids = SESSION_TIDS_C; creationConfig.targetWorkDurationNanos = 0L; IHintSession c = service.getBinderServiceInstance().createHintSessionWithConfig(token, - SessionTag.GAME, creationConfig, config3); + SessionTag.GAME, creationConfig, config3).session; assertNotNull(c); assertEquals(SESSION_IDS[2], config3.id); verify(mNativeWrapperMock, times(3)).halCreateHintSessionWithConfig(anyInt(), anyInt(), @@ -465,16 +465,14 @@ public class HintManagerServiceTest { SessionConfig config = new SessionConfig(); IHintSession a = service.getBinderServiceInstance().createHintSessionWithConfig(token, - SessionTag.OTHER, creationConfig, config); + SessionTag.OTHER, creationConfig, config).session; assertNotNull(a); assertEquals(sessionId1, config.id); creationConfig.tids = createThreads(1, stopLatch1); - assertThrows(IllegalArgumentException.class, () -> { - service.getBinderServiceInstance().createHintSessionWithConfig(token, - SessionTag.OTHER, creationConfig, config); - }); + assertEquals(service.getBinderServiceInstance().createHintSessionWithConfig(token, + SessionTag.OTHER, creationConfig, config).pipelineThreadLimitExceeded, true); } @Test @@ -486,7 +484,7 @@ public class HintManagerServiceTest { AppHintSession a = (AppHintSession) service.getBinderServiceInstance() .createHintSessionWithConfig(token, SessionTag.OTHER, - creationConfig, new SessionConfig()); + creationConfig, new SessionConfig()).session; // Set session to background and calling updateHintAllowedByProcState() would invoke // pause(); @@ -526,7 +524,7 @@ public class HintManagerServiceTest { makeSessionCreationConfig(SESSION_TIDS_A, DEFAULT_TARGET_DURATION); IHintSession a = service.getBinderServiceInstance().createHintSessionWithConfig(token, - SessionTag.OTHER, creationConfig, new SessionConfig()); + SessionTag.OTHER, creationConfig, new SessionConfig()).session; a.close(); verify(mNativeWrapperMock, times(1)).halCloseHintSession(anyLong()); @@ -540,16 +538,12 @@ public class HintManagerServiceTest { makeSessionCreationConfig(SESSION_TIDS_A, DEFAULT_TARGET_DURATION); IHintSession a = service.getBinderServiceInstance().createHintSessionWithConfig(token, - SessionTag.OTHER, creationConfig, new SessionConfig()); + SessionTag.OTHER, creationConfig, new SessionConfig()).session; assertThrows(IllegalArgumentException.class, () -> { a.updateTargetWorkDuration(-1L); }); - assertThrows(IllegalArgumentException.class, () -> { - a.updateTargetWorkDuration(0L); - }); - a.updateTargetWorkDuration(100L); verify(mNativeWrapperMock, times(1)).halUpdateTargetWorkDuration(anyLong(), eq(100L)); } @@ -563,7 +557,7 @@ public class HintManagerServiceTest { AppHintSession a = (AppHintSession) service.getBinderServiceInstance() .createHintSessionWithConfig(token, SessionTag.OTHER, - creationConfig, new SessionConfig()); + creationConfig, new SessionConfig()).session; a.updateTargetWorkDuration(100L); a.reportActualWorkDuration(DURATIONS_THREE, TIMESTAMPS_THREE); @@ -608,7 +602,7 @@ public class HintManagerServiceTest { AppHintSession a = (AppHintSession) service.getBinderServiceInstance() .createHintSessionWithConfig(token, SessionTag.OTHER, - creationConfig, new SessionConfig()); + creationConfig, new SessionConfig()).session; a.sendHint(PerformanceHintManager.Session.CPU_LOAD_RESET); verify(mNativeWrapperMock, times(1)).halSendHint(anyLong(), @@ -637,7 +631,7 @@ public class HintManagerServiceTest { AppHintSession a = (AppHintSession) service.getBinderServiceInstance() .createHintSessionWithConfig(token, SessionTag.OTHER, - creationConfig, new SessionConfig()); + creationConfig, new SessionConfig()).session; service.mUidObserver.onUidStateChanged( a.mUid, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND, 0, 0); @@ -661,7 +655,7 @@ public class HintManagerServiceTest { AppHintSession a = (AppHintSession) service.getBinderServiceInstance() .createHintSessionWithConfig(token, SessionTag.OTHER, - creationConfig, new SessionConfig()); + creationConfig, new SessionConfig()).session; service.mUidObserver.onUidStateChanged( a.mUid, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 0, 0); @@ -677,7 +671,7 @@ public class HintManagerServiceTest { AppHintSession a = (AppHintSession) service.getBinderServiceInstance() .createHintSessionWithConfig(token, SessionTag.OTHER, - creationConfig, new SessionConfig()); + creationConfig, new SessionConfig()).session; a.updateTargetWorkDuration(100L); @@ -717,7 +711,7 @@ public class HintManagerServiceTest { makeSessionCreationConfig(tids1, DEFAULT_TARGET_DURATION); AppHintSession session1 = (AppHintSession) service.getBinderServiceInstance() .createHintSessionWithConfig(token, SessionTag.OTHER, - creationConfig, new SessionConfig()); + creationConfig, new SessionConfig()).session; assertNotNull(session1); // trigger UID state change by making the process foreground->background, but because the @@ -754,7 +748,7 @@ public class HintManagerServiceTest { makeSessionCreationConfig(tids1, DEFAULT_TARGET_DURATION); AppHintSession session1 = (AppHintSession) service.getBinderServiceInstance() .createHintSessionWithConfig(token, SessionTag.OTHER, - creationConfig, new SessionConfig()); + creationConfig, new SessionConfig()).session; assertNotNull(session1); // let all session 1 threads to exit and the cleanup should force pause the session 1 @@ -865,7 +859,7 @@ public class HintManagerServiceTest { AppHintSession a = (AppHintSession) service.getBinderServiceInstance() .createHintSessionWithConfig(token, SessionTag.OTHER, - creationConfig, new SessionConfig()); + creationConfig, new SessionConfig()).session; a.setMode(0, true); verify(mNativeWrapperMock, times(1)).halSetMode(anyLong(), @@ -885,7 +879,7 @@ public class HintManagerServiceTest { AppHintSession a = (AppHintSession) service.getBinderServiceInstance() .createHintSessionWithConfig(token, SessionTag.OTHER, - creationConfig, new SessionConfig()); + creationConfig, new SessionConfig()).session; // Set session to background, then the duration would not be updated. service.mUidObserver.onUidStateChanged( @@ -906,7 +900,7 @@ public class HintManagerServiceTest { AppHintSession a = (AppHintSession) service.getBinderServiceInstance() .createHintSessionWithConfig(token, SessionTag.OTHER, - creationConfig, new SessionConfig()); + creationConfig, new SessionConfig()).session; assertThrows(IllegalArgumentException.class, () -> { a.setMode(-1, true); @@ -923,7 +917,7 @@ public class HintManagerServiceTest { AppHintSession a = (AppHintSession) service.getBinderServiceInstance() .createHintSessionWithConfig(token, SessionTag.OTHER, - creationConfig, new SessionConfig()); + creationConfig, new SessionConfig()).session; assertNotNull(a); verify(mNativeWrapperMock, times(1)).halSetMode(anyLong(), eq(0), eq(true)); @@ -1124,7 +1118,7 @@ public class HintManagerServiceTest { AppHintSession a = (AppHintSession) service.getBinderServiceInstance() .createHintSessionWithConfig(token, SessionTag.OTHER, - creationConfig, new SessionConfig()); + creationConfig, new SessionConfig()).session; // we will start some threads and get their valid TIDs to update int threadCount = 3; // the list of TIDs @@ -1194,7 +1188,7 @@ public class HintManagerServiceTest { AppHintSession a = (AppHintSession) service.getBinderServiceInstance() .createHintSessionWithConfig(token, SessionTag.OTHER, - creationConfig, new SessionConfig()); + creationConfig, new SessionConfig()).session; a.updateTargetWorkDuration(100L); a.reportActualWorkDuration2(WORK_DURATIONS_FIVE); |