blob: 4208d093f80809818626255a2442b47b49b3b809 [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>
Xiang Wange88a10c2023-09-12 17:29:38 -070023#include <unordered_map>
Peiyong Lin56960752022-09-30 21:52:52 +000024#include <vector>
25
26#define LOG_TAG "thermal_aidl_hal_test"
27
28#include <aidl/Gtest.h>
29#include <aidl/Vintf.h>
TeYuan Wang2bbd1ec2023-12-11 14:55:39 -080030#include <aidl/android/hardware/thermal/BnCoolingDeviceChangedCallback.h>
Peiyong Lin56960752022-09-30 21:52:52 +000031#include <aidl/android/hardware/thermal/BnThermal.h>
32#include <aidl/android/hardware/thermal/BnThermalChangedCallback.h>
33#include <android-base/logging.h>
34#include <android-base/properties.h>
35#include <android/binder_ibinder.h>
36#include <android/binder_interface_utils.h>
37#include <android/binder_manager.h>
38#include <android/binder_process.h>
39#include <android/binder_status.h>
40#include <gtest/gtest.h>
41
42#include <unistd.h>
43
44namespace aidl::android::hardware::thermal {
45
46namespace {
47
48using ::android::sp;
49using android::hardware::thermal::CoolingDevice;
50using android::hardware::thermal::IThermal;
51using android::hardware::thermal::Temperature;
52using android::hardware::thermal::TemperatureType;
53
54using namespace std::string_literals;
55using namespace std::chrono_literals;
56
57static const Temperature kThrottleTemp = {
58 .type = TemperatureType::SKIN,
59 .name = "test temperature sensor",
60 .value = 98.6,
61 .throttlingStatus = ThrottlingSeverity::CRITICAL,
62};
63
TeYuan Wang2bbd1ec2023-12-11 14:55:39 -080064static const CoolingDevice kCoolingDevice = {
65 .type = CoolingType::CPU,
66 .name = "test cooling device",
67 .value = 1,
68 .powerLimitMw = 300,
69 .powerMw = 500,
70 .timeWindowMs = 7000,
71};
72
Peiyong Lin56960752022-09-30 21:52:52 +000073// Callback class for receiving thermal event notifications from main class
74class ThermalCallback : public BnThermalChangedCallback {
75 public:
76 ndk::ScopedAStatus notifyThrottling(const Temperature&) override {
77 {
78 std::lock_guard<std::mutex> lock(mMutex);
79 mInvoke = true;
80 }
81 mNotifyThrottling.notify_all();
82 return ndk::ScopedAStatus::ok();
83 }
84
85 template <typename R, typename P>
86 [[nodiscard]] bool waitForCallback(std::chrono::duration<R, P> duration) {
87 std::unique_lock<std::mutex> lock(mMutex);
88 bool r = mNotifyThrottling.wait_for(lock, duration, [this] { return this->mInvoke; });
89 mInvoke = false;
90 return r;
91 }
92
93 private:
94 std::mutex mMutex;
95 std::condition_variable mNotifyThrottling;
96 bool mInvoke = false;
97};
98
TeYuan Wang2bbd1ec2023-12-11 14:55:39 -080099// Callback class for receiving cooling device event notifications from main class
100class CoolingDeviceCallback : public BnCoolingDeviceChangedCallback {
101 public:
102 ndk::ScopedAStatus notifyCoolingDeviceChanged(const CoolingDevice&) override {
103 {
104 std::lock_guard<std::mutex> lock(mMutex);
105 mInvoke = true;
106 }
107 mNotifyCoolingDeviceChanged.notify_all();
108 return ndk::ScopedAStatus::ok();
109 }
110
111 template <typename R, typename P>
112 [[nodiscard]] bool waitForCallback(std::chrono::duration<R, P> duration) {
113 std::unique_lock<std::mutex> lock(mMutex);
114 bool r = mNotifyCoolingDeviceChanged.wait_for(lock, duration,
115 [this] { return this->mInvoke; });
116 mInvoke = false;
117 return r;
118 }
119
120 private:
121 std::mutex mMutex;
122 std::condition_variable mNotifyCoolingDeviceChanged;
123 bool mInvoke = false;
124};
125
Peiyong Lin56960752022-09-30 21:52:52 +0000126// The main test class for THERMAL HIDL HAL.
127class ThermalAidlTest : public testing::TestWithParam<std::string> {
128 public:
129 void SetUp() override {
130 AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
131 ASSERT_NE(binder, nullptr);
132 mThermal = IThermal::fromBinder(ndk::SpAIBinder(binder));
133
134 mThermalCallback = ndk::SharedRefBase::make<ThermalCallback>();
135 ASSERT_NE(mThermalCallback, nullptr);
Xiang Wange7b177e2022-12-21 17:55:11 -0800136 ::ndk::ScopedAStatus status = mThermal->registerThermalChangedCallback(mThermalCallback);
137 ASSERT_TRUE(status.isOk()) << status.getMessage();
TeYuan Wang2bbd1ec2023-12-11 14:55:39 -0800138
139 auto ret = mThermal->getInterfaceVersion(&thermal_version);
140 ASSERT_TRUE(ret.isOk()) << ret;
141 if (thermal_version > 1) {
142 mCoolingDeviceCallback = ndk::SharedRefBase::make<CoolingDeviceCallback>();
143 ASSERT_NE(mCoolingDeviceCallback, nullptr);
144 status = mThermal->registerCoolingDeviceChangedCallbackWithType(mCoolingDeviceCallback,
145 kCoolingDevice.type);
146 ASSERT_TRUE(status.isOk()) << status.getMessage();
147 }
Peiyong Lin56960752022-09-30 21:52:52 +0000148 }
149
150 void TearDown() override {
Xiang Wange7b177e2022-12-21 17:55:11 -0800151 ::ndk::ScopedAStatus status = mThermal->unregisterThermalChangedCallback(mThermalCallback);
152 ASSERT_TRUE(status.isOk()) << status.getMessage();
TeYuan Wang2bbd1ec2023-12-11 14:55:39 -0800153
Peiyong Lin56960752022-09-30 21:52:52 +0000154 // Expect to fail if unregister again
Xiang Wangd43e8732023-02-07 12:10:33 -0800155 status = mThermal->unregisterThermalChangedCallback(mThermalCallback);
Xiang Wangd43e8732023-02-07 12:10:33 -0800156 ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
TeYuan Wang2bbd1ec2023-12-11 14:55:39 -0800157
158 auto ret = mThermal->getInterfaceVersion(&thermal_version);
159 ASSERT_TRUE(ret.isOk()) << ret;
160 if (thermal_version > 1) {
161 status = mThermal->unregisterCoolingDeviceChangedCallback(mCoolingDeviceCallback);
162 ASSERT_TRUE(status.isOk()) << status.getMessage();
163 status = mThermal->unregisterCoolingDeviceChangedCallback(mCoolingDeviceCallback);
164 ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
165 }
Peiyong Lin56960752022-09-30 21:52:52 +0000166 }
TeYuan Wang2bbd1ec2023-12-11 14:55:39 -0800167 // Stores thermal version
168 int32_t thermal_version;
Peiyong Lin56960752022-09-30 21:52:52 +0000169
170 protected:
171 std::shared_ptr<IThermal> mThermal;
172 std::shared_ptr<ThermalCallback> mThermalCallback;
TeYuan Wang2bbd1ec2023-12-11 14:55:39 -0800173 std::shared_ptr<CoolingDeviceCallback> mCoolingDeviceCallback;
Peiyong Lin56960752022-09-30 21:52:52 +0000174};
175
176// Test ThermalChangedCallback::notifyThrottling().
177// This just calls into and back from our local ThermalChangedCallback impl.
178TEST_P(ThermalAidlTest, NotifyThrottlingTest) {
179 std::shared_ptr<ThermalCallback> thermalCallback = ndk::SharedRefBase::make<ThermalCallback>();
Xiang Wange7b177e2022-12-21 17:55:11 -0800180 ::ndk::ScopedAStatus status = thermalCallback->notifyThrottling(kThrottleTemp);
181 ASSERT_TRUE(status.isOk()) << status.getMessage();
Peiyong Lin56960752022-09-30 21:52:52 +0000182 ASSERT_TRUE(thermalCallback->waitForCallback(200ms));
183}
184
TeYuan Wang2bbd1ec2023-12-11 14:55:39 -0800185// Test CoolingDeviceChangedCallback::notifyCoolingDeviceChanged().
186// This just calls into and back from our local CoolingDeviceChangedCallback impl.
187TEST_P(ThermalAidlTest, NotifyCoolingDeviceChangedTest) {
188 auto ret = mThermal->getInterfaceVersion(&thermal_version);
189 ASSERT_TRUE(ret.isOk()) << ret;
190 if (thermal_version < 2) {
191 return;
192 }
193 std::shared_ptr<CoolingDeviceCallback> cdevCallback =
194 ndk::SharedRefBase::make<CoolingDeviceCallback>();
195 ::ndk::ScopedAStatus status = cdevCallback->notifyCoolingDeviceChanged(kCoolingDevice);
196 ASSERT_TRUE(status.isOk()) << status.getMessage();
197 ASSERT_TRUE(cdevCallback->waitForCallback(200ms));
198}
199
Xiang Wange7b177e2022-12-21 17:55:11 -0800200// Test Thermal->registerThermalChangedCallback.
201TEST_P(ThermalAidlTest, RegisterThermalChangedCallbackTest) {
202 // Expect to fail with same callback
203 ::ndk::ScopedAStatus status = mThermal->registerThermalChangedCallback(mThermalCallback);
204 ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
205 // Expect to fail with null callback
206 status = mThermal->registerThermalChangedCallback(nullptr);
Sean Dooher3869fa62023-06-12 20:14:00 +0000207 ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT
208 || status.getExceptionCode() == EX_NULL_POINTER);
Xiang Wange7b177e2022-12-21 17:55:11 -0800209 std::shared_ptr<ThermalCallback> localThermalCallback =
210 ndk::SharedRefBase::make<ThermalCallback>();
211 // Expect to succeed with different callback
212 status = mThermal->registerThermalChangedCallback(localThermalCallback);
213 ASSERT_TRUE(status.isOk()) << status.getMessage();
Xiang Wange7b177e2022-12-21 17:55:11 -0800214 // Remove the local callback
215 status = mThermal->unregisterThermalChangedCallback(localThermalCallback);
216 ASSERT_TRUE(status.isOk()) << status.getMessage();
217 // Expect to fail with null callback
218 status = mThermal->unregisterThermalChangedCallback(nullptr);
Sean Dooher3869fa62023-06-12 20:14:00 +0000219 ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT
220 || status.getExceptionCode() == EX_NULL_POINTER);
Xiang Wange7b177e2022-12-21 17:55:11 -0800221}
222
223// Test Thermal->registerThermalChangedCallbackWithType.
224TEST_P(ThermalAidlTest, RegisterThermalChangedCallbackWithTypeTest) {
225 // Expect to fail with same callback
226 ::ndk::ScopedAStatus status = mThermal->registerThermalChangedCallbackWithType(
227 mThermalCallback, TemperatureType::SKIN);
228 ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
229 // Expect to fail with null callback
230 status = mThermal->registerThermalChangedCallbackWithType(nullptr, TemperatureType::SKIN);
Sean Dooher3869fa62023-06-12 20:14:00 +0000231 ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT
232 || status.getExceptionCode() == EX_NULL_POINTER);
Xiang Wange7b177e2022-12-21 17:55:11 -0800233 std::shared_ptr<ThermalCallback> localThermalCallback =
234 ndk::SharedRefBase::make<ThermalCallback>();
235 // Expect to succeed with different callback
236 status = mThermal->registerThermalChangedCallbackWithType(localThermalCallback,
237 TemperatureType::SKIN);
238 ASSERT_TRUE(status.isOk()) << status.getMessage();
Xiang Wange7b177e2022-12-21 17:55:11 -0800239 // Remove the local callback
240 status = mThermal->unregisterThermalChangedCallback(localThermalCallback);
241 ASSERT_TRUE(status.isOk()) << status.getMessage();
242 // Expect to fail with null callback
243 status = mThermal->unregisterThermalChangedCallback(nullptr);
Sean Dooher3869fa62023-06-12 20:14:00 +0000244 ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT
245 || status.getExceptionCode() == EX_NULL_POINTER);
Xiang Wange7b177e2022-12-21 17:55:11 -0800246}
247
TeYuan Wang2bbd1ec2023-12-11 14:55:39 -0800248// Test Thermal->registerCoolingDeviceChangedCallbackWithType.
249TEST_P(ThermalAidlTest, RegisterCoolingDeviceChangedCallbackWithTypeTest) {
250 auto ret = mThermal->getInterfaceVersion(&thermal_version);
251 ASSERT_TRUE(ret.isOk()) << ret;
252 if (thermal_version < 2) {
253 return;
254 }
255
256 // Expect to fail with same callback
257 ::ndk::ScopedAStatus status = mThermal->registerCoolingDeviceChangedCallbackWithType(
258 mCoolingDeviceCallback, CoolingType::CPU);
259 ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
260 // Expect to fail with null callback
261 status = mThermal->registerCoolingDeviceChangedCallbackWithType(nullptr, CoolingType::CPU);
262 ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT ||
263 status.getExceptionCode() == EX_NULL_POINTER);
264 std::shared_ptr<CoolingDeviceCallback> localCoolingDeviceCallback =
265 ndk::SharedRefBase::make<CoolingDeviceCallback>();
266 // Expect to succeed with different callback
267 status = mThermal->registerCoolingDeviceChangedCallbackWithType(localCoolingDeviceCallback,
268 CoolingType::CPU);
269 ASSERT_TRUE(status.isOk()) << status.getMessage();
270 // Remove the local callback
271 status = mThermal->unregisterCoolingDeviceChangedCallback(localCoolingDeviceCallback);
272 ASSERT_TRUE(status.isOk()) << status.getMessage();
273 // Expect to fail with null callback
274 status = mThermal->unregisterCoolingDeviceChangedCallback(nullptr);
275 ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT ||
276 status.getExceptionCode() == EX_NULL_POINTER);
277}
278
Xiang Wange7b177e2022-12-21 17:55:11 -0800279// Test Thermal->getCurrentTemperatures().
280TEST_P(ThermalAidlTest, TemperatureTest) {
281 std::vector<Temperature> ret;
282 ::ndk::ScopedAStatus status = mThermal->getTemperatures(&ret);
283 if (status.isOk()) {
284 for (auto& i : ret) {
285 EXPECT_LT(0u, i.name.size());
286 LOG(INFO) << i.name + " " + toString(i.type) << "\n";
287 }
288 } else {
289 ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
290 }
291
292 auto types = ::ndk::enum_range<TemperatureType>();
293 for (const auto& type : types) {
294 status = mThermal->getTemperaturesWithType(type, &ret);
295
296 if (status.isOk()) {
297 for (auto& i : ret) {
298 EXPECT_EQ(type, i.type) << "Expect type " + toString(type) + " but got " +
299 toString(i.type) + " for " + i.name;
300 EXPECT_LT(0u, i.name.size());
301 }
302 } else {
303 ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
304 }
305 }
306}
307
308// Test Thermal->getTemperatureThresholds().
309TEST_P(ThermalAidlTest, TemperatureThresholdTest) {
310 std::vector<TemperatureThreshold> ret;
311 ::ndk::ScopedAStatus status = mThermal->getTemperatureThresholds(&ret);
312 if (status.isOk()) {
313 for (auto& i : ret) {
314 EXPECT_LT(0u, i.name.size());
315 LOG(INFO) << i.name + " " + toString(i.type) << "\n";
316 }
317 } else {
318 ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
319 }
320
321 auto types = ::ndk::enum_range<TemperatureType>();
322 for (const auto& type : types) {
323 status = mThermal->getTemperatureThresholdsWithType(type, &ret);
324
325 if (status.isOk()) {
326 for (auto& i : ret) {
327 EXPECT_EQ(type, i.type) << "Expect type " + toString(type) + " but got " +
328 toString(i.type) + " for " + i.name;
329 EXPECT_LT(0u, i.name.size());
330 }
331 } else {
332 ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
333 }
334 }
335}
336
Xiang Wange88a10c2023-09-12 17:29:38 -0700337// Test Thermal->getTemperatureThresholdsWithType(SKIN).
338// @VsrTest = GMS-VSR-3.2.5-001
339// @VsrTest = VSR-3.2.5-001
340// @VsrTest = GMS-VSR-3.2.5-002
341// @VsrTest = VSR-3.2.5-002
342TEST_P(ThermalAidlTest, SkinTemperatureThresholdsTest) {
343 auto apiLevel = ::android::base::GetIntProperty<int32_t>("ro.vendor.api_level", 0);
344 if (apiLevel < 35) {
345 GTEST_SKIP() << "Skipping test as the vendor level is below 35: " << apiLevel;
346 }
347 std::vector<Temperature> temperatures;
348 ::ndk::ScopedAStatus status =
349 mThermal->getTemperaturesWithType(TemperatureType::SKIN, &temperatures);
350 ASSERT_TRUE(status.isOk()) << "getTemperaturesWithType(SKIN) failed";
351 ASSERT_FALSE(temperatures.empty()) << "getTemperaturesWithType(SKIN) returns empty";
352 ASSERT_EQ(1, temperatures.size())
353 << "getTemperaturesWithType(SKIN) returns multiple temperatures";
354
355 std::vector<TemperatureThreshold> thresholds;
356 status = mThermal->getTemperatureThresholdsWithType(TemperatureType::SKIN, &thresholds);
357 ASSERT_TRUE(status.isOk()) << "getTemperatureThresholdsWithType(SKIN) failed";
358 ASSERT_FALSE(thresholds.empty()) << "getTemperatureThresholdsWithType(SKIN) returns empty";
359 ASSERT_EQ(1, thresholds.size())
360 << "getTemperatureThresholdsWithType(SKIN) returns multiple thresholds";
361 auto temperature = temperatures[0];
362 auto threshold = thresholds[0];
363 ASSERT_EQ(temperature.name, threshold.name);
364 auto severities = ::ndk::enum_range<ThrottlingSeverity>();
365 auto cardinality = std::distance(severities.begin(), severities.end());
366 ASSERT_NE(NAN, temperature.value);
367 ASSERT_EQ(cardinality, threshold.hotThrottlingThresholds.size());
368 float lastThreshold = threshold.hotThrottlingThresholds[1];
369 // skip NONE, and check that the rest should be set and non-decreasing
370 for (auto i = 2; i < cardinality; i++) {
371 float t = threshold.hotThrottlingThresholds[i];
372 ASSERT_NE(NAN, t);
373 ASSERT_TRUE(t >= lastThreshold) << "Temperature thresholds should be non-decreasing "
374 << "but got " << t << " for status " << i << " and "
375 << lastThreshold << " for status " << i - 1;
376 lastThreshold = t;
377 }
378}
379
Xiang Wange7b177e2022-12-21 17:55:11 -0800380// Test Thermal->getCoolingDevices().
381TEST_P(ThermalAidlTest, CoolingDeviceTest) {
382 std::vector<CoolingDevice> ret;
383 ::ndk::ScopedAStatus status = mThermal->getCoolingDevices(&ret);
384 if (status.isOk()) {
385 for (auto& i : ret) {
386 EXPECT_LT(0u, i.name.size());
387 LOG(INFO) << i.name + " " + toString(i.type) << "\n";
388 }
389 } else {
390 ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
391 }
392
393 auto types = ::ndk::enum_range<CoolingType>();
394 for (const auto& type : types) {
395 status = mThermal->getCoolingDevicesWithType(type, &ret);
396 if (status.isOk()) {
397 ASSERT_TRUE(status.isOk());
398 for (auto& i : ret) {
399 EXPECT_EQ(type, i.type) << "Expect type " + toString(type) + " but got " +
400 toString(i.type) + " for " + i.name;
401 EXPECT_LT(0u, i.name.size());
402 }
403 } else {
404 ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
405 }
406 }
407}
408
Peiyong Lin56960752022-09-30 21:52:52 +0000409GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ThermalAidlTest);
410INSTANTIATE_TEST_SUITE_P(
411 Thermal, ThermalAidlTest,
412 testing::ValuesIn(::android::getAidlHalInstanceNames(IThermal::descriptor)),
413 ::android::PrintInstanceNameToString);
414
415} // namespace
Xiang Wangdd0edc62023-02-08 16:47:06 -0800416} // namespace aidl::android::hardware::thermal
Peiyong Lin56960752022-09-30 21:52:52 +0000417
418int main(int argc, char** argv) {
419 ::testing::InitGoogleTest(&argc, argv);
420 ABinderProcess_setThreadPoolMaxThreadCount(1);
421 ABinderProcess_startThreadPool();
422 return RUN_ALL_TESTS();
423}