C++程序  |  282行  |  12.09 KB

/*
 * Copyright (C) 2018 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 <android/hardware/thermal/2.0/IThermal.h>
#include <android/hardware/thermal/2.0/IThermalChangedCallback.h>
#include <android/hardware/thermal/2.0/types.h>

#include <VtsHalHidlTargetCallbackBase.h>
#include <VtsHalHidlTargetTestBase.h>
#include <VtsHalHidlTargetTestEnvBase.h>

using ::android::sp;
using ::android::hardware::hidl_enum_range;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::thermal::V1_0::ThermalStatus;
using ::android::hardware::thermal::V1_0::ThermalStatusCode;
using ::android::hardware::thermal::V2_0::CoolingDevice;
using ::android::hardware::thermal::V2_0::CoolingType;
using ::android::hardware::thermal::V2_0::IThermal;
using ::android::hardware::thermal::V2_0::IThermalChangedCallback;
using ::android::hardware::thermal::V2_0::Temperature;
using ::android::hardware::thermal::V2_0::TemperatureThreshold;
using ::android::hardware::thermal::V2_0::TemperatureType;
using ::android::hardware::thermal::V2_0::ThrottlingSeverity;

constexpr char kCallbackNameNotifyThrottling[] = "notifyThrottling";
static const Temperature kThrottleTemp = {
    .type = TemperatureType::SKIN,
    .name = "test temperature sensor",
    .value = 98.6,
    .throttlingStatus = ThrottlingSeverity::CRITICAL,
};

class ThermalCallbackArgs {
   public:
    Temperature temperature;
};

// Callback class for receiving thermal event notifications from main class
class ThermalCallback : public ::testing::VtsHalHidlTargetCallbackBase<ThermalCallbackArgs>,
                        public IThermalChangedCallback {
   public:
    Return<void> notifyThrottling(const Temperature& temperature) override {
        ThermalCallbackArgs args;
        args.temperature = temperature;
        NotifyFromCallback(kCallbackNameNotifyThrottling, args);
        return Void();
    }
};

// Test environment for Thermal HIDL HAL.
class ThermalHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
   public:
    // get the test environment singleton
    static ThermalHidlEnvironment* Instance() {
        static ThermalHidlEnvironment* instance = new ThermalHidlEnvironment;
        return instance;
    }

    void registerTestServices() override { registerTestService<IThermal>(); }

   private:
    ThermalHidlEnvironment() {}
};

// The main test class for THERMAL HIDL HAL 2.0.
class ThermalHidlTest : public ::testing::VtsHalHidlTargetTestBase {
   public:
    virtual void SetUp() override {
        mThermal = ::testing::VtsHalHidlTargetTestBase::getService<IThermal>(
            ThermalHidlEnvironment::Instance()->getServiceName<IThermal>());
        ASSERT_NE(mThermal, nullptr);
        mThermalCallback = new (std::nothrow) ThermalCallback();
        ASSERT_NE(mThermalCallback, nullptr);
        auto ret = mThermal->registerThermalChangedCallback(
            mThermalCallback, false, TemperatureType::SKIN,
            [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
        ASSERT_TRUE(ret.isOk());
        // Expect to fail if register again
        ret = mThermal->registerThermalChangedCallback(
            mThermalCallback, false, TemperatureType::SKIN,
            [](ThermalStatus status) { EXPECT_NE(ThermalStatusCode::SUCCESS, status.code); });
        ASSERT_TRUE(ret.isOk());
    }

    virtual void TearDown() override {
        auto ret = mThermal->unregisterThermalChangedCallback(
            mThermalCallback,
            [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
        ASSERT_TRUE(ret.isOk());
        // Expect to fail if unregister again
        ret = mThermal->unregisterThermalChangedCallback(
            mThermalCallback,
            [](ThermalStatus status) { EXPECT_NE(ThermalStatusCode::SUCCESS, status.code); });
        ASSERT_TRUE(ret.isOk());
    }

   protected:
    sp<IThermal> mThermal;
    sp<ThermalCallback> mThermalCallback;
};  // class ThermalHidlTest

// Test ThermalChangedCallback::notifyThrottling().
// This just calls into and back from our local ThermalChangedCallback impl.
// Note: a real thermal throttling event from the Thermal HAL could be
// inadvertently received here.
TEST_F(ThermalHidlTest, NotifyThrottlingTest) {
    auto ret = mThermalCallback->notifyThrottling(kThrottleTemp);
    ASSERT_TRUE(ret.isOk());
    auto res = mThermalCallback->WaitForCallback(kCallbackNameNotifyThrottling);
    EXPECT_TRUE(res.no_timeout);
    ASSERT_TRUE(res.args);
    EXPECT_EQ(kThrottleTemp, res.args->temperature);
}

// Test Thermal->registerThermalChangedCallback.
TEST_F(ThermalHidlTest, RegisterThermalChangedCallbackTest) {
    // Expect to fail with same callback
    auto ret = mThermal->registerThermalChangedCallback(
            mThermalCallback, false, TemperatureType::SKIN,
            [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::FAILURE, status.code); });
    ASSERT_TRUE(ret.isOk());
    // Expect to fail with null callback
    ret = mThermal->registerThermalChangedCallback(
            nullptr, false, TemperatureType::SKIN,
            [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::FAILURE, status.code); });
    ASSERT_TRUE(ret.isOk());
    sp<ThermalCallback> localThermalCallback = new (std::nothrow) ThermalCallback();
    // Expect to succeed with different callback
    ret = mThermal->registerThermalChangedCallback(
        localThermalCallback, false, TemperatureType::SKIN,
        [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
    ASSERT_TRUE(ret.isOk());
    // Remove the local callback
    ret = mThermal->unregisterThermalChangedCallback(
        localThermalCallback,
        [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
    ASSERT_TRUE(ret.isOk());
    // Expect to fail with null callback
    ret = mThermal->unregisterThermalChangedCallback(nullptr, [](ThermalStatus status) {
        EXPECT_EQ(ThermalStatusCode::FAILURE, status.code);
    });
    ASSERT_TRUE(ret.isOk());
}

// Test Thermal->unregisterThermalChangedCallback.
TEST_F(ThermalHidlTest, UnregisterThermalChangedCallbackTest) {
    sp<ThermalCallback> localThermalCallback = new (std::nothrow) ThermalCallback();
    // Expect to fail as the callback was not registered before
    auto ret = mThermal->unregisterThermalChangedCallback(
        localThermalCallback,
        [](ThermalStatus status) { EXPECT_NE(ThermalStatusCode::SUCCESS, status.code); });
    ASSERT_TRUE(ret.isOk());
    // Register a local callback
    ret = mThermal->registerThermalChangedCallback(
        localThermalCallback, false, TemperatureType::SKIN,
        [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
    ASSERT_TRUE(ret.isOk());
    // Expect to succeed with callback removed
    ret = mThermal->unregisterThermalChangedCallback(
        localThermalCallback,
        [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
    ASSERT_TRUE(ret.isOk());
    // Expect to fail as the callback has been unregistered already
    ret = mThermal->unregisterThermalChangedCallback(
        localThermalCallback,
        [](ThermalStatus status) { EXPECT_NE(ThermalStatusCode::SUCCESS, status.code); });
    ASSERT_TRUE(ret.isOk());
}

// Sanity test for Thermal::getCurrentTemperatures().
TEST_F(ThermalHidlTest, TemperatureTest) {
    mThermal->getCurrentTemperatures(false, TemperatureType::SKIN,
                                     [](ThermalStatus status, hidl_vec<Temperature> temperatures) {
                                         if (temperatures.size()) {
                                             EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
                                         } else {
                                             EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
                                         }
                                         for (int i = 0; i < temperatures.size(); ++i) {
                                             EXPECT_LT(0u, temperatures[i].name.size());
                                         }
                                     });
    auto types = hidl_enum_range<TemperatureType>();
    for (const auto& type : types) {
        mThermal->getCurrentTemperatures(
            true, type, [&type](ThermalStatus status, hidl_vec<Temperature> temperatures) {
                if (temperatures.size()) {
                    EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
                } else {
                    EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
                }
                for (int i = 0; i < temperatures.size(); ++i) {
                    EXPECT_EQ(type, temperatures[i].type);
                    EXPECT_LT(0u, temperatures[i].name.size());
                }
            });
    }
}

// Sanity test for Thermal::getTemperatureThresholds().
TEST_F(ThermalHidlTest, TemperatureThresholdTest) {
    mThermal->getTemperatureThresholds(
        false, TemperatureType::SKIN,
        [](ThermalStatus status, hidl_vec<TemperatureThreshold> temperatures) {
            if (temperatures.size()) {
                EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
            } else {
                EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
            }
        });
    for (int i = static_cast<int>(TemperatureType::UNKNOWN);
         i <= static_cast<int>(TemperatureType::POWER_AMPLIFIER); ++i) {
        auto type = static_cast<TemperatureType>(i);
        mThermal->getTemperatureThresholds(
            true, type, [&type](ThermalStatus status, hidl_vec<TemperatureThreshold> temperatures) {
                if (temperatures.size()) {
                    EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
                } else {
                    EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
                }
                for (int i = 0; i < temperatures.size(); ++i) {
                    EXPECT_EQ(type, temperatures[i].type);
                }
            });
    }
}

// Sanity test for Thermal::getCurrentCoolingDevices().
TEST_F(ThermalHidlTest, CoolingDeviceTest) {
    mThermal->getCurrentCoolingDevices(
        false, CoolingType::CPU, [](ThermalStatus status, hidl_vec<CoolingDevice> cooling_devices) {
            if (cooling_devices.size()) {
                EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
            } else {
                EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
            }
            for (int i = 0; i < cooling_devices.size(); ++i) {
                EXPECT_LT(0u, cooling_devices[i].name.size());
            }
        });
    for (int i = 0; i <= static_cast<int>(CoolingType::COMPONENT); ++i) {
        auto type = static_cast<CoolingType>(i);
        mThermal->getCurrentCoolingDevices(
            true, type, [&type](ThermalStatus status, hidl_vec<CoolingDevice> cooling_devices) {
                if (cooling_devices.size()) {
                    EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
                } else {
                    EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
                }
                for (int i = 0; i < cooling_devices.size(); ++i) {
                    EXPECT_EQ(type, cooling_devices[i].type);
                    EXPECT_LT(0u, cooling_devices[i].name.size());
                }
            });
    }
}

int main(int argc, char** argv) {
    ::testing::AddGlobalTestEnvironment(ThermalHidlEnvironment::Instance());
    ::testing::InitGoogleTest(&argc, argv);
    ThermalHidlEnvironment::Instance()->init(&argc, argv);
    int status = RUN_ALL_TESTS();
    cout << "Test result = " << status << std::endl;
    return status;
}