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