1 /*
2  * Copyright (C) 2020 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 "ThermalManagerTest"
18 //#define LOG_NDEBUG 0
19 
20 #include <thread>
21 
22 #include <android/os/BnThermalStatusListener.h>
23 #include <android/os/IThermalService.h>
24 #include <binder/IPCThreadState.h>
25 #include <binder/IServiceManager.h>
26 #include <binder/Parcel.h>
27 #include <condition_variable>
28 #include <gtest/gtest.h>
29 #include <powermanager/PowerManager.h>
30 #include <utils/Log.h>
31 
32 using namespace android;
33 using namespace android::os;
34 using namespace std::chrono_literals;
35 
36 class IThermalServiceTestListener : public BnThermalStatusListener {
37     public:
38         virtual binder::Status onStatusChange(int status) override;
39         std::condition_variable mCondition;
40         int mListenerStatus = 0;
41         std::mutex mMutex;
42 };
43 
onStatusChange(int status)44 binder::Status IThermalServiceTestListener::onStatusChange(int status) {
45     std::unique_lock<std::mutex> lock(mMutex);
46     mListenerStatus = status;
47     ALOGI("IThermalServiceTestListener::notifyListener %d", mListenerStatus);
48     mCondition.notify_all();
49     return binder::Status::ok();
50 }
51 
52 class IThermalServiceTest : public testing::Test {
53     public:
54         IThermalServiceTest();
55         void setThermalOverride(int level);
56         int getStatusFromService();
57         void SetUp() override;
58         void TearDown() override;
59     protected:
60         sp<IThermalService> mThermalSvc;
61         int mServiceStatus;
62         sp<IThermalServiceTestListener> mCallback;
63 };
64 
IThermalServiceTest()65 IThermalServiceTest::IThermalServiceTest()
66  : mServiceStatus(0),
67    mCallback(sp<IThermalServiceTestListener>::make()) {
68 }
69 
setThermalOverride(int level)70 void IThermalServiceTest::setThermalOverride(int level) {
71     std::string cmdStr = "cmd thermalservice override-status " + std::to_string(level);
72     system(cmdStr.c_str());
73 }
74 
getStatusFromService()75 int IThermalServiceTest::getStatusFromService() {
76     int status;
77     binder::Status ret = mThermalSvc->getCurrentThermalStatus(&status);
78     if (ret.isOk()) {
79         return status;
80     } else {
81         return BAD_VALUE;
82     }
83 }
84 
SetUp()85 void IThermalServiceTest::SetUp() {
86     setThermalOverride(0);
87     // use checkService() to avoid blocking if thermal service is not up yet
88     sp<IBinder> binder =
89         defaultServiceManager()->checkService(String16("thermalservice"));
90     EXPECT_NE(binder, nullptr);
91     mThermalSvc = interface_cast<IThermalService>(binder);
92     EXPECT_NE(mThermalSvc, nullptr);
93     // Lock mutex for operation, so listener will only be processed after wait_for is called
94     std::unique_lock<std::mutex> lock(mCallback->mMutex);
95     bool success = false;
96     binder::Status ret = mThermalSvc->registerThermalStatusListener(mCallback, &success);
97     // Check the result
98     ASSERT_TRUE(success);
99     ASSERT_TRUE(ret.isOk());
100     // Wait for listener called after registration, shouldn't timeout
101     EXPECT_NE(mCallback->mCondition.wait_for(lock, 1s), std::cv_status::timeout);
102 }
103 
TearDown()104 void IThermalServiceTest::TearDown() {
105     bool success = false;
106     binder::Status ret = mThermalSvc->unregisterThermalStatusListener(mCallback, &success);
107     ASSERT_TRUE(success);
108     ASSERT_TRUE(ret.isOk());
109 }
110 
111 class IThermalListenerTest : public IThermalServiceTest, public testing::WithParamInterface<int32_t> {
112   public:
PrintParam(const testing::TestParamInfo<ParamType> & info)113     static auto PrintParam(const testing::TestParamInfo<ParamType> &info) {
114         return std::to_string(info.param);
115     }
116 };
117 
TEST_P(IThermalListenerTest,TestListener)118 TEST_P(IThermalListenerTest, TestListener) {
119     int level = GetParam();
120     // Lock mutex for operation, so listener will only be processed after wait_for is called
121     std::unique_lock<std::mutex> lock(mCallback->mMutex);
122     // Set the override thermal status
123     setThermalOverride(level);
124     // Wait for listener called, shouldn't timeout
125     EXPECT_NE(mCallback->mCondition.wait_for(lock, 1s), std::cv_status::timeout);
126     // Check the result
127     EXPECT_EQ(level, mCallback->mListenerStatus);
128     ALOGI("Thermal listener status %d, expecting %d", mCallback->mListenerStatus, level);
129 }
130 
131 INSTANTIATE_TEST_SUITE_P(TestListenerLevels, IThermalListenerTest, testing::Range(
132         static_cast<int>(ThermalStatus::THERMAL_STATUS_LIGHT),
133         static_cast<int>(ThermalStatus::THERMAL_STATUS_SHUTDOWN)),
134         IThermalListenerTest::PrintParam);
135 
136 class IThermalLevelTest : public IThermalServiceTest, public testing::WithParamInterface<int32_t> {
137   public:
PrintParam(const testing::TestParamInfo<ParamType> & info)138     static auto PrintParam(const testing::TestParamInfo<ParamType> &info) {
139         return std::to_string(info.param);
140     }
141 };
142 
TEST_P(IThermalLevelTest,TestGetStatusLevel)143 TEST_P(IThermalLevelTest, TestGetStatusLevel) {
144     int level = GetParam();
145     setThermalOverride(level);
146     mServiceStatus = getStatusFromService();
147     EXPECT_EQ(level, mServiceStatus);
148 }
149 
150 INSTANTIATE_TEST_SUITE_P(TestStatusLevels, IThermalLevelTest, testing::Range(
151         static_cast<int>(ThermalStatus::THERMAL_STATUS_NONE),
152         static_cast<int>(ThermalStatus::THERMAL_STATUS_SHUTDOWN)),
153         IThermalLevelTest::PrintParam);
154 
main(int argc,char ** argv)155 int main(int argc, char **argv) {
156     std::unique_ptr<std::thread> binderLoop;
157     binderLoop = std::make_unique<std::thread>(
158             [&] { IPCThreadState::self()->joinThreadPool(true); });
159 
160     ::testing::InitGoogleTest(&argc, argv);
161     int status = RUN_ALL_TESTS();
162     ALOGV("Test result = %d\n", status);
163 
164     return status;
165 }
166