/*
* Copyright (C) 2016 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.
*/
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#define LOG_TAG "thermal_hidl_hal_test"
#include <android-base/logging.h>
#include <android/hardware/thermal/1.0/IThermal.h>
#include <android/hardware/thermal/1.0/types.h>
#include <VtsHalHidlTargetTestBase.h>
#include <unistd.h>
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::thermal::V1_0::CoolingDevice;
using ::android::hardware::thermal::V1_0::CpuUsage;
using ::android::hardware::thermal::V1_0::IThermal;
using ::android::hardware::thermal::V1_0::Temperature;
using ::android::hardware::thermal::V1_0::TemperatureType;
using ::android::hardware::thermal::V1_0::ThermalStatus;
using ::android::hardware::thermal::V1_0::ThermalStatusCode;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;
#define MONITORING_OPERATION_NUMBER 10
#define MAX_DEVICE_TEMPERATURE 200
#define MAX_FAN_SPEED 20000
// The main test class for THERMAL HIDL HAL.
class ThermalHidlTest : public ::testing::VtsHalHidlTargetTestBase {
public:
virtual void SetUp() override {
thermal_ = ::testing::VtsHalHidlTargetTestBase::getService<IThermal>();
ASSERT_NE(thermal_, nullptr);
baseSize_ = 0;
names_.clear();
}
virtual void TearDown() override {}
protected:
// Check validity of temperatures returned by Thremal HAL.
void checkTemperatures(const hidl_vec<Temperature> temperatures) {
size_t size = temperatures.size();
EXPECT_LE(baseSize_, size);
for (size_t i = 0; i < size; ++i) {
checkDeviceTemperature(temperatures[i]);
if (i < baseSize_) {
EXPECT_EQ(names_[i], temperatures[i].name.c_str());
} else {
// Names must be unique.
EXPECT_EQ(names_.end(), std::find(names_.begin(), names_.end(),
temperatures[i].name.c_str()));
names_.push_back(temperatures[i].name);
}
}
baseSize_ = size;
}
// Check validity of CPU usages returned by Thermal HAL.
void checkCpuUsages(const hidl_vec<CpuUsage>& cpuUsages) {
size_t size = cpuUsages.size();
// A number of CPU's does not change.
if (baseSize_ != 0) EXPECT_EQ(baseSize_, size);
for (size_t i = 0; i < size; ++i) {
checkCpuUsage(cpuUsages[i]);
if (i < baseSize_) {
EXPECT_EQ(names_[i], cpuUsages[i].name.c_str());
} else {
// Names must be unique.
EXPECT_EQ(names_.end(), std::find(names_.begin(), names_.end(),
cpuUsages[i].name.c_str()));
names_.push_back(cpuUsages[i].name);
}
}
baseSize_ = size;
}
// Check validity of cooling devices information returned by Thermal HAL.
void checkCoolingDevices(const hidl_vec<CoolingDevice> coolingDevices) {
size_t size = coolingDevices.size();
EXPECT_LE(baseSize_, size);
for (size_t i = 0; i < size; ++i) {
checkCoolingDevice(coolingDevices[i]);
if (i < baseSize_) {
EXPECT_EQ(names_[i], coolingDevices[i].name.c_str());
} else {
// Names must be unique.
EXPECT_EQ(names_.end(), std::find(names_.begin(), names_.end(),
coolingDevices[i].name.c_str()));
names_.push_back(coolingDevices[i].name);
}
}
baseSize_ = size;
}
sp<IThermal> thermal_;
private:
// Check validity of temperature returned by Thermal HAL.
void checkDeviceTemperature(const Temperature& temperature) {
// .currentValue of known type is in Celsius and must be reasonable.
EXPECT_TRUE(temperature.type == TemperatureType::UNKNOWN ||
std::abs(temperature.currentValue) < MAX_DEVICE_TEMPERATURE ||
isnan(temperature.currentValue));
// .name must not be empty.
EXPECT_LT(0u, temperature.name.size());
// .currentValue must not exceed .shutdwonThreshold if defined.
EXPECT_TRUE(temperature.currentValue < temperature.shutdownThreshold ||
isnan(temperature.currentValue) || isnan(temperature.shutdownThreshold));
// .throttlingThreshold must not exceed .shutdownThreshold if defined.
EXPECT_TRUE(temperature.throttlingThreshold < temperature.shutdownThreshold ||
isnan(temperature.throttlingThreshold) || isnan(temperature.shutdownThreshold));
}
// Check validity of CPU usage returned by Thermal HAL.
void checkCpuUsage(const CpuUsage& cpuUsage) {
// .active must be less than .total if CPU is online.
EXPECT_TRUE(!cpuUsage.isOnline ||
(cpuUsage.active >= 0 && cpuUsage.total >= 0 &&
cpuUsage.total >= cpuUsage.active));
// .name must be not empty.
EXPECT_LT(0u, cpuUsage.name.size());
}
// Check validity of a cooling device information returned by Thermal HAL.
void checkCoolingDevice(const CoolingDevice& coolingDevice) {
EXPECT_LE(0, coolingDevice.currentValue);
EXPECT_GT(MAX_FAN_SPEED, coolingDevice.currentValue);
EXPECT_LT(0u, coolingDevice.name.size());
}
size_t baseSize_;
std::vector<hidl_string> names_;
};
// Sanity test for Thermal::getTemperatures().
TEST_F(ThermalHidlTest, TemperatureTest) {
hidl_vec<Temperature> passed;
for (size_t i = 0; i < MONITORING_OPERATION_NUMBER; ++i) {
thermal_->getTemperatures(
[&passed](ThermalStatus status, hidl_vec<Temperature> temperatures) {
EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
passed = temperatures;
});
checkTemperatures(passed);
sleep(1);
}
}
// Sanity test for Thermal::getCpuUsages().
TEST_F(ThermalHidlTest, CpuUsageTest) {
hidl_vec<CpuUsage> passed;
for (size_t i = 0; i < MONITORING_OPERATION_NUMBER; ++i) {
thermal_->getCpuUsages(
[&passed](ThermalStatus status, hidl_vec<CpuUsage> cpuUsages) {
EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
passed = cpuUsages;
});
checkCpuUsages(passed);
sleep(1);
}
}
// Sanity test for Thermal::getCoolingDevices().
TEST_F(ThermalHidlTest, CoolingDeviceTest) {
hidl_vec<CoolingDevice> passed;
for (size_t i = 0; i < MONITORING_OPERATION_NUMBER; ++i) {
thermal_->getCoolingDevices([&passed](
ThermalStatus status, hidl_vec<CoolingDevice> coolingDevices) {
EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
passed = coolingDevices;
});
checkCoolingDevices(passed);
sleep(1);
}
}
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
int status = RUN_ALL_TESTS();
LOG(INFO) << "Test result = " << status;
return status;
}