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

Commit 778b15a2 authored by Brian Lindahl's avatar Brian Lindahl
Browse files

Fix bug with parsing vectors

Also move to StringUtils, add unit test and use std::from_chars.

Bug: 234833109
Test: statsd_testdrive 684 while watching YouTube videos
Test: atest mediametrics_tests#parseVector
Change-Id: I0eff0bcb7fb9542fdab0c08b98f7789decedb7d2
parent 13e40cb2
Loading
Loading
Loading
Loading
+23 −1
Original line number Original line Diff line number Diff line
@@ -15,11 +15,13 @@
 */
 */


//#define LOG_NDEBUG 0
//#define LOG_NDEBUG 0
#define LOG_TAG "MediaMetricsService::stringutils"
#define LOG_TAG "mediametrics::stringutils"
#include <utils/Log.h>
#include <utils/Log.h>


#include "StringUtils.h"
#include "StringUtils.h"


#include <charconv>

#include "AudioTypes.h"
#include "AudioTypes.h"


namespace android::mediametrics::stringutils {
namespace android::mediametrics::stringutils {
@@ -54,6 +56,26 @@ std::vector<std::string> split(const std::string& flags, const char *delim)
    }
    }
}
}


bool parseVector(const std::string &str, std::vector<int32_t> *vector) {
    std::vector<int32_t> values;
    const char *p = str.c_str();
    const char *last = p + str.size();
    while (p != last) {
        if (*p == ',' || *p == '{' || *p == '}') {
            p++;
        }
        int32_t value = -1;
        auto [ptr, error] = std::from_chars(p, last, value);
        if (error == std::errc::invalid_argument || error == std::errc::result_out_of_range) {
            return false;
        }
        p = ptr;
        values.push_back(value);
    }
    *vector = std::move(values);
    return true;
}

std::vector<std::pair<std::string, std::string>> getDeviceAddressPairs(const std::string& devices)
std::vector<std::pair<std::string, std::string>> getDeviceAddressPairs(const std::string& devices)
{
{
    std::vector<std::pair<std::string, std::string>> result;
    std::vector<std::pair<std::string, std::string>> result;
+4 −2
Original line number Original line Diff line number Diff line
@@ -16,11 +16,13 @@


#pragma once
#pragma once


#include <audio_utils/SimpleLog.h>
#include <map>
#include <map>
#include <mutex>
#include <mutex>
#include <sstream>
#include <sstream>


#include <android-base/thread_annotations.h>
#include <audio_utils/SimpleLog.h>

namespace android::mediametrics {
namespace android::mediametrics {


class StatsdLog {
class StatsdLog {
@@ -61,9 +63,9 @@ public:
   }
   }


private:
private:
    mutable std::mutex mLock;
    SimpleLog mSimpleLog; // internally locked
    SimpleLog mSimpleLog; // internally locked
    std::map<int /* atom */, size_t /* count */> mCountMap GUARDED_BY(mLock); // sorted
    std::map<int /* atom */, size_t /* count */> mCountMap GUARDED_BY(mLock); // sorted
    mutable std::mutex mLock;
};
};


} // namespace android::mediametrics
} // namespace android::mediametrics
+6 −0
Original line number Original line Diff line number Diff line
@@ -71,6 +71,12 @@ std::string tokenizer(std::string::const_iterator& it,
 */
 */
std::vector<std::string> split(const std::string& flags, const char *delim);
std::vector<std::string> split(const std::string& flags, const char *delim);


/**
 * Parses a vector of integers using ',' '{' and '}' as delimeters. Leaves
 * vector unmodified if the parsing fails.
 */
bool parseVector(const std::string &str, std::vector<int32_t> *vector);

/**
/**
 * Parse the devices string and return a vector of device address pairs.
 * Parse the devices string and return a vector of device address pairs.
 *
 *
+2 −0
Original line number Original line Diff line number Diff line
@@ -15,7 +15,9 @@
 */
 */


#include <memory>
#include <memory>

#include <stats_event.h>
#include <stats_event.h>
#include <StatsdLog.h>


namespace android {
namespace android {
namespace mediametrics {
namespace mediametrics {
+9 −26
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@
#include <pthread.h>
#include <pthread.h>
#include <pwd.h>
#include <pwd.h>
#include <stdint.h>
#include <stdint.h>
#include <string>
#include <string.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/time.h>
@@ -32,11 +33,12 @@
#include <stats_media_metrics.h>
#include <stats_media_metrics.h>
#include <stats_event.h>
#include <stats_event.h>


#include "cleaner.h"
#include <frameworks/proto_logging/stats/message/mediametrics_message.pb.h>
#include "MediaMetricsService.h"
#include <mediametricsservice/cleaner.h>
#include "ValidateId.h"
#include <mediametricsservice/iface_statsd.h>
#include "frameworks/proto_logging/stats/message/mediametrics_message.pb.h"
#include <mediametricsservice/MediaMetricsService.h>
#include "iface_statsd.h"
#include <mediametricsservice/StringUtils.h>
#include <mediametricsservice/ValidateId.h>


namespace android {
namespace android {


@@ -169,27 +171,8 @@ static int32_t getMetricsHdrFormatEnum(std::string &mime, std::string &component
}
}


static void parseVector(const std::string &str, std::vector<int32_t> *vector) {
static void parseVector(const std::string &str, std::vector<int32_t> *vector) {
    char valueStr[12] = {};
    if (!mediametrics::stringutils::parseVector(str, vector)) {
    int i = 0;
        ALOGE("failed to parse integer vector from '%s'", str.c_str());
    for (char const * p = str.c_str(); *p != 0; ++p) {
        if (*p == ',' || *p == '{' || *p == '}') {
            valueStr[i] = 0;
            int64_t value = strtol(valueStr, nullptr, 10);
            if (value >= std::numeric_limits<int32_t>::max() ||
                value <= std::numeric_limits<int32_t>::min() ||
                value == 0) {
                ALOGE("failed to parse integer vector at '%s' from '%s'", p, str.c_str());
                return;
            }
            vector->push_back(int32_t(value));
            i = valueStr[0] = 0;
        } else {
            valueStr[i++] = *p;
            if (i == sizeof(valueStr) - 1) { // -1 because we need space for a null terminator
                ALOGE("failed to parse integer vector at '%s' from '%s'", p, str.c_str());
                return;
            }
        }
    }
    }
}
}


Loading