blob: 741495878ad8b2914ce3e395f0cae192502b1902 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "ThermalManagerTest"
//#define LOG_NDEBUG 0
#include <thread>
#include <android/os/BnThermalStatusListener.h>
#include <android/os/IThermalService.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/Parcel.h>
#include <condition_variable>
#include <gtest/gtest.h>
#include <powermanager/PowerManager.h>
#include <utils/Log.h>
using namespace android;
using namespace android::os;
using namespace std::chrono_literals;
class IThermalServiceTestListener : public BnThermalStatusListener {
public:
virtual binder::Status onStatusChange(int status) override;
std::condition_variable mCondition;
int mListenerStatus = 0;
std::mutex mMutex;
};
binder::Status IThermalServiceTestListener::onStatusChange(int status) {
std::unique_lock<std::mutex> lock(mMutex);
mListenerStatus = status;
ALOGI("IThermalServiceTestListener::notifyListener %d", mListenerStatus);
mCondition.notify_all();
return binder::Status::ok();
}
class IThermalServiceTest : public testing::Test {
public:
IThermalServiceTest();
void setThermalOverride(int level);
int getStatusFromService();
void SetUp() override;
void TearDown() override;
protected:
sp<IThermalService> mThermalSvc;
int mServiceStatus;
sp<IThermalServiceTestListener> mCallback;
};
IThermalServiceTest::IThermalServiceTest()
: mServiceStatus(0),
mCallback(sp<IThermalServiceTestListener>::make()) {
}
void IThermalServiceTest::setThermalOverride(int level) {
std::string cmdStr = "cmd thermalservice override-status " + std::to_string(level);
system(cmdStr.c_str());
}
int IThermalServiceTest::getStatusFromService() {
int status;
binder::Status ret = mThermalSvc->getCurrentThermalStatus(&status);
if (ret.isOk()) {
return status;
} else {
return BAD_VALUE;
}
}
void IThermalServiceTest::SetUp() {
setThermalOverride(0);
// use checkService() to avoid blocking if thermal service is not up yet
sp<IBinder> binder =
defaultServiceManager()->checkService(String16("thermalservice"));
EXPECT_NE(binder, nullptr);
mThermalSvc = interface_cast<IThermalService>(binder);
EXPECT_NE(mThermalSvc, nullptr);
// Lock mutex for operation, so listener will only be processed after wait_for is called
std::unique_lock<std::mutex> lock(mCallback->mMutex);
bool success = false;
binder::Status ret = mThermalSvc->registerThermalStatusListener(mCallback, &success);
// Check the result
ASSERT_TRUE(success);
ASSERT_TRUE(ret.isOk());
// Wait for listener called after registration, shouldn't timeout
EXPECT_NE(mCallback->mCondition.wait_for(lock, 1s), std::cv_status::timeout);
}
void IThermalServiceTest::TearDown() {
bool success = false;
binder::Status ret = mThermalSvc->unregisterThermalStatusListener(mCallback, &success);
ASSERT_TRUE(success);
ASSERT_TRUE(ret.isOk());
}
class IThermalListenerTest : public IThermalServiceTest, public testing::WithParamInterface<int32_t> {
public:
static auto PrintParam(const testing::TestParamInfo<ParamType> &info) {
return std::to_string(info.param);
}
};
TEST_P(IThermalListenerTest, TestListener) {
int level = GetParam();
// Lock mutex for operation, so listener will only be processed after wait_for is called
std::unique_lock<std::mutex> lock(mCallback->mMutex);
// Set the override thermal status
setThermalOverride(level);
// Wait for listener called, shouldn't timeout
EXPECT_NE(mCallback->mCondition.wait_for(lock, 1s), std::cv_status::timeout);
// Check the result
EXPECT_EQ(level, mCallback->mListenerStatus);
ALOGI("Thermal listener status %d, expecting %d", mCallback->mListenerStatus, level);
}
INSTANTIATE_TEST_SUITE_P(TestListenerLevels, IThermalListenerTest, testing::Range(
static_cast<int>(ThermalStatus::THERMAL_STATUS_LIGHT),
static_cast<int>(ThermalStatus::THERMAL_STATUS_SHUTDOWN)),
IThermalListenerTest::PrintParam);
class IThermalLevelTest : public IThermalServiceTest, public testing::WithParamInterface<int32_t> {
public:
static auto PrintParam(const testing::TestParamInfo<ParamType> &info) {
return std::to_string(info.param);
}
};
TEST_P(IThermalLevelTest, TestGetStatusLevel) {
int level = GetParam();
setThermalOverride(level);
mServiceStatus = getStatusFromService();
EXPECT_EQ(level, mServiceStatus);
}
INSTANTIATE_TEST_SUITE_P(TestStatusLevels, IThermalLevelTest, testing::Range(
static_cast<int>(ThermalStatus::THERMAL_STATUS_NONE),
static_cast<int>(ThermalStatus::THERMAL_STATUS_SHUTDOWN)),
IThermalLevelTest::PrintParam);
int main(int argc, char **argv) {
std::unique_ptr<std::thread> binderLoop;
binderLoop = std::make_unique<std::thread>(
[&] { IPCThreadState::self()->joinThreadPool(true); });
::testing::InitGoogleTest(&argc, argv);
int status = RUN_ALL_TESTS();
ALOGV("Test result = %d\n", status);
return status;
}