1 /*
2  * Copyright (C) 2017 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 #define LOG_TAG "incident_helper"
17 
18 #include <android/util/ProtoOutputStream.h>
19 
20 #include "frameworks/base/core/proto/android/os/system_properties.proto.h"
21 #include "ih_util.h"
22 #include "SystemPropertiesParser.h"
23 
24 using namespace android::os;
25 
26 const string LINE_DELIMITER = "]: [";
27 
28 // system properties' names sometimes are not valid proto field names, make the names valid.
convertToFieldName(const string & name)29 static string convertToFieldName(const string& name) {
30     int len = (int)name.length();
31     char cstr[len + 1];
32     strcpy(cstr, name.c_str());
33     for (int i = 0; i < len; i++) {
34         if (!isValidChar(cstr[i])) {
35             cstr[i] = '_';
36         }
37     }
38     return string(cstr);
39 }
40 
41 status_t
Parse(const int in,const int out) const42 SystemPropertiesParser::Parse(const int in, const int out) const
43 {
44     Reader reader(in);
45     string line;
46     string name;  // the name of the property
47     string value; // the string value of the property
48     ProtoOutputStream proto;
49     vector<pair<string, string>> extras;
50 
51     Table sysPropTable(SystemPropertiesProto::_FIELD_NAMES,
52                 SystemPropertiesProto::_FIELD_IDS,
53                 SystemPropertiesProto::_FIELD_COUNT);
54     Message sysProp(&sysPropTable);
55 
56     Table aacDrcTable(SystemPropertiesProto::AacDrc::_FIELD_NAMES,
57             SystemPropertiesProto::AacDrc::_FIELD_IDS,
58             SystemPropertiesProto::AacDrc::_FIELD_COUNT);
59     Message aacDrc(&aacDrcTable);
60     sysProp.addSubMessage(SystemPropertiesProto::AAC_DRC, &aacDrc);
61 
62     Table aaudioTable(SystemPropertiesProto::Aaudio::_FIELD_NAMES,
63             SystemPropertiesProto::Aaudio::_FIELD_IDS,
64             SystemPropertiesProto::Aaudio::_FIELD_COUNT);
65     Message aaudio(&aaudioTable);
66     sysProp.addSubMessage(SystemPropertiesProto::AAUDIO, &aaudio);
67 
68     Table cameraTable(SystemPropertiesProto::Camera::_FIELD_NAMES,
69             SystemPropertiesProto::Camera::_FIELD_IDS,
70             SystemPropertiesProto::Camera::_FIELD_COUNT);
71     Message camera(&cameraTable);
72     sysProp.addSubMessage(SystemPropertiesProto::CAMERA, &camera);
73 
74     Table dalvikVmTable(SystemPropertiesProto::DalvikVm::_FIELD_NAMES,
75             SystemPropertiesProto::DalvikVm::_FIELD_IDS,
76             SystemPropertiesProto::DalvikVm::_FIELD_COUNT);
77     Message dalvikVm(&dalvikVmTable);
78     sysProp.addSubMessage(SystemPropertiesProto::DALVIK_VM, &dalvikVm);
79 
80     Table initSvcTable(SystemPropertiesProto::InitSvc::_FIELD_NAMES,
81             SystemPropertiesProto::InitSvc::_FIELD_IDS,
82             SystemPropertiesProto::InitSvc::_FIELD_COUNT);
83     initSvcTable.addEnumNameToValue("running", SystemPropertiesProto::InitSvc::STATUS_RUNNING);
84     initSvcTable.addEnumNameToValue("stopped", SystemPropertiesProto::InitSvc::STATUS_STOPPED);
85     Message initSvc(&initSvcTable);
86     sysProp.addSubMessage(SystemPropertiesProto::INIT_SVC, &initSvc);
87 
88     Table logTable(SystemPropertiesProto::Log::_FIELD_NAMES,
89             SystemPropertiesProto::Log::_FIELD_IDS,
90             SystemPropertiesProto::Log::_FIELD_COUNT);
91     Message logMsg(&logTable);
92     sysProp.addSubMessage(SystemPropertiesProto::LOG, &logMsg);
93 
94     Table persistTable(SystemPropertiesProto::Persist::_FIELD_NAMES,
95             SystemPropertiesProto::Persist::_FIELD_IDS,
96             SystemPropertiesProto::Persist::_FIELD_COUNT);
97     Message persist(&persistTable);
98     sysProp.addSubMessage(SystemPropertiesProto::PERSIST, &persist);
99 
100     Table pmDexoptTable(SystemPropertiesProto::PmDexopt::_FIELD_NAMES,
101             SystemPropertiesProto::PmDexopt::_FIELD_IDS,
102             SystemPropertiesProto::PmDexopt::_FIELD_COUNT);
103     Message pmDexopt(&pmDexoptTable);
104     sysProp.addSubMessage(SystemPropertiesProto::PM_DEXOPT, &pmDexopt);
105 
106     Table roTable(SystemPropertiesProto::Ro::_FIELD_NAMES,
107             SystemPropertiesProto::Ro::_FIELD_IDS,
108             SystemPropertiesProto::Ro::_FIELD_COUNT);
109     Message ro(&roTable);
110 
111     Table bootTable(SystemPropertiesProto::Ro::Boot::_FIELD_NAMES,
112             SystemPropertiesProto::Ro::Boot::_FIELD_IDS,
113             SystemPropertiesProto::Ro::Boot::_FIELD_COUNT);
114     Message boot(&bootTable);
115     ro.addSubMessage(SystemPropertiesProto::Ro::BOOT, &boot);
116 
117     Table bootimageTable(SystemPropertiesProto::Ro::BootImage::_FIELD_NAMES,
118             SystemPropertiesProto::Ro::BootImage::_FIELD_IDS,
119             SystemPropertiesProto::Ro::BootImage::_FIELD_COUNT);
120     Message bootimage(&bootimageTable);
121     ro.addSubMessage(SystemPropertiesProto::Ro::BOOTIMAGE, &bootimage);
122 
123     Table buildTable(SystemPropertiesProto::Ro::Build::_FIELD_NAMES,
124             SystemPropertiesProto::Ro::Build::_FIELD_IDS,
125             SystemPropertiesProto::Ro::Build::_FIELD_COUNT);
126     Message build(&buildTable);
127 
128     Table versionTable(SystemPropertiesProto::Ro::Build::Version::_FIELD_NAMES,
129             SystemPropertiesProto::Ro::Build::Version::_FIELD_IDS,
130             SystemPropertiesProto::Ro::Build::Version::_FIELD_COUNT);
131     Message version(&versionTable);
132     build.addSubMessage(SystemPropertiesProto::Ro::Build::VERSION, &version);
133     ro.addSubMessage(SystemPropertiesProto::Ro::BUILD, &build);
134 
135     Table configTable(SystemPropertiesProto::Ro::Config::_FIELD_NAMES,
136             SystemPropertiesProto::Ro::Config::_FIELD_IDS,
137             SystemPropertiesProto::Ro::Config::_FIELD_COUNT);
138     Message config(&configTable);
139     ro.addSubMessage(SystemPropertiesProto::Ro::CONFIG, &config);
140 
141     Table hardwareTable(SystemPropertiesProto::Ro::Hardware::_FIELD_NAMES,
142                    SystemPropertiesProto::Ro::Hardware::_FIELD_IDS,
143                    SystemPropertiesProto::Ro::Hardware::_FIELD_COUNT);
144     Message hardware(&hardwareTable);
145     ro.addSubMessage(SystemPropertiesProto::Ro::HARDWARE, &hardware);
146 
147     Table productTable(SystemPropertiesProto::Ro::Product::_FIELD_NAMES,
148                    SystemPropertiesProto::Ro::Product::_FIELD_IDS,
149                    SystemPropertiesProto::Ro::Product::_FIELD_COUNT);
150     Message product(&productTable);
151 
152     Table pVendorTable(SystemPropertiesProto::Ro::Product::Vendor::_FIELD_NAMES,
153             SystemPropertiesProto::Ro::Product::Vendor::_FIELD_IDS,
154             SystemPropertiesProto::Ro::Product::Vendor::_FIELD_COUNT);
155     Message pVendor(&pVendorTable);
156     product.addSubMessage(SystemPropertiesProto::Ro::Product::VENDOR, &pVendor);
157     ro.addSubMessage(SystemPropertiesProto::Ro::PRODUCT, &product);
158 
159     Table telephonyTable(SystemPropertiesProto::Ro::Telephony::_FIELD_NAMES,
160                    SystemPropertiesProto::Ro::Telephony::_FIELD_IDS,
161                    SystemPropertiesProto::Ro::Telephony::_FIELD_COUNT);
162     Message telephony(&telephonyTable);
163     ro.addSubMessage(SystemPropertiesProto::Ro::TELEPHONY, &telephony);
164 
165     Table vendorTable(SystemPropertiesProto::Ro::Vendor::_FIELD_NAMES,
166                    SystemPropertiesProto::Ro::Vendor::_FIELD_IDS,
167                    SystemPropertiesProto::Ro::Vendor::_FIELD_COUNT);
168     Message vendor(&vendorTable);
169     ro.addSubMessage(SystemPropertiesProto::Ro::VENDOR, &vendor);
170 
171     sysProp.addSubMessage(SystemPropertiesProto::RO, &ro);
172 
173     Table sysTable(SystemPropertiesProto::Sys::_FIELD_NAMES,
174                    SystemPropertiesProto::Sys::_FIELD_IDS,
175                    SystemPropertiesProto::Sys::_FIELD_COUNT);
176     Message sys(&sysTable);
177 
178     Table usbTable(SystemPropertiesProto::Sys::Usb::_FIELD_NAMES,
179                    SystemPropertiesProto::Sys::Usb::_FIELD_IDS,
180                    SystemPropertiesProto::Sys::Usb::_FIELD_COUNT);
181     Message usb(&usbTable);
182     sys.addSubMessage(SystemPropertiesProto::Sys::USB, &usb);
183 
184     sysProp.addSubMessage(SystemPropertiesProto::SYS, &sys);
185 
186     // parse line by line
187     while (reader.readLine(&line)) {
188         if (line.empty()) continue;
189 
190         line = line.substr(1, line.size() - 2); // trim []
191         size_t index = line.find(LINE_DELIMITER); // split by "]: ["
192         if (index == string::npos) {
193             fprintf(stderr, "Bad Line %s\n", line.c_str());
194             continue;
195         }
196         name = line.substr(0, index);
197         value = trim(line.substr(index + 4), DEFAULT_WHITESPACE);
198         if (value.empty()) continue;
199 
200         // if the property name couldn't be found in proto definition or the value has mistype,
201         // add to extra properties with its name and value
202         if (!sysProp.insertField(&proto, convertToFieldName(name), value)) {
203             extras.push_back(make_pair(name, value));
204         }
205     }
206     // end session for the last write.
207     sysProp.endSession(&proto);
208 
209     for (auto it = extras.begin(); it != extras.end(); it++) {
210         uint64_t token = proto.start(SystemPropertiesProto::EXTRA_PROPERTIES);
211         proto.write(SystemPropertiesProto::Property::NAME, it->first);
212         proto.write(SystemPropertiesProto::Property::VALUE, it->second);
213         proto.end(token);
214     }
215 
216     if (!reader.ok(&line)) {
217         fprintf(stderr, "Bad read from fd %d: %s\n", in, line.c_str());
218         return -1;
219     }
220 
221     if (!proto.flush(out)) {
222         fprintf(stderr, "[%s]Error writing proto back\n", this->name.string());
223         return -1;
224     }
225     fprintf(stderr, "[%s]Proto size: %zu bytes\n", this->name.string(), proto.size());
226     return NO_ERROR;
227 }
228