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