Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e3da439d authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 8317698 from 5c2dfc5e to tm-d1-release

Change-Id: If06fa00eda8814ba03bf1bca85aaccb57c8f844e
parents 092f9280 5c2dfc5e
Loading
Loading
Loading
Loading
+0 −263
Original line number Diff line number Diff line
/*
 * 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 "VtsHalAutomotiveVehicle"

#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
#include <utils/Log.h>
#include <unordered_set>

#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>

using namespace android::hardware::automotive::vehicle::V2_0;
using ::android::sp;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;

constexpr auto kTimeout = std::chrono::milliseconds(500);
constexpr auto kInvalidProp = 0x31600207;

class VtsVehicleCallback : public IVehicleCallback {
  private:
    using MutexGuard = std::lock_guard<std::mutex>;
    using HidlVecOfValues = hidl_vec<VehiclePropValue>;
    std::mutex mLock;
    std::condition_variable mEventCond;
    std::vector<HidlVecOfValues> mReceivedEvents;

  public:
    Return<void> onPropertyEvent(const hidl_vec<VehiclePropValue>& values) override {
        {
            MutexGuard guard(mLock);
            mReceivedEvents.push_back(values);
        }
        mEventCond.notify_one();
        return Return<void>();
    }

    Return<void> onPropertySet(const VehiclePropValue& /* value */) override {
        return Return<void>();
    }
    Return<void> onPropertySetError(StatusCode /* errorCode */, int32_t /* propId */,
                                    int32_t /* areaId */) override {
        return Return<void>();
    }

    bool waitForExpectedEvents(size_t expectedEvents) {
        std::unique_lock<std::mutex> g(mLock);

        if (expectedEvents == 0 && mReceivedEvents.size() == 0) {
            return mEventCond.wait_for(g, kTimeout) == std::cv_status::timeout;
        }

        while (expectedEvents != mReceivedEvents.size()) {
            if (mEventCond.wait_for(g, kTimeout) == std::cv_status::timeout) {
                return false;
            }
        }
        return true;
    }

    void reset() { mReceivedEvents.clear(); }
};

class VehicleHalHidlTest : public testing::TestWithParam<std::string> {
  public:
    virtual void SetUp() override {
        mVehicle = IVehicle::getService(GetParam());
        ASSERT_NE(mVehicle.get(), nullptr);
    }
    virtual void TearDown() override {}

    sp<IVehicle> mVehicle;

    bool isBooleanGlobalProp(int32_t property) {
        return (property & (int)VehiclePropertyType::MASK) == (int)VehiclePropertyType::BOOLEAN &&
               (property & (int)VehicleArea::MASK) == (int)VehicleArea::GLOBAL;
    }

    void invokeGet(int32_t property, int32_t areaId) {
        VehiclePropValue requestedValue{};
        requestedValue.prop = property;
        requestedValue.areaId = areaId;

        invokeGet(requestedValue);
    }

    void invokeGet(const VehiclePropValue& requestedPropValue) {
        mActualValue = VehiclePropValue{};  // reset previous values

        StatusCode refStatus;
        VehiclePropValue refValue;
        bool isCalled = false;
        mVehicle->get(requestedPropValue,
                      [&refStatus, &refValue, &isCalled](StatusCode status,
                                                         const VehiclePropValue& value) {
                          refStatus = status;
                          refValue = value;
                          isCalled = true;
                      });
        ASSERT_TRUE(isCalled) << "callback wasn't called for property: " << requestedPropValue.prop;

        mActualValue = refValue;
        mActualStatusCode = refStatus;
    }

    VehiclePropValue mActualValue;
    StatusCode mActualStatusCode;
};

// Test getAllPropConfig() returns at least 4 property configs.
TEST_P(VehicleHalHidlTest, getAllPropConfigs) {
    ALOGD("VehicleHalHidlTest::getAllPropConfigs");
    bool isCalled = false;
    hidl_vec<VehiclePropConfig> propConfigs;
    mVehicle->getAllPropConfigs([&isCalled, &propConfigs](const hidl_vec<VehiclePropConfig>& cfgs) {
        propConfigs = cfgs;
        isCalled = true;
    });
    ASSERT_TRUE(isCalled);
    ASSERT_GE(propConfigs.size(), 4);
}

// Test getPropConfig() can query all properties listed in CDD.
TEST_P(VehicleHalHidlTest, getPropConfigs) {
    ALOGD("VehicleHalHidlTest::getPropConfigs");
    // Check the properties listed in CDD
    hidl_vec<int32_t> properties = {
            (int)VehicleProperty::GEAR_SELECTION, (int)VehicleProperty::NIGHT_MODE,
            (int)VehicleProperty::PARKING_BRAKE_ON, (int)VehicleProperty::PERF_VEHICLE_SPEED};
    bool isCalled = false;
    mVehicle->getPropConfigs(
            properties, [&isCalled](StatusCode status, const hidl_vec<VehiclePropConfig>& cfgs) {
                ASSERT_EQ(StatusCode::OK, status);
                ASSERT_EQ(4u, cfgs.size());
                isCalled = true;
            });
    ASSERT_TRUE(isCalled);
}

// Test getPropConfig() with an invalid propertyId returns an error code.
TEST_P(VehicleHalHidlTest, getPropConfigsWithInvalidProp) {
    ALOGD("VehicleHalHidlTest::getPropConfigsWithInvalidProp");
    hidl_vec<int32_t> properties = {kInvalidProp};
    bool isCalled = false;
    mVehicle->getPropConfigs(
            properties, [&isCalled](StatusCode status, const hidl_vec<VehiclePropConfig>& cfgs) {
                ASSERT_NE(StatusCode::OK, status);
                ASSERT_EQ(0, cfgs.size());
                isCalled = true;
            });
    ASSERT_TRUE(isCalled);
}

// Test get() return current value for properties.
TEST_P(VehicleHalHidlTest, get) {
    ALOGD("VehicleHalHidlTest::get");
    invokeGet((int)VehicleProperty::PERF_VEHICLE_SPEED, 0);
    ASSERT_EQ(StatusCode::OK, mActualStatusCode);
}

// Test get() with an invalid propertyId return an error codes.
TEST_P(VehicleHalHidlTest, getInvalidProp) {
    ALOGD("VehicleHalHidlTest::getInvalidProp");

    invokeGet(kInvalidProp, 0);
    ASSERT_NE(StatusCode::OK, mActualStatusCode);
}

// Test set() on read_write properties.
TEST_P(VehicleHalHidlTest, setProp) {
    ALOGD("VehicleHalHidlTest::setProp");
    hidl_vec<VehiclePropConfig> propConfigs;
    // skip hvac related properties
    std::unordered_set<int32_t> hvacProps = {(int)VehicleProperty::HVAC_DEFROSTER,
                                             (int)VehicleProperty::HVAC_AC_ON,
                                             (int)VehicleProperty::HVAC_MAX_AC_ON,
                                             (int)VehicleProperty::HVAC_MAX_DEFROST_ON,
                                             (int)VehicleProperty::HVAC_RECIRC_ON,
                                             (int)VehicleProperty::HVAC_DUAL_ON,
                                             (int)VehicleProperty::HVAC_AUTO_ON,
                                             (int)VehicleProperty::HVAC_POWER_ON,
                                             (int)VehicleProperty::HVAC_AUTO_RECIRC_ON,
                                             (int)VehicleProperty::HVAC_ELECTRIC_DEFROSTER_ON};
    mVehicle->getAllPropConfigs(
            [&propConfigs](const hidl_vec<VehiclePropConfig>& cfgs) { propConfigs = cfgs; });
    for (const VehiclePropConfig& cfg : propConfigs) {
        // test on boolean and writable property
        if (cfg.access == VehiclePropertyAccess::READ_WRITE && isBooleanGlobalProp(cfg.prop) &&
            !hvacProps.count(cfg.prop)) {
            invokeGet(cfg.prop, 0);
            int setValue = mActualValue.value.int32Values[0] == 1 ? 0 : 1;
            VehiclePropValue propToSet = mActualValue;
            propToSet.value.int32Values[0] = setValue;
            ASSERT_EQ(StatusCode::OK, mVehicle->set(propToSet))
                    << "Invalid status code for setting property: " << cfg.prop;
            // check set success
            invokeGet(cfg.prop, 0);
            ASSERT_EQ(StatusCode::OK, mActualStatusCode);
            ASSERT_EQ(setValue, mActualValue.value.int32Values[0])
                    << "Failed to set value for property: " << cfg.prop;
        }
    }
}

// Test set() on an read_only property.
TEST_P(VehicleHalHidlTest, setNotWritableProp) {
    ALOGD("VehicleHalHidlTest::setNotWritableProp");
    invokeGet(static_cast<int>(VehicleProperty::PERF_VEHICLE_SPEED), 0);
    ASSERT_EQ(StatusCode::OK, mActualStatusCode);
    VehiclePropValue vehicleSpeed = mActualValue;

    ASSERT_EQ(StatusCode::ACCESS_DENIED, mVehicle->set(vehicleSpeed));
}

// Test subscribe() and unsubscribe().
TEST_P(VehicleHalHidlTest, subscribeAndUnsubscribe) {
    ALOGD("VehicleHalHidlTest::subscribeAndUnsubscribe");
    const auto prop = static_cast<int>(VehicleProperty::PERF_VEHICLE_SPEED);
    sp<VtsVehicleCallback> cb = new VtsVehicleCallback();

    hidl_vec<SubscribeOptions> options = {
            SubscribeOptions{.propId = prop, 100.0, .flags = SubscribeFlags::EVENTS_FROM_CAR}};

    ASSERT_EQ(StatusCode::OK, mVehicle->subscribe(cb, options));
    ASSERT_TRUE(cb->waitForExpectedEvents(10));

    ASSERT_EQ(StatusCode::OK, mVehicle->unsubscribe(cb, prop));
    cb->reset();
    ASSERT_FALSE(cb->waitForExpectedEvents(10));
}

// Test subscribe() with an invalid property.
TEST_P(VehicleHalHidlTest, subscribeInvalidProp) {
    ALOGD("VehicleHalHidlTest::subscribeInvalidProp");

    sp<VtsVehicleCallback> cb = new VtsVehicleCallback();

    hidl_vec<SubscribeOptions> options = {SubscribeOptions{
            .propId = kInvalidProp, 10.0, .flags = SubscribeFlags::EVENTS_FROM_CAR}};

    ASSERT_NE(StatusCode::OK, mVehicle->subscribe(cb, options));
}

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VehicleHalHidlTest);
INSTANTIATE_TEST_SUITE_P(
        PerInstance, VehicleHalHidlTest,
        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IVehicle::descriptor)),
        android::hardware::PrintInstanceNameToString);
+5 −0
Original line number Diff line number Diff line
@@ -24,5 +24,10 @@
    {
      "name": "DefaultVehicleHalTest"
    }
  ],
  "auto-presubmit": [
    {
      "name": "VtsHalAutomotiveVehicle_TargetTest"
    }
  ]
}
+5 −0
Original line number Diff line number Diff line
@@ -165,6 +165,11 @@ interface IVehicle {
     *    a property set failure message sent from the vehicle bus.
     * @param options List of options to subscribe. SubscribeOption contains
     *    information such as property Id, area Id, sample rate, etc.
     *    For continuous properties, sample rate must be provided. If sample
     *    rate is less than {@link VehiclePropConfig#minSampleRate}, the sample
     *    rate would be minSampleRate. If sample rate is larger than
     *    {@link VehiclePropValue#maxSampleRate}, the sample rate would be
     *    maxSampleRate.
     * @param maxSharedMemoryFileCount The maximum number of shared memory files
     *    allocated for in VHAL for this subscription. When a memory file is
     *    handled back to the client, it cannot be used by VHAL to deliver
+5 −5
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ namespace fake {

class FakeVehicleHardware : public IVehicleHardware {
  public:
    using ValueResultType = android::base::Result<VehiclePropValuePool::RecyclableType, VhalError>;
    using ValueResultType = VhalResult<VehiclePropValuePool::RecyclableType>;

    FakeVehicleHardware();

@@ -90,7 +90,7 @@ class FakeVehicleHardware : public IVehicleHardware {
    ValueResultType getValue(
            const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const;

    android::base::Result<void, VhalError> setValue(
    VhalResult<void> setValue(
            const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);

  private:
@@ -117,17 +117,17 @@ class FakeVehicleHardware : public IVehicleHardware {
    // Override the properties using config files in 'overrideDir'.
    void overrideProperties(const char* overrideDir);

    android::base::Result<void, VhalError> maybeSetSpecialValue(
    VhalResult<void> maybeSetSpecialValue(
            const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
            bool* isSpecialValue);
    ValueResultType maybeGetSpecialValue(
            const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
            bool* isSpecialValue) const;
    android::base::Result<void, VhalError> setApPowerStateReport(
    VhalResult<void> setApPowerStateReport(
            const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
    VehiclePropValuePool::RecyclableType createApPowerStateReq(
            aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq state);
    android::base::Result<void, VhalError> setUserHalProp(
    VhalResult<void> setUserHalProp(
            const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
    ValueResultType getUserHalProp(
            const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const;
+5 −7
Original line number Diff line number Diff line
@@ -68,8 +68,6 @@ using ::android::base::Result;
using ::android::base::StartsWith;
using ::android::base::StringPrintf;

using StatusError = android::base::Error<VhalError>;

const char* VENDOR_OVERRIDE_DIR = "/vendor/etc/automotive/vhaloverride/";
const char* OVERRIDE_PROPERTY = "persist.vendor.vhal_init_value_override";

@@ -193,7 +191,7 @@ VehiclePropValuePool::RecyclableType FakeVehicleHardware::createApPowerStateReq(
    return req;
}

Result<void, VhalError> FakeVehicleHardware::setApPowerStateReport(const VehiclePropValue& value) {
VhalResult<void> FakeVehicleHardware::setApPowerStateReport(const VehiclePropValue& value) {
    auto updatedValue = mValuePool->obtain(value);
    updatedValue->timestamp = elapsedRealtimeNano();

@@ -270,7 +268,7 @@ bool FakeVehicleHardware::isHvacPropAndHvacNotAvailable(int32_t propId) {
    return false;
}

Result<void, VhalError> FakeVehicleHardware::setUserHalProp(const VehiclePropValue& value) {
VhalResult<void> FakeVehicleHardware::setUserHalProp(const VehiclePropValue& value) {
    auto result = mFakeUserHal->onSetProperty(value);
    if (!result.ok()) {
        return StatusError(getErrorCode(result))
@@ -345,7 +343,7 @@ FakeVehicleHardware::ValueResultType FakeVehicleHardware::maybeGetSpecialValue(
    return nullptr;
}

Result<void, VhalError> FakeVehicleHardware::maybeSetSpecialValue(const VehiclePropValue& value,
VhalResult<void> FakeVehicleHardware::maybeSetSpecialValue(const VehiclePropValue& value,
                                                           bool* isSpecialValue) {
    *isSpecialValue = false;
    VehiclePropValuePool::RecyclableType updatedValue;
@@ -442,7 +440,7 @@ StatusCode FakeVehicleHardware::setValues(std::shared_ptr<const SetValuesCallbac
    return StatusCode::OK;
}

Result<void, VhalError> FakeVehicleHardware::setValue(const VehiclePropValue& value) {
VhalResult<void> FakeVehicleHardware::setValue(const VehiclePropValue& value) {
    bool isSpecialValue = false;
    auto setSpecialValueResult = maybeSetSpecialValue(value, &isSpecialValue);

Loading