1*4d7e907cSAndroid Build Coastguard Worker /*
2*4d7e907cSAndroid Build Coastguard Worker * Copyright (C) 2022 The Android Open Source Project
3*4d7e907cSAndroid Build Coastguard Worker *
4*4d7e907cSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*4d7e907cSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*4d7e907cSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*4d7e907cSAndroid Build Coastguard Worker *
8*4d7e907cSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*4d7e907cSAndroid Build Coastguard Worker *
10*4d7e907cSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*4d7e907cSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*4d7e907cSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4d7e907cSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*4d7e907cSAndroid Build Coastguard Worker * limitations under the License.
15*4d7e907cSAndroid Build Coastguard Worker */
16*4d7e907cSAndroid Build Coastguard Worker
17*4d7e907cSAndroid Build Coastguard Worker #include <algorithm>
18*4d7e907cSAndroid Build Coastguard Worker #include <chrono>
19*4d7e907cSAndroid Build Coastguard Worker #include <cmath>
20*4d7e907cSAndroid Build Coastguard Worker #include <memory>
21*4d7e907cSAndroid Build Coastguard Worker #include <string>
22*4d7e907cSAndroid Build Coastguard Worker #include <thread>
23*4d7e907cSAndroid Build Coastguard Worker #include <unordered_map>
24*4d7e907cSAndroid Build Coastguard Worker #include <vector>
25*4d7e907cSAndroid Build Coastguard Worker
26*4d7e907cSAndroid Build Coastguard Worker #define LOG_TAG "thermal_aidl_hal_test"
27*4d7e907cSAndroid Build Coastguard Worker
28*4d7e907cSAndroid Build Coastguard Worker #include <VtsCoreUtil.h>
29*4d7e907cSAndroid Build Coastguard Worker #include <aidl/Gtest.h>
30*4d7e907cSAndroid Build Coastguard Worker #include <aidl/Vintf.h>
31*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/thermal/BnCoolingDeviceChangedCallback.h>
32*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/thermal/BnThermal.h>
33*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/thermal/BnThermalChangedCallback.h>
34*4d7e907cSAndroid Build Coastguard Worker #include <android-base/logging.h>
35*4d7e907cSAndroid Build Coastguard Worker #include <android-base/properties.h>
36*4d7e907cSAndroid Build Coastguard Worker #include <android/binder_ibinder.h>
37*4d7e907cSAndroid Build Coastguard Worker #include <android/binder_interface_utils.h>
38*4d7e907cSAndroid Build Coastguard Worker #include <android/binder_manager.h>
39*4d7e907cSAndroid Build Coastguard Worker #include <android/binder_process.h>
40*4d7e907cSAndroid Build Coastguard Worker #include <android/binder_status.h>
41*4d7e907cSAndroid Build Coastguard Worker #include <gtest/gtest.h>
42*4d7e907cSAndroid Build Coastguard Worker
43*4d7e907cSAndroid Build Coastguard Worker #include <unistd.h>
44*4d7e907cSAndroid Build Coastguard Worker
45*4d7e907cSAndroid Build Coastguard Worker namespace aidl::android::hardware::thermal {
46*4d7e907cSAndroid Build Coastguard Worker
47*4d7e907cSAndroid Build Coastguard Worker namespace {
48*4d7e907cSAndroid Build Coastguard Worker
49*4d7e907cSAndroid Build Coastguard Worker using ::android::sp;
50*4d7e907cSAndroid Build Coastguard Worker using android::hardware::thermal::CoolingDevice;
51*4d7e907cSAndroid Build Coastguard Worker using android::hardware::thermal::IThermal;
52*4d7e907cSAndroid Build Coastguard Worker using android::hardware::thermal::Temperature;
53*4d7e907cSAndroid Build Coastguard Worker using android::hardware::thermal::TemperatureType;
54*4d7e907cSAndroid Build Coastguard Worker
55*4d7e907cSAndroid Build Coastguard Worker using namespace std::string_literals;
56*4d7e907cSAndroid Build Coastguard Worker using namespace std::chrono_literals;
57*4d7e907cSAndroid Build Coastguard Worker
58*4d7e907cSAndroid Build Coastguard Worker static const Temperature kThrottleTemp = {
59*4d7e907cSAndroid Build Coastguard Worker .type = TemperatureType::SKIN,
60*4d7e907cSAndroid Build Coastguard Worker .name = "test temperature sensor",
61*4d7e907cSAndroid Build Coastguard Worker .value = 98.6,
62*4d7e907cSAndroid Build Coastguard Worker .throttlingStatus = ThrottlingSeverity::CRITICAL,
63*4d7e907cSAndroid Build Coastguard Worker };
64*4d7e907cSAndroid Build Coastguard Worker
65*4d7e907cSAndroid Build Coastguard Worker static const CoolingDevice kCoolingDevice = {
66*4d7e907cSAndroid Build Coastguard Worker .type = CoolingType::CPU,
67*4d7e907cSAndroid Build Coastguard Worker .name = "test cooling device",
68*4d7e907cSAndroid Build Coastguard Worker .value = 1,
69*4d7e907cSAndroid Build Coastguard Worker .powerLimitMw = 300,
70*4d7e907cSAndroid Build Coastguard Worker .powerMw = 500,
71*4d7e907cSAndroid Build Coastguard Worker .timeWindowMs = 7000,
72*4d7e907cSAndroid Build Coastguard Worker };
73*4d7e907cSAndroid Build Coastguard Worker
74*4d7e907cSAndroid Build Coastguard Worker static const std::string FEATURE_WATCH = "android.hardware.type.watch";
75*4d7e907cSAndroid Build Coastguard Worker static const std::string FEATURE_TELEVISION = "android.hardware.type.television";
76*4d7e907cSAndroid Build Coastguard Worker static const std::string FEATURE_LEANBACK = "android.software.leanback";
77*4d7e907cSAndroid Build Coastguard Worker static const std::string FEATURE_AUTOMOTIVE = "android.hardware.type.automotive";
78*4d7e907cSAndroid Build Coastguard Worker static const std::string FEATURE_PC = "android.hardware.type.pc";
79*4d7e907cSAndroid Build Coastguard Worker static const std::string FEATURE_EMBEDDED = "android.hardware.type.embedded";
80*4d7e907cSAndroid Build Coastguard Worker static const std::string kNonHandheldFeatures[] = {FEATURE_AUTOMOTIVE, FEATURE_LEANBACK,
81*4d7e907cSAndroid Build Coastguard Worker FEATURE_PC, FEATURE_TELEVISION,
82*4d7e907cSAndroid Build Coastguard Worker FEATURE_WATCH, FEATURE_EMBEDDED};
83*4d7e907cSAndroid Build Coastguard Worker
84*4d7e907cSAndroid Build Coastguard Worker // Callback class for receiving thermal event notifications from main class
85*4d7e907cSAndroid Build Coastguard Worker class ThermalCallback : public BnThermalChangedCallback {
86*4d7e907cSAndroid Build Coastguard Worker public:
notifyThrottling(const Temperature &)87*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus notifyThrottling(const Temperature&) override {
88*4d7e907cSAndroid Build Coastguard Worker {
89*4d7e907cSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
90*4d7e907cSAndroid Build Coastguard Worker mInvoke = true;
91*4d7e907cSAndroid Build Coastguard Worker }
92*4d7e907cSAndroid Build Coastguard Worker mNotifyThrottling.notify_all();
93*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
94*4d7e907cSAndroid Build Coastguard Worker }
95*4d7e907cSAndroid Build Coastguard Worker
notifyThresholdChanged(const TemperatureThreshold &)96*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus notifyThresholdChanged(const TemperatureThreshold&) {
97*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
98*4d7e907cSAndroid Build Coastguard Worker }
99*4d7e907cSAndroid Build Coastguard Worker
100*4d7e907cSAndroid Build Coastguard Worker template <typename R, typename P>
waitForCallback(std::chrono::duration<R,P> duration)101*4d7e907cSAndroid Build Coastguard Worker [[nodiscard]] bool waitForCallback(std::chrono::duration<R, P> duration) {
102*4d7e907cSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mMutex);
103*4d7e907cSAndroid Build Coastguard Worker bool r = mNotifyThrottling.wait_for(lock, duration, [this] { return this->mInvoke; });
104*4d7e907cSAndroid Build Coastguard Worker mInvoke = false;
105*4d7e907cSAndroid Build Coastguard Worker return r;
106*4d7e907cSAndroid Build Coastguard Worker }
107*4d7e907cSAndroid Build Coastguard Worker
108*4d7e907cSAndroid Build Coastguard Worker private:
109*4d7e907cSAndroid Build Coastguard Worker std::mutex mMutex;
110*4d7e907cSAndroid Build Coastguard Worker std::condition_variable mNotifyThrottling;
111*4d7e907cSAndroid Build Coastguard Worker bool mInvoke = false;
112*4d7e907cSAndroid Build Coastguard Worker };
113*4d7e907cSAndroid Build Coastguard Worker
114*4d7e907cSAndroid Build Coastguard Worker // Callback class for receiving cooling device event notifications from main class
115*4d7e907cSAndroid Build Coastguard Worker class CoolingDeviceCallback : public BnCoolingDeviceChangedCallback {
116*4d7e907cSAndroid Build Coastguard Worker public:
notifyCoolingDeviceChanged(const CoolingDevice &)117*4d7e907cSAndroid Build Coastguard Worker ndk::ScopedAStatus notifyCoolingDeviceChanged(const CoolingDevice&) override {
118*4d7e907cSAndroid Build Coastguard Worker {
119*4d7e907cSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mMutex);
120*4d7e907cSAndroid Build Coastguard Worker mInvoke = true;
121*4d7e907cSAndroid Build Coastguard Worker }
122*4d7e907cSAndroid Build Coastguard Worker mNotifyCoolingDeviceChanged.notify_all();
123*4d7e907cSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
124*4d7e907cSAndroid Build Coastguard Worker }
125*4d7e907cSAndroid Build Coastguard Worker
126*4d7e907cSAndroid Build Coastguard Worker template <typename R, typename P>
waitForCallback(std::chrono::duration<R,P> duration)127*4d7e907cSAndroid Build Coastguard Worker [[nodiscard]] bool waitForCallback(std::chrono::duration<R, P> duration) {
128*4d7e907cSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mMutex);
129*4d7e907cSAndroid Build Coastguard Worker bool r = mNotifyCoolingDeviceChanged.wait_for(lock, duration,
130*4d7e907cSAndroid Build Coastguard Worker [this] { return this->mInvoke; });
131*4d7e907cSAndroid Build Coastguard Worker mInvoke = false;
132*4d7e907cSAndroid Build Coastguard Worker return r;
133*4d7e907cSAndroid Build Coastguard Worker }
134*4d7e907cSAndroid Build Coastguard Worker
135*4d7e907cSAndroid Build Coastguard Worker private:
136*4d7e907cSAndroid Build Coastguard Worker std::mutex mMutex;
137*4d7e907cSAndroid Build Coastguard Worker std::condition_variable mNotifyCoolingDeviceChanged;
138*4d7e907cSAndroid Build Coastguard Worker bool mInvoke = false;
139*4d7e907cSAndroid Build Coastguard Worker };
140*4d7e907cSAndroid Build Coastguard Worker
141*4d7e907cSAndroid Build Coastguard Worker // The main test class for THERMAL HIDL HAL.
142*4d7e907cSAndroid Build Coastguard Worker class ThermalAidlTest : public testing::TestWithParam<std::string> {
143*4d7e907cSAndroid Build Coastguard Worker public:
SetUp()144*4d7e907cSAndroid Build Coastguard Worker void SetUp() override {
145*4d7e907cSAndroid Build Coastguard Worker AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
146*4d7e907cSAndroid Build Coastguard Worker ASSERT_NE(binder, nullptr);
147*4d7e907cSAndroid Build Coastguard Worker mThermal = IThermal::fromBinder(ndk::SpAIBinder(binder));
148*4d7e907cSAndroid Build Coastguard Worker
149*4d7e907cSAndroid Build Coastguard Worker mThermalCallback = ndk::SharedRefBase::make<ThermalCallback>();
150*4d7e907cSAndroid Build Coastguard Worker ASSERT_NE(mThermalCallback, nullptr);
151*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus status = mThermal->registerThermalChangedCallback(mThermalCallback);
152*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.isOk()) << status.getMessage();
153*4d7e907cSAndroid Build Coastguard Worker
154*4d7e907cSAndroid Build Coastguard Worker auto ret = mThermal->getInterfaceVersion(&thermal_version);
155*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(ret.isOk()) << ret;
156*4d7e907cSAndroid Build Coastguard Worker if (thermal_version > 1) {
157*4d7e907cSAndroid Build Coastguard Worker mCoolingDeviceCallback = ndk::SharedRefBase::make<CoolingDeviceCallback>();
158*4d7e907cSAndroid Build Coastguard Worker ASSERT_NE(mCoolingDeviceCallback, nullptr);
159*4d7e907cSAndroid Build Coastguard Worker status = mThermal->registerCoolingDeviceChangedCallbackWithType(mCoolingDeviceCallback,
160*4d7e907cSAndroid Build Coastguard Worker kCoolingDevice.type);
161*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.isOk()) << status.getMessage();
162*4d7e907cSAndroid Build Coastguard Worker }
163*4d7e907cSAndroid Build Coastguard Worker }
164*4d7e907cSAndroid Build Coastguard Worker
TearDown()165*4d7e907cSAndroid Build Coastguard Worker void TearDown() override {
166*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus status = mThermal->unregisterThermalChangedCallback(mThermalCallback);
167*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.isOk()) << status.getMessage();
168*4d7e907cSAndroid Build Coastguard Worker
169*4d7e907cSAndroid Build Coastguard Worker // Expect to fail if unregister again
170*4d7e907cSAndroid Build Coastguard Worker status = mThermal->unregisterThermalChangedCallback(mThermalCallback);
171*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
172*4d7e907cSAndroid Build Coastguard Worker
173*4d7e907cSAndroid Build Coastguard Worker auto ret = mThermal->getInterfaceVersion(&thermal_version);
174*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(ret.isOk()) << ret;
175*4d7e907cSAndroid Build Coastguard Worker if (thermal_version > 1) {
176*4d7e907cSAndroid Build Coastguard Worker status = mThermal->unregisterCoolingDeviceChangedCallback(mCoolingDeviceCallback);
177*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.isOk()) << status.getMessage();
178*4d7e907cSAndroid Build Coastguard Worker status = mThermal->unregisterCoolingDeviceChangedCallback(mCoolingDeviceCallback);
179*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
180*4d7e907cSAndroid Build Coastguard Worker }
181*4d7e907cSAndroid Build Coastguard Worker }
182*4d7e907cSAndroid Build Coastguard Worker // Stores thermal version
183*4d7e907cSAndroid Build Coastguard Worker int32_t thermal_version;
184*4d7e907cSAndroid Build Coastguard Worker
185*4d7e907cSAndroid Build Coastguard Worker protected:
186*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<IThermal> mThermal;
187*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<ThermalCallback> mThermalCallback;
188*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<CoolingDeviceCallback> mCoolingDeviceCallback;
189*4d7e907cSAndroid Build Coastguard Worker };
190*4d7e907cSAndroid Build Coastguard Worker
191*4d7e907cSAndroid Build Coastguard Worker // Test ThermalChangedCallback::notifyThrottling().
192*4d7e907cSAndroid Build Coastguard Worker // This just calls into and back from our local ThermalChangedCallback impl.
TEST_P(ThermalAidlTest,NotifyThrottlingTest)193*4d7e907cSAndroid Build Coastguard Worker TEST_P(ThermalAidlTest, NotifyThrottlingTest) {
194*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<ThermalCallback> thermalCallback = ndk::SharedRefBase::make<ThermalCallback>();
195*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus status = thermalCallback->notifyThrottling(kThrottleTemp);
196*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.isOk()) << status.getMessage();
197*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(thermalCallback->waitForCallback(200ms));
198*4d7e907cSAndroid Build Coastguard Worker }
199*4d7e907cSAndroid Build Coastguard Worker
200*4d7e907cSAndroid Build Coastguard Worker // Test CoolingDeviceChangedCallback::notifyCoolingDeviceChanged().
201*4d7e907cSAndroid Build Coastguard Worker // This just calls into and back from our local CoolingDeviceChangedCallback impl.
TEST_P(ThermalAidlTest,NotifyCoolingDeviceChangedTest)202*4d7e907cSAndroid Build Coastguard Worker TEST_P(ThermalAidlTest, NotifyCoolingDeviceChangedTest) {
203*4d7e907cSAndroid Build Coastguard Worker auto ret = mThermal->getInterfaceVersion(&thermal_version);
204*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(ret.isOk()) << ret;
205*4d7e907cSAndroid Build Coastguard Worker if (thermal_version < 2) {
206*4d7e907cSAndroid Build Coastguard Worker return;
207*4d7e907cSAndroid Build Coastguard Worker }
208*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<CoolingDeviceCallback> cdevCallback =
209*4d7e907cSAndroid Build Coastguard Worker ndk::SharedRefBase::make<CoolingDeviceCallback>();
210*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus status = cdevCallback->notifyCoolingDeviceChanged(kCoolingDevice);
211*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.isOk()) << status.getMessage();
212*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(cdevCallback->waitForCallback(200ms));
213*4d7e907cSAndroid Build Coastguard Worker }
214*4d7e907cSAndroid Build Coastguard Worker
215*4d7e907cSAndroid Build Coastguard Worker // Test Thermal->registerThermalChangedCallback.
TEST_P(ThermalAidlTest,RegisterThermalChangedCallbackTest)216*4d7e907cSAndroid Build Coastguard Worker TEST_P(ThermalAidlTest, RegisterThermalChangedCallbackTest) {
217*4d7e907cSAndroid Build Coastguard Worker // Expect to fail with same callback
218*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus status = mThermal->registerThermalChangedCallback(mThermalCallback);
219*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
220*4d7e907cSAndroid Build Coastguard Worker // Expect to fail with null callback
221*4d7e907cSAndroid Build Coastguard Worker status = mThermal->registerThermalChangedCallback(nullptr);
222*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT
223*4d7e907cSAndroid Build Coastguard Worker || status.getExceptionCode() == EX_NULL_POINTER);
224*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<ThermalCallback> localThermalCallback =
225*4d7e907cSAndroid Build Coastguard Worker ndk::SharedRefBase::make<ThermalCallback>();
226*4d7e907cSAndroid Build Coastguard Worker // Expect to succeed with different callback
227*4d7e907cSAndroid Build Coastguard Worker status = mThermal->registerThermalChangedCallback(localThermalCallback);
228*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.isOk()) << status.getMessage();
229*4d7e907cSAndroid Build Coastguard Worker // Remove the local callback
230*4d7e907cSAndroid Build Coastguard Worker status = mThermal->unregisterThermalChangedCallback(localThermalCallback);
231*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.isOk()) << status.getMessage();
232*4d7e907cSAndroid Build Coastguard Worker // Expect to fail with null callback
233*4d7e907cSAndroid Build Coastguard Worker status = mThermal->unregisterThermalChangedCallback(nullptr);
234*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT
235*4d7e907cSAndroid Build Coastguard Worker || status.getExceptionCode() == EX_NULL_POINTER);
236*4d7e907cSAndroid Build Coastguard Worker }
237*4d7e907cSAndroid Build Coastguard Worker
238*4d7e907cSAndroid Build Coastguard Worker // Test Thermal->registerThermalChangedCallbackWithType.
TEST_P(ThermalAidlTest,RegisterThermalChangedCallbackWithTypeTest)239*4d7e907cSAndroid Build Coastguard Worker TEST_P(ThermalAidlTest, RegisterThermalChangedCallbackWithTypeTest) {
240*4d7e907cSAndroid Build Coastguard Worker // Expect to fail with same callback
241*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus status = mThermal->registerThermalChangedCallbackWithType(
242*4d7e907cSAndroid Build Coastguard Worker mThermalCallback, TemperatureType::SKIN);
243*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
244*4d7e907cSAndroid Build Coastguard Worker // Expect to fail with null callback
245*4d7e907cSAndroid Build Coastguard Worker status = mThermal->registerThermalChangedCallbackWithType(nullptr, TemperatureType::SKIN);
246*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT
247*4d7e907cSAndroid Build Coastguard Worker || status.getExceptionCode() == EX_NULL_POINTER);
248*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<ThermalCallback> localThermalCallback =
249*4d7e907cSAndroid Build Coastguard Worker ndk::SharedRefBase::make<ThermalCallback>();
250*4d7e907cSAndroid Build Coastguard Worker // Expect to succeed with different callback
251*4d7e907cSAndroid Build Coastguard Worker status = mThermal->registerThermalChangedCallbackWithType(localThermalCallback,
252*4d7e907cSAndroid Build Coastguard Worker TemperatureType::SKIN);
253*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.isOk()) << status.getMessage();
254*4d7e907cSAndroid Build Coastguard Worker // Remove the local callback
255*4d7e907cSAndroid Build Coastguard Worker status = mThermal->unregisterThermalChangedCallback(localThermalCallback);
256*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.isOk()) << status.getMessage();
257*4d7e907cSAndroid Build Coastguard Worker // Expect to fail with null callback
258*4d7e907cSAndroid Build Coastguard Worker status = mThermal->unregisterThermalChangedCallback(nullptr);
259*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT
260*4d7e907cSAndroid Build Coastguard Worker || status.getExceptionCode() == EX_NULL_POINTER);
261*4d7e907cSAndroid Build Coastguard Worker }
262*4d7e907cSAndroid Build Coastguard Worker
263*4d7e907cSAndroid Build Coastguard Worker // Test Thermal->registerCoolingDeviceChangedCallbackWithType.
TEST_P(ThermalAidlTest,RegisterCoolingDeviceChangedCallbackWithTypeTest)264*4d7e907cSAndroid Build Coastguard Worker TEST_P(ThermalAidlTest, RegisterCoolingDeviceChangedCallbackWithTypeTest) {
265*4d7e907cSAndroid Build Coastguard Worker auto ret = mThermal->getInterfaceVersion(&thermal_version);
266*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(ret.isOk()) << ret;
267*4d7e907cSAndroid Build Coastguard Worker if (thermal_version < 2) {
268*4d7e907cSAndroid Build Coastguard Worker return;
269*4d7e907cSAndroid Build Coastguard Worker }
270*4d7e907cSAndroid Build Coastguard Worker
271*4d7e907cSAndroid Build Coastguard Worker // Expect to fail with same callback
272*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus status = mThermal->registerCoolingDeviceChangedCallbackWithType(
273*4d7e907cSAndroid Build Coastguard Worker mCoolingDeviceCallback, CoolingType::CPU);
274*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
275*4d7e907cSAndroid Build Coastguard Worker // Expect to fail with null callback
276*4d7e907cSAndroid Build Coastguard Worker status = mThermal->registerCoolingDeviceChangedCallbackWithType(nullptr, CoolingType::CPU);
277*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT ||
278*4d7e907cSAndroid Build Coastguard Worker status.getExceptionCode() == EX_NULL_POINTER);
279*4d7e907cSAndroid Build Coastguard Worker std::shared_ptr<CoolingDeviceCallback> localCoolingDeviceCallback =
280*4d7e907cSAndroid Build Coastguard Worker ndk::SharedRefBase::make<CoolingDeviceCallback>();
281*4d7e907cSAndroid Build Coastguard Worker // Expect to succeed with different callback
282*4d7e907cSAndroid Build Coastguard Worker status = mThermal->registerCoolingDeviceChangedCallbackWithType(localCoolingDeviceCallback,
283*4d7e907cSAndroid Build Coastguard Worker CoolingType::CPU);
284*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.isOk()) << status.getMessage();
285*4d7e907cSAndroid Build Coastguard Worker // Remove the local callback
286*4d7e907cSAndroid Build Coastguard Worker status = mThermal->unregisterCoolingDeviceChangedCallback(localCoolingDeviceCallback);
287*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.isOk()) << status.getMessage();
288*4d7e907cSAndroid Build Coastguard Worker // Expect to fail with null callback
289*4d7e907cSAndroid Build Coastguard Worker status = mThermal->unregisterCoolingDeviceChangedCallback(nullptr);
290*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.getExceptionCode() == EX_ILLEGAL_ARGUMENT ||
291*4d7e907cSAndroid Build Coastguard Worker status.getExceptionCode() == EX_NULL_POINTER);
292*4d7e907cSAndroid Build Coastguard Worker }
293*4d7e907cSAndroid Build Coastguard Worker
294*4d7e907cSAndroid Build Coastguard Worker // Test Thermal->getCurrentTemperatures().
TEST_P(ThermalAidlTest,TemperatureTest)295*4d7e907cSAndroid Build Coastguard Worker TEST_P(ThermalAidlTest, TemperatureTest) {
296*4d7e907cSAndroid Build Coastguard Worker std::vector<Temperature> ret;
297*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus status = mThermal->getTemperatures(&ret);
298*4d7e907cSAndroid Build Coastguard Worker if (status.isOk()) {
299*4d7e907cSAndroid Build Coastguard Worker for (auto& i : ret) {
300*4d7e907cSAndroid Build Coastguard Worker EXPECT_LT(0u, i.name.size());
301*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << i.name + " " + toString(i.type) << "\n";
302*4d7e907cSAndroid Build Coastguard Worker }
303*4d7e907cSAndroid Build Coastguard Worker } else {
304*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
305*4d7e907cSAndroid Build Coastguard Worker }
306*4d7e907cSAndroid Build Coastguard Worker
307*4d7e907cSAndroid Build Coastguard Worker auto types = ::ndk::enum_range<TemperatureType>();
308*4d7e907cSAndroid Build Coastguard Worker for (const auto& type : types) {
309*4d7e907cSAndroid Build Coastguard Worker status = mThermal->getTemperaturesWithType(type, &ret);
310*4d7e907cSAndroid Build Coastguard Worker
311*4d7e907cSAndroid Build Coastguard Worker if (status.isOk()) {
312*4d7e907cSAndroid Build Coastguard Worker for (auto& i : ret) {
313*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(type, i.type) << "Expect type " + toString(type) + " but got " +
314*4d7e907cSAndroid Build Coastguard Worker toString(i.type) + " for " + i.name;
315*4d7e907cSAndroid Build Coastguard Worker EXPECT_LT(0u, i.name.size());
316*4d7e907cSAndroid Build Coastguard Worker }
317*4d7e907cSAndroid Build Coastguard Worker } else {
318*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
319*4d7e907cSAndroid Build Coastguard Worker }
320*4d7e907cSAndroid Build Coastguard Worker }
321*4d7e907cSAndroid Build Coastguard Worker }
322*4d7e907cSAndroid Build Coastguard Worker
323*4d7e907cSAndroid Build Coastguard Worker // Test Thermal->getTemperatureThresholds().
TEST_P(ThermalAidlTest,TemperatureThresholdTest)324*4d7e907cSAndroid Build Coastguard Worker TEST_P(ThermalAidlTest, TemperatureThresholdTest) {
325*4d7e907cSAndroid Build Coastguard Worker std::vector<TemperatureThreshold> ret;
326*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus status = mThermal->getTemperatureThresholds(&ret);
327*4d7e907cSAndroid Build Coastguard Worker if (status.isOk()) {
328*4d7e907cSAndroid Build Coastguard Worker for (auto& i : ret) {
329*4d7e907cSAndroid Build Coastguard Worker EXPECT_LT(0u, i.name.size());
330*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << i.name + " " + toString(i.type) << "\n";
331*4d7e907cSAndroid Build Coastguard Worker }
332*4d7e907cSAndroid Build Coastguard Worker } else {
333*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
334*4d7e907cSAndroid Build Coastguard Worker }
335*4d7e907cSAndroid Build Coastguard Worker
336*4d7e907cSAndroid Build Coastguard Worker auto types = ::ndk::enum_range<TemperatureType>();
337*4d7e907cSAndroid Build Coastguard Worker for (const auto& type : types) {
338*4d7e907cSAndroid Build Coastguard Worker status = mThermal->getTemperatureThresholdsWithType(type, &ret);
339*4d7e907cSAndroid Build Coastguard Worker
340*4d7e907cSAndroid Build Coastguard Worker if (status.isOk()) {
341*4d7e907cSAndroid Build Coastguard Worker for (auto& i : ret) {
342*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(type, i.type) << "Expect type " + toString(type) + " but got " +
343*4d7e907cSAndroid Build Coastguard Worker toString(i.type) + " for " + i.name;
344*4d7e907cSAndroid Build Coastguard Worker EXPECT_LT(0u, i.name.size());
345*4d7e907cSAndroid Build Coastguard Worker }
346*4d7e907cSAndroid Build Coastguard Worker } else {
347*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
348*4d7e907cSAndroid Build Coastguard Worker }
349*4d7e907cSAndroid Build Coastguard Worker }
350*4d7e907cSAndroid Build Coastguard Worker }
351*4d7e907cSAndroid Build Coastguard Worker
352*4d7e907cSAndroid Build Coastguard Worker // Test Thermal->getTemperatureThresholdsWithType(SKIN).
353*4d7e907cSAndroid Build Coastguard Worker // @VsrTest = GMS-VSR-3.2.5-001
354*4d7e907cSAndroid Build Coastguard Worker // @VsrTest = VSR-3.2.5-001
355*4d7e907cSAndroid Build Coastguard Worker // @VsrTest = GMS-VSR-3.2.5-002
356*4d7e907cSAndroid Build Coastguard Worker // @VsrTest = VSR-3.2.5-002
TEST_P(ThermalAidlTest,SkinTemperatureThresholdsTest)357*4d7e907cSAndroid Build Coastguard Worker TEST_P(ThermalAidlTest, SkinTemperatureThresholdsTest) {
358*4d7e907cSAndroid Build Coastguard Worker auto apiLevel = ::android::base::GetIntProperty<int32_t>("ro.vendor.api_level", 0);
359*4d7e907cSAndroid Build Coastguard Worker if (apiLevel < 202404) {
360*4d7e907cSAndroid Build Coastguard Worker GTEST_SKIP() << "Skipping test as the vendor level is below 202404: " << apiLevel;
361*4d7e907cSAndroid Build Coastguard Worker }
362*4d7e907cSAndroid Build Coastguard Worker for (const auto& feature : kNonHandheldFeatures) {
363*4d7e907cSAndroid Build Coastguard Worker if (::testing::deviceSupportsFeature(feature.c_str())) {
364*4d7e907cSAndroid Build Coastguard Worker GTEST_SKIP() << "Skipping test as the device has feature: " << feature;
365*4d7e907cSAndroid Build Coastguard Worker }
366*4d7e907cSAndroid Build Coastguard Worker }
367*4d7e907cSAndroid Build Coastguard Worker std::vector<Temperature> temperatures;
368*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus status =
369*4d7e907cSAndroid Build Coastguard Worker mThermal->getTemperaturesWithType(TemperatureType::SKIN, &temperatures);
370*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.isOk()) << "getTemperaturesWithType(SKIN) failed";
371*4d7e907cSAndroid Build Coastguard Worker ASSERT_FALSE(temperatures.empty()) << "getTemperaturesWithType(SKIN) returns empty";
372*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(1, temperatures.size())
373*4d7e907cSAndroid Build Coastguard Worker << "getTemperaturesWithType(SKIN) returns multiple temperatures";
374*4d7e907cSAndroid Build Coastguard Worker
375*4d7e907cSAndroid Build Coastguard Worker std::vector<TemperatureThreshold> thresholds;
376*4d7e907cSAndroid Build Coastguard Worker status = mThermal->getTemperatureThresholdsWithType(TemperatureType::SKIN, &thresholds);
377*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.isOk()) << "getTemperatureThresholdsWithType(SKIN) failed";
378*4d7e907cSAndroid Build Coastguard Worker ASSERT_FALSE(thresholds.empty()) << "getTemperatureThresholdsWithType(SKIN) returns empty";
379*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(1, thresholds.size())
380*4d7e907cSAndroid Build Coastguard Worker << "getTemperatureThresholdsWithType(SKIN) returns multiple thresholds";
381*4d7e907cSAndroid Build Coastguard Worker auto temperature = temperatures[0];
382*4d7e907cSAndroid Build Coastguard Worker auto threshold = thresholds[0];
383*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(temperature.name, threshold.name);
384*4d7e907cSAndroid Build Coastguard Worker auto severities = ::ndk::enum_range<ThrottlingSeverity>();
385*4d7e907cSAndroid Build Coastguard Worker auto cardinality = std::distance(severities.begin(), severities.end());
386*4d7e907cSAndroid Build Coastguard Worker ASSERT_NE(NAN, temperature.value);
387*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(cardinality, threshold.hotThrottlingThresholds.size());
388*4d7e907cSAndroid Build Coastguard Worker float lastThreshold = threshold.hotThrottlingThresholds[1];
389*4d7e907cSAndroid Build Coastguard Worker // skip NONE, and check that the rest should be set and non-decreasing
390*4d7e907cSAndroid Build Coastguard Worker for (auto i = 2; i < cardinality; i++) {
391*4d7e907cSAndroid Build Coastguard Worker float t = threshold.hotThrottlingThresholds[i];
392*4d7e907cSAndroid Build Coastguard Worker ASSERT_NE(NAN, t);
393*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(t >= lastThreshold) << "Temperature thresholds should be non-decreasing "
394*4d7e907cSAndroid Build Coastguard Worker << "but got " << t << " for status " << i << " and "
395*4d7e907cSAndroid Build Coastguard Worker << lastThreshold << " for status " << i - 1;
396*4d7e907cSAndroid Build Coastguard Worker lastThreshold = t;
397*4d7e907cSAndroid Build Coastguard Worker }
398*4d7e907cSAndroid Build Coastguard Worker }
399*4d7e907cSAndroid Build Coastguard Worker
400*4d7e907cSAndroid Build Coastguard Worker // Test Thermal->getCoolingDevices().
TEST_P(ThermalAidlTest,CoolingDeviceTest)401*4d7e907cSAndroid Build Coastguard Worker TEST_P(ThermalAidlTest, CoolingDeviceTest) {
402*4d7e907cSAndroid Build Coastguard Worker std::vector<CoolingDevice> ret;
403*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus status = mThermal->getCoolingDevices(&ret);
404*4d7e907cSAndroid Build Coastguard Worker if (status.isOk()) {
405*4d7e907cSAndroid Build Coastguard Worker for (auto& i : ret) {
406*4d7e907cSAndroid Build Coastguard Worker EXPECT_LT(0u, i.name.size());
407*4d7e907cSAndroid Build Coastguard Worker LOG(INFO) << i.name + " " + toString(i.type) << "\n";
408*4d7e907cSAndroid Build Coastguard Worker }
409*4d7e907cSAndroid Build Coastguard Worker } else {
410*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
411*4d7e907cSAndroid Build Coastguard Worker }
412*4d7e907cSAndroid Build Coastguard Worker
413*4d7e907cSAndroid Build Coastguard Worker auto types = ::ndk::enum_range<CoolingType>();
414*4d7e907cSAndroid Build Coastguard Worker for (const auto& type : types) {
415*4d7e907cSAndroid Build Coastguard Worker status = mThermal->getCoolingDevicesWithType(type, &ret);
416*4d7e907cSAndroid Build Coastguard Worker if (status.isOk()) {
417*4d7e907cSAndroid Build Coastguard Worker ASSERT_TRUE(status.isOk());
418*4d7e907cSAndroid Build Coastguard Worker for (auto& i : ret) {
419*4d7e907cSAndroid Build Coastguard Worker EXPECT_EQ(type, i.type) << "Expect type " + toString(type) + " but got " +
420*4d7e907cSAndroid Build Coastguard Worker toString(i.type) + " for " + i.name;
421*4d7e907cSAndroid Build Coastguard Worker EXPECT_LT(0u, i.name.size());
422*4d7e907cSAndroid Build Coastguard Worker }
423*4d7e907cSAndroid Build Coastguard Worker } else {
424*4d7e907cSAndroid Build Coastguard Worker ASSERT_EQ(EX_ILLEGAL_STATE, status.getExceptionCode());
425*4d7e907cSAndroid Build Coastguard Worker }
426*4d7e907cSAndroid Build Coastguard Worker }
427*4d7e907cSAndroid Build Coastguard Worker }
428*4d7e907cSAndroid Build Coastguard Worker
429*4d7e907cSAndroid Build Coastguard Worker // Test Thermal->forecastSkinTemperature.
TEST_P(ThermalAidlTest,ForecastSkinTemperatureTest)430*4d7e907cSAndroid Build Coastguard Worker TEST_P(ThermalAidlTest, ForecastSkinTemperatureTest) {
431*4d7e907cSAndroid Build Coastguard Worker auto apiLevel = ::android::base::GetIntProperty<int32_t>("ro.vendor.api_level", 0);
432*4d7e907cSAndroid Build Coastguard Worker if (apiLevel < 202504) {
433*4d7e907cSAndroid Build Coastguard Worker GTEST_SKIP() << "Skipping test as the vendor level is below 202504: " << apiLevel;
434*4d7e907cSAndroid Build Coastguard Worker }
435*4d7e907cSAndroid Build Coastguard Worker float temperature = 0.0f;
436*4d7e907cSAndroid Build Coastguard Worker ::ndk::ScopedAStatus status = mThermal->forecastSkinTemperature(1, &temperature);
437*4d7e907cSAndroid Build Coastguard Worker if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
438*4d7e907cSAndroid Build Coastguard Worker GTEST_SKIP() << "Skipping test as temperature forecast is not supported";
439*4d7e907cSAndroid Build Coastguard Worker }
440*4d7e907cSAndroid Build Coastguard Worker for (int i = 0; i <= 60; i++) {
441*4d7e907cSAndroid Build Coastguard Worker status = mThermal->forecastSkinTemperature(i, &temperature);
442*4d7e907cSAndroid Build Coastguard Worker ASSERT_NE(NAN, temperature);
443*4d7e907cSAndroid Build Coastguard Worker }
444*4d7e907cSAndroid Build Coastguard Worker }
445*4d7e907cSAndroid Build Coastguard Worker
446*4d7e907cSAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ThermalAidlTest);
447*4d7e907cSAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(
448*4d7e907cSAndroid Build Coastguard Worker Thermal, ThermalAidlTest,
449*4d7e907cSAndroid Build Coastguard Worker testing::ValuesIn(::android::getAidlHalInstanceNames(IThermal::descriptor)),
450*4d7e907cSAndroid Build Coastguard Worker ::android::PrintInstanceNameToString);
451*4d7e907cSAndroid Build Coastguard Worker
452*4d7e907cSAndroid Build Coastguard Worker } // namespace
453*4d7e907cSAndroid Build Coastguard Worker } // namespace aidl::android::hardware::thermal
454*4d7e907cSAndroid Build Coastguard Worker
main(int argc,char ** argv)455*4d7e907cSAndroid Build Coastguard Worker int main(int argc, char** argv) {
456*4d7e907cSAndroid Build Coastguard Worker ::testing::InitGoogleTest(&argc, argv);
457*4d7e907cSAndroid Build Coastguard Worker ABinderProcess_setThreadPoolMaxThreadCount(1);
458*4d7e907cSAndroid Build Coastguard Worker ABinderProcess_startThreadPool();
459*4d7e907cSAndroid Build Coastguard Worker return RUN_ALL_TESTS();
460*4d7e907cSAndroid Build Coastguard Worker }
461