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 #include <aidl/android/hardware/thermal/BnThermalChangedCallback.h>
18 #include <log/log.h>
19 
20 #include "Thermal.h"
21 #include "mock_thermal_helper.h"
22 
23 namespace aidl::android::hardware::thermal::implementation {
24 
25 class ThermalLooperTest : public testing::Test {
26   protected:
SetUp()27     void SetUp() override {
28         ON_CALL(*helper, isInitializedOk).WillByDefault(testing::Return(true));
29     }
30 
31     std::shared_ptr<testing::NiceMock<MockThermalHelper>> helper =
32             std::make_shared<testing::NiceMock<MockThermalHelper>>();
33     std::shared_ptr<Thermal> thermal = ndk::SharedRefBase::make<Thermal>(helper);
34 };
35 
36 class TestCallback : public BnThermalChangedCallback {
37   public:
notifyThrottling(const Temperature & t)38     ndk::ScopedAStatus notifyThrottling(const Temperature &t) override {
39         std::lock_guard<std::mutex> lock_guard(mMutex);
40         mTemperatures.emplace_back(t);
41         return ndk::ScopedAStatus::ok();
42     }
43 
notifyThresholdChanged(const TemperatureThreshold &)44     ndk::ScopedAStatus notifyThresholdChanged(const TemperatureThreshold &) override {
45         // no impl for threshold change
46         return ndk::ScopedAStatus::ok();
47     }
48 
getTemperatures()49     std::vector<Temperature> getTemperatures() {
50         std::lock_guard<std::mutex> lock_guard(mMutex);
51         return mTemperatures;
52     }
53 
clear()54     void clear() {
55         std::lock_guard<std::mutex> lock_guard(mMutex);
56         mTemperatures.clear();
57     }
58 
59   private:
60     std::vector<Temperature> mTemperatures;
61     std::mutex mMutex;
62 };
63 
TEST_F(ThermalLooperTest,AsyncCallbackTest)64 TEST_F(ThermalLooperTest, AsyncCallbackTest) {
65     Temperature t1;
66     t1.type = TemperatureType::SKIN;
67     Temperature t2;
68     t2.type = TemperatureType::UNKNOWN;
69     ON_CALL(*helper, fillCurrentTemperatures)
70             .WillByDefault([this, t1, t2](bool, bool, TemperatureType,
71                                           std::vector<Temperature> *temperatures) {
72                 std::vector<Temperature> ret = {t1, t2};
73                 *temperatures = ret;
74                 sleep(1);
75                 return true;
76             });
77     std::shared_ptr<TestCallback> callback = ndk::SharedRefBase::make<TestCallback>();
78     std::shared_ptr<TestCallback> callbackWithType = ndk::SharedRefBase::make<TestCallback>();
79 
80     // if callback immediately unregistered, no async callback should be scheduled
81     ASSERT_TRUE(thermal->registerThermalChangedCallback(callback).isOk());
82     ASSERT_TRUE(
83             thermal->registerThermalChangedCallbackWithType(callbackWithType, TemperatureType::SKIN)
84                     .isOk());
85     ASSERT_TRUE(thermal->unregisterThermalChangedCallback(callback).isOk());
86     ASSERT_TRUE(thermal->unregisterThermalChangedCallback(callbackWithType).isOk());
87     sleep(3);
88     ASSERT_TRUE(callback->getTemperatures().empty());
89     ASSERT_TRUE(callbackWithType->getTemperatures().empty());
90 
91     // otherwise, async callback should be scheduled if registered
92     ASSERT_TRUE(thermal->registerThermalChangedCallback(callback).isOk());
93     ASSERT_TRUE(
94             thermal->registerThermalChangedCallbackWithType(callbackWithType, TemperatureType::SKIN)
95                     .isOk());
96     sleep(3);
97     ASSERT_THAT(callback->getTemperatures(), testing::UnorderedElementsAreArray({t1, t2}));
98     ASSERT_THAT(callbackWithType->getTemperatures(), testing::UnorderedElementsAreArray({t1}));
99 }
100 
101 }  // namespace aidl::android::hardware::thermal::implementation
102