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

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

Snap for 7607904 from 0786af29 to sc-v2-release

Change-Id: Idfb31b46d9ff230f4dc2b8a5a0aec328311ac32d
parents 2dfe052a 0786af29
Loading
Loading
Loading
Loading
+70 −45
Original line number Diff line number Diff line
@@ -2269,12 +2269,41 @@ TEST_P(EvsHidlTest, CameraStreamExternalBuffering) {

    // Acquire the graphics buffer allocator
    android::GraphicBufferAllocator& alloc(android::GraphicBufferAllocator::get());
    const auto usage = GRALLOC_USAGE_HW_TEXTURE |
                       GRALLOC_USAGE_SW_READ_RARELY |
                       GRALLOC_USAGE_SW_WRITE_OFTEN;
    const auto usage =
            GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_OFTEN;
    const auto format = HAL_PIXEL_FORMAT_RGBA_8888;
    const auto width = 640;
    const auto height = 360;
    uint32_t width = 640;
    uint32_t height = 360;
    camera_metadata_entry_t streamCfgs;

    // Test each reported camera
    for (auto&& cam : cameraInfo) {
        bool foundCfg = false;
        if (!find_camera_metadata_entry(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()),
                                        ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
                                        &streamCfgs)) {
            // Stream configurations are found in metadata
            RawStreamConfig* ptr = reinterpret_cast<RawStreamConfig*>(streamCfgs.data.i32);

            LOG(DEBUG) << __LINE__ << " start searching " << streamCfgs.count;
            for (unsigned idx = 0; idx < streamCfgs.count; idx++) {
                LOG(DEBUG) << "ptr->direction= " << ptr->direction
                           << " ptr->format= " << ptr->format;
                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
                    ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
                    width = ptr->width;
                    height = ptr->height;
                    foundCfg = true;
                    // Always use the 1st available configuration
                    break;
                }
                ++ptr;
            }
        }

        if (!foundCfg) {
            LOG(INFO) << "No configuration found. Use default stream configurations.";
        }

        // Allocate buffers to use
        hidl_vec<BufferDesc> buffers;
@@ -2282,17 +2311,16 @@ TEST_P(EvsHidlTest, CameraStreamExternalBuffering) {
        for (auto i = 0; i < kBuffersToHold; ++i) {
            unsigned pixelsPerLine;
            buffer_handle_t memHandle = nullptr;
        android::status_t result = alloc.allocate(width,
                                                  height,
                                                  format,
                                                  1,
                                                  usage,
                                                  &memHandle,
                                                  &pixelsPerLine,
                                                  0,
                                                  "EvsApp");
            android::status_t result =
                    alloc.allocate(width, height, format, 1, usage, &memHandle, &pixelsPerLine, 0,
                                   "CameraStreamExternalBufferingTest");
            if (result != android::NO_ERROR) {
                LOG(ERROR) << __FUNCTION__ << " failed to allocate memory.";
                // Release previous allocated buffers
                for (auto j = 0; j < i; j++) {
                    alloc.free(buffers[i].buffer.nativeHandle);
                }
                return;
            } else {
                BufferDesc buf;
                AHardwareBuffer_Desc* pDesc =
@@ -2309,8 +2337,6 @@ TEST_P(EvsHidlTest, CameraStreamExternalBuffering) {
            }
        }

    // Test each reported camera
    for (auto&& cam: cameraInfo) {
        bool isLogicalCam = false;
        getPhysicalCameraIds(cam.v1.cameraId, isLogicalCam);

@@ -2374,14 +2400,13 @@ TEST_P(EvsHidlTest, CameraStreamExternalBuffering) {
        // Explicitly release the camera
        pEnumerator->closeCamera(pCam);
        activeCameras.clear();
    }

        // Release buffers
        for (auto& b : buffers) {
            alloc.free(b.buffer.nativeHandle);
        }
        buffers.resize(0);
    }
}


/*
+1 −0
Original line number Diff line number Diff line
@@ -182,6 +182,7 @@ cc_test {
    ],
    shared_libs: [
        "libbase",
        "libcutils",
    ],
    header_libs: ["libbase_headers"],
    test_suites: ["general-tests"],
+23 −3
Original line number Diff line number Diff line
@@ -76,6 +76,9 @@ public:
    Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;

  private:
    // Set unit test class as friend class to test private functions.
    friend class VehicleHalManagerTestHelper;

    using VehiclePropValuePtr = VehicleHal::VehiclePropValuePtr;
    // Returns true if needs to call again shortly.
    using RetriableAction = std::function<bool()>;
@@ -105,14 +108,20 @@ public:
    void cmdDumpOneProperty(int fd, int32_t prop, int32_t areaId);
    void cmdDumpOneProperty(int fd, int rowNumber, const VehiclePropConfig& config);

    bool cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options);

    static bool checkArgumentsSize(int fd, const hidl_vec<hidl_string>& options, size_t minSize);
    static bool checkCallerHasWritePermissions(int fd);
    static bool safelyParseInt(int fd, int index, std::string s, int* out);
    template <typename T>
    static bool safelyParseInt(int fd, int index, const std::string& s, T* out);
    static bool safelyParseFloat(int fd, int index, const std::string& s, float* out);
    // Parses "s" as a hex string and populate "*bytes". The hex string must be in the format of
    // valid hex format, e.g. "0xABCD".
    static bool parseHexString(int fd, const std::string& s, std::vector<uint8_t>* bytes);
    void cmdHelp(int fd) const;
    void cmdListAllProperties(int fd) const;
    void cmdDumpAllProperties(int fd);
    void cmdDumpSpecificProperties(int fd, const hidl_vec<hidl_string>& options);
    void cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options);

    static bool isSubscribable(const VehiclePropConfig& config,
                               SubscribeFlags flags);
@@ -120,6 +129,17 @@ public:
    static float checkSampleRate(const VehiclePropConfig& config,
                                 float sampleRate);
    static ClientId getClientId(const sp<IVehicleCallback>& callback);

    // Parses the cmdline options for "--set" command. "*prop" would be populated with the
    // the properties to be set. Returns true when the cmdline options are valid, false otherwise.
    static bool parseSetPropOptions(int fd, const hidl_vec<hidl_string>& options,
                                    VehiclePropValue* prop);
    // Parses the options and get the values for the current option specified by "*index". "*index"
    // would advance to the next option field (e.g., the next "-f"). Returns a list of values for
    // the current option.
    static std::vector<std::string> getOptionValues(const hidl_vec<hidl_string>& options,
                                                    size_t* index);

  private:
    VehicleHal* mHal;
    std::unique_ptr<VehiclePropConfigIndex> mConfigIndex;
+220 −86
Original line number Diff line number Diff line
@@ -20,7 +20,9 @@

#include <cmath>
#include <fstream>
#include <unordered_set>

#include <android-base/parsedouble.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <android/hardware/automotive/vehicle/2.0/BpHwVehicleCallback.h>
@@ -44,15 +46,34 @@ using ::android::base::EqualsIgnoreCase;
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_string;

namespace {

constexpr std::chrono::milliseconds kHalEventBatchingTimeWindow(10);

const VehiclePropValue kEmptyValue{};

// A list of supported options for "--set" command.
const std::unordered_set<std::string> kSetPropOptions = {
        // integer.
        "-i",
        // 64bit integer.
        "-i64",
        // float.
        "-f",
        // string.
        "-s",
        // bytes in hex format, e.g. 0xDEADBEEF.
        "-b",
        // Area id in integer.
        "-a"};

}  // namespace

/**
 * Indicates what's the maximum size of hidl_vec<VehiclePropValue> we want
 * to store in reusable object pool.
 */
constexpr auto kMaxHidlVecOfVehiclPropValuePoolSize = 20;
constexpr auto kMaxHidlVecOfVehiclePropValuePoolSize = 20;

Return<void> VehicleHalManager::getAllPropConfigs(getAllPropConfigs_cb _hidl_cb) {
    ALOGI("getAllPropConfigs called");
@@ -213,6 +234,11 @@ void VehicleHalManager::cmdDump(int fd, const hidl_vec<hidl_string>& options) {
    } else if (EqualsIgnoreCase(option, "--get")) {
        cmdDumpSpecificProperties(fd, options);
    } else if (EqualsIgnoreCase(option, "--set")) {
        if (!checkCallerHasWritePermissions(fd)) {
            dprintf(fd, "Caller does not have write permission\n");
            return;
        }
        // Ignore the return value for this.
        cmdSetOneProperty(fd, options);
    } else {
        dprintf(fd, "Invalid option: %s\n", option.c_str());
@@ -239,7 +265,8 @@ bool VehicleHalManager::checkArgumentsSize(int fd, const hidl_vec<hidl_string>&
    return false;
}

bool VehicleHalManager::safelyParseInt(int fd, int index, std::string s, int* out) {
template <typename T>
bool VehicleHalManager::safelyParseInt(int fd, int index, const std::string& s, T* out) {
    if (!android::base::ParseInt(s, out)) {
        dprintf(fd, "non-integer argument at index %d: %s\n", index, s.c_str());
        return false;
@@ -247,19 +274,27 @@ bool VehicleHalManager::safelyParseInt(int fd, int index, std::string s, int* ou
    return true;
}

bool VehicleHalManager::safelyParseFloat(int fd, int index, const std::string& s, float* out) {
    if (!android::base::ParseFloat(s, out)) {
        dprintf(fd, "non-float argument at index %d: %s\n", index, s.c_str());
        return false;
    }
    return true;
}

void VehicleHalManager::cmdHelp(int fd) const {
    dprintf(fd, "Usage: \n\n");
    dprintf(fd, "[no args]: dumps (id and value) all supported properties \n");
    dprintf(fd, "--help: shows this help\n");
    dprintf(fd, "--list: lists the ids of all supported properties\n");
    dprintf(fd, "--get <PROP1> [PROP2] [PROPN]: dumps the value of specific properties \n");
    // TODO: support other formats (int64, float, bytes)
    dprintf(fd,
            "--set <PROP> <i|s> <VALUE_1> [<i|s> <VALUE_N>] [a AREA_ID] : sets the value of "
            "property PROP, using arbitrary number of key/value parameters (i for int32, "
            "s for string) and an optional area.\n"
            "Notice that the string value can be set just once, while the other can have multiple "
            "values (so they're used in the respective array)\n");
            "--set <PROP> [-i INT_VALUE [INT_VALUE ...]] [-i64 INT64_VALUE [INT64_VALUE ...]] "
            "[-f FLOAT_VALUE [FLOAT_VALUE ...]] [-s STR_VALUE] "
            "[-b BYTES_VALUE] [-a AREA_ID] : sets the value of property PROP. "
            "Notice that the string, bytes and area value can be set just once, while the other can"
            " have multiple values (so they're used in the respective array), "
            "BYTES_VALUE is in the form of 0xXXXX, e.g. 0xdeadbeef.\n");
}

void VehicleHalManager::cmdListAllProperties(int fd) const {
@@ -337,102 +372,49 @@ void VehicleHalManager::cmdDumpOneProperty(int fd, int32_t prop, int32_t areaId)
    VehiclePropValue input;
    input.prop = prop;
    input.areaId = areaId;
    auto callback = [&](StatusCode status, const VehiclePropValue& output) {
    auto callback = [&fd, &prop](StatusCode status, const VehiclePropValue& output) {
        if (status == StatusCode::OK) {
            dprintf(fd, "%s\n", toString(output).c_str());
        } else {
            dprintf(fd, "Could not get property %d. Error: %s\n", prop, toString(status).c_str());
        }
    };
    get(input, callback);
}

void VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
    if (!checkCallerHasWritePermissions(fd) || !checkArgumentsSize(fd, options, 3)) return;

    size_t size = options.size();

    // Syntax is --set PROP Type1 Value1 TypeN ValueN, so number of arguments must be even
    if (size % 2 != 0) {
        dprintf(fd, "must pass even number of arguments (passed %zu)\n", size);
        return;
    }
    int numberValues = (size - 2) / 2;

    VehiclePropValue prop;
    if (!safelyParseInt(fd, 1, options[1], &prop.prop)) return;
    prop.timestamp = elapsedRealtimeNano();
    prop.status = VehiclePropertyStatus::AVAILABLE;

    // First pass: calculate sizes
    int sizeInt32 = 0;
    int stringIndex = 0;
    int areaIndex = 0;
    for (int i = 2, kv = 1; kv <= numberValues; kv++) {
        // iterate through the kv=1..n key/value pairs, accessing indexes i / i+1 at each step
        std::string type = options[i];
        std::string value = options[i + 1];
        if (EqualsIgnoreCase(type, "i")) {
            sizeInt32++;
        } else if (EqualsIgnoreCase(type, "s")) {
            if (stringIndex != 0) {
                dprintf(fd,
                        "defining string value (%s) again at index %d (already defined at %d=%s"
                        ")\n",
                        value.c_str(), i, stringIndex, options[stringIndex + 1].c_str());
                return;
            }
            stringIndex = i;
        } else if (EqualsIgnoreCase(type, "a")) {
            if (areaIndex != 0) {
                dprintf(fd,
                        "defining area value (%s) again at index %d (already defined at %d=%s"
                        ")\n",
                        value.c_str(), i, areaIndex, options[areaIndex + 1].c_str());
                return;
            }
            areaIndex = i;
        } else {
            dprintf(fd, "invalid (%s) type at index %d\n", type.c_str(), i);
            return;
        }
        i += 2;
    StatusCode status;
    auto value = mHal->get(input, &status);
    callback(status, value.get() ? *value : kEmptyValue);
}
    prop.value.int32Values.resize(sizeInt32);

    // Second pass: populate it
    int indexInt32 = 0;
    for (int i = 2, kv = 1; kv <= numberValues; kv++) {
        // iterate through the kv=1..n key/value pairs, accessing indexes i / i+1 at each step
        int valueIndex = i + 1;
        std::string type = options[i];
        std::string value = options[valueIndex];
        if (EqualsIgnoreCase(type, "i")) {
            int safeInt;
            if (!safelyParseInt(fd, valueIndex, value, &safeInt)) return;
            prop.value.int32Values[indexInt32++] = safeInt;
        } else if (EqualsIgnoreCase(type, "s")) {
            prop.value.stringValue = value;
        } else if (EqualsIgnoreCase(type, "a")) {
            if (!safelyParseInt(fd, valueIndex, value, &prop.areaId)) return;
bool VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
    if (!checkArgumentsSize(fd, options, 4)) {
        dprintf(fd, "Requires at least 4 options, see help\n");
        return false;
    }
        i += 2;

    VehiclePropValue prop = {};
    if (!parseSetPropOptions(fd, options, &prop)) {
        return false;
    }
    ALOGD("Setting prop %s", toString(prop).c_str());
    auto status = set(prop);

    // Do not use VehicleHalManager::set here because we don't want to check write permission.
    // Caller should be able to use the debug interface to set read-only properties.
    handlePropertySetEvent(prop);
    auto status = mHal->set(prop);

    if (status == StatusCode::OK) {
        dprintf(fd, "Set property %s\n", toString(prop).c_str());
    } else {
        return true;
    }
    dprintf(fd, "Failed to set property %s: %s\n", toString(prop).c_str(),
            toString(status).c_str());
    }
    return false;
}

void VehicleHalManager::init() {
    ALOGI("VehicleHalManager::init");

    mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclPropValuePoolSize);

    mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclePropValuePoolSize);

    mBatchingConsumer.run(&mEventQueue,
                          kHalEventBatchingTimeWindow,
@@ -486,7 +468,7 @@ void VehicleHalManager::onBatchHalEvent(const std::vector<VehiclePropValuePtr>&
    for (const HalClientValues& cv : clientValues) {
        auto vecSize = cv.values.size();
        hidl_vec<VehiclePropValue> vec;
        if (vecSize < kMaxHidlVecOfVehiclPropValuePoolSize) {
        if (vecSize < kMaxHidlVecOfVehiclePropValuePoolSize) {
            vec.setToExternal(&mHidlVecOfVehiclePropValuePool[0], vecSize);
        } else {
            vec.resize(vecSize);
@@ -595,6 +577,158 @@ ClientId VehicleHalManager::getClientId(const sp<IVehicleCallback>& callback) {
    }
}

std::vector<std::string> VehicleHalManager::getOptionValues(const hidl_vec<hidl_string>& options,
                                                            size_t* index) {
    std::vector<std::string> values;
    while (*index < options.size()) {
        std::string option = options[*index];
        if (kSetPropOptions.find(option) != kSetPropOptions.end()) {
            return std::move(values);
        }
        values.push_back(option);
        (*index)++;
    }
    return std::move(values);
}

bool VehicleHalManager::parseSetPropOptions(int fd, const hidl_vec<hidl_string>& options,
                                            VehiclePropValue* prop) {
    // Options format:
    // --set PROP [-f f1 f2...] [-i i1 i2...] [-i64 i1 i2...] [-s s1 s2...] [-b b1 b2...] [-a a]
    size_t optionIndex = 1;
    int propValue;
    if (!safelyParseInt(fd, optionIndex, options[optionIndex], &propValue)) {
        dprintf(fd, "property value: \"%s\" is not a valid int\n", options[optionIndex].c_str());
        return false;
    }
    prop->prop = propValue;
    prop->timestamp = elapsedRealtimeNano();
    prop->status = VehiclePropertyStatus::AVAILABLE;
    optionIndex++;
    std::unordered_set<std::string> parsedOptions;

    while (optionIndex < options.size()) {
        std::string type = options[optionIndex];
        optionIndex++;
        size_t currentIndex = optionIndex;
        std::vector<std::string> values = getOptionValues(options, &optionIndex);
        if (parsedOptions.find(type) != parsedOptions.end()) {
            dprintf(fd, "duplicate \"%s\" options\n", type.c_str());
            return false;
        }
        parsedOptions.insert(type);
        if (EqualsIgnoreCase(type, "-i")) {
            if (values.size() == 0) {
                dprintf(fd, "no values specified when using \"-i\"\n");
                return false;
            }
            prop->value.int32Values.resize(values.size());
            for (size_t i = 0; i < values.size(); i++) {
                int32_t safeInt;
                if (!safelyParseInt(fd, currentIndex + i, values[i], &safeInt)) {
                    dprintf(fd, "value: \"%s\" is not a valid int\n", values[i].c_str());
                    return false;
                }
                prop->value.int32Values[i] = safeInt;
            }
        } else if (EqualsIgnoreCase(type, "-i64")) {
            if (values.size() == 0) {
                dprintf(fd, "no values specified when using \"-i64\"\n");
                return false;
            }
            prop->value.int64Values.resize(values.size());
            for (size_t i = 0; i < values.size(); i++) {
                int64_t safeInt;
                if (!safelyParseInt(fd, currentIndex + i, values[i], &safeInt)) {
                    dprintf(fd, "value: \"%s\" is not a valid int64\n", values[i].c_str());
                    return false;
                }
                prop->value.int64Values[i] = safeInt;
            }
        } else if (EqualsIgnoreCase(type, "-f")) {
            if (values.size() == 0) {
                dprintf(fd, "no values specified when using \"-f\"\n");
                return false;
            }
            prop->value.floatValues.resize(values.size());
            for (size_t i = 0; i < values.size(); i++) {
                float safeFloat;
                if (!safelyParseFloat(fd, currentIndex + i, values[i], &safeFloat)) {
                    dprintf(fd, "value: \"%s\" is not a valid float\n", values[i].c_str());
                    return false;
                }
                prop->value.floatValues[i] = safeFloat;
            }
        } else if (EqualsIgnoreCase(type, "-s")) {
            if (values.size() != 1) {
                dprintf(fd, "expect exact one value when using \"-s\"\n");
                return false;
            }
            prop->value.stringValue = values[0];
        } else if (EqualsIgnoreCase(type, "-b")) {
            if (values.size() != 1) {
                dprintf(fd, "expect exact one value when using \"-b\"\n");
                return false;
            }
            std::vector<uint8_t> bytes;
            if (!parseHexString(fd, values[0], &bytes)) {
                dprintf(fd, "value: \"%s\" is not a valid hex string\n", values[0].c_str());
                return false;
            }
            prop->value.bytes = bytes;
        } else if (EqualsIgnoreCase(type, "-a")) {
            if (values.size() != 1) {
                dprintf(fd, "expect exact one value when using \"-a\"\n");
                return false;
            }
            if (!safelyParseInt(fd, currentIndex, values[0], &(prop->areaId))) {
                dprintf(fd, "area ID: \"%s\" is not a valid int\n", values[0].c_str());
                return false;
            }
        } else {
            dprintf(fd, "unknown option: %s\n", type.c_str());
            return false;
        }
    }

    return true;
}

bool VehicleHalManager::parseHexString(int fd, const std::string& s, std::vector<uint8_t>* bytes) {
    if (s.size() % 2 != 0) {
        dprintf(fd, "invalid hex string: %s, should have even size\n", s.c_str());
        return false;
    }
    if (strncmp(s.substr(0, 2).c_str(), "0x", 2)) {
        dprintf(fd, "hex string should start with \"0x\", got %s\n", s.c_str());
        return false;
    }
    std::string subs = s.substr(2);
    std::transform(subs.begin(), subs.end(), subs.begin(),
                   [](unsigned char c) { return std::tolower(c); });

    bool highDigit = true;
    for (size_t i = 0; i < subs.size(); i++) {
        char c = subs[i];
        uint8_t v;
        if (c >= '0' && c <= '9') {
            v = c - '0';
        } else if (c >= 'a' && c <= 'f') {
            v = c - 'a' + 10;
        } else {
            dprintf(fd, "invalid character %c in hex string %s\n", c, subs.c_str());
            return false;
        }
        if (highDigit) {
            (*bytes).push_back(v * 16);
        } else {
            (*bytes)[bytes->size() - 1] += v;
        }
        highDigit = !highDigit;
    }
    return true;
}

}  // namespace V2_0
}  // namespace vehicle
}  // namespace automotive
+179 −28

File changed.

Preview size limit exceeded, changes collapsed.