1 /*
2 * Copyright (C) 2024 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 #define LOG_TAG "NativeSystemHealthUnitTest"
18
19 #include <aidl/android/os/IHintManager.h>
20 #include <android/binder_manager.h>
21 #include <android/binder_status.h>
22 #include <android/system_health.h>
23 #include <gmock/gmock.h>
24 #include <gtest/gtest.h>
25 #include <system_health_private.h>
26
27 #include <memory>
28 #include <optional>
29 #include <vector>
30
31 using namespace std::chrono_literals;
32 namespace hal = aidl::android::hardware::power;
33 using aidl::android::os::CpuHeadroomParamsInternal;
34 using aidl::android::os::GpuHeadroomParamsInternal;
35 using aidl::android::os::IHintManager;
36 using aidl::android::os::IHintSession;
37 using aidl::android::os::SessionCreationConfig;
38 using ndk::ScopedAStatus;
39 using ndk::SpAIBinder;
40
41 using namespace android;
42 using namespace testing;
43
44 class MockIHintManager : public IHintManager {
45 public:
46 MOCK_METHOD(ScopedAStatus, createHintSessionWithConfig,
47 (const SpAIBinder& token, hal::SessionTag tag,
48 const SessionCreationConfig& creationConfig, hal::SessionConfig* config,
49 IHintManager::SessionCreationReturn* _aidl_return),
50 (override));
51 MOCK_METHOD(ScopedAStatus, setHintSessionThreads,
52 (const std::shared_ptr<IHintSession>& _, const ::std::vector<int32_t>& tids),
53 (override));
54 MOCK_METHOD(ScopedAStatus, getHintSessionThreadIds,
55 (const std::shared_ptr<IHintSession>& _, ::std::vector<int32_t>* tids), (override));
56 MOCK_METHOD(ScopedAStatus, getSessionChannel,
57 (const ::ndk::SpAIBinder& in_token,
58 std::optional<hal::ChannelConfig>* _aidl_return),
59 (override));
60 MOCK_METHOD(ScopedAStatus, closeSessionChannel, (), (override));
61 MOCK_METHOD(ScopedAStatus, getCpuHeadroom,
62 (const CpuHeadroomParamsInternal& _,
63 std::optional<hal::CpuHeadroomResult>* _aidl_return),
64 (override));
65 MOCK_METHOD(ScopedAStatus, getCpuHeadroomMinIntervalMillis, (int64_t*), (override));
66 MOCK_METHOD(ScopedAStatus, getGpuHeadroom,
67 (const GpuHeadroomParamsInternal& _,
68 std::optional<hal::GpuHeadroomResult>* _aidl_return),
69 (override));
70 MOCK_METHOD(ScopedAStatus, getGpuHeadroomMinIntervalMillis, (int64_t* _aidl_return),
71 (override));
72 MOCK_METHOD(ScopedAStatus, passSessionManagerBinder, (const SpAIBinder& sessionManager));
73 MOCK_METHOD(ScopedAStatus, registerClient,
74 (const std::shared_ptr<aidl::android::os::IHintManager::IHintManagerClient>& _,
75 aidl::android::os::IHintManager::HintManagerClientData* _aidl_return),
76 (override));
77 MOCK_METHOD(ScopedAStatus, getClientData,
78 (aidl::android::os::IHintManager::HintManagerClientData * _aidl_return),
79 (override));
80 MOCK_METHOD(SpAIBinder, asBinder, (), (override));
81 MOCK_METHOD(bool, isRemote, (), (override));
82 };
83
84 class NativeSystemHealthUnitTest : public Test {
85 public:
SetUp()86 void SetUp() override {
87 mMockIHintManager = ndk::SharedRefBase::make<NiceMock<MockIHintManager>>();
88 ASystemHealth_setIHintManagerForTesting(&mMockIHintManager);
89 ON_CALL(*mMockIHintManager, getClientData(_))
90 .WillByDefault(
91 DoAll(SetArgPointee<0>(mClientData), [] { return ScopedAStatus::ok(); }));
92 }
93
TearDown()94 void TearDown() override {
95 ASystemHealth_setIHintManagerForTesting(nullptr);
96 }
97
98 IHintManager::HintManagerClientData mClientData{
99 .powerHalVersion = 6,
100 .maxCpuHeadroomThreads = 10,
101 .supportInfo{.headroom{
102 .isCpuSupported = true,
103 .isGpuSupported = true,
104 .cpuMinIntervalMillis = 999,
105 .gpuMinIntervalMillis = 998,
106 .cpuMinCalculationWindowMillis = 45,
107 .cpuMaxCalculationWindowMillis = 9999,
108 .gpuMinCalculationWindowMillis = 46,
109 .gpuMaxCalculationWindowMillis = 9998,
110 }},
111 };
112
113 std::shared_ptr<NiceMock<MockIHintManager>> mMockIHintManager = nullptr;
114 };
115
TEST_F(NativeSystemHealthUnitTest,headroomParamsValueRange)116 TEST_F(NativeSystemHealthUnitTest, headroomParamsValueRange) {
117 int64_t minIntervalMillis = 0;
118 int minCalculationWindowMillis = 0;
119 int maxCalculationWindowMillis = 0;
120 ASSERT_EQ(OK, ASystemHealth_getCpuHeadroomMinIntervalMillis(&minIntervalMillis));
121 ASSERT_EQ(OK,
122 ASystemHealth_getCpuHeadroomCalculationWindowRange(&minCalculationWindowMillis,
123 &maxCalculationWindowMillis));
124 ASSERT_EQ(minIntervalMillis, mClientData.supportInfo.headroom.cpuMinIntervalMillis);
125 ASSERT_EQ(minCalculationWindowMillis,
126 mClientData.supportInfo.headroom.cpuMinCalculationWindowMillis);
127 ASSERT_EQ(maxCalculationWindowMillis,
128 mClientData.supportInfo.headroom.cpuMaxCalculationWindowMillis);
129
130 ASSERT_EQ(OK, ASystemHealth_getGpuHeadroomMinIntervalMillis(&minIntervalMillis));
131 ASSERT_EQ(OK,
132 ASystemHealth_getGpuHeadroomCalculationWindowRange(&minCalculationWindowMillis,
133 &maxCalculationWindowMillis));
134 ASSERT_EQ(minIntervalMillis, mClientData.supportInfo.headroom.gpuMinIntervalMillis);
135 ASSERT_EQ(minCalculationWindowMillis,
136 mClientData.supportInfo.headroom.gpuMinCalculationWindowMillis);
137 ASSERT_EQ(maxCalculationWindowMillis,
138 mClientData.supportInfo.headroom.gpuMaxCalculationWindowMillis);
139 }
140
TEST_F(NativeSystemHealthUnitTest,getCpuHeadroom)141 TEST_F(NativeSystemHealthUnitTest, getCpuHeadroom) {
142 CpuHeadroomParamsInternal internalParams1;
143 ACpuHeadroomParams* params2 = ACpuHeadroomParams_create();
144 ACpuHeadroomParams_setCalculationWindowMillis(params2, 200);
145 CpuHeadroomParamsInternal internalParams2;
146 internalParams2.calculationWindowMillis = 200;
147 ACpuHeadroomParams* params3 = ACpuHeadroomParams_create();
148 ACpuHeadroomParams_setCalculationType(params3, ACPU_HEADROOM_CALCULATION_TYPE_AVERAGE);
149 CpuHeadroomParamsInternal internalParams3;
150 internalParams3.calculationType = hal::CpuHeadroomParams::CalculationType::AVERAGE;
151 ACpuHeadroomParams* params4 = ACpuHeadroomParams_create();
152 int tids[3] = {1, 2, 3};
153 ACpuHeadroomParams_setTids(params4, tids, 3);
154 CpuHeadroomParamsInternal internalParams4;
155 internalParams4.tids = {1, 2, 3};
156
157 EXPECT_CALL(*mMockIHintManager, getCpuHeadroom(internalParams1, _))
158 .Times(Exactly(1))
159 .WillOnce(DoAll(SetArgPointee<1>(hal::CpuHeadroomResult::make<
160 hal::CpuHeadroomResult::globalHeadroom>(1.0f)),
161 [] { return ScopedAStatus::ok(); }));
162 EXPECT_CALL(*mMockIHintManager, getCpuHeadroom(internalParams2, _))
163 .Times(Exactly(1))
164 .WillOnce(DoAll(SetArgPointee<1>(hal::CpuHeadroomResult::make<
165 hal::CpuHeadroomResult::globalHeadroom>(2.0f)),
166 [] { return ScopedAStatus::ok(); }));
167 EXPECT_CALL(*mMockIHintManager, getCpuHeadroom(internalParams3, _))
168 .Times(Exactly(1))
169 .WillOnce(DoAll(SetArgPointee<1>(std::nullopt), [] { return ScopedAStatus::ok(); }));
170 EXPECT_CALL(*mMockIHintManager, getCpuHeadroom(internalParams4, _))
171 .Times(Exactly(1))
172 .WillOnce(DoAll(SetArgPointee<1>(hal::CpuHeadroomResult::make<
173 hal::CpuHeadroomResult::globalHeadroom>(4.0f)),
174 [] { return ScopedAStatus::ok(); }));
175
176 float headroom1 = 0.0f;
177 float headroom2 = 0.0f;
178 float headroom3 = 0.0f;
179 float headroom4 = 0.0f;
180 ASSERT_EQ(OK, ASystemHealth_getCpuHeadroom(nullptr, &headroom1));
181 ASSERT_EQ(OK, ASystemHealth_getCpuHeadroom(params2, &headroom2));
182 ASSERT_EQ(OK, ASystemHealth_getCpuHeadroom(params3, &headroom3));
183 ASSERT_EQ(OK, ASystemHealth_getCpuHeadroom(params4, &headroom4));
184 ASSERT_EQ(1.0f, headroom1);
185 ASSERT_EQ(2.0f, headroom2);
186 ASSERT_TRUE(isnan(headroom3));
187 ASSERT_EQ(4.0f, headroom4);
188
189 ACpuHeadroomParams_destroy(params2);
190 ACpuHeadroomParams_destroy(params3);
191 ACpuHeadroomParams_destroy(params4);
192 }
193
TEST_F(NativeSystemHealthUnitTest,getGpuHeadroom)194 TEST_F(NativeSystemHealthUnitTest, getGpuHeadroom) {
195 GpuHeadroomParamsInternal internalParams1;
196 AGpuHeadroomParams* params2 = AGpuHeadroomParams_create();
197 AGpuHeadroomParams_setCalculationWindowMillis(params2, 200);
198 GpuHeadroomParamsInternal internalParams2;
199 internalParams2.calculationWindowMillis = 200;
200 AGpuHeadroomParams* params3 = AGpuHeadroomParams_create();
201 AGpuHeadroomParams_setCalculationType(params3, AGPU_HEADROOM_CALCULATION_TYPE_AVERAGE);
202 GpuHeadroomParamsInternal internalParams3;
203 internalParams3.calculationType = hal::GpuHeadroomParams::CalculationType::AVERAGE;
204
205 EXPECT_CALL(*mMockIHintManager, getGpuHeadroom(internalParams1, _))
206 .Times(Exactly(1))
207 .WillOnce(DoAll(SetArgPointee<1>(hal::GpuHeadroomResult::make<
208 hal::GpuHeadroomResult::globalHeadroom>(1.0f)),
209 [] { return ScopedAStatus::ok(); }));
210 EXPECT_CALL(*mMockIHintManager, getGpuHeadroom(internalParams2, _))
211 .Times(Exactly(1))
212 .WillOnce(DoAll(SetArgPointee<1>(hal::GpuHeadroomResult::make<
213 hal::GpuHeadroomResult::globalHeadroom>(2.0f)),
214 [] { return ScopedAStatus::ok(); }));
215 EXPECT_CALL(*mMockIHintManager, getGpuHeadroom(internalParams3, _))
216 .Times(Exactly(1))
217 .WillOnce(DoAll(SetArgPointee<1>(std::nullopt), [] { return ScopedAStatus::ok(); }));
218
219 float headroom1 = 0.0f;
220 float headroom2 = 0.0f;
221 float headroom3 = 0.0f;
222 ASSERT_EQ(OK, ASystemHealth_getGpuHeadroom(nullptr, &headroom1));
223 ASSERT_EQ(OK, ASystemHealth_getGpuHeadroom(params2, &headroom2));
224 ASSERT_EQ(OK, ASystemHealth_getGpuHeadroom(params3, &headroom3));
225 ASSERT_EQ(1.0f, headroom1);
226 ASSERT_EQ(2.0f, headroom2);
227 ASSERT_TRUE(isnan(headroom3));
228
229 AGpuHeadroomParams_destroy(params2);
230 AGpuHeadroomParams_destroy(params3);
231 }
232