diff options
5 files changed, 260 insertions, 84 deletions
diff --git a/core/java/android/os/IHintManager.aidl b/core/java/android/os/IHintManager.aidl index 4a14a8d0faf8..56a089aff78a 100644 --- a/core/java/android/os/IHintManager.aidl +++ b/core/java/android/os/IHintManager.aidl @@ -21,11 +21,13 @@ import android.os.CpuHeadroomParamsInternal; import android.os.GpuHeadroomParamsInternal; import android.os.IHintSession; import android.os.SessionCreationConfig; -import android.hardware.power.CpuHeadroomResult; + import android.hardware.power.ChannelConfig; +import android.hardware.power.CpuHeadroomResult; import android.hardware.power.GpuHeadroomResult; import android.hardware.power.SessionConfig; import android.hardware.power.SessionTag; +import android.hardware.power.SupportInfo; /** {@hide} */ interface IHintManager { @@ -40,11 +42,6 @@ interface IHintManager { IHintSession createHintSessionWithConfig(in IBinder token, in SessionTag tag, in SessionCreationConfig creationConfig, out SessionConfig config); - /** - * Get preferred rate limit in nanoseconds. - */ - long getHintSessionPreferredRate(); - void setHintSessionThreads(in IHintSession hintSession, in int[] tids); int[] getHintSessionThreadIds(in IHintSession hintSession); @@ -61,13 +58,28 @@ interface IHintManager { 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; * for internal use only. */ 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); } diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp index 0db99ffd208a..9257901bcd1f 100644 --- a/native/android/performance_hint.cpp +++ b/native/android/performance_hint.cpp @@ -22,6 +22,7 @@ #include <aidl/android/hardware/power/SessionHint.h> #include <aidl/android/hardware/power/SessionMode.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/WorkDurationFixedV1.h> #include <aidl/android/os/IHintManager.h> @@ -148,10 +149,36 @@ private: 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 { public: 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(); @@ -169,29 +196,21 @@ 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); + ndk::SpAIBinder& getToken(); + SupportInfoWrapper& getSupportInfo(); 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); std::shared_ptr<IHintManager> mHintManager; + std::shared_ptr<HintManagerClient> mCallbackClient; + IHintManager::HintManagerClientData mClientData; + SupportInfoWrapper mSupportInfoWrapper; ndk::SpAIBinder mToken; - const int64_t mPreferredRateNanos; - std::optional<int32_t> mMaxGraphicsPipelineThreadsCount; FMQWrapper mFMQWrapper; double mHintBudget = kMaxLoadHintsPerInterval; int64_t mLastBudgetReplenish = 0; @@ -273,14 +292,27 @@ static FMQWrapper& getFMQ() { 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::APerformanceHintManager(std::shared_ptr<IHintManager>& manager, - int64_t preferredRateNanos) - : mHintManager(std::move(manager)), mPreferredRateNanos(preferredRateNanos) { - static AIBinder_Class* tokenBinderClass = - AIBinder_Class_define("phm_token", tokenStubOnCreate, tokenStubOnDestroy, - tokenStubOnTransact); - mToken = ndk::SpAIBinder(AIBinder_new(tokenBinderClass, nullptr)); + IHintManager::HintManagerClientData&& clientData, + std::shared_ptr<HintManagerClient> callbackClient) + : mHintManager(std::move(manager)), + mCallbackClient(callbackClient), + mClientData(clientData), + mSupportInfoWrapper(clientData.supportInfo), + mToken(callbackClient->asBinder()) { if (mFMQWrapper.isSupported()) { mFMQWrapper.setToken(mToken); mFMQWrapper.startChannel(mHintManager.get()); @@ -315,16 +347,17 @@ APerformanceHintManager* APerformanceHintManager::create(std::shared_ptr<IHintMa ALOGE("%s: PerformanceHint service is not ready ", __FUNCTION__); return nullptr; } - int64_t preferredRateNanos = -1L; - ndk::ScopedAStatus ret = manager->getHintSessionPreferredRate(&preferredRateNanos); + std::shared_ptr<HintManagerClient> client = ndk::SharedRefBase::make<HintManagerClient>(); + IHintManager::HintManagerClientData clientData; + ndk::ScopedAStatus ret = manager->registerClient(client, &clientData); 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; } - if (preferredRateNanos <= 0) { - preferredRateNanos = -1L; + if (clientData.preferredRateNanos <= 0) { + 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) { @@ -389,7 +422,9 @@ APerformanceHintSession* APerformanceHintManager::createSessionUsingConfig( ALOGE("%s: PerformanceHint cannot create session. %s", __FUNCTION__, ret.getMessage()); return nullptr; } - auto out = new APerformanceHintSession(mHintManager, std::move(session), mPreferredRateNanos, + + auto out = new APerformanceHintSession(mHintManager, std::move(session), + mClientData.preferredRateNanos, sessionCreationConfig->targetWorkDurationNanos, isJava, sessionConfig.id == -1 ? std::nullopt @@ -416,24 +451,11 @@ APerformanceHintSession* APerformanceHintManager::getSessionFromJava(JNIEnv* env } int64_t APerformanceHintManager::getPreferredRateNanos() const { - return mPreferredRateNanos; + return mClientData.preferredRateNanos; } int32_t APerformanceHintManager::getMaxGraphicsPipelineThreadsCount() { - if (!mMaxGraphicsPipelineThreadsCount.has_value()) { - 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(); + return mClientData.maxGraphicsPipelineThreads; } FMQWrapper& APerformanceHintManager::getFMQWrapper() { @@ -450,6 +472,14 @@ void APerformanceHintManager::initJava(JNIEnv* _Nonnull env) { mJavaInitialized = true; } +ndk::SpAIBinder& APerformanceHintManager::getToken() { + return mToken; +} + +SupportInfoWrapper& APerformanceHintManager::getSupportInfo() { + return mSupportInfoWrapper; +} + // ===================================== APerformanceHintSession implementation constexpr int kNumEnums = enum_size<hal::SessionHint>(); diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp index c166e738ffb2..e3c10f63abb4 100644 --- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp +++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp @@ -56,9 +56,6 @@ public: const SessionCreationConfig& creationConfig, hal::SessionConfig* config, std::shared_ptr<IHintSession>* _aidl_return), (override)); - MOCK_METHOD(ScopedAStatus, getHintSessionPreferredRate, (int64_t * _aidl_return), (override)); - MOCK_METHOD(ScopedAStatus, getMaxGraphicsPipelineThreadsCount, (int32_t* _aidl_return), - (override)); MOCK_METHOD(ScopedAStatus, setHintSessionThreads, (const std::shared_ptr<IHintSession>& hintSession, const ::std::vector<int32_t>& tids), @@ -84,6 +81,11 @@ public: MOCK_METHOD(ScopedAStatus, getGpuHeadroomMinIntervalMillis, (int64_t* _aidl_return), (override)); 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(bool, isRemote, (), (override)); }; @@ -125,10 +127,9 @@ public: APerformanceHintManager* createManager() { APerformanceHint_setUseFMQForTesting(mUsingFMQ); - ON_CALL(*mMockIHintManager, getHintSessionPreferredRate(_)) - .WillByDefault(DoAll(SetArgPointee<0>(123L), [] { return ScopedAStatus::ok(); })); - ON_CALL(*mMockIHintManager, getMaxGraphicsPipelineThreadsCount(_)) - .WillByDefault(DoAll(SetArgPointee<0>(5), [] { return ScopedAStatus::ok(); })); + ON_CALL(*mMockIHintManager, registerClient(_, _)) + .WillByDefault( + DoAll(SetArgPointee<1>(mClientData), [] { return ScopedAStatus::ok(); })); return APerformanceHint_getManager(); } @@ -238,6 +239,20 @@ public: int kMockQueueSize = 20; 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; int64_t mLoadHintInterval; @@ -256,12 +271,6 @@ bool equalsWithoutTimestamp(hal::WorkDuration lhs, hal::WorkDuration rhs) { 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) { APerformanceHintManager* manager = createManager(); APerformanceHintSession* session = createSession(manager); 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 7c7504dccf94..aae7417970eb 100644 --- a/services/core/java/com/android/server/power/hint/HintManagerService.java +++ b/services/core/java/com/android/server/power/hint/HintManagerService.java @@ -297,7 +297,11 @@ public final class HintManagerService extends SystemService { mPowerHalVersion = 0; mUsesFmq = false; if (mPowerHal != null) { - mSupportInfo = getSupportInfo(); + try { + mSupportInfo = getSupportInfo(); + } catch (RemoteException e) { + throw new IllegalStateException("Could not contact PowerHAL!", e); + } } mDefaultCpuHeadroomCalculationWindowMillis = new CpuHeadroomParamsInternal().calculationWindowMillis; @@ -315,7 +319,7 @@ public final class HintManagerService extends SystemService { } } - SupportInfo getSupportInfo() { + SupportInfo getSupportInfo() throws RemoteException { try { mPowerHalVersion = mPowerHal.getInterfaceVersion(); if (mPowerHalVersion >= 6) { @@ -326,9 +330,42 @@ public final class HintManagerService extends SystemService { } 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.isCpuSupported = false; supportInfo.headroom.isGpuSupported = false; + + supportInfo.compositionData = new SupportInfo.CompositionDataSupportInfo(); + 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; } @@ -1229,7 +1266,7 @@ public final class HintManagerService extends SystemService { @SessionTag int tag, SessionCreationConfig creationConfig, SessionConfig config) { if (!isHintSessionSupported()) { - throw new UnsupportedOperationException("PowerHAL is not supported!"); + throw new UnsupportedOperationException("PowerHintSessions are not supported!"); } java.util.Objects.requireNonNull(token); @@ -1425,12 +1462,6 @@ public final class HintManagerService extends SystemService { removeChannelItem(callingTgid, callingUid); }; - @Override - public long getHintSessionPreferredRate() { - return mHintSessionPreferredRate; - } - - @Override public int getMaxGraphicsPipelineThreadsCount() { return MAX_GRAPHICS_PIPELINE_THREADS_COUNT; } @@ -1621,13 +1652,24 @@ public final class HintManagerService extends SystemService { } @Override + 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 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) { return; } pw.println("HintSessionPreferredRate: " + mHintSessionPreferredRate); pw.println("MaxGraphicsPipelineThreadsCount: " + MAX_GRAPHICS_PIPELINE_THREADS_COUNT); - pw.println("HAL Support: " + isHintSessionSupported()); + pw.println("Hint Session Support: " + isHintSessionSupported()); pw.println("Active Sessions:"); synchronized (mLock) { for (int i = 0; i < mActiveSessions.size(); i++) { 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 5c73fd33f46f..4b2e850d08e7 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 @@ -64,6 +64,7 @@ import android.os.Binder; import android.os.CpuHeadroomParamsInternal; import android.os.GpuHeadroomParamsInternal; import android.os.IBinder; +import android.os.IHintManager; import android.os.IHintSession; import android.os.PerformanceHintManager; import android.os.Process; @@ -154,6 +155,8 @@ public class HintManagerServiceTest { private ActivityManagerInternal mAmInternalMock; @Mock private PackageManager mMockPackageManager; + @Mock + private IHintManager.IHintManagerClient mClientCallback; @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @@ -171,6 +174,24 @@ 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; + mSupportInfo.compositionData = new SupportInfo.CompositionDataSupportInfo(); + return mSupportInfo; + } + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); @@ -181,12 +202,7 @@ public class HintManagerServiceTest { mConfig.eventFlagDescriptor = new MQDescriptor<Byte, Byte>(); ApplicationInfo applicationInfo = new ApplicationInfo(); applicationInfo.category = ApplicationInfo.CATEGORY_GAME; - mSupportInfo = new SupportInfo(); - mSupportInfo.headroom = new SupportInfo.HeadroomSupportInfo(); - mSupportInfo.headroom.isCpuSupported = true; - mSupportInfo.headroom.cpuMinIntervalMillis = 2000; - mSupportInfo.headroom.isGpuSupported = true; - mSupportInfo.headroom.gpuMinIntervalMillis = 2000; + mSupportInfo = makeDefaultSupportInfo(); when(mContext.getPackageManager()).thenReturn(mMockPackageManager); when(mMockPackageManager.getNameForUid(anyInt())).thenReturn(TEST_APP_NAME); when(mMockPackageManager.getApplicationInfo(eq(TEST_APP_NAME), anyInt())) @@ -215,6 +231,7 @@ public class HintManagerServiceTest { when(mIPowerMock.getInterfaceVersion()).thenReturn(6); when(mIPowerMock.getSupportInfo()).thenReturn(mSupportInfo); when(mIPowerMock.getSessionChannel(anyInt(), anyInt())).thenReturn(mConfig); + when(mIPowerMock.getSupportInfo()).thenReturn(mSupportInfo); LocalServices.removeServiceForTest(ActivityManagerInternal.class); LocalServices.addService(ActivityManagerInternal.class, mAmInternalMock); } @@ -409,8 +426,11 @@ public class HintManagerServiceTest { HintManagerService service = createService(); IBinder token = new Binder(); - final int threadCount = - service.getBinderServiceInstance().getMaxGraphicsPipelineThreadsCount(); + IHintManager.HintManagerClientData data = service.getBinderServiceInstance() + .registerClient(mClientCallback); + + final int threadCount = data.maxGraphicsPipelineThreads; + long sessionPtr1 = 1111L; long sessionId1 = 11111L; CountDownLatch stopLatch1 = new CountDownLatch(1); @@ -1447,4 +1467,67 @@ public class HintManagerServiceTest { verify(mIPowerMock, times(1)).getGpuHeadroom(eq(halParams1)); 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); + } } |