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