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 #define LOG_TAG "thermal_hidl_wrapper_test"
18 #include <VtsHalHidlTargetCallbackBase.h>
19 #include <aidl/Vintf.h>
20 #include <aidl/android/hardware/thermal/BnThermal.h>
21 #include <aidl/android/hardware/thermal/BnThermalChangedCallback.h>
22 #include <android-base/logging.h>
23 #include <android-base/properties.h>
24 #include <android/binder_ibinder.h>
25 #include <android/binder_interface_utils.h>
26 #include <android/binder_manager.h>
27 #include <android/binder_process.h>
28 #include <android/binder_status.h>
29 #include <android/hardware/thermal/2.0/IThermal.h>
30 #include <android/hardware/thermal/2.0/IThermalChangedCallback.h>
31 #include <android/hardware/thermal/2.0/types.h>
32 #include <gtest/gtest.h>
33 #include <hidl/GtestPrinter.h>
34 #include <hidl/ServiceManagement.h>
35 #include <thermalutils/ThermalHidlWrapper.h>
36 #include <unistd.h>
37
38 #include <algorithm>
39 #include <chrono>
40 #include <cmath>
41 #include <memory>
42 #include <string>
43 #include <thread>
44 #include <vector>
45
46 namespace aidl::android::hardware::thermal {
47
48 namespace {
49
50 using ::android::sp;
51 using ::android::hardware::hidl_enum_range;
52 using ::android::hardware::hidl_vec;
53 using ::android::hardware::Return;
54 using ::android::hardware::Void;
55
56 using ::android::hardware::thermal::V1_0::ThermalStatus;
57 using ::android::hardware::thermal::V1_0::ThermalStatusCode;
58 using ::android::hardware::thermal::V2_0::CoolingDevice;
59 using ::android::hardware::thermal::V2_0::CoolingType;
60 using IThermal_2_0 = ::android::hardware::thermal::V2_0::IThermal;
61 using ::android::hardware::thermal::V2_0::IThermalChangedCallback;
62 using ::android::hardware::thermal::V2_0::Temperature;
63 using ::android::hardware::thermal::V2_0::TemperatureThreshold;
64 using ::android::hardware::thermal::V2_0::TemperatureType;
65 using ::android::hardware::thermal::V2_0::ThrottlingSeverity;
66
67 constexpr char kCallbackNameNotifyThrottling[] = "notifyThrottling";
68 static const Temperature kThrottleTemp = {
69 .type = TemperatureType::SKIN,
70 .name = "test temperature sensor",
71 .value = 98.6,
72 .throttlingStatus = ThrottlingSeverity::CRITICAL,
73 };
74
75 class ThermalCallbackArgs {
76 public:
77 Temperature temperature;
78 };
79
80 // Callback class for receiving thermal event notifications from main class
81 class ThermalCallback : public ::testing::VtsHalHidlTargetCallbackBase<ThermalCallbackArgs>,
82 public IThermalChangedCallback {
83 public:
notifyThrottling(const Temperature & temperature)84 Return<void> notifyThrottling(const Temperature& temperature) override {
85 ThermalCallbackArgs args;
86 args.temperature = temperature;
87 NotifyFromCallback(kCallbackNameNotifyThrottling, args);
88 return Void();
89 }
90 };
91
92 // The main test class for THERMAL HIDL HAL 2.0.
93 class ThermalHidlWrapperTest : public ::testing::TestWithParam<std::string> {
94 public:
SetUp()95 void SetUp() override {
96 AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
97 ASSERT_NE(binder, nullptr);
98 mThermal = sp<ThermalHidlWrapper>::make(IThermal::fromBinder(ndk::SpAIBinder(binder)));
99 ASSERT_NE(mThermal, nullptr);
100 mThermalCallback = new (std::nothrow) ThermalCallback();
101 ASSERT_NE(mThermalCallback, nullptr);
102 auto ret = mThermal->registerThermalChangedCallback(
103 mThermalCallback, false, TemperatureType::SKIN,
104 [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
105 ASSERT_TRUE(ret.isOk());
106 // Expect to fail if register again
107 ret = mThermal->registerThermalChangedCallback(
108 mThermalCallback, false, TemperatureType::SKIN,
109 [](ThermalStatus status) { EXPECT_NE(ThermalStatusCode::SUCCESS, status.code); });
110 ASSERT_TRUE(ret.isOk());
111 }
112
TearDown()113 void TearDown() override {
114 auto ret = mThermal->unregisterThermalChangedCallback(
115 mThermalCallback,
116 [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
117 ASSERT_TRUE(ret.isOk());
118 // Expect to fail if unregister again
119 ret = mThermal->unregisterThermalChangedCallback(
120 mThermalCallback,
121 [](ThermalStatus status) { EXPECT_NE(ThermalStatusCode::SUCCESS, status.code); });
122 ASSERT_TRUE(ret.isOk());
123 }
124
125 protected:
126 sp<IThermal_2_0> mThermal;
127 sp<ThermalCallback> mThermalCallback;
128 }; // class ThermalHidlWrapperTest
129
130 // Test ThermalChangedCallback::notifyThrottling().
131 // This just calls into and back from our local ThermalChangedCallback impl.
TEST_P(ThermalHidlWrapperTest,NotifyThrottlingTest)132 TEST_P(ThermalHidlWrapperTest, NotifyThrottlingTest) {
133 sp<ThermalCallback> thermalCallback = new (std::nothrow) ThermalCallback();
134 auto ret = thermalCallback->notifyThrottling(kThrottleTemp);
135 ASSERT_TRUE(ret.isOk());
136 auto res = thermalCallback->WaitForCallback(kCallbackNameNotifyThrottling);
137 EXPECT_TRUE(res.no_timeout);
138 ASSERT_TRUE(res.args);
139 EXPECT_EQ(kThrottleTemp, res.args->temperature);
140 }
141
142 // Test Thermal->registerThermalChangedCallback.
TEST_P(ThermalHidlWrapperTest,RegisterThermalChangedCallbackTest)143 TEST_P(ThermalHidlWrapperTest, RegisterThermalChangedCallbackTest) {
144 // Expect to fail with same callback
145 auto ret = mThermal->registerThermalChangedCallback(
146 mThermalCallback, false, TemperatureType::SKIN,
147 [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::FAILURE, status.code); });
148 ASSERT_TRUE(ret.isOk());
149 // Expect to fail with null callback
150 ret = mThermal->registerThermalChangedCallback(
151 nullptr, false, TemperatureType::SKIN,
152 [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::FAILURE, status.code); });
153 ASSERT_TRUE(ret.isOk());
154 sp<ThermalCallback> localThermalCallback = new (std::nothrow) ThermalCallback();
155 // Expect to succeed with different callback
156 ret = mThermal->registerThermalChangedCallback(
157 localThermalCallback, false, TemperatureType::SKIN,
158 [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
159 ASSERT_TRUE(ret.isOk());
160 // Remove the local callback
161 ret = mThermal->unregisterThermalChangedCallback(
162 localThermalCallback,
163 [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
164 ASSERT_TRUE(ret.isOk());
165 // Expect to fail with null callback
166 ret = mThermal->unregisterThermalChangedCallback(nullptr, [](ThermalStatus status) {
167 EXPECT_EQ(ThermalStatusCode::FAILURE, status.code);
168 });
169 ASSERT_TRUE(ret.isOk());
170 }
171
172 // Test Thermal->unregisterThermalChangedCallback.
TEST_P(ThermalHidlWrapperTest,UnregisterThermalChangedCallbackTest)173 TEST_P(ThermalHidlWrapperTest, UnregisterThermalChangedCallbackTest) {
174 sp<ThermalCallback> localThermalCallback = new (std::nothrow) ThermalCallback();
175 // Expect to fail as the callback was not registered before
176 auto ret = mThermal->unregisterThermalChangedCallback(
177 localThermalCallback,
178 [](ThermalStatus status) { EXPECT_NE(ThermalStatusCode::SUCCESS, status.code); });
179 ASSERT_TRUE(ret.isOk());
180 // Register a local callback
181 ret = mThermal->registerThermalChangedCallback(
182 localThermalCallback, false, TemperatureType::SKIN,
183 [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
184 ASSERT_TRUE(ret.isOk());
185 // Expect to succeed with callback removed
186 ret = mThermal->unregisterThermalChangedCallback(
187 localThermalCallback,
188 [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
189 ASSERT_TRUE(ret.isOk());
190 // Expect to fail as the callback has been unregistered already
191 ret = mThermal->unregisterThermalChangedCallback(
192 localThermalCallback,
193 [](ThermalStatus status) { EXPECT_NE(ThermalStatusCode::SUCCESS, status.code); });
194 ASSERT_TRUE(ret.isOk());
195 }
196
197 // Sanity test for Thermal::getCurrentTemperatures().
TEST_P(ThermalHidlWrapperTest,TemperatureTest)198 TEST_P(ThermalHidlWrapperTest, TemperatureTest) {
199 mThermal->getCurrentTemperatures(false, TemperatureType::SKIN,
200 [](ThermalStatus status, hidl_vec<Temperature> temperatures) {
201 if (temperatures.size()) {
202 EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
203 } else {
204 EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
205 }
206 for (int i = 0; i < temperatures.size(); ++i) {
207 EXPECT_LT(0u, temperatures[i].name.size());
208 }
209 });
210 auto types = hidl_enum_range<TemperatureType>();
211 for (const auto& type : types) {
212 mThermal->getCurrentTemperatures(
213 true, type, [&type](ThermalStatus status, hidl_vec<Temperature> temperatures) {
214 if (temperatures.size()) {
215 EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
216 } else {
217 EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
218 }
219 for (int i = 0; i < temperatures.size(); ++i) {
220 EXPECT_EQ(type, temperatures[i].type);
221 EXPECT_LT(0u, temperatures[i].name.size());
222 }
223 });
224 }
225 }
226
227 // Sanity test for Thermal::getTemperatureThresholds().
TEST_P(ThermalHidlWrapperTest,TemperatureThresholdTest)228 TEST_P(ThermalHidlWrapperTest, TemperatureThresholdTest) {
229 mThermal->getTemperatureThresholds(
230 false, TemperatureType::SKIN,
231 [](ThermalStatus status, hidl_vec<TemperatureThreshold> temperatures) {
232 if (temperatures.size()) {
233 EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
234 } else {
235 EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
236 }
237 });
238 for (int i = static_cast<int>(TemperatureType::UNKNOWN);
239 i <= static_cast<int>(TemperatureType::POWER_AMPLIFIER); ++i) {
240 auto type = static_cast<TemperatureType>(i);
241 mThermal->getTemperatureThresholds(
242 true, type,
243 [&type](ThermalStatus status, hidl_vec<TemperatureThreshold> temperatures) {
244 if (temperatures.size()) {
245 EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
246 } else {
247 EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
248 }
249 for (int i = 0; i < temperatures.size(); ++i) {
250 EXPECT_EQ(type, temperatures[i].type);
251 }
252 });
253 }
254 }
255
256 // Sanity test for Thermal::getCurrentCoolingDevices().
TEST_P(ThermalHidlWrapperTest,CoolingDeviceTest)257 TEST_P(ThermalHidlWrapperTest, CoolingDeviceTest) {
258 mThermal->getCurrentCoolingDevices(
259 false, CoolingType::CPU,
260 [](ThermalStatus status, hidl_vec<CoolingDevice> cooling_devices) {
261 if (cooling_devices.size()) {
262 EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
263 } else {
264 EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
265 }
266 for (int i = 0; i < cooling_devices.size(); ++i) {
267 EXPECT_LT(0u, cooling_devices[i].name.size());
268 }
269 });
270 for (int i = 0; i <= static_cast<int>(CoolingType::COMPONENT); ++i) {
271 auto type = static_cast<CoolingType>(i);
272 mThermal->getCurrentCoolingDevices(
273 true, type, [&type](ThermalStatus status, hidl_vec<CoolingDevice> cooling_devices) {
274 if (cooling_devices.size()) {
275 EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
276 } else {
277 EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
278 }
279 for (int i = 0; i < cooling_devices.size(); ++i) {
280 EXPECT_EQ(type, cooling_devices[i].type);
281 EXPECT_LT(0u, cooling_devices[i].name.size());
282 }
283 });
284 }
285 }
286
287 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ThermalHidlWrapperTest);
288 INSTANTIATE_TEST_SUITE_P(
289 PerInstance, ThermalHidlWrapperTest,
290 testing::ValuesIn(::android::getAidlHalInstanceNames(IThermal::descriptor)),
291 ::android::hardware::PrintInstanceNameToString);
292
293 } // namespace
294
main(int argc,char ** argv)295 int main(int argc, char** argv) {
296 ::testing::InitGoogleTest(&argc, argv);
297 ABinderProcess_setThreadPoolMaxThreadCount(1);
298 ABinderProcess_startThreadPool();
299 return RUN_ALL_TESTS();
300 }
301
302 } // namespace aidl::android::hardware::thermal
303