1 /*
2 * Copyright (C) 2023 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 #define LOG_TAG "NativeThermalUnitTest"
18
19 #include <android/os/IThermalService.h>
20 #include <android/thermal.h>
21 #include <binder/IBinder.h>
22 #include <gmock/gmock.h>
23 #include <gtest/gtest.h>
24 #include <thermal_private.h>
25
26 using android::binder::Status;
27
28 using namespace testing;
29 using namespace android;
30 using namespace android::os;
31
32 class MockIThermalService : public IThermalService {
33 public:
34 MOCK_METHOD(Status, registerThermalEventListener,
35 (const ::android::sp<::android::os::IThermalEventListener>& listener,
36 bool* _aidl_return),
37 (override));
38 MOCK_METHOD(Status, registerThermalEventListenerWithType,
39 (const ::android::sp<::android::os::IThermalEventListener>& listener, int32_t type,
40 bool* _aidl_return),
41 (override));
42 MOCK_METHOD(Status, unregisterThermalEventListener,
43 (const ::android::sp<::android::os::IThermalEventListener>& listener,
44 bool* _aidl_return),
45 (override));
46 MOCK_METHOD(Status, getCurrentTemperatures,
47 (::std::vector<::android::os::Temperature> * _aidl_return), (override));
48 MOCK_METHOD(Status, getCurrentTemperaturesWithType,
49 (int32_t type, ::std::vector<::android::os::Temperature>* _aidl_return),
50 (override));
51 MOCK_METHOD(Status, registerThermalStatusListener,
52 (const ::android::sp<::android::os::IThermalStatusListener>& listener,
53 bool* _aidl_return),
54 (override));
55 MOCK_METHOD(Status, unregisterThermalStatusListener,
56 (const ::android::sp<::android::os::IThermalStatusListener>& listener,
57 bool* _aidl_return),
58 (override));
59 MOCK_METHOD(Status, getCurrentThermalStatus, (int32_t * _aidl_return), (override));
60 MOCK_METHOD(Status, getCurrentCoolingDevices,
61 (::std::vector<::android::os::CoolingDevice> * _aidl_return), (override));
62 MOCK_METHOD(Status, getCurrentCoolingDevicesWithType,
63 (int32_t type, ::std::vector<::android::os::CoolingDevice>* _aidl_return),
64 (override));
65 MOCK_METHOD(Status, getThermalHeadroom, (int32_t forecastSeconds, float* _aidl_return),
66 (override));
67 MOCK_METHOD(Status, getThermalHeadroomThresholds, (::std::vector<float> * _aidl_return),
68 (override));
69 MOCK_METHOD(IBinder*, onAsBinder, (), (override));
70 MOCK_METHOD(Status, registerThermalHeadroomListener,
71 (const ::android::sp<::android::os::IThermalHeadroomListener>& listener,
72 bool* _aidl_return),
73 (override));
74 MOCK_METHOD(Status, unregisterThermalHeadroomListener,
75 (const ::android::sp<::android::os::IThermalHeadroomListener>& listener,
76 bool* _aidl_return),
77 (override));
78 };
79
80 struct HeadroomCallbackData {
81 void* data;
82 float headroom;
83 float forecast;
84 int32_t forecastSeconds;
85 const std::vector<float> thresholds;
86 };
87
88 struct StatusCallbackData {
89 void* data;
90 AThermalStatus status;
91 };
92
93 static std::optional<HeadroomCallbackData> headroomCalled1;
94 static std::optional<HeadroomCallbackData> headroomCalled2;
95 static std::optional<StatusCallbackData> statusCalled1;
96 static std::optional<StatusCallbackData> statusCalled2;
97
convertThresholds(const AThermalHeadroomThreshold * thresholds,size_t size)98 static std::vector<float> convertThresholds(const AThermalHeadroomThreshold* thresholds,
99 size_t size) {
100 std::vector<float> ret;
101 for (int i = 0; i < (int)size; i++) {
102 ret.emplace_back(thresholds[i].headroom);
103 }
104 return ret;
105 };
106
onHeadroomChange1(void * data,float headroom,float forecast,int32_t forecastSeconds,const AThermalHeadroomThreshold * thresholds,size_t size)107 static void onHeadroomChange1(void* data, float headroom, float forecast, int32_t forecastSeconds,
108 const AThermalHeadroomThreshold* thresholds, size_t size) {
109 headroomCalled1.emplace(data, headroom, forecast, forecastSeconds,
110 convertThresholds(thresholds, size));
111 }
112
onHeadroomChange2(void * data,float headroom,float forecast,int32_t forecastSeconds,const AThermalHeadroomThreshold * thresholds,size_t size)113 static void onHeadroomChange2(void* data, float headroom, float forecast, int32_t forecastSeconds,
114 const AThermalHeadroomThreshold* thresholds, size_t size) {
115 headroomCalled2.emplace(data, headroom, forecast, forecastSeconds,
116 convertThresholds(thresholds, size));
117 }
118
onStatusChange1(void * data,AThermalStatus status)119 static void onStatusChange1(void* data, AThermalStatus status) {
120 statusCalled1.emplace(data, status);
121 }
onStatusChange2(void * data,AThermalStatus status)122 static void onStatusChange2(void* data, AThermalStatus status) {
123 statusCalled2.emplace(data, status);
124 }
125
126 class NativeThermalUnitTest : public Test {
127 public:
SetUp()128 void SetUp() override {
129 mMockIThermalService = new StrictMock<MockIThermalService>();
130 AThermal_setIThermalServiceForTesting(mMockIThermalService);
131 mThermalManager = AThermal_acquireManager();
132 headroomCalled1.reset();
133 headroomCalled2.reset();
134 statusCalled1.reset();
135 statusCalled2.reset();
136 }
137
TearDown()138 void TearDown() override {
139 AThermal_setIThermalServiceForTesting(nullptr);
140 AThermal_releaseManager(mThermalManager);
141 }
142
143 StrictMock<MockIThermalService>* mMockIThermalService = nullptr;
144 AThermalManager* mThermalManager = nullptr;
145 };
146
checkThermalHeadroomThresholds(const std::vector<float> & expected,const AThermalHeadroomThreshold * thresholds,size_t size)147 static void checkThermalHeadroomThresholds(const std::vector<float>& expected,
148 const AThermalHeadroomThreshold* thresholds,
149 size_t size) {
150 if (thresholds == nullptr) {
151 FAIL() << "Unexpected null thresholds pointer";
152 }
153 for (int i = 0; i < (int)size; i++) {
154 auto t = thresholds[i];
155 ASSERT_EQ(i, t.thermalStatus) << "threshold " << i << " should have status " << i;
156 ASSERT_EQ(expected[i], t.headroom)
157 << "threshold " << i << " should have headroom " << expected[i];
158 }
159 }
160
TEST_F(NativeThermalUnitTest,TestGetThermalHeadroomThresholds)161 TEST_F(NativeThermalUnitTest, TestGetThermalHeadroomThresholds) {
162 std::vector<float> expected = {1, 2, 3, 4, 5, 6, 7, 8, 9};
163 EXPECT_CALL(*mMockIThermalService, getThermalHeadroomThresholds(_))
164 .Times(Exactly(1))
165 .WillRepeatedly(DoAll(SetArgPointee<0>(expected), Return(Status())));
166 const AThermalHeadroomThreshold* thresholds1 = nullptr;
167 size_t size1;
168 ASSERT_EQ(OK, AThermal_getThermalHeadroomThresholds(mThermalManager, &thresholds1, &size1));
169 checkThermalHeadroomThresholds(expected, thresholds1, size1);
170 // following calls should not be cached
171 expected = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
172 EXPECT_CALL(*mMockIThermalService, getThermalHeadroomThresholds(_))
173 .Times(Exactly(1))
174 .WillRepeatedly(DoAll(SetArgPointee<0>(expected), Return(Status())));
175 const AThermalHeadroomThreshold* thresholds2 = nullptr;
176 size_t size2;
177 ASSERT_EQ(OK, AThermal_getThermalHeadroomThresholds(mThermalManager, &thresholds2, &size2));
178 checkThermalHeadroomThresholds(expected, thresholds2, size2);
179 }
180
TEST_F(NativeThermalUnitTest,TestGetThermalHeadroomThresholdsFailedWithServerError)181 TEST_F(NativeThermalUnitTest, TestGetThermalHeadroomThresholdsFailedWithServerError) {
182 const AThermalHeadroomThreshold* thresholds = nullptr;
183 size_t size;
184 EXPECT_CALL(*mMockIThermalService, getThermalHeadroomThresholds(_))
185 .Times(Exactly(1))
186 .WillOnce(Return(
187 Status::fromExceptionCode(binder::Status::Exception::EX_ILLEGAL_ARGUMENT)));
188 ASSERT_EQ(EPIPE, AThermal_getThermalHeadroomThresholds(mThermalManager, &thresholds, &size));
189 ASSERT_EQ(nullptr, thresholds);
190 }
191
TEST_F(NativeThermalUnitTest,TestGetThermalHeadroomThresholdsFailedWithFeatureDisabled)192 TEST_F(NativeThermalUnitTest, TestGetThermalHeadroomThresholdsFailedWithFeatureDisabled) {
193 const AThermalHeadroomThreshold* thresholds = nullptr;
194 size_t size;
195 EXPECT_CALL(*mMockIThermalService, getThermalHeadroomThresholds(_))
196 .Times(Exactly(1))
197 .WillOnce(Return(Status::fromExceptionCode(
198 binder::Status::Exception::EX_UNSUPPORTED_OPERATION)));
199 ASSERT_EQ(ENOSYS, AThermal_getThermalHeadroomThresholds(mThermalManager, &thresholds, &size));
200 ASSERT_EQ(nullptr, thresholds);
201 }
202
TEST_F(NativeThermalUnitTest,TestGetThermalHeadroomThresholdsFailedWithNullPtr)203 TEST_F(NativeThermalUnitTest, TestGetThermalHeadroomThresholdsFailedWithNullPtr) {
204 const AThermalHeadroomThreshold* thresholds = nullptr;
205 size_t size;
206 size_t* nullSize = nullptr;
207 ASSERT_EQ(EINVAL,
208 AThermal_getThermalHeadroomThresholds(mThermalManager, &thresholds, nullSize));
209 ASSERT_EQ(nullptr, thresholds);
210 ASSERT_EQ(EINVAL, AThermal_getThermalHeadroomThresholds(mThermalManager, nullptr, &size));
211 }
212
TEST_F(NativeThermalUnitTest,TestGetThermalHeadroomThresholdsFailedWithNonEmptyPtr)213 TEST_F(NativeThermalUnitTest, TestGetThermalHeadroomThresholdsFailedWithNonEmptyPtr) {
214 const AThermalHeadroomThreshold* initialized = new AThermalHeadroomThreshold[1];
215 size_t size;
216 ASSERT_EQ(EINVAL, AThermal_getThermalHeadroomThresholds(mThermalManager, &initialized, &size));
217 delete[] initialized;
218 }
219
TEST_F(NativeThermalUnitTest,TestRegisterThermalHeadroomListener)220 TEST_F(NativeThermalUnitTest, TestRegisterThermalHeadroomListener) {
221 EXPECT_CALL(*mMockIThermalService, registerThermalHeadroomListener(_, _))
222 .Times(Exactly(2))
223 .WillOnce(Return(
224 Status::fromExceptionCode(binder::Status::Exception::EX_TRANSACTION_FAILED)));
225 float data1 = 1.0f;
226 float data2 = 2.0f;
227 ASSERT_EQ(EPIPE,
228 AThermal_registerThermalHeadroomListener(mThermalManager, onHeadroomChange1, &data1));
229 ASSERT_EQ(EPIPE,
230 AThermal_registerThermalHeadroomListener(mThermalManager, onHeadroomChange2, &data2));
231
232 // verify only 1 service call to register a global listener
233 sp<IThermalHeadroomListener> capturedServiceListener;
234 Mock::VerifyAndClearExpectations(mMockIThermalService);
235 EXPECT_CALL(*mMockIThermalService, registerThermalHeadroomListener(_, _))
236 .Times(Exactly(1))
237 .WillOnce(DoAll(testing::SaveArg<0>(&capturedServiceListener),
238 testing::Invoke([](const sp<IThermalHeadroomListener>&,
239 bool* aidl_return) { *aidl_return = true; }),
240 Return(Status::ok())));
241 ASSERT_EQ(0,
242 AThermal_registerThermalHeadroomListener(mThermalManager, onHeadroomChange1, &data1));
243 ASSERT_EQ(EINVAL,
244 AThermal_registerThermalHeadroomListener(mThermalManager, onHeadroomChange1, &data1));
245 ASSERT_EQ(0,
246 AThermal_registerThermalHeadroomListener(mThermalManager, onHeadroomChange2, &data2));
247 const ::std::vector<float> thresholds = {0.1f, 0.2f};
248 capturedServiceListener->onHeadroomChange(0.1f, 0.3f, 20, thresholds);
249 ASSERT_TRUE(headroomCalled1.has_value());
250 EXPECT_EQ(headroomCalled1->data, &data1);
251 EXPECT_EQ(headroomCalled1->headroom, 0.1f);
252 EXPECT_EQ(headroomCalled1->forecast, 0.3f);
253 EXPECT_EQ(headroomCalled1->forecastSeconds, 20);
254 EXPECT_EQ(headroomCalled1->thresholds, thresholds);
255 ASSERT_TRUE(headroomCalled2.has_value());
256 EXPECT_EQ(headroomCalled2->data, &data2);
257 EXPECT_EQ(headroomCalled2->headroom, 0.1f);
258 EXPECT_EQ(headroomCalled2->forecast, 0.3f);
259 EXPECT_EQ(headroomCalled2->forecastSeconds, 20);
260 EXPECT_EQ(headroomCalled2->thresholds, thresholds);
261
262 // after test finished the global service listener should be unregistered
263 EXPECT_CALL(*mMockIThermalService, unregisterThermalHeadroomListener(_, _))
264 .Times(Exactly(1))
265 .WillOnce(Return(binder::Status::ok()));
266 }
267
TEST_F(NativeThermalUnitTest,TestUnregisterThermalHeadroomListener)268 TEST_F(NativeThermalUnitTest, TestUnregisterThermalHeadroomListener) {
269 sp<IThermalHeadroomListener> capturedServiceListener;
270 EXPECT_CALL(*mMockIThermalService, registerThermalHeadroomListener(_, _))
271 .Times(Exactly(1))
272 .WillOnce(DoAll(testing::SaveArg<0>(&capturedServiceListener),
273 testing::Invoke([](const sp<IThermalHeadroomListener>&,
274 bool* aidl_return) { *aidl_return = true; }),
275 Return(Status::ok())));
276 float data1 = 1.0f;
277 float data2 = 2.0f;
278 ASSERT_EQ(0,
279 AThermal_registerThermalHeadroomListener(mThermalManager, onHeadroomChange1, &data1));
280 ASSERT_EQ(0,
281 AThermal_registerThermalHeadroomListener(mThermalManager, onHeadroomChange2, &data2));
282 capturedServiceListener->onHeadroomChange(0.1f, 0.3f, 20, {});
283 ASSERT_TRUE(headroomCalled1.has_value());
284 ASSERT_TRUE(headroomCalled2.has_value());
285
286 EXPECT_CALL(*mMockIThermalService, unregisterThermalHeadroomListener(_, _))
287 .Times(Exactly(1))
288 .WillRepeatedly(Return(
289 Status::fromExceptionCode(binder::Status::Exception::EX_TRANSACTION_FAILED)));
290
291 // callback 1 should be unregistered and callback 2 unregistration should fail due to service
292 // listener unregistration call failure
293 ASSERT_EQ(0,
294 AThermal_unregisterThermalHeadroomListener(mThermalManager, onHeadroomChange1,
295 &data1));
296 ASSERT_EQ(EPIPE,
297 AThermal_unregisterThermalHeadroomListener(mThermalManager, onHeadroomChange2,
298 &data2));
299 // verify only callback 2 is called after callback 1 is unregistered
300 std::vector<float> thresholds = {0.1f, 0.2f};
301 headroomCalled1.reset();
302 headroomCalled2.reset();
303 capturedServiceListener->onHeadroomChange(0.1f, 0.3f, 20, thresholds);
304 ASSERT_TRUE(!headroomCalled1.has_value());
305 ASSERT_TRUE(headroomCalled2.has_value());
306
307 // verify only 1 service call to unregister global service listener
308 Mock::VerifyAndClearExpectations(mMockIThermalService);
309 EXPECT_CALL(*mMockIThermalService, unregisterThermalHeadroomListener(_, _))
310 .Times(Exactly(1))
311 .WillOnce(DoAll(testing::Invoke([](const sp<IThermalHeadroomListener>&,
312 bool* aidl_return) { *aidl_return = true; }),
313 Return(Status::ok())));
314 ASSERT_EQ(EINVAL,
315 AThermal_unregisterThermalHeadroomListener(mThermalManager, onHeadroomChange1,
316 &data1));
317 ASSERT_EQ(0,
318 AThermal_unregisterThermalHeadroomListener(mThermalManager, onHeadroomChange2,
319 &data2));
320 // verify neither callback is called after global service listener is unregistered
321 headroomCalled1.reset();
322 headroomCalled2.reset();
323 capturedServiceListener->onHeadroomChange(0.1f, 0.3f, 20, thresholds);
324 ASSERT_TRUE(!headroomCalled1.has_value());
325 ASSERT_TRUE(!headroomCalled2.has_value());
326
327 // verify adding a new callback will still work
328 Mock::VerifyAndClearExpectations(mMockIThermalService);
329 EXPECT_CALL(*mMockIThermalService, registerThermalHeadroomListener(_, _))
330 .Times(Exactly(1))
331 .WillOnce(DoAll(testing::SaveArg<0>(&capturedServiceListener),
332 testing::Invoke([](const sp<IThermalHeadroomListener>&,
333 bool* aidl_return) { *aidl_return = true; }),
334 Return(Status::ok())));
335 ASSERT_EQ(0,
336 AThermal_registerThermalHeadroomListener(mThermalManager, onHeadroomChange1, &data1));
337 headroomCalled1.reset();
338 capturedServiceListener->onHeadroomChange(0.1f, 0.3f, 20, thresholds);
339 ASSERT_TRUE(headroomCalled1.has_value());
340 EXPECT_EQ(headroomCalled1->data, &data1);
341 EXPECT_EQ(headroomCalled1->headroom, 0.1f);
342 EXPECT_EQ(headroomCalled1->forecast, 0.3f);
343 EXPECT_EQ(headroomCalled1->forecastSeconds, 20);
344 EXPECT_EQ(headroomCalled1->thresholds, thresholds);
345
346 // after test finished the global service listener should be unregistered
347 EXPECT_CALL(*mMockIThermalService, unregisterThermalHeadroomListener(_, _))
348 .Times(Exactly(1))
349 .WillOnce(Return(binder::Status::ok()));
350 }
351
TEST_F(NativeThermalUnitTest,TestRegisterThermalStatusListener)352 TEST_F(NativeThermalUnitTest, TestRegisterThermalStatusListener) {
353 EXPECT_CALL(*mMockIThermalService, registerThermalStatusListener(_, _))
354 .Times(Exactly(2))
355 .WillOnce(Return(
356 Status::fromExceptionCode(binder::Status::Exception::EX_TRANSACTION_FAILED)));
357 int data1 = 1;
358 int data2 = 2;
359 ASSERT_EQ(EPIPE,
360 AThermal_registerThermalStatusListener(mThermalManager, onStatusChange1, &data1));
361 ASSERT_EQ(EPIPE,
362 AThermal_registerThermalStatusListener(mThermalManager, onStatusChange2, &data2));
363
364 // verify only 1 service call to register a global listener
365 sp<IThermalStatusListener> capturedServiceListener;
366 Mock::VerifyAndClearExpectations(mMockIThermalService);
367 EXPECT_CALL(*mMockIThermalService, registerThermalStatusListener(_, _))
368 .Times(Exactly(1))
369 .WillOnce(DoAll(testing::SaveArg<0>(&capturedServiceListener),
370 testing::Invoke([](const sp<IThermalStatusListener>&,
371 bool* aidl_return) { *aidl_return = true; }),
372 Return(Status::ok())));
373 ASSERT_EQ(0, AThermal_registerThermalStatusListener(mThermalManager, onStatusChange1, &data1));
374 ASSERT_EQ(EINVAL,
375 AThermal_registerThermalStatusListener(mThermalManager, onStatusChange1, &data1));
376 ASSERT_EQ(0, AThermal_registerThermalStatusListener(mThermalManager, onStatusChange2, &data2));
377
378 capturedServiceListener->onStatusChange(AThermalStatus::ATHERMAL_STATUS_LIGHT);
379 ASSERT_TRUE(statusCalled1.has_value());
380 EXPECT_EQ(statusCalled1->data, &data1);
381 EXPECT_EQ(statusCalled1->status, AThermalStatus::ATHERMAL_STATUS_LIGHT);
382 ASSERT_TRUE(statusCalled2.has_value());
383 EXPECT_EQ(statusCalled2->data, &data2);
384 EXPECT_EQ(statusCalled2->status, AThermalStatus::ATHERMAL_STATUS_LIGHT);
385
386 // after test finished the callback should be unregistered
387 EXPECT_CALL(*mMockIThermalService, unregisterThermalStatusListener(_, _))
388 .Times(Exactly(1))
389 .WillOnce(Return(binder::Status::ok()));
390 }
391
TEST_F(NativeThermalUnitTest,TestUnregisterThermalStatusListener)392 TEST_F(NativeThermalUnitTest, TestUnregisterThermalStatusListener) {
393 sp<IThermalStatusListener> capturedServiceListener;
394 EXPECT_CALL(*mMockIThermalService, registerThermalStatusListener(_, _))
395 .Times(Exactly(1))
396 .WillOnce(DoAll(testing::SaveArg<0>(&capturedServiceListener),
397 testing::Invoke([](const sp<IThermalStatusListener>&,
398 bool* aidl_return) { *aidl_return = true; }),
399 Return(Status::ok())));
400 int data1 = 1;
401 int data2 = 2;
402 ASSERT_EQ(0, AThermal_registerThermalStatusListener(mThermalManager, onStatusChange1, &data1));
403 ASSERT_EQ(0, AThermal_registerThermalStatusListener(mThermalManager, onStatusChange2, &data2));
404 capturedServiceListener->onStatusChange(AThermalStatus::ATHERMAL_STATUS_LIGHT);
405 ASSERT_TRUE(statusCalled1.has_value());
406 ASSERT_TRUE(statusCalled2.has_value());
407
408 EXPECT_CALL(*mMockIThermalService, unregisterThermalStatusListener(_, _))
409 .Times(Exactly(1))
410 .WillOnce(Return(
411 Status::fromExceptionCode(binder::Status::Exception::EX_TRANSACTION_FAILED)));
412 // callback 1 should be unregistered and callback 2 unregistration should fail due to service
413 // listener unregistration call failure
414 ASSERT_EQ(0,
415 AThermal_unregisterThermalStatusListener(mThermalManager, onStatusChange1, &data1));
416 ASSERT_EQ(EPIPE,
417 AThermal_unregisterThermalStatusListener(mThermalManager, onStatusChange2, &data2));
418
419 // verify only callback 2 is called after callback 1 is unregistered
420 statusCalled1.reset();
421 statusCalled2.reset();
422 capturedServiceListener->onStatusChange(AThermalStatus::ATHERMAL_STATUS_LIGHT);
423 ASSERT_TRUE(!statusCalled1.has_value());
424 ASSERT_TRUE(statusCalled2.has_value());
425
426 // verify only 1 service call to unregister global service listener
427 Mock::VerifyAndClearExpectations(mMockIThermalService);
428 EXPECT_CALL(*mMockIThermalService, unregisterThermalStatusListener(_, _))
429 .Times(Exactly(1))
430 .WillOnce(DoAll(testing::Invoke([](const sp<IThermalStatusListener>&,
431 bool* aidl_return) { *aidl_return = true; }),
432 Return(Status::ok())));
433 ASSERT_EQ(EINVAL,
434 AThermal_unregisterThermalStatusListener(mThermalManager, onStatusChange1, &data1));
435 ASSERT_EQ(0,
436 AThermal_unregisterThermalStatusListener(mThermalManager, onStatusChange2, &data2));
437 // verify neither callback is called after global service listener is unregistered
438 statusCalled1.reset();
439 statusCalled2.reset();
440 capturedServiceListener->onStatusChange(AThermalStatus::ATHERMAL_STATUS_LIGHT);
441 ASSERT_TRUE(!statusCalled1.has_value());
442 ASSERT_TRUE(!statusCalled2.has_value());
443
444 // verify adding a new callback will still work
445 Mock::VerifyAndClearExpectations(mMockIThermalService);
446 EXPECT_CALL(*mMockIThermalService, registerThermalStatusListener(_, _))
447 .Times(Exactly(1))
448 .WillOnce(DoAll(testing::SaveArg<0>(&capturedServiceListener),
449 testing::Invoke([](const sp<IThermalStatusListener>&,
450 bool* aidl_return) { *aidl_return = true; }),
451 Return(Status::ok())));
452 ASSERT_EQ(0, AThermal_registerThermalStatusListener(mThermalManager, onStatusChange1, &data1));
453 statusCalled1.reset();
454 capturedServiceListener->onStatusChange(AThermalStatus::ATHERMAL_STATUS_LIGHT);
455 ASSERT_TRUE(statusCalled1.has_value());
456 EXPECT_EQ(statusCalled1->data, &data1);
457 EXPECT_EQ(statusCalled1->status, AThermalStatus::ATHERMAL_STATUS_LIGHT);
458
459 // after test finished the global service listener should be unregistered
460 EXPECT_CALL(*mMockIThermalService, unregisterThermalStatusListener(_, _))
461 .Times(Exactly(1))
462 .WillOnce(Return(binder::Status::ok()));
463 }
464