blob: 4b0eb655b54071898c81ee4893e81b94440ff21e [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>
29#include <aidl/android/hardware/thermal/BnThermal.h>
30#include <aidl/android/hardware/thermal/BnThermalChangedCallback.h>
31#include <android-base/logging.h>
32#include <android-base/properties.h>
33#include <android/binder_ibinder.h>
34#include <android/binder_interface_utils.h>
35#include <android/binder_manager.h>
36#include <android/binder_process.h>
37#include <android/binder_status.h>
38#include <gtest/gtest.h>
39
40#include <unistd.h>
41
42namespace aidl::android::hardware::thermal {
43
44namespace {
45
46using ::android::sp;
47using android::hardware::thermal::CoolingDevice;
48using android::hardware::thermal::IThermal;
49using android::hardware::thermal::Temperature;
50using android::hardware::thermal::TemperatureType;
51
52using namespace std::string_literals;
53using namespace std::chrono_literals;
54
55static const Temperature kThrottleTemp = {
56 .type = TemperatureType::SKIN,
57 .name = "test temperature sensor",
58 .value = 98.6,
59 .throttlingStatus = ThrottlingSeverity::CRITICAL,
60};
61
62// Callback class for receiving thermal event notifications from main class
63class ThermalCallback : public BnThermalChangedCallback {
64 public:
65 ndk::ScopedAStatus notifyThrottling(const Temperature&) override {
66 {
67 std::lock_guard<std::mutex> lock(mMutex);
68 mInvoke = true;
69 }
70 mNotifyThrottling.notify_all();
71 return ndk::ScopedAStatus::ok();
72 }
73
74 template <typename R, typename P>
75 [[nodiscard]] bool waitForCallback(std::chrono::duration<R, P> duration) {
76 std::unique_lock<std::mutex> lock(mMutex);
77 bool r = mNotifyThrottling.wait_for(lock, duration, [this] { return this->mInvoke; });
78 mInvoke = false;
79 return r;
80 }
81
82 private:
83 std::mutex mMutex;
84 std::condition_variable mNotifyThrottling;
85 bool mInvoke = false;
86};
87
88// The main test class for THERMAL HIDL HAL.
89class ThermalAidlTest : public testing::TestWithParam<std::string> {
90 public:
91 void SetUp() override {
92 AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
93 ASSERT_NE(binder, nullptr);
94 mThermal = IThermal::fromBinder(ndk::SpAIBinder(binder));
95
96 mThermalCallback = ndk::SharedRefBase::make<ThermalCallback>();
97 ASSERT_NE(mThermalCallback, nullptr);
Xiang Wange7b177e2022-12-21 17:55:11 -080098 ::ndk::ScopedAStatus status = mThermal->registerThermalChangedCallback(mThermalCallback);
99 ASSERT_TRUE(status.isOk()) << status.getMessage();
Peiyong Lin56960752022-09-30 21:52:52 +0000100 }
101
102 void TearDown() override {
Xiang Wange7b177e2022-12-21 17:55:11 -0800103 ::ndk::ScopedAStatus status = mThermal->unregisterThermalChangedCallback(mThermalCallback);
104 ASSERT_TRUE(status.isOk()) << status.getMessage();
Peiyong Lin56960752022-09-30 21:52:52 +0000105 // Expect to fail if unregister again
Xiang Wangd43e8732023-02-07 12:10:33 -0800106 status = mThermal->unregisterThermalChangedCallback(mThermalCallback);
Xiang Wangd43e8732023-02-07 12:10:33 -0800107 ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
Peiyong Lin56960752022-09-30 21:52:52 +0000108 }
109
110 protected:
111 std::shared_ptr<IThermal> mThermal;
112 std::shared_ptr<ThermalCallback> mThermalCallback;
113};
114
115// Test ThermalChangedCallback::notifyThrottling().
116// This just calls into and back from our local ThermalChangedCallback impl.
117TEST_P(ThermalAidlTest, NotifyThrottlingTest) {
118 std::shared_ptr<ThermalCallback> thermalCallback = ndk::SharedRefBase::make<ThermalCallback>();
Xiang Wange7b177e2022-12-21 17:55:11 -0800119 ::ndk::ScopedAStatus status = thermalCallback->notifyThrottling(kThrottleTemp);
120 ASSERT_TRUE(status.isOk()) << status.getMessage();
Peiyong Lin56960752022-09-30 21:52:52 +0000121 ASSERT_TRUE(thermalCallback->waitForCallback(200ms));
122}
123
Xiang Wange7b177e2022-12-21 17:55:11 -0800124// Test Thermal->registerThermalChangedCallback.
125TEST_P(ThermalAidlTest, RegisterThermalChangedCallbackTest) {
126 // Expect to fail with same callback
127 ::ndk::ScopedAStatus status = mThermal->registerThermalChangedCallback(mThermalCallback);
128 ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
129 // Expect to fail with null callback
130 status = mThermal->registerThermalChangedCallback(nullptr);
Sean Dooher3869fa62023-06-12 20:14:00 +0000131 ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT
132 || status.getExceptionCode() == EX_NULL_POINTER);
Xiang Wange7b177e2022-12-21 17:55:11 -0800133 std::shared_ptr<ThermalCallback> localThermalCallback =
134 ndk::SharedRefBase::make<ThermalCallback>();
135 // Expect to succeed with different callback
136 status = mThermal->registerThermalChangedCallback(localThermalCallback);
137 ASSERT_TRUE(status.isOk()) << status.getMessage();
Xiang Wange7b177e2022-12-21 17:55:11 -0800138 // Remove the local callback
139 status = mThermal->unregisterThermalChangedCallback(localThermalCallback);
140 ASSERT_TRUE(status.isOk()) << status.getMessage();
141 // Expect to fail with null callback
142 status = mThermal->unregisterThermalChangedCallback(nullptr);
Sean Dooher3869fa62023-06-12 20:14:00 +0000143 ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT
144 || status.getExceptionCode() == EX_NULL_POINTER);
Xiang Wange7b177e2022-12-21 17:55:11 -0800145}
146
147// Test Thermal->registerThermalChangedCallbackWithType.
148TEST_P(ThermalAidlTest, RegisterThermalChangedCallbackWithTypeTest) {
149 // Expect to fail with same callback
150 ::ndk::ScopedAStatus status = mThermal->registerThermalChangedCallbackWithType(
151 mThermalCallback, TemperatureType::SKIN);
152 ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
153 // Expect to fail with null callback
154 status = mThermal->registerThermalChangedCallbackWithType(nullptr, TemperatureType::SKIN);
Sean Dooher3869fa62023-06-12 20:14:00 +0000155 ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT
156 || status.getExceptionCode() == EX_NULL_POINTER);
Xiang Wange7b177e2022-12-21 17:55:11 -0800157 std::shared_ptr<ThermalCallback> localThermalCallback =
158 ndk::SharedRefBase::make<ThermalCallback>();
159 // Expect to succeed with different callback
160 status = mThermal->registerThermalChangedCallbackWithType(localThermalCallback,
161 TemperatureType::SKIN);
162 ASSERT_TRUE(status.isOk()) << status.getMessage();
Xiang Wange7b177e2022-12-21 17:55:11 -0800163 // Remove the local callback
164 status = mThermal->unregisterThermalChangedCallback(localThermalCallback);
165 ASSERT_TRUE(status.isOk()) << status.getMessage();
166 // Expect to fail with null callback
167 status = mThermal->unregisterThermalChangedCallback(nullptr);
Sean Dooher3869fa62023-06-12 20:14:00 +0000168 ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT
169 || status.getExceptionCode() == EX_NULL_POINTER);
Xiang Wange7b177e2022-12-21 17:55:11 -0800170}
171
172// Test Thermal->getCurrentTemperatures().
173TEST_P(ThermalAidlTest, TemperatureTest) {
174 std::vector<Temperature> ret;
175 ::ndk::ScopedAStatus status = mThermal->getTemperatures(&ret);
176 if (status.isOk()) {
177 for (auto& i : ret) {
178 EXPECT_LT(0u, i.name.size());
179 LOG(INFO) << i.name + " " + toString(i.type) << "\n";
180 }
181 } else {
182 ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
183 }
184
185 auto types = ::ndk::enum_range<TemperatureType>();
186 for (const auto& type : types) {
187 status = mThermal->getTemperaturesWithType(type, &ret);
188
189 if (status.isOk()) {
190 for (auto& i : ret) {
191 EXPECT_EQ(type, i.type) << "Expect type " + toString(type) + " but got " +
192 toString(i.type) + " for " + i.name;
193 EXPECT_LT(0u, i.name.size());
194 }
195 } else {
196 ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
197 }
198 }
199}
200
201// Test Thermal->getTemperatureThresholds().
202TEST_P(ThermalAidlTest, TemperatureThresholdTest) {
203 std::vector<TemperatureThreshold> ret;
204 ::ndk::ScopedAStatus status = mThermal->getTemperatureThresholds(&ret);
205 if (status.isOk()) {
206 for (auto& i : ret) {
207 EXPECT_LT(0u, i.name.size());
208 LOG(INFO) << i.name + " " + toString(i.type) << "\n";
209 }
210 } else {
211 ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
212 }
213
214 auto types = ::ndk::enum_range<TemperatureType>();
215 for (const auto& type : types) {
216 status = mThermal->getTemperatureThresholdsWithType(type, &ret);
217
218 if (status.isOk()) {
219 for (auto& i : ret) {
220 EXPECT_EQ(type, i.type) << "Expect type " + toString(type) + " but got " +
221 toString(i.type) + " for " + i.name;
222 EXPECT_LT(0u, i.name.size());
223 }
224 } else {
225 ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
226 }
227 }
228}
229
230// Test Thermal->getCoolingDevices().
231TEST_P(ThermalAidlTest, CoolingDeviceTest) {
232 std::vector<CoolingDevice> ret;
233 ::ndk::ScopedAStatus status = mThermal->getCoolingDevices(&ret);
234 if (status.isOk()) {
235 for (auto& i : ret) {
236 EXPECT_LT(0u, i.name.size());
237 LOG(INFO) << i.name + " " + toString(i.type) << "\n";
238 }
239 } else {
240 ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
241 }
242
243 auto types = ::ndk::enum_range<CoolingType>();
244 for (const auto& type : types) {
245 status = mThermal->getCoolingDevicesWithType(type, &ret);
246 if (status.isOk()) {
247 ASSERT_TRUE(status.isOk());
248 for (auto& i : ret) {
249 EXPECT_EQ(type, i.type) << "Expect type " + toString(type) + " but got " +
250 toString(i.type) + " for " + i.name;
251 EXPECT_LT(0u, i.name.size());
252 }
253 } else {
254 ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
255 }
256 }
257}
258
Peiyong Lin56960752022-09-30 21:52:52 +0000259GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ThermalAidlTest);
260INSTANTIATE_TEST_SUITE_P(
261 Thermal, ThermalAidlTest,
262 testing::ValuesIn(::android::getAidlHalInstanceNames(IThermal::descriptor)),
263 ::android::PrintInstanceNameToString);
264
265} // namespace
Xiang Wangdd0edc62023-02-08 16:47:06 -0800266} // namespace aidl::android::hardware::thermal
Peiyong Lin56960752022-09-30 21:52:52 +0000267
268int main(int argc, char** argv) {
269 ::testing::InitGoogleTest(&argc, argv);
270 ABinderProcess_setThreadPoolMaxThreadCount(1);
271 ABinderProcess_startThreadPool();
272 return RUN_ALL_TESTS();
273}