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

Commit e39d3942 authored by Yu Shan's avatar Yu Shan Committed by Android (Google) Code Review
Browse files

Merge "Add heart beat event to Default VHAL."

parents dbd46942 fdf28cf2
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */
#define LOG_TAG "DefaultVehicleHal_v2_0"

#include <android-base/chrono_utils.h>
#include <assert.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>
@@ -32,6 +33,10 @@ namespace V2_0 {

namespace impl {

namespace {
constexpr std::chrono::nanoseconds kHeartBeatIntervalNs = 3s;
}  // namespace

DefaultVehicleHal::DefaultVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client)
    : mPropStore(propStore), mRecurrentTimer(getTimerAction()), mVehicleClient(client) {
    initStaticConfig();
@@ -297,6 +302,41 @@ void DefaultVehicleHal::onCreate() {
    }

    mVehicleClient->triggerSendAllValues();
    registerHeartBeatEvent();
}

DefaultVehicleHal::~DefaultVehicleHal() {
    mRecurrentTimer.unregisterRecurrentEvent(static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT));
}

void DefaultVehicleHal::registerHeartBeatEvent() {
    mRecurrentTimer.registerRecurrentEvent(kHeartBeatIntervalNs,
                                           static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT));
}

VehicleHal::VehiclePropValuePtr DefaultVehicleHal::doInternalHealthCheck() {
    VehicleHal::VehiclePropValuePtr v = nullptr;

    // This is an example of very simple health checking. VHAL is considered healthy if we can read
    // PERF_VEHICLE_SPEED. The more comprehensive health checking is required.
    VehiclePropValue propValue = {
            .prop = static_cast<int32_t>(VehicleProperty::PERF_VEHICLE_SPEED),
    };
    auto internalPropValue = mPropStore->readValueOrNull(propValue);
    if (internalPropValue != nullptr) {
        v = createVhalHeartBeatProp();
    } else {
        ALOGW("VHAL health check failed");
    }
    return v;
}

VehicleHal::VehiclePropValuePtr DefaultVehicleHal::createVhalHeartBeatProp() {
    VehicleHal::VehiclePropValuePtr v = getValuePool()->obtainInt64(uptimeMillis());
    v->prop = static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT);
    v->areaId = 0;
    v->status = VehiclePropertyStatus::AVAILABLE;
    return v;
}

void DefaultVehicleHal::onContinuousPropertyTimer(const std::vector<int32_t>& properties) {
@@ -309,6 +349,10 @@ void DefaultVehicleHal::onContinuousPropertyTimer(const std::vector<int32_t>& pr
            if (internalPropValue != nullptr) {
                v = pool.obtain(*internalPropValue);
            }
        } else if (property == static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT)) {
            // VHAL_HEARTBEAT is not a continuous value, but it needs to be updated periodically.
            // So, the update is done through onContinuousPropertyTimer.
            v = doInternalHealthCheck();
        } else {
            ALOGE("Unexpected onContinuousPropertyTimer for property: 0x%x", property);
            continue;
+8 −2
Original line number Diff line number Diff line
@@ -35,9 +35,9 @@ namespace impl {
class DefaultVehicleHal : public VehicleHal {
  public:
    DefaultVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client);
    ~DefaultVehicleHal() = default;
    ~DefaultVehicleHal();

    //  Methods from VehicleHal
    // Initialize VHAL. Should always call registerHeartBeatEvent() during onCreate.
    void onCreate() override;
    std::vector<VehiclePropConfig> listProperties() override;
    VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue,
@@ -65,6 +65,12 @@ class DefaultVehicleHal : public VehicleHal {
    StatusCode checkPropValue(const VehiclePropValue& propValue, const VehiclePropConfig* config);
    // Check whether the property value is within the range according to area config.
    StatusCode checkValueRange(const VehiclePropValue& propValue, const VehiclePropConfig* config);
    // Register the heart beat event to be sent every 3s. This is required to inform watch dog that
    // VHAL is alive. Subclasses should always calls this function during onCreate.
    void registerHeartBeatEvent();

    VehicleHal::VehiclePropValuePtr doInternalHealthCheck();
    VehicleHal::VehiclePropValuePtr createVhalHeartBeatProp();

  private:
    // Check whether a vendor mixed value property is valid according to its config array.
+28 −3
Original line number Diff line number Diff line
@@ -56,14 +56,21 @@ const size_t MAX_PROP_ID_LENGTH = 100;

class DefaultVhalImplTest : public ::testing::Test {
  public:
    ~DefaultVhalImplTest() { mEventQueue.deactivate(); }
    ~DefaultVhalImplTest() {
        mEventQueue.deactivate();
        mHeartBeatQueue.deactivate();
        // Destroy mHal before destroying its dependencies.
        mHal.reset();
        mConnector.reset();
        mPropStore.reset();
    }

  protected:
    void SetUp() override {
        mPropStore.reset(new VehiclePropertyStore);
        mConnector.reset(new DefaultVehicleConnector);
        mHal.reset(new DefaultVehicleHal(mPropStore.get(), mConnector.get()));
        mConnector->setValuePool(&mValueObjectPool);
        mHal.reset(new DefaultVehicleHal(mPropStore.get(), mConnector.get()));
        mHal->init(&mValueObjectPool,
                   std::bind(&DefaultVhalImplTest::onHalEvent, this, std::placeholders::_1),
                   std::bind(&DefaultVhalImplTest::onHalPropertySetError, this,
@@ -71,7 +78,14 @@ class DefaultVhalImplTest : public ::testing::Test {
    }

  private:
    void onHalEvent(VehiclePropValuePtr v) { mEventQueue.push(std::move(v)); }
    void onHalEvent(VehiclePropValuePtr v) {
        if (v->prop != toInt(VehicleProperty::VHAL_HEARTBEAT)) {
            // Ignore heartbeat properties.
            mEventQueue.push(std::move(v));
        } else {
            mHeartBeatQueue.push(std::move(v));
        }
    }

    void onHalPropertySetError(StatusCode /*errorCode*/, int32_t /*property*/, int32_t /*areaId*/) {
    }
@@ -82,6 +96,7 @@ class DefaultVhalImplTest : public ::testing::Test {
    std::unique_ptr<VehiclePropertyStore> mPropStore;
    VehiclePropValuePool mValueObjectPool;
    android::ConcurrentQueue<VehiclePropValuePtr> mEventQueue;
    android::ConcurrentQueue<VehiclePropValuePtr> mHeartBeatQueue;
};

TEST_F(DefaultVhalImplTest, testListProperties) {
@@ -724,4 +739,14 @@ TEST_F(DefaultVhalImplTest, testDebugGenFakeDataKeyPress) {
    EXPECT_EQ(2, events[1]->value.int32Values[2]);
}

TEST_F(DefaultVhalImplTest, testHeartBeatEvent) {
    // A heart beat would be sent every 3s, but let's wait for 6s to be sure at least 2 events have
    // been generated (at 0s and 3s).
    std::this_thread::sleep_for(std::chrono::milliseconds(6000));

    auto events = mHeartBeatQueue.flush();
    ASSERT_GE(events.size(), (size_t)2);
    ASSERT_EQ(toInt(VehicleProperty::VHAL_HEARTBEAT), events[0]->prop);
}

}  // namespace