summaryrefslogtreecommitdiff
path: root/cmds/incident_helper
diff options
context:
space:
mode:
authorYi Jin <jinyithu@google.com>2017-12-05 17:44:48 -0800
committerYi Jin <jinyithu@google.com>2017-12-11 15:05:25 -0800
commit9299af93945376c4390cc24f5a0c1844997a694b (patch)
tree5af64f66cb46c052557b19c0c2941c1b4fe26492 /cmds/incident_helper
parent6348b054cdf98e007b0f921f0e7143a50b7bcfaf (diff)
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
Diffstat (limited to 'cmds/incident_helper')
-rw-r--r--cmds/incident_helper/src/ih_util.cpp79
-rw-r--r--cmds/incident_helper/src/ih_util.h64
-rw-r--r--cmds/incident_helper/src/parsers/SystemPropertiesParser.cpp132
-rw-r--r--cmds/incident_helper/testdata/system_properties.txt15
-rw-r--r--cmds/incident_helper/tests/SystemPropertiesParser_test.cpp55
5 files changed, 301 insertions, 44 deletions
diff --git a/cmds/incident_helper/src/ih_util.cpp b/cmds/incident_helper/src/ih_util.cpp
index db4f586c7e31..4bf956a9a03d 100644
--- a/cmds/incident_helper/src/ih_util.cpp
+++ b/cmds/incident_helper/src/ih_util.cpp
@@ -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 = "";
+}
diff --git a/cmds/incident_helper/src/ih_util.h b/cmds/incident_helper/src/ih_util.h
index 4a5fe1dd7a42..58ef29044048 100644
--- a/cmds/incident_helper/src/ih_util.h
+++ b/cmds/incident_helper/src/ih_util.h
@@ -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
diff --git a/cmds/incident_helper/src/parsers/SystemPropertiesParser.cpp b/cmds/incident_helper/src/parsers/SystemPropertiesParser.cpp
index ee5feb03242e..a41ed6ebaa22 100644
--- a/cmds/incident_helper/src/parsers/SystemPropertiesParser.cpp
+++ b/cmds/incident_helper/src/parsers/SystemPropertiesParser.cpp
@@ -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)) {
- long long token = proto.start(SystemPropertiesProto::EXTRA_PROPERTIES);
- proto.write(SystemPropertiesProto::Property::NAME, name);
- proto.write(SystemPropertiesProto::Property::VALUE, value);
- proto.end(token);
+ 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, 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());
diff --git a/cmds/incident_helper/testdata/system_properties.txt b/cmds/incident_helper/testdata/system_properties.txt
index 57c07ee9d75e..51a2dfd96869 100644
--- a/cmds/incident_helper/testdata/system_properties.txt
+++ b/cmds/incident_helper/testdata/system_properties.txt
@@ -1,14 +1,13 @@
[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.wifi.channels]: [] \ No newline at end of file
+[ro.hardware]: [marlin]
+[ro.hardware.power]: [marlin-profile]
+[ro.wifi.channels]: []
diff --git a/cmds/incident_helper/tests/SystemPropertiesParser_test.cpp b/cmds/incident_helper/tests/SystemPropertiesParser_test.cpp
index 23e292a512b9..98838e98d796 100644
--- a/cmds/incident_helper/tests/SystemPropertiesParser_test.cpp
+++ b/cmds/incident_helper/tests/SystemPropertiesParser_test.cpp
@@ -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);