blob: 403c6c85a728a2c2d2b8125cc7962794c30cb6af [file] [log] [blame]
Peiyong Lin56960752022-09-30 21:52:52 +00001/*
2 * Copyright (C) 2022 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 <algorithm>
18#include <chrono>
19#include <cmath>
20#include <memory>
21#include <string>
22#include <thread>
23#include <vector>
24
25#define LOG_TAG "thermal_aidl_hal_test"
26
27#include <aidl/Gtest.h>
28#include <aidl/Vintf.h>
TeYuan Wang2bbd1ec2023-12-11 14:55:39 -080029#include <aidl/android/hardware/thermal/BnCoolingDeviceChangedCallback.h>
Peiyong Lin56960752022-09-30 21:52:52 +000030#include <aidl/android/hardware/thermal/BnThermal.h>
31#include <aidl/android/hardware/thermal/BnThermalChangedCallback.h>
32#include <android-base/logging.h>
33#include <android-base/properties.h>
34#include <android/binder_ibinder.h>
35#include <android/binder_interface_utils.h>
36#include <android/binder_manager.h>
37#include <android/binder_process.h>
38#include <android/binder_status.h>
39#include <gtest/gtest.h>
40
41#include <unistd.h>
42
43namespace aidl::android::hardware::thermal {
44
45namespace {
46
47using ::android::sp;
48using android::hardware::thermal::CoolingDevice;
49using android::hardware::thermal::IThermal;
50using android::hardware::thermal::Temperature;
51using android::hardware::thermal::TemperatureType;
52
53using namespace std::string_literals;
54using namespace std::chrono_literals;
55
56static const Temperature kThrottleTemp = {
57 .type = TemperatureType::SKIN,
58 .name = "test temperature sensor",
59 .value = 98.6,
60 .throttlingStatus = ThrottlingSeverity::CRITICAL,
61};
62
TeYuan Wang2bbd1ec2023-12-11 14:55:39 -080063static const CoolingDevice kCoolingDevice = {
64 .type = CoolingType::CPU,
65 .name = "test cooling device",
66 .value = 1,
67 .powerLimitMw = 300,
68 .powerMw = 500,
69 .timeWindowMs = 7000,
70};
71
Peiyong Lin56960752022-09-30 21:52:52 +000072// Callback class for receiving thermal event notifications from main class
73class ThermalCallback : public BnThermalChangedCallback {
74 public:
75 ndk::ScopedAStatus notifyThrottling(const Temperature&) override {
76 {
77 std::lock_guard<std::mutex> lock(mMutex);
78 mInvoke = true;
79 }
80 mNotifyThrottling.notify_all();
81 return ndk::ScopedAStatus::ok();
82 }
83
84 template <typename R, typename P>
85 [[nodiscard]] bool waitForCallback(std::chrono::duration<R, P> duration) {
86 std::unique_lock<std::mutex> lock(mMutex);
87 bool r = mNotifyThrottling.wait_for(lock, duration, [this] { return this->mInvoke; });
88 mInvoke = false;
89 return r;
90 }
91
92 private:
93 std::mutex mMutex;
94 std::condition_variable mNotifyThrottling;
95 bool mInvoke = false;
96};
97
TeYuan Wang2bbd1ec2023-12-11 14:55:39 -080098// Callback class for receiving cooling device event notifications from main class
99class CoolingDeviceCallback : public BnCoolingDeviceChangedCallback {
100 public:
101 ndk::ScopedAStatus notifyCoolingDeviceChanged(const CoolingDevice&) override {
102 {
103 std::lock_guard<std::mutex> lock(mMutex);
104 mInvoke = true;
105 }
106 mNotifyCoolingDeviceChanged.notify_all();
107 return ndk::ScopedAStatus::ok();
108 }
109
110 template <typename R, typename P>
111 [[nodiscard]] bool waitForCallback(std::chrono::duration<R, P> duration) {
112 std::unique_lock<std::mutex> lock(mMutex);
113 bool r = mNotifyCoolingDeviceChanged.wait_for(lock, duration,
114 [this] { return this->mInvoke; });
115 mInvoke = false;
116 return r;
117 }
118
119 private:
120 std::mutex mMutex;
121 std::condition_variable mNotifyCoolingDeviceChanged;
122 bool mInvoke = false;
123};
124
Peiyong Lin56960752022-09-30 21:52:52 +0000125// The main test class for THERMAL HIDL HAL.
126class ThermalAidlTest : public testing::TestWithParam<std::string> {
127 public:
128 void SetUp() override {
129 AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
130 ASSERT_NE(binder, nullptr);
131 mThermal = IThermal::fromBinder(ndk::SpAIBinder(binder));
132
133 mThermalCallback = ndk::SharedRefBase::make<ThermalCallback>();
134 ASSERT_NE(mThermalCallback, nullptr);
Xiang Wange7b177e2022-12-21 17:55:11 -0800135 ::ndk::ScopedAStatus status = mThermal->registerThermalChangedCallback(mThermalCallback);
136 ASSERT_TRUE(status.isOk()) << status.getMessage();
TeYuan Wang2bbd1ec2023-12-11 14:55:39 -0800137
138 auto ret = mThermal->getInterfaceVersion(&thermal_version);
139 ASSERT_TRUE(ret.isOk()) << ret;
140 if (thermal_version > 1) {
141 mCoolingDeviceCallback = ndk::SharedRefBase::make<CoolingDeviceCallback>();
142 ASSERT_NE(mCoolingDeviceCallback, nullptr);
143 status = mThermal->registerCoolingDeviceChangedCallbackWithType(mCoolingDeviceCallback,
144 kCoolingDevice.type);
145 ASSERT_TRUE(status.isOk()) << status.getMessage();
146 }
Peiyong Lin56960752022-09-30 21:52:52 +0000147 }
148
149 void TearDown() override {
Xiang Wange7b177e2022-12-21 17:55:11 -0800150 ::ndk::ScopedAStatus status = mThermal->unregisterThermalChangedCallback(mThermalCallback);
151 ASSERT_TRUE(status.isOk()) << status.getMessage();
TeYuan Wang2bbd1ec2023-12-11 14:55:39 -0800152
Peiyong Lin56960752022-09-30 21:52:52 +0000153 // Expect to fail if unregister again
Xiang Wangd43e8732023-02-07 12:10:33 -0800154 status = mThermal->unregisterThermalChangedCallback(mThermalCallback);
Xiang Wangd43e8732023-02-07 12:10:33 -0800155 ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
TeYuan Wang2bbd1ec2023-12-11 14:55:39 -0800156
157 auto ret = mThermal->getInterfaceVersion(&thermal_version);
158 ASSERT_TRUE(ret.isOk()) << ret;
159 if (thermal_version > 1) {
160 status = mThermal->unregisterCoolingDeviceChangedCallback(mCoolingDeviceCallback);
161 ASSERT_TRUE(status.isOk()) << status.getMessage();
162 status = mThermal->unregisterCoolingDeviceChangedCallback(mCoolingDeviceCallback);
163 ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
164 }
Peiyong Lin56960752022-09-30 21:52:52 +0000165 }
TeYuan Wang2bbd1ec2023-12-11 14:55:39 -0800166 // Stores thermal version
167 int32_t thermal_version;
Peiyong Lin56960752022-09-30 21:52:52 +0000168
169 protected:
170 std::shared_ptr<IThermal> mThermal;
171 std::shared_ptr<ThermalCallback> mThermalCallback;
TeYuan Wang2bbd1ec2023-12-11 14:55:39 -0800172 std::shared_ptr<CoolingDeviceCallback> mCoolingDeviceCallback;
Peiyong Lin56960752022-09-30 21:52:52 +0000173};
174
175// Test ThermalChangedCallback::notifyThrottling().
176// This just calls into and back from our local ThermalChangedCallback impl.
177TEST_P(ThermalAidlTest, NotifyThrottlingTest) {
178 std::shared_ptr<ThermalCallback> thermalCallback = ndk::SharedRefBase::make<ThermalCallback>();
Xiang Wange7b177e2022-12-21 17:55:11 -0800179 ::ndk::ScopedAStatus status = thermalCallback->notifyThrottling(kThrottleTemp);
180 ASSERT_TRUE(status.isOk()) << status.getMessage();
Peiyong Lin56960752022-09-30 21:52:52 +0000181 ASSERT_TRUE(thermalCallback->waitForCallback(200ms));
182}
183
TeYuan Wang2bbd1ec2023-12-11 14:55:39 -0800184// Test CoolingDeviceChangedCallback::notifyCoolingDeviceChanged().
185// This just calls into and back from our local CoolingDeviceChangedCallback impl.
186TEST_P(ThermalAidlTest, NotifyCoolingDeviceChangedTest) {
187 auto ret = mThermal->getInterfaceVersion(&thermal_version);
188 ASSERT_TRUE(ret.isOk()) << ret;
189 if (thermal_version < 2) {
190 return;
191 }
192 std::shared_ptr<CoolingDeviceCallback> cdevCallback =
193 ndk::SharedRefBase::make<CoolingDeviceCallback>();
194 ::ndk::ScopedAStatus status = cdevCallback->notifyCoolingDeviceChanged(kCoolingDevice);
195 ASSERT_TRUE(status.isOk()) << status.getMessage();
196 ASSERT_TRUE(cdevCallback->waitForCallback(200ms));
197}
198
Xiang Wange7b177e2022-12-21 17:55:11 -0800199// Test Thermal->registerThermalChangedCallback.
200TEST_P(ThermalAidlTest, RegisterThermalChangedCallbackTest) {
201 // Expect to fail with same callback
202 ::ndk::ScopedAStatus status = mThermal->registerThermalChangedCallback(mThermalCallback);
203 ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
204 // Expect to fail with null callback
205 status = mThermal->registerThermalChangedCallback(nullptr);
Sean Dooher3869fa62023-06-12 20:14:00 +0000206 ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT
207 || status.getExceptionCode() == EX_NULL_POINTER);
Xiang Wange7b177e2022-12-21 17:55:11 -0800208 std::shared_ptr<ThermalCallback> localThermalCallback =
209 ndk::SharedRefBase::make<ThermalCallback>();
210 // Expect to succeed with different callback
211 status = mThermal->registerThermalChangedCallback(localThermalCallback);
212 ASSERT_TRUE(status.isOk()) << status.getMessage();
Xiang Wange7b177e2022-12-21 17:55:11 -0800213 // Remove the local callback
214 status = mThermal->unregisterThermalChangedCallback(localThermalCallback);
215 ASSERT_TRUE(status.isOk()) << status.getMessage();
216 // Expect to fail with null callback
217 status = mThermal->unregisterThermalChangedCallback(nullptr);
Sean Dooher3869fa62023-06-12 20:14:00 +0000218 ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT
219 || status.getExceptionCode() == EX_NULL_POINTER);
Xiang Wange7b177e2022-12-21 17:55:11 -0800220}
221
222// Test Thermal->registerThermalChangedCallbackWithType.
223TEST_P(ThermalAidlTest, RegisterThermalChangedCallbackWithTypeTest) {
224 // Expect to fail with same callback
225 ::ndk::ScopedAStatus status = mThermal->registerThermalChangedCallbackWithType(
226 mThermalCallback, TemperatureType::SKIN);
227 ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
228 // Expect to fail with null callback
229 status = mThermal->registerThermalChangedCallbackWithType(nullptr, TemperatureType::SKIN);
Sean Dooher3869fa62023-06-12 20:14:00 +0000230 ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT
231 || status.getExceptionCode() == EX_NULL_POINTER);
Xiang Wange7b177e2022-12-21 17:55:11 -0800232 std::shared_ptr<ThermalCallback> localThermalCallback =
233 ndk::SharedRefBase::make<ThermalCallback>();
234 // Expect to succeed with different callback
235 status = mThermal->registerThermalChangedCallbackWithType(localThermalCallback,
236 TemperatureType::SKIN);
237 ASSERT_TRUE(status.isOk()) << status.getMessage();
Xiang Wange7b177e2022-12-21 17:55:11 -0800238 // Remove the local callback
239 status = mThermal->unregisterThermalChangedCallback(localThermalCallback);
240 ASSERT_TRUE(status.isOk()) << status.getMessage();
241 // Expect to fail with null callback
242 status = mThermal->unregisterThermalChangedCallback(nullptr);
Sean Dooher3869fa62023-06-12 20:14:00 +0000243 ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT
244 || status.getExceptionCode() == EX_NULL_POINTER);
Xiang Wange7b177e2022-12-21 17:55:11 -0800245}
246
TeYuan Wang2bbd1ec2023-12-11 14:55:39 -0800247// Test Thermal->registerCoolingDeviceChangedCallbackWithType.
248TEST_P(ThermalAidlTest, RegisterCoolingDeviceChangedCallbackWithTypeTest) {
249 auto ret = mThermal->getInterfaceVersion(&thermal_version);
250 ASSERT_TRUE(ret.isOk()) << ret;
251 if (thermal_version < 2) {
252 return;
253 }
254
255 // Expect to fail with same callback
256 ::ndk::ScopedAStatus status = mThermal->registerCoolingDeviceChangedCallbackWithType(
257 mCoolingDeviceCallback, CoolingType::CPU);
258 ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
259 // Expect to fail with null callback
260 status = mThermal->registerCoolingDeviceChangedCallbackWithType(nullptr, CoolingType::CPU);
261 ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT ||
262 status.getExceptionCode() == EX_NULL_POINTER);
263 std::shared_ptr<CoolingDeviceCallback> localCoolingDeviceCallback =
264 ndk::SharedRefBase::make<CoolingDeviceCallback>();
265 // Expect to succeed with different callback
266 status = mThermal->registerCoolingDeviceChangedCallbackWithType(localCoolingDeviceCallback,
267 CoolingType::CPU);
268 ASSERT_TRUE(status.isOk()) << status.getMessage();
269 // Remove the local callback
270 status = mThermal->unregisterCoolingDeviceChangedCallback(localCoolingDeviceCallback);
271 ASSERT_TRUE(status.isOk()) << status.getMessage();
272 // Expect to fail with null callback
273 status = mThermal->unregisterCoolingDeviceChangedCallback(nullptr);
274 ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT ||
275 status.getExceptionCode() == EX_NULL_POINTER);
276}
277
Xiang Wange7b177e2022-12-21 17:55:11 -0800278// Test Thermal->getCurrentTemperatures().
279TEST_P(ThermalAidlTest, TemperatureTest) {
280 std::vector<Temperature> ret;
281 ::ndk::ScopedAStatus status = mThermal->getTemperatures(&ret);
282 if (status.isOk()) {
283 for (auto& i : ret) {
284 EXPECT_LT(0u, i.name.size());
285 LOG(INFO) << i.name + " " + toString(i.type) << "\n";
286 }
287 } else {
288 ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
289 }
290
291 auto types = ::ndk::enum_range<TemperatureType>();
292 for (const auto& type : types) {
293 status = mThermal->getTemperaturesWithType(type, &ret);
294
295 if (status.isOk()) {
296 for (auto& i : ret) {
297 EXPECT_EQ(type, i.type) << "Expect type " + toString(type) + " but got " +
298 toString(i.type) + " for " + i.name;
299 EXPECT_LT(0u, i.name.size());
300 }
301 } else {
302 ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
303 }
304 }
305}
306
307// Test Thermal->getTemperatureThresholds().
308TEST_P(ThermalAidlTest, TemperatureThresholdTest) {
309 std::vector<TemperatureThreshold> ret;
310 ::ndk::ScopedAStatus status = mThermal->getTemperatureThresholds(&ret);
311 if (status.isOk()) {
312 for (auto& i : ret) {
313 EXPECT_LT(0u, i.name.size());
314 LOG(INFO) << i.name + " " + toString(i.type) << "\n";
315 }
316 } else {
317 ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
318 }
319
320 auto types = ::ndk::enum_range<TemperatureType>();
321 for (const auto& type : types) {
322 status = mThermal->getTemperatureThresholdsWithType(type, &ret);
323
324 if (status.isOk()) {
325 for (auto& i : ret) {
326 EXPECT_EQ(type, i.type) << "Expect type " + toString(type) + " but got " +
327 toString(i.type) + " for " + i.name;
328 EXPECT_LT(0u, i.name.size());
329 }
330 } else {
331 ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
332 }
333 }
334}
335
336// Test Thermal->getCoolingDevices().
337TEST_P(ThermalAidlTest, CoolingDeviceTest) {
338 std::vector<CoolingDevice> ret;
339 ::ndk::ScopedAStatus status = mThermal->getCoolingDevices(&ret);
340 if (status.isOk()) {
341 for (auto& i : ret) {
342 EXPECT_LT(0u, i.name.size());
343 LOG(INFO) << i.name + " " + toString(i.type) << "\n";
344 }
345 } else {
346 ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
347 }
348
349 auto types = ::ndk::enum_range<CoolingType>();
350 for (const auto& type : types) {
351 status = mThermal->getCoolingDevicesWithType(type, &ret);
352 if (status.isOk()) {
353 ASSERT_TRUE(status.isOk());
354 for (auto& i : ret) {
355 EXPECT_EQ(type, i.type) << "Expect type " + toString(type) + " but got " +
356 toString(i.type) + " for " + i.name;
357 EXPECT_LT(0u, i.name.size());
358 }
359 } else {
360 ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
361 }
362 }
363}
364
Peiyong Lin56960752022-09-30 21:52:52 +0000365GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ThermalAidlTest);
366INSTANTIATE_TEST_SUITE_P(
367 Thermal, ThermalAidlTest,
368 testing::ValuesIn(::android::getAidlHalInstanceNames(IThermal::descriptor)),
369 ::android::PrintInstanceNameToString);
370
371} // namespace
Xiang Wangdd0edc62023-02-08 16:47:06 -0800372} // namespace aidl::android::hardware::thermal
Peiyong Lin56960752022-09-30 21:52:52 +0000373
374int main(int argc, char** argv) {
375 ::testing::InitGoogleTest(&argc, argv);
376 ABinderProcess_setThreadPoolMaxThreadCount(1);
377 ABinderProcess_startThreadPool();
378 return RUN_ALL_TESTS();
379}