Loading core/java/android/os/IHintManager.aidl +6 −0 Original line number Diff line number Diff line Loading @@ -64,4 +64,10 @@ interface IHintManager { * Get Maximum number of graphics pipeline threads allowed per-app. */ int getMaxGraphicsPipelineThreadsCount(); /** * Used by the JNI to pass an interface to the SessionManager; * for internal use only. */ oneway void passSessionManagerBinder(in IBinder sessionManager); } core/java/android/os/IHintSession.aidl +5 −0 Original line number Diff line number Diff line Loading @@ -27,4 +27,9 @@ oneway interface IHintSession { void sendHint(int hint); void setMode(int mode, boolean enabled); void reportActualWorkDuration2(in WorkDuration[] workDurations); /** * Used by apps to associate a session to a given set of layers */ oneway void associateToLayers(in IBinder[] layerTokens); } core/java/android/os/SessionCreationConfig.aidl +8 −0 Original line number Diff line number Diff line Loading @@ -36,4 +36,12 @@ parcelable SessionCreationConfig { * List of the modes to be enabled upon session creation. */ SessionMode[] modesToEnable; /** * List of layers to attach this session to. * * Note: DO NOT STORE THESE IN HintSessionManager, as * it will break the layer lifecycle. */ IBinder[] layerTokens; } native/android/libandroid.map.txt +3 −0 Original line number Diff line number Diff line Loading @@ -376,6 +376,7 @@ LIBANDROID { APerformanceHint_notifyWorkloadIncrease; # introduced=36 APerformanceHint_notifyWorkloadReset; # introduced=36 APerformanceHint_borrowSessionFromJava; # introduced=36 APerformanceHint_setNativeSurfaces; # introduced=36 AWorkDuration_create; # introduced=VanillaIceCream AWorkDuration_release; # introduced=VanillaIceCream AWorkDuration_setWorkPeriodStartTimestampNanos; # introduced=VanillaIceCream Loading @@ -388,6 +389,8 @@ LIBANDROID { ASessionCreationConfig_setTargetWorkDurationNanos; # introduced=36 ASessionCreationConfig_setPreferPowerEfficiency; # introduced=36 ASessionCreationConfig_setGraphicsPipeline; # introduced=36 ASessionCreationConfig_setNativeSurfaces; # introduced=36 ASessionCreationConfig_setUseAutoTiming; # introduced=36 local: *; }; Loading native/android/performance_hint.cpp +151 −9 Original line number Diff line number Diff line Loading @@ -29,13 +29,19 @@ #include <aidl/android/os/SessionCreationConfig.h> #include <android-base/stringprintf.h> #include <android-base/thread_annotations.h> #include <android/binder_libbinder.h> #include <android/binder_manager.h> #include <android/binder_status.h> #include <android/native_window.h> #include <android/performance_hint.h> #include <android/surface_control.h> #include <android/trace.h> #include <android_os.h> #include <cutils/trace.h> #include <fmq/AidlMessageQueue.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> #include <gui/SurfaceControl.h> #include <inttypes.h> #include <jni_wrappers.h> #include <performance_hint_private.h> Loading Loading @@ -66,7 +72,12 @@ struct APerformanceHintSession; constexpr int64_t SEND_HINT_TIMEOUT = std::chrono::nanoseconds(100ms).count(); struct AWorkDuration : public hal::WorkDuration {}; struct ASessionCreationConfig : public SessionCreationConfig {}; struct ASessionCreationConfig : public SessionCreationConfig { std::vector<wp<IBinder>> layers{}; bool hasMode(hal::SessionMode&& mode) { return std::find(modesToEnable.begin(), modesToEnable.end(), mode) != modesToEnable.end(); } }; bool kForceGraphicsPipeline = false; Loading Loading @@ -158,6 +169,11 @@ public: FMQWrapper& getFMQWrapper(); bool canSendLoadHints(std::vector<hal::SessionHint>& hints, int64_t now) REQUIRES(sHintMutex); void initJava(JNIEnv* _Nonnull env); ndk::ScopedAIBinder_Weak x; template <class T> static void layersFromNativeSurfaces(ANativeWindow** windows, int numWindows, ASurfaceControl** controls, int numSurfaceControls, std::vector<T>& out); private: // Necessary to create an empty binder object Loading Loading @@ -203,6 +219,8 @@ public: int setPreferPowerEfficiency(bool enabled); int reportActualWorkDuration(AWorkDuration* workDuration); bool isJava(); status_t setNativeSurfaces(ANativeWindow** windows, int numWindows, ASurfaceControl** controls, int numSurfaceControls); private: friend struct APerformanceHintManager; Loading Loading @@ -231,7 +249,7 @@ private: static int64_t sIDCounter GUARDED_BY(sHintMutex); // The most recent set of thread IDs std::vector<int32_t> mLastThreadIDs GUARDED_BY(sHintMutex); std::optional<hal::SessionConfig> mSessionConfig GUARDED_BY(sHintMutex); std::optional<hal::SessionConfig> mSessionConfig; // Tracing helpers void traceThreads(const std::vector<int32_t>& tids) REQUIRES(sHintMutex); void tracePowerEfficient(bool powerEfficient); Loading Loading @@ -329,14 +347,12 @@ APerformanceHintSession* APerformanceHintManager::createSession( ndk::ScopedAStatus ret; hal::SessionConfig sessionConfig{.id = -1}; SessionCreationConfig creationConfig{ ASessionCreationConfig creationConfig{{ .tids = std::vector<int32_t>(threadIds, threadIds + size), .targetWorkDurationNanos = initialTargetWorkDurationNanos, }; }}; return APerformanceHintManager::createSessionUsingConfig(static_cast<ASessionCreationConfig*>( &creationConfig), tag, isJava); return APerformanceHintManager::createSessionUsingConfig(&creationConfig, tag, isJava); } APerformanceHintSession* APerformanceHintManager::createSessionUsingConfig( Loading @@ -345,11 +361,29 @@ APerformanceHintSession* APerformanceHintManager::createSessionUsingConfig( hal::SessionConfig sessionConfig{.id = -1}; ndk::ScopedAStatus ret; // Hold the tokens weakly until we actually need them, // then promote them, then drop all strong refs after if (!sessionCreationConfig->layers.empty()) { for (auto&& layerIter = sessionCreationConfig->layers.begin(); layerIter != sessionCreationConfig->layers.end();) { sp<IBinder> promoted = layerIter->promote(); if (promoted == nullptr) { layerIter = sessionCreationConfig->layers.erase(layerIter); } else { sessionCreationConfig->layerTokens.push_back( ndk::SpAIBinder(AIBinder_fromPlatformBinder(promoted.get()))); ++layerIter; } } } ret = mHintManager->createHintSessionWithConfig(mToken, tag, *static_cast<SessionCreationConfig*>( sessionCreationConfig), &sessionConfig, &session); sessionCreationConfig->layerTokens.clear(); if (!ret.isOk() || !session) { ALOGE("%s: PerformanceHint cannot create session. %s", __FUNCTION__, ret.getMessage()); return nullptr; Loading Loading @@ -679,6 +713,57 @@ int APerformanceHintSession::reportActualWorkDurationInternal(AWorkDuration* wor return 0; } status_t APerformanceHintSession::setNativeSurfaces(ANativeWindow** windows, int numWindows, ASurfaceControl** controls, int numSurfaceControls) { if (!mSessionConfig.has_value()) { return ENOTSUP; } std::vector<sp<IBinder>> layerHandles; APerformanceHintManager::layersFromNativeSurfaces<sp<IBinder>>(windows, numWindows, controls, numSurfaceControls, layerHandles); std::vector<ndk::SpAIBinder> ndkLayerHandles; for (auto&& handle : layerHandles) { ndkLayerHandles.emplace_back(ndk::SpAIBinder(AIBinder_fromPlatformBinder(handle))); } mHintSession->associateToLayers(ndkLayerHandles); return 0; } template <class T> void APerformanceHintManager::layersFromNativeSurfaces(ANativeWindow** windows, int numWindows, ASurfaceControl** controls, int numSurfaceControls, std::vector<T>& out) { std::scoped_lock lock(sHintMutex); if (windows != nullptr) { std::vector<ANativeWindow*> windowVec(windows, windows + numWindows); for (auto&& window : windowVec) { Surface* surface = static_cast<Surface*>(window); if (Surface::isValid(surface)) { const sp<IBinder>& handle = surface->getSurfaceControlHandle(); if (handle != nullptr) { out.push_back(handle); } } } } if (controls != nullptr) { std::vector<ASurfaceControl*> controlVec(controls, controls + numSurfaceControls); for (auto&& aSurfaceControl : controlVec) { SurfaceControl* control = reinterpret_cast<SurfaceControl*>(aSurfaceControl); if (control->isValid()) { out.push_back(control->getHandle()); } } } } // ===================================== FMQ wrapper implementation bool FMQWrapper::isActive() { Loading Loading @@ -963,8 +1048,7 @@ APerformanceHintSession* APerformanceHint_createSessionFromJava( hal::SessionTag::APP, true); } APerformanceHintSession* APerformanceHint_borrowSessionFromJava(JNIEnv* env, jobject sessionObj) { APerformanceHintSession* APerformanceHint_borrowSessionFromJava(JNIEnv* env, jobject sessionObj) { VALIDATE_PTR(env) VALIDATE_PTR(sessionObj) return APerformanceHintManager::getInstance()->getSessionFromJava(env, sessionObj); Loading Loading @@ -1065,6 +1149,14 @@ int APerformanceHint_notifyWorkloadReset(APerformanceHintSession* session, bool return session->notifyWorkloadReset(cpu, gpu, debugName); } int APerformanceHint_setNativeSurfaces(APerformanceHintSession* session, ANativeWindow** nativeWindows, int nativeWindowsSize, ASurfaceControl** surfaceControls, int surfaceControlsSize) { VALIDATE_PTR(session) return session->setNativeSurfaces(nativeWindows, nativeWindowsSize, surfaceControls, surfaceControlsSize); } AWorkDuration* AWorkDuration_create() { return new AWorkDuration(); } Loading Loading @@ -1180,6 +1272,11 @@ int ASessionCreationConfig_setGraphicsPipeline(ASessionCreationConfig* config, b 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; } Loading @@ -1197,3 +1294,48 @@ void APerformanceHint_getRateLimiterPropertiesForTesting(int32_t* maxLoadHintsPe void APerformanceHint_setUseNewLoadHintBehaviorForTesting(bool newBehavior) { kForceNewHintBehavior = newBehavior; } int ASessionCreationConfig_setNativeSurfaces(ASessionCreationConfig* config, ANativeWindow** nativeWindows, int nativeWindowsSize, ASurfaceControl** surfaceControls, int 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) { 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; } Loading
core/java/android/os/IHintManager.aidl +6 −0 Original line number Diff line number Diff line Loading @@ -64,4 +64,10 @@ interface IHintManager { * Get Maximum number of graphics pipeline threads allowed per-app. */ int getMaxGraphicsPipelineThreadsCount(); /** * Used by the JNI to pass an interface to the SessionManager; * for internal use only. */ oneway void passSessionManagerBinder(in IBinder sessionManager); }
core/java/android/os/IHintSession.aidl +5 −0 Original line number Diff line number Diff line Loading @@ -27,4 +27,9 @@ oneway interface IHintSession { void sendHint(int hint); void setMode(int mode, boolean enabled); void reportActualWorkDuration2(in WorkDuration[] workDurations); /** * Used by apps to associate a session to a given set of layers */ oneway void associateToLayers(in IBinder[] layerTokens); }
core/java/android/os/SessionCreationConfig.aidl +8 −0 Original line number Diff line number Diff line Loading @@ -36,4 +36,12 @@ parcelable SessionCreationConfig { * List of the modes to be enabled upon session creation. */ SessionMode[] modesToEnable; /** * List of layers to attach this session to. * * Note: DO NOT STORE THESE IN HintSessionManager, as * it will break the layer lifecycle. */ IBinder[] layerTokens; }
native/android/libandroid.map.txt +3 −0 Original line number Diff line number Diff line Loading @@ -376,6 +376,7 @@ LIBANDROID { APerformanceHint_notifyWorkloadIncrease; # introduced=36 APerformanceHint_notifyWorkloadReset; # introduced=36 APerformanceHint_borrowSessionFromJava; # introduced=36 APerformanceHint_setNativeSurfaces; # introduced=36 AWorkDuration_create; # introduced=VanillaIceCream AWorkDuration_release; # introduced=VanillaIceCream AWorkDuration_setWorkPeriodStartTimestampNanos; # introduced=VanillaIceCream Loading @@ -388,6 +389,8 @@ LIBANDROID { ASessionCreationConfig_setTargetWorkDurationNanos; # introduced=36 ASessionCreationConfig_setPreferPowerEfficiency; # introduced=36 ASessionCreationConfig_setGraphicsPipeline; # introduced=36 ASessionCreationConfig_setNativeSurfaces; # introduced=36 ASessionCreationConfig_setUseAutoTiming; # introduced=36 local: *; }; Loading
native/android/performance_hint.cpp +151 −9 Original line number Diff line number Diff line Loading @@ -29,13 +29,19 @@ #include <aidl/android/os/SessionCreationConfig.h> #include <android-base/stringprintf.h> #include <android-base/thread_annotations.h> #include <android/binder_libbinder.h> #include <android/binder_manager.h> #include <android/binder_status.h> #include <android/native_window.h> #include <android/performance_hint.h> #include <android/surface_control.h> #include <android/trace.h> #include <android_os.h> #include <cutils/trace.h> #include <fmq/AidlMessageQueue.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> #include <gui/SurfaceControl.h> #include <inttypes.h> #include <jni_wrappers.h> #include <performance_hint_private.h> Loading Loading @@ -66,7 +72,12 @@ struct APerformanceHintSession; constexpr int64_t SEND_HINT_TIMEOUT = std::chrono::nanoseconds(100ms).count(); struct AWorkDuration : public hal::WorkDuration {}; struct ASessionCreationConfig : public SessionCreationConfig {}; struct ASessionCreationConfig : public SessionCreationConfig { std::vector<wp<IBinder>> layers{}; bool hasMode(hal::SessionMode&& mode) { return std::find(modesToEnable.begin(), modesToEnable.end(), mode) != modesToEnable.end(); } }; bool kForceGraphicsPipeline = false; Loading Loading @@ -158,6 +169,11 @@ public: FMQWrapper& getFMQWrapper(); bool canSendLoadHints(std::vector<hal::SessionHint>& hints, int64_t now) REQUIRES(sHintMutex); void initJava(JNIEnv* _Nonnull env); ndk::ScopedAIBinder_Weak x; template <class T> static void layersFromNativeSurfaces(ANativeWindow** windows, int numWindows, ASurfaceControl** controls, int numSurfaceControls, std::vector<T>& out); private: // Necessary to create an empty binder object Loading Loading @@ -203,6 +219,8 @@ public: int setPreferPowerEfficiency(bool enabled); int reportActualWorkDuration(AWorkDuration* workDuration); bool isJava(); status_t setNativeSurfaces(ANativeWindow** windows, int numWindows, ASurfaceControl** controls, int numSurfaceControls); private: friend struct APerformanceHintManager; Loading Loading @@ -231,7 +249,7 @@ private: static int64_t sIDCounter GUARDED_BY(sHintMutex); // The most recent set of thread IDs std::vector<int32_t> mLastThreadIDs GUARDED_BY(sHintMutex); std::optional<hal::SessionConfig> mSessionConfig GUARDED_BY(sHintMutex); std::optional<hal::SessionConfig> mSessionConfig; // Tracing helpers void traceThreads(const std::vector<int32_t>& tids) REQUIRES(sHintMutex); void tracePowerEfficient(bool powerEfficient); Loading Loading @@ -329,14 +347,12 @@ APerformanceHintSession* APerformanceHintManager::createSession( ndk::ScopedAStatus ret; hal::SessionConfig sessionConfig{.id = -1}; SessionCreationConfig creationConfig{ ASessionCreationConfig creationConfig{{ .tids = std::vector<int32_t>(threadIds, threadIds + size), .targetWorkDurationNanos = initialTargetWorkDurationNanos, }; }}; return APerformanceHintManager::createSessionUsingConfig(static_cast<ASessionCreationConfig*>( &creationConfig), tag, isJava); return APerformanceHintManager::createSessionUsingConfig(&creationConfig, tag, isJava); } APerformanceHintSession* APerformanceHintManager::createSessionUsingConfig( Loading @@ -345,11 +361,29 @@ APerformanceHintSession* APerformanceHintManager::createSessionUsingConfig( hal::SessionConfig sessionConfig{.id = -1}; ndk::ScopedAStatus ret; // Hold the tokens weakly until we actually need them, // then promote them, then drop all strong refs after if (!sessionCreationConfig->layers.empty()) { for (auto&& layerIter = sessionCreationConfig->layers.begin(); layerIter != sessionCreationConfig->layers.end();) { sp<IBinder> promoted = layerIter->promote(); if (promoted == nullptr) { layerIter = sessionCreationConfig->layers.erase(layerIter); } else { sessionCreationConfig->layerTokens.push_back( ndk::SpAIBinder(AIBinder_fromPlatformBinder(promoted.get()))); ++layerIter; } } } ret = mHintManager->createHintSessionWithConfig(mToken, tag, *static_cast<SessionCreationConfig*>( sessionCreationConfig), &sessionConfig, &session); sessionCreationConfig->layerTokens.clear(); if (!ret.isOk() || !session) { ALOGE("%s: PerformanceHint cannot create session. %s", __FUNCTION__, ret.getMessage()); return nullptr; Loading Loading @@ -679,6 +713,57 @@ int APerformanceHintSession::reportActualWorkDurationInternal(AWorkDuration* wor return 0; } status_t APerformanceHintSession::setNativeSurfaces(ANativeWindow** windows, int numWindows, ASurfaceControl** controls, int numSurfaceControls) { if (!mSessionConfig.has_value()) { return ENOTSUP; } std::vector<sp<IBinder>> layerHandles; APerformanceHintManager::layersFromNativeSurfaces<sp<IBinder>>(windows, numWindows, controls, numSurfaceControls, layerHandles); std::vector<ndk::SpAIBinder> ndkLayerHandles; for (auto&& handle : layerHandles) { ndkLayerHandles.emplace_back(ndk::SpAIBinder(AIBinder_fromPlatformBinder(handle))); } mHintSession->associateToLayers(ndkLayerHandles); return 0; } template <class T> void APerformanceHintManager::layersFromNativeSurfaces(ANativeWindow** windows, int numWindows, ASurfaceControl** controls, int numSurfaceControls, std::vector<T>& out) { std::scoped_lock lock(sHintMutex); if (windows != nullptr) { std::vector<ANativeWindow*> windowVec(windows, windows + numWindows); for (auto&& window : windowVec) { Surface* surface = static_cast<Surface*>(window); if (Surface::isValid(surface)) { const sp<IBinder>& handle = surface->getSurfaceControlHandle(); if (handle != nullptr) { out.push_back(handle); } } } } if (controls != nullptr) { std::vector<ASurfaceControl*> controlVec(controls, controls + numSurfaceControls); for (auto&& aSurfaceControl : controlVec) { SurfaceControl* control = reinterpret_cast<SurfaceControl*>(aSurfaceControl); if (control->isValid()) { out.push_back(control->getHandle()); } } } } // ===================================== FMQ wrapper implementation bool FMQWrapper::isActive() { Loading Loading @@ -963,8 +1048,7 @@ APerformanceHintSession* APerformanceHint_createSessionFromJava( hal::SessionTag::APP, true); } APerformanceHintSession* APerformanceHint_borrowSessionFromJava(JNIEnv* env, jobject sessionObj) { APerformanceHintSession* APerformanceHint_borrowSessionFromJava(JNIEnv* env, jobject sessionObj) { VALIDATE_PTR(env) VALIDATE_PTR(sessionObj) return APerformanceHintManager::getInstance()->getSessionFromJava(env, sessionObj); Loading Loading @@ -1065,6 +1149,14 @@ int APerformanceHint_notifyWorkloadReset(APerformanceHintSession* session, bool return session->notifyWorkloadReset(cpu, gpu, debugName); } int APerformanceHint_setNativeSurfaces(APerformanceHintSession* session, ANativeWindow** nativeWindows, int nativeWindowsSize, ASurfaceControl** surfaceControls, int surfaceControlsSize) { VALIDATE_PTR(session) return session->setNativeSurfaces(nativeWindows, nativeWindowsSize, surfaceControls, surfaceControlsSize); } AWorkDuration* AWorkDuration_create() { return new AWorkDuration(); } Loading Loading @@ -1180,6 +1272,11 @@ int ASessionCreationConfig_setGraphicsPipeline(ASessionCreationConfig* config, b 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; } Loading @@ -1197,3 +1294,48 @@ void APerformanceHint_getRateLimiterPropertiesForTesting(int32_t* maxLoadHintsPe void APerformanceHint_setUseNewLoadHintBehaviorForTesting(bool newBehavior) { kForceNewHintBehavior = newBehavior; } int ASessionCreationConfig_setNativeSurfaces(ASessionCreationConfig* config, ANativeWindow** nativeWindows, int nativeWindowsSize, ASurfaceControl** surfaceControls, int 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) { 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; }