Home | History | Annotate | Download | only in vhal_v2_0
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "JsonFakeValueGenerator"
     18 
     19 #include <fstream>
     20 
     21 #include <log/log.h>
     22 #include <vhal_v2_0/VehicleUtils.h>
     23 
     24 #include "JsonFakeValueGenerator.h"
     25 
     26 namespace android {
     27 namespace hardware {
     28 namespace automotive {
     29 namespace vehicle {
     30 namespace V2_0 {
     31 
     32 namespace impl {
     33 
     34 JsonFakeValueGenerator::JsonFakeValueGenerator(const OnHalEvent& onHalEvent)
     35     : mOnHalEvent(onHalEvent), mThread(&JsonFakeValueGenerator::loop, this) {}
     36 
     37 JsonFakeValueGenerator::~JsonFakeValueGenerator() {
     38     mStopRequested = true;
     39     {
     40         MuxGuard g(mLock);
     41         mGenCfg.index = 0;
     42         mGenCfg.events.clear();
     43     }
     44     mCond.notify_one();
     45     if (mThread.joinable()) {
     46         mThread.join();
     47     }
     48 }
     49 
     50 StatusCode JsonFakeValueGenerator::start(const VehiclePropValue& request) {
     51     const auto& v = request.value;
     52     if (v.stringValue.empty()) {
     53         ALOGE("%s: path to JSON file is missing", __func__);
     54         return StatusCode::INVALID_ARG;
     55     }
     56     const char* file = v.stringValue.c_str();
     57     std::ifstream ifs(file);
     58     if (!ifs) {
     59         ALOGE("%s: couldn't open %s for parsing.", __func__, file);
     60         return StatusCode::INTERNAL_ERROR;
     61     }
     62     std::vector<VehiclePropValue> fakeVhalEvents = parseFakeValueJson(ifs);
     63 
     64     {
     65         MuxGuard g(mLock);
     66         mGenCfg = {0, fakeVhalEvents};
     67     }
     68     mCond.notify_one();
     69     return StatusCode::OK;
     70 }
     71 
     72 StatusCode JsonFakeValueGenerator::stop(const VehiclePropValue& request) {
     73     const auto& v = request.value;
     74     if (!v.stringValue.empty()) {
     75         ALOGI("%s: %s", __func__, v.stringValue.c_str());
     76     }
     77 
     78     {
     79         MuxGuard g(mLock);
     80         mGenCfg.index = 0;
     81         mGenCfg.events.clear();
     82     }
     83     mCond.notify_one();
     84     return StatusCode::OK;
     85 }
     86 
     87 std::vector<VehiclePropValue> JsonFakeValueGenerator::parseFakeValueJson(std::istream& is) {
     88     std::vector<VehiclePropValue> fakeVhalEvents;
     89 
     90     Json::Reader reader;
     91     Json::Value rawEvents;
     92     if (!reader.parse(is, rawEvents)) {
     93         ALOGE("%s: Failed to parse fake data JSON file. Error: %s", __func__,
     94               reader.getFormattedErrorMessages().c_str());
     95         return fakeVhalEvents;
     96     }
     97 
     98     for (Json::Value::ArrayIndex i = 0; i < rawEvents.size(); i++) {
     99         Json::Value rawEvent = rawEvents[i];
    100         if (!rawEvent.isObject()) {
    101             ALOGE("%s: VHAL JSON event should be an object, %s", __func__,
    102                   rawEvent.toStyledString().c_str());
    103             continue;
    104         }
    105         if (rawEvent["prop"].empty() || rawEvent["areaId"].empty() || rawEvent["value"].empty() ||
    106             rawEvent["timestamp"].empty()) {
    107             ALOGE("%s: VHAL JSON event has missing fields, skip it, %s", __func__,
    108                   rawEvent.toStyledString().c_str());
    109             continue;
    110         }
    111         VehiclePropValue event = {.prop = rawEvent["prop"].asInt(),
    112                                   .areaId = rawEvent["areaId"].asInt(),
    113                                   .timestamp = rawEvent["timestamp"].asInt64()};
    114 
    115         Json::Value rawEventValue = rawEvent["value"];
    116         auto& value = event.value;
    117         switch (getPropType(event.prop)) {
    118             case VehiclePropertyType::BOOLEAN:
    119             case VehiclePropertyType::INT32:
    120                 value.int32Values.resize(1);
    121                 value.int32Values[0] = rawEventValue.asInt();
    122                 break;
    123             case VehiclePropertyType::INT64:
    124                 value.int64Values.resize(1);
    125                 value.int64Values[0] = rawEventValue.asInt64();
    126                 break;
    127             case VehiclePropertyType::FLOAT:
    128                 value.floatValues.resize(1);
    129                 value.floatValues[0] = rawEventValue.asFloat();
    130                 break;
    131             case VehiclePropertyType::STRING:
    132                 value.stringValue = rawEventValue.asString();
    133                 break;
    134             default:
    135                 ALOGE("%s: unsupported type for property: 0x%x with value: %s", __func__,
    136                       event.prop, rawEventValue.asString().c_str());
    137                 continue;
    138         }
    139         fakeVhalEvents.push_back(event);
    140     }
    141     return fakeVhalEvents;
    142 }
    143 
    144 void JsonFakeValueGenerator::loop() {
    145     static constexpr auto kInvalidTime = TimePoint(Nanos::max());
    146 
    147     while (!mStopRequested) {
    148         auto nextEventTime = kInvalidTime;
    149         {
    150             MuxGuard g(mLock);
    151             if (mGenCfg.index < mGenCfg.events.size()) {
    152                 mOnHalEvent(mGenCfg.events[mGenCfg.index]);
    153             }
    154             if (!mGenCfg.events.empty() && mGenCfg.index < mGenCfg.events.size() - 1) {
    155                 Nanos intervalNano =
    156                     static_cast<Nanos>(mGenCfg.events[mGenCfg.index + 1].timestamp -
    157                                        mGenCfg.events[mGenCfg.index].timestamp);
    158                 nextEventTime = Clock::now() + intervalNano;
    159             }
    160             mGenCfg.index++;
    161         }
    162 
    163         std::unique_lock<std::mutex> g(mLock);
    164         mCond.wait_until(g, nextEventTime);
    165     }
    166 }
    167 
    168 }  // namespace impl
    169 
    170 }  // namespace V2_0
    171 }  // namespace vehicle
    172 }  // namespace automotive
    173 }  // namespace hardware
    174 }  // namespace android
    175