xref: /aosp_15_r20/frameworks/base/native/android/tests/thermal/NativeThermalUnitTest.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
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