1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
19 #include <private/performance_hint_private.h>
20 #include <renderthread/HintSessionWrapper.h>
21 #include <utils/Log.h>
22
23 #include <chrono>
24
25 #include "Properties.h"
26
27 using namespace testing;
28 using namespace std::chrono_literals;
29
30 APerformanceHintManager* managerPtr = reinterpret_cast<APerformanceHintManager*>(123);
31 APerformanceHintSession* sessionPtr = reinterpret_cast<APerformanceHintSession*>(456);
32 int uiThreadId = 1;
33 int renderThreadId = 2;
34
35 namespace android::uirenderer::renderthread {
36
37 class HintSessionWrapperTests : public testing::Test {
38 public:
39 void SetUp() override;
40 void TearDown() override;
41
42 protected:
43 std::shared_ptr<HintSessionWrapper> mWrapper;
44
45 class MockHintSessionBinding : public HintSessionWrapper::HintSessionBinding {
46 public:
47 void init() override;
48
49 MOCK_METHOD(APerformanceHintManager*, fakeGetManager, ());
50 MOCK_METHOD(APerformanceHintSession*, fakeCreateSession,
51 (APerformanceHintManager*, const int32_t*, size_t, int64_t));
52 MOCK_METHOD(void, fakeCloseSession, (APerformanceHintSession*));
53 MOCK_METHOD(void, fakeUpdateTargetWorkDuration, (APerformanceHintSession*, int64_t));
54 MOCK_METHOD(void, fakeReportActualWorkDuration, (APerformanceHintSession*, int64_t));
55 MOCK_METHOD(void, fakeSendHint, (APerformanceHintSession*, int32_t));
56 };
57
58 // Must be static so it can have function pointers we can point to with static methods
59 static std::shared_ptr<MockHintSessionBinding> sMockBinding;
60
61 // Must be static so we can point to them as normal fn pointers with HintSessionBinding
stubGetManager()62 static APerformanceHintManager* stubGetManager() { return sMockBinding->fakeGetManager(); };
stubCreateSession(APerformanceHintManager * manager,const int32_t * ids,size_t idsSize,int64_t initialTarget)63 static APerformanceHintSession* stubCreateSession(APerformanceHintManager* manager,
64 const int32_t* ids, size_t idsSize,
65 int64_t initialTarget) {
66 return sMockBinding->fakeCreateSession(manager, ids, idsSize, initialTarget);
67 }
stubSlowCreateSession(APerformanceHintManager * manager,const int32_t * ids,size_t idsSize,int64_t initialTarget)68 static APerformanceHintSession* stubSlowCreateSession(APerformanceHintManager* manager,
69 const int32_t* ids, size_t idsSize,
70 int64_t initialTarget) {
71 std::this_thread::sleep_for(50ms);
72 return sMockBinding->fakeCreateSession(manager, ids, idsSize, initialTarget);
73 }
stubCloseSession(APerformanceHintSession * session)74 static void stubCloseSession(APerformanceHintSession* session) {
75 sMockBinding->fakeCloseSession(session);
76 };
stubUpdateTargetWorkDuration(APerformanceHintSession * session,int64_t workDuration)77 static void stubUpdateTargetWorkDuration(APerformanceHintSession* session,
78 int64_t workDuration) {
79 sMockBinding->fakeUpdateTargetWorkDuration(session, workDuration);
80 }
stubReportActualWorkDuration(APerformanceHintSession * session,int64_t workDuration)81 static void stubReportActualWorkDuration(APerformanceHintSession* session,
82 int64_t workDuration) {
83 sMockBinding->fakeReportActualWorkDuration(session, workDuration);
84 }
stubSendHint(APerformanceHintSession * session,int32_t hintId)85 static void stubSendHint(APerformanceHintSession* session, int32_t hintId) {
86 sMockBinding->fakeSendHint(session, hintId);
87 };
waitForWrapperReady()88 void waitForWrapperReady() { mWrapper->mHintSessionFuture.wait(); }
89 };
90
91 std::shared_ptr<HintSessionWrapperTests::MockHintSessionBinding>
92 HintSessionWrapperTests::sMockBinding;
93
SetUp()94 void HintSessionWrapperTests::SetUp() {
95 // Pretend it's supported even if we're in an emulator
96 Properties::useHintManager = true;
97 sMockBinding = std::make_shared<NiceMock<MockHintSessionBinding>>();
98 mWrapper = std::make_shared<HintSessionWrapper>(uiThreadId, renderThreadId);
99 mWrapper->mBinding = sMockBinding;
100 EXPECT_CALL(*sMockBinding, fakeGetManager).WillOnce(Return(managerPtr));
101 ON_CALL(*sMockBinding, fakeCreateSession).WillByDefault(Return(sessionPtr));
102 }
103
init()104 void HintSessionWrapperTests::MockHintSessionBinding::init() {
105 sMockBinding->getManager = &stubGetManager;
106 if (sMockBinding->createSession == nullptr) {
107 sMockBinding->createSession = &stubCreateSession;
108 }
109 sMockBinding->closeSession = &stubCloseSession;
110 sMockBinding->updateTargetWorkDuration = &stubUpdateTargetWorkDuration;
111 sMockBinding->reportActualWorkDuration = &stubReportActualWorkDuration;
112 sMockBinding->sendHint = &stubSendHint;
113 }
114
TearDown()115 void HintSessionWrapperTests::TearDown() {
116 mWrapper = nullptr;
117 sMockBinding = nullptr;
118 }
119
TEST_F(HintSessionWrapperTests,destructorClosesBackgroundSession)120 TEST_F(HintSessionWrapperTests, destructorClosesBackgroundSession) {
121 EXPECT_CALL(*sMockBinding, fakeCloseSession(sessionPtr)).Times(1);
122 sMockBinding->createSession = stubSlowCreateSession;
123 mWrapper->init();
124 mWrapper = nullptr;
125 }
126
TEST_F(HintSessionWrapperTests,sessionInitializesCorrectly)127 TEST_F(HintSessionWrapperTests, sessionInitializesCorrectly) {
128 EXPECT_CALL(*sMockBinding, fakeCreateSession(managerPtr, _, Gt(1), _)).Times(1);
129 mWrapper->init();
130 waitForWrapperReady();
131 }
132
TEST_F(HintSessionWrapperTests,loadUpHintsSendCorrectly)133 TEST_F(HintSessionWrapperTests, loadUpHintsSendCorrectly) {
134 EXPECT_CALL(*sMockBinding,
135 fakeSendHint(sessionPtr, static_cast<int32_t>(SessionHint::CPU_LOAD_UP)))
136 .Times(1);
137 mWrapper->init();
138 waitForWrapperReady();
139 mWrapper->sendLoadIncreaseHint();
140 }
141
TEST_F(HintSessionWrapperTests,loadResetHintsSendCorrectly)142 TEST_F(HintSessionWrapperTests, loadResetHintsSendCorrectly) {
143 EXPECT_CALL(*sMockBinding,
144 fakeSendHint(sessionPtr, static_cast<int32_t>(SessionHint::CPU_LOAD_RESET)))
145 .Times(1);
146 mWrapper->init();
147 waitForWrapperReady();
148 mWrapper->sendLoadResetHint();
149 }
150
151 } // namespace android::uirenderer::renderthread