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

Commit 9299af93 authored by Yi Jin's avatar Yi Jin
Browse files

Refactor system properties protos to just include the list treble team

defines http://go/treble-sysprop-compatibility.

Also refactored system properties proto to have nested proto
definitions. The reason to do it is to have flat proto definition makes
it super hard to manage its field numbers as well as hard to use.
Since we have a predefined list. Support parsing nested proto here.

Bug: 68774852
Test: unit tested and on device test
      $ out/host/linux-x86/bin/incident_report -w system_properties
Change-Id: Icfc7cdcae184fb204c81e6434d21399aa84a1285
parent 6348b054
Loading
Loading
Loading
Loading
+79 −0
Original line number Diff line number Diff line
@@ -297,3 +297,82 @@ Table::insertField(ProtoOutputStream* proto, const std::string& name, const std:
    }
    return true;
}

// ================================================================================
Message::Message(Table* table)
        :mTable(table),
         mPreviousField(""),
         mTokens(),
         mSubMessages()
{
}

Message::~Message()
{
}

void
Message::addSubMessage(uint64_t fieldId, Message* fieldMsg)
{
    for (auto iter = mTable->mFields.begin(); iter != mTable->mFields.end(); iter++) {
        if (iter->second == fieldId) {
            mSubMessages[iter->first] = fieldMsg;
            return;
        }
    }
}

bool
Message::insertField(ProtoOutputStream* proto, const std::string& name, const std::string& value)
{
    // If the field name can be found, it means the name is a primitive field.
    if (mTable->mFields.find(name) != mTable->mFields.end()) {
        endSession(proto);
        // The only edge case is for example ro.hardware itself is a message, so a field called "value"
        // would be defined in proto Ro::Hardware and it must be the first field.
        if (mSubMessages.find(name) != mSubMessages.end()) {
            startSession(proto, name);
            return mSubMessages[name]->insertField(proto, "value", value);
        } else {
            return mTable->insertField(proto, name, value);
        }
    }

    // Try to find the message field which is the prefix of name, so the value would be inserted
    // recursively into the submessage.
    string mutableName = name;
    for (auto iter = mSubMessages.begin(); iter != mSubMessages.end(); iter++) {
        string fieldName = iter->first;
        string prefix = fieldName + "_"; // underscore is the delimiter in the name
        if (stripPrefix(&mutableName, prefix.c_str())) {
            if (mPreviousField != fieldName) {
                endSession(proto);
                startSession(proto, fieldName);
            }
            return mSubMessages[fieldName]->insertField(proto, mutableName, value);
        }
    }
    // Can't find the name in proto definition, handle it separately.
    return false;
}

void
Message::startSession(ProtoOutputStream* proto, const string& name)
{
    uint64_t fieldId = mTable->mFields[name];
    long long token = proto->start(fieldId);
    mPreviousField = name;
    mTokens.push(token);
}

void
Message::endSession(ProtoOutputStream* proto)
{
    if (mPreviousField == "") return;
    if (mSubMessages.find(mPreviousField) != mSubMessages.end()) {
        mSubMessages[mPreviousField]->endSession(proto);
    }
    proto->end(mTokens.top());
    mTokens.pop();
    mPreviousField = "";
}
+60 −4
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#define INCIDENT_HELPER_UTIL_H

#include <map>
#include <stack>
#include <string>
#include <vector>

@@ -34,7 +35,7 @@ const std::string DEFAULT_NEWLINE = "\r\n";
const std::string TAB_DELIMITER = "\t";
const std::string COMMA_DELIMITER = ",";

// returns true if c is a-zA-Z0-9 or underscore _
// returns true if c is a-zA-Z0-9 or underscore
bool isValidChar(char c);

// trim the string with the given charset
@@ -102,11 +103,20 @@ private:
};

/**
 * The class contains a mapping between table headers to its field ids.
 * And allow users to insert the field values to proto based on its header name.
 * The Table class is constructed from two arrays generated by the given message with
 * option (stream_proto.stream_msg).enable_fields_mapping = true.
 * The names are each field's names in the message and must corresponding to the header/name of
 * the text to be parsed, and the ids are the streaming proto encoded field ids.
 *
 * This class then allows users to insert the table values to proto based on its header.
 *
 * Advance feature: if some fields in the message are enums, user must explicitly add the
 * mapping from enum name string to its enum values.
 */
class Message;
class Table
{
friend class Message;
public:
    Table(const char* names[], const uint64_t ids[], const int count);
    ~Table();
@@ -114,9 +124,12 @@ public:
    // Add enum names to values for parsing purpose.
    void addEnumTypeMap(const char* field, const char* enumNames[], const int enumValues[], const int enumSize);

    // manually add enum names to values mapping, useful when an Enum type is used by a lot of fields, and there are no name conflicts
    // Manually add enum names to values mapping, useful when an Enum type is used by
    // a number of fields, there must not be any enum name conflicts.
    void addEnumNameToValue(const char* enumName, const int enumValue);

    // Based on given name, find the right field id, parse the text value and insert to proto.
    // Return false if the given name can't be found.
    bool insertField(ProtoOutputStream* proto, const std::string& name, const std::string& value);
private:
    map<std::string, uint64_t> mFields;
@@ -124,4 +137,47 @@ private:
    map<std::string, int> mEnumValuesByName;
};

/**
 * Reconstructs a typical proto message given its message Table, adds submessage fields explicitly.
 * It allows user to insert nested proto values purely by the names. See insertField for detail.
 */
class Message
{
public:
    Message(Table* table);
    ~Message();

    // Reconstructs the typical proto message by adding its message fields.
    void addSubMessage(uint64_t fieldId, Message* fieldMsg);

    // Inserts value if the given name has the corresponding field in its message and return true.
    // It will recursively search the name in submessages and find the correct field to insert.
    // For example, when the name is dalvik_vm_heapsize, and the message's corresponding proto is:
    //     message Properties {
    //         message DalvikVm {
    //             int32 heapsize = 1;
    //             bool  usejit = 2;
    //         }
    //         DalvikVm dalvik_vm = 1;
    //         string hack_in = 2;
    //     }
    // The value will be inserted into field heapsize in dalvik_vm submessage.
    //
    // Also value belongs to same submessage MUST be inserted contiguously.
    // For example, dalvik_vm_usejit must be inserted directly after dalvik_vm_heapsize, otherwise
    // if hack_in attempts to be inserted before dalvik_vm_usejit, value of usejit isn't added as expected.
    bool insertField(ProtoOutputStream* proto, const std::string& name, const std::string& value);

    // Starts a new message field proto session.
    void startSession(ProtoOutputStream* proto, const string& name);

    // Ends the previous message field proto session.
    void endSession(ProtoOutputStream* proto);
private:
    Table* mTable;
    std::string mPreviousField;
    stack<long long> mTokens;
    map<std::string, Message*> mSubMessages;
};

#endif  // INCIDENT_HELPER_UTIL_H
+123 −9
Original line number Diff line number Diff line
@@ -45,11 +45,119 @@ SystemPropertiesParser::Parse(const int in, const int out) const
    string line;
    string name;  // the name of the property
    string value; // the string value of the property

    ProtoOutputStream proto;
    Table table(SystemPropertiesProto::_FIELD_NAMES, SystemPropertiesProto::_FIELD_IDS, SystemPropertiesProto::_FIELD_COUNT);
    table.addEnumNameToValue("running", SystemPropertiesProto::STATUS_RUNNING);
    table.addEnumNameToValue("stopped", SystemPropertiesProto::STATUS_STOPPED);
    vector<pair<string, string>> extras;

    Table sysPropTable(SystemPropertiesProto::_FIELD_NAMES,
                SystemPropertiesProto::_FIELD_IDS,
                SystemPropertiesProto::_FIELD_COUNT);
    Message sysProp(&sysPropTable);

    Table aaudioT(SystemPropertiesProto::Aaudio::_FIELD_NAMES,
            SystemPropertiesProto::Aaudio::_FIELD_IDS,
            SystemPropertiesProto::Aaudio::_FIELD_COUNT);
    Message aaudio(&aaudioT);
    sysProp.addSubMessage(SystemPropertiesProto::AAUDIO, &aaudio);

    Table cameraTable(SystemPropertiesProto::Camera::_FIELD_NAMES,
            SystemPropertiesProto::Camera::_FIELD_IDS,
            SystemPropertiesProto::Camera::_FIELD_COUNT);
    Message camera(&cameraTable);
    sysProp.addSubMessage(SystemPropertiesProto::CAMERA, &camera);

    Table dalvikVmTable(SystemPropertiesProto::DalvikVm::_FIELD_NAMES,
            SystemPropertiesProto::DalvikVm::_FIELD_IDS,
            SystemPropertiesProto::DalvikVm::_FIELD_COUNT);
    Message dalvikVm(&dalvikVmTable);
    sysProp.addSubMessage(SystemPropertiesProto::DALVIK_VM, &dalvikVm);

    Table initSvcTable(SystemPropertiesProto::InitSvc::_FIELD_NAMES,
            SystemPropertiesProto::InitSvc::_FIELD_IDS,
            SystemPropertiesProto::InitSvc::_FIELD_COUNT);
    initSvcTable.addEnumNameToValue("running", SystemPropertiesProto::InitSvc::STATUS_RUNNING);
    initSvcTable.addEnumNameToValue("stopped", SystemPropertiesProto::InitSvc::STATUS_STOPPED);
    Message initSvc(&initSvcTable);
    sysProp.addSubMessage(SystemPropertiesProto::INIT_SVC, &initSvc);

    Table logTable(SystemPropertiesProto::Log::_FIELD_NAMES,
            SystemPropertiesProto::Log::_FIELD_IDS,
            SystemPropertiesProto::Log::_FIELD_COUNT);
    Message logMsg(&logTable);
    sysProp.addSubMessage(SystemPropertiesProto::LOG, &logMsg);

    Table persistTable(SystemPropertiesProto::Persist::_FIELD_NAMES,
            SystemPropertiesProto::Persist::_FIELD_IDS,
            SystemPropertiesProto::Persist::_FIELD_COUNT);
    Message persist(&persistTable);
    sysProp.addSubMessage(SystemPropertiesProto::PERSIST, &persist);

    Table pmDexoptTable(SystemPropertiesProto::PmDexopt::_FIELD_NAMES,
            SystemPropertiesProto::PmDexopt::_FIELD_IDS,
            SystemPropertiesProto::PmDexopt::_FIELD_COUNT);
    Message pmDexopt(&pmDexoptTable);
    sysProp.addSubMessage(SystemPropertiesProto::PM_DEXOPT, &pmDexopt);

    Table roTable(SystemPropertiesProto::Ro::_FIELD_NAMES,
            SystemPropertiesProto::Ro::_FIELD_IDS,
            SystemPropertiesProto::Ro::_FIELD_COUNT);
    Message ro(&roTable);

    Table bootTable(SystemPropertiesProto::Ro::Boot::_FIELD_NAMES,
            SystemPropertiesProto::Ro::Boot::_FIELD_IDS,
            SystemPropertiesProto::Ro::Boot::_FIELD_COUNT);
    Message boot(&bootTable);
    ro.addSubMessage(SystemPropertiesProto::Ro::BOOT, &boot);

    Table bootimageTable(SystemPropertiesProto::Ro::BootImage::_FIELD_NAMES,
            SystemPropertiesProto::Ro::BootImage::_FIELD_IDS,
            SystemPropertiesProto::Ro::BootImage::_FIELD_COUNT);
    Message bootimage(&bootimageTable);
    ro.addSubMessage(SystemPropertiesProto::Ro::BOOTIMAGE, &bootimage);

    Table buildTable(SystemPropertiesProto::Ro::Build::_FIELD_NAMES,
            SystemPropertiesProto::Ro::Build::_FIELD_IDS,
            SystemPropertiesProto::Ro::Build::_FIELD_COUNT);
    Message build(&buildTable);

    Table versionTable(SystemPropertiesProto::Ro::Build::Version::_FIELD_NAMES,
            SystemPropertiesProto::Ro::Build::Version::_FIELD_IDS,
            SystemPropertiesProto::Ro::Build::Version::_FIELD_COUNT);
    Message version(&versionTable);
    build.addSubMessage(SystemPropertiesProto::Ro::Build::VERSION, &version);
    ro.addSubMessage(SystemPropertiesProto::Ro::BUILD, &build);

    Table configTable(SystemPropertiesProto::Ro::Config::_FIELD_NAMES,
            SystemPropertiesProto::Ro::Config::_FIELD_IDS,
            SystemPropertiesProto::Ro::Config::_FIELD_COUNT);
    Message config(&configTable);
    ro.addSubMessage(SystemPropertiesProto::Ro::CONFIG, &config);

    Table hardwareTable(SystemPropertiesProto::Ro::Hardware::_FIELD_NAMES,
                   SystemPropertiesProto::Ro::Hardware::_FIELD_IDS,
                   SystemPropertiesProto::Ro::Hardware::_FIELD_COUNT);
    Message hardware(&hardwareTable);
    ro.addSubMessage(SystemPropertiesProto::Ro::HARDWARE, &hardware);

    Table productTable(SystemPropertiesProto::Ro::Product::_FIELD_NAMES,
                   SystemPropertiesProto::Ro::Product::_FIELD_IDS,
                   SystemPropertiesProto::Ro::Product::_FIELD_COUNT);
    Message product(&productTable);
    ro.addSubMessage(SystemPropertiesProto::Ro::PRODUCT, &product);

    sysProp.addSubMessage(SystemPropertiesProto::RO, &ro);

    Table sysTable(SystemPropertiesProto::Sys::_FIELD_NAMES,
                   SystemPropertiesProto::Sys::_FIELD_IDS,
                   SystemPropertiesProto::Sys::_FIELD_COUNT);
    Message sys(&sysTable);

    Table usbTable(SystemPropertiesProto::Sys::Usb::_FIELD_NAMES,
                   SystemPropertiesProto::Sys::Usb::_FIELD_IDS,
                   SystemPropertiesProto::Sys::Usb::_FIELD_COUNT);
    Message usb(&usbTable);
    sys.addSubMessage(SystemPropertiesProto::Sys::USB, &usb);

    sysProp.addSubMessage(SystemPropertiesProto::SYS, &sys);

    // parse line by line
    while (reader.readLine(&line)) {
@@ -67,13 +175,19 @@ SystemPropertiesParser::Parse(const int in, const int out) const

        // if the property name couldn't be found in proto definition or the value has mistype,
        // add to extra properties with its name and value
        if (!table.insertField(&proto, convertToFieldName(name), value)) {
        if (!sysProp.insertField(&proto, convertToFieldName(name), value)) {
            extras.push_back(make_pair(name, value));
        }
    }
    // end session for the last write.
    sysProp.endSession(&proto);

    for (auto it = extras.begin(); it != extras.end(); it++) {
        long long token = proto.start(SystemPropertiesProto::EXTRA_PROPERTIES);
            proto.write(SystemPropertiesProto::Property::NAME, name);
            proto.write(SystemPropertiesProto::Property::VALUE, value);
        proto.write(SystemPropertiesProto::Property::NAME, it->first);
        proto.write(SystemPropertiesProto::Property::VALUE, it->second);
        proto.end(token);
    }
    }

    if (!reader.ok(&line)) {
        fprintf(stderr, "Bad read from fd %d: %s\n", in, line.c_str());
+7 −8
Original line number Diff line number Diff line
[aaudio.hw_burst_min_usec]: [2000]
[aaudio.mmap_exclusive_policy]: [2]
[dalvik.vm.appimageformat]: [lz4]
[gsm.operator.isroaming]: [false]
[init.svc.vendor.imsqmidaemon]: [running]
[init.svc.vendor.init-radio-sh]: [stopped]
[net.dns1]: [2001:4860:4860::8844]
[net.tcp.buffersize.wifi]: [524288,2097152,4194304,262144,524288,1048576]
[nfc.initialized]: [True]
[persist_radio_VT_ENABLE]: [1]
[drm_64bit_enabled]: [false]
[init.svc.adbd]: [running]
[init.svc.lmkd]: [stopped]
[media_mediadrmservice_enable]: [True]
[ro.boot.boottime]: [1BLL:85,1BLE:898,2BLL:0,2BLE:862,SW:6739,KL:340]
[ro.bootimage.build.date.utc]: [1509394807]
[ro.bootimage.build.fingerprint]: [google/marlin/marlin:P/MASTER/jinyithu10301320:eng/dev-keys]
[ro.hardware]: [marlin]
[ro.hardware.power]: [marlin-profile]
[ro.wifi.channels]: []
+32 −23
Original line number Diff line number Diff line
@@ -61,29 +61,38 @@ TEST_F(SystemPropertiesParserTest, HasSwapInfo) {
    SystemPropertiesParser parser;
    SystemPropertiesProto expected;

    expected.set_aaudio_hw_burst_min_usec(2000);
    expected.set_aaudio_mmap_exclusive_policy(2);
    expected.set_dalvik_vm_appimageformat("lz4");
    expected.set_gsm_operator_isroaming(false);
    expected.set_init_svc_vendor_imsqmidaemon(SystemPropertiesProto_Status_STATUS_RUNNING);
    expected.set_init_svc_vendor_init_radio_sh(SystemPropertiesProto_Status_STATUS_STOPPED);
    expected.set_net_dns1("2001:4860:4860::8844");
    expected.add_net_tcp_buffersize_wifi(524288);
    expected.add_net_tcp_buffersize_wifi(2097152);
    expected.add_net_tcp_buffersize_wifi(4194304);
    expected.add_net_tcp_buffersize_wifi(262144);
    expected.add_net_tcp_buffersize_wifi(524288);
    expected.add_net_tcp_buffersize_wifi(1048576);
    expected.set_nfc_initialized(true);
    expected.set_persist_radio_vt_enable(1);
    expected.add_ro_boot_boottime("1BLL:85");
    expected.add_ro_boot_boottime("1BLE:898");
    expected.add_ro_boot_boottime("2BLL:0");
    expected.add_ro_boot_boottime("2BLE:862");
    expected.add_ro_boot_boottime("SW:6739");
    expected.add_ro_boot_boottime("KL:340");
    expected.set_ro_bootimage_build_date_utc(1509394807LL);
    expected.set_ro_bootimage_build_fingerprint("google/marlin/marlin:P/MASTER/jinyithu10301320:eng/dev-keys");
    SystemPropertiesProto::Aaudio* aaudio = expected.mutable_aaudio();
    aaudio->set_hw_burst_min_usec(2000);
    aaudio->set_mmap_exclusive_policy(2);

    SystemPropertiesProto::DalvikVm* dalvikVm = expected.mutable_dalvik_vm();
    dalvikVm->set_appimageformat("lz4");

    expected.set_drm_64bit_enabled(false);

    SystemPropertiesProto::InitSvc* initSvc = expected.mutable_init_svc();
    initSvc->set_adbd(SystemPropertiesProto_InitSvc_Status_STATUS_RUNNING);
    initSvc->set_lmkd(SystemPropertiesProto_InitSvc_Status_STATUS_STOPPED);

    expected.set_media_mediadrmservice_enable(true);

    SystemPropertiesProto::Ro* ro = expected.mutable_ro();

    SystemPropertiesProto::Ro::Boot* boot = ro->mutable_boot();
    boot->add_boottime("1BLL:85");
    boot->add_boottime("1BLE:898");
    boot->add_boottime("2BLL:0");
    boot->add_boottime("2BLE:862");
    boot->add_boottime("SW:6739");
    boot->add_boottime("KL:340");

    SystemPropertiesProto::Ro::BootImage* bootimage = ro->mutable_bootimage();
    bootimage->set_build_date_utc(1509394807LL);
    bootimage->set_build_fingerprint("google/marlin/marlin:P/MASTER/jinyithu10301320:eng/dev-keys");

    SystemPropertiesProto::Ro::Hardware* hardware = ro->mutable_hardware();
    hardware->set_value("marlin");
    hardware->set_power("marlin-profile");

    int fd = open(testFile.c_str(), O_RDONLY);
    ASSERT_TRUE(fd != -1);
Loading