• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 // Convert objects from and to strings.
18 
19 #include "parse_string.h"
20 
21 #include <android-base/parseint.h>
22 #include <android-base/strings.h>
23 
24 #include "constants-private.h"
25 
26 namespace android {
27 using base::ParseUint;
28 
29 namespace vintf {
30 
SplitString(const std::string & s,char c)31 std::vector<std::string> SplitString(const std::string &s, char c) {
32     std::vector<std::string> components;
33 
34     size_t startPos = 0;
35     size_t matchPos;
36     while ((matchPos = s.find(c, startPos)) != std::string::npos) {
37         components.push_back(s.substr(startPos, matchPos - startPos));
38         startPos = matchPos + 1;
39     }
40 
41     if (startPos <= s.length()) {
42         components.push_back(s.substr(startPos));
43     }
44     return components;
45 }
46 
47 template <typename T>
operator <<(std::ostream & os,const std::vector<T> objs)48 std::ostream &operator<<(std::ostream &os, const std::vector<T> objs) {
49     bool first = true;
50     for (const T &v : objs) {
51         if (!first) {
52             os << ",";
53         }
54         os << v;
55         first = false;
56     }
57     return os;
58 }
59 
60 template <typename T>
parse(const std::string & s,std::vector<T> * objs)61 bool parse(const std::string &s, std::vector<T> *objs) {
62     std::vector<std::string> v = SplitString(s, ',');
63     objs->resize(v.size());
64     size_t idx = 0;
65     for (const auto &item : v) {
66         T ver;
67         if (!parse(item, &ver)) {
68             return false;
69         }
70         objs->at(idx++) = ver;
71     }
72     return true;
73 }
74 
75 template<typename E, typename Array>
parseEnum(const std::string & s,E * e,const Array & strings)76 bool parseEnum(const std::string &s, E *e, const Array &strings) {
77     for (size_t i = 0; i < strings.size(); ++i) {
78         if (s == strings.at(i)) {
79             *e = static_cast<E>(i);
80             return true;
81         }
82     }
83     return false;
84 }
85 
86 #define DEFINE_PARSE_STREAMIN_FOR_ENUM(ENUM) \
87     bool parse(const std::string &s, ENUM *hf) {                   \
88         return parseEnum(s, hf, g##ENUM##Strings);                 \
89     }                                                              \
90     std::ostream &operator<<(std::ostream &os, ENUM hf) {          \
91         return os << g##ENUM##Strings.at(static_cast<size_t>(hf)); \
92     }                                                              \
93 
94 DEFINE_PARSE_STREAMIN_FOR_ENUM(HalFormat)
95 DEFINE_PARSE_STREAMIN_FOR_ENUM(Transport)
96 DEFINE_PARSE_STREAMIN_FOR_ENUM(Arch)
97 DEFINE_PARSE_STREAMIN_FOR_ENUM(KernelConfigType)
98 DEFINE_PARSE_STREAMIN_FOR_ENUM(Tristate)
99 DEFINE_PARSE_STREAMIN_FOR_ENUM(SchemaType)
100 DEFINE_PARSE_STREAMIN_FOR_ENUM(XmlSchemaFormat)
101 DEFINE_PARSE_STREAMIN_FOR_ENUM(ExclusiveTo)
102 
103 std::ostream &operator<<(std::ostream &os, const KernelConfigTypedValue &kctv) {
104     switch (kctv.mType) {
105         case KernelConfigType::STRING:
106             return os << kctv.mStringValue;
107         case KernelConfigType::INTEGER:
108             return os << to_string(kctv.mIntegerValue);
109         case KernelConfigType::RANGE:
110             return os << to_string(kctv.mRangeValue.first) << "-"
111                       << to_string(kctv.mRangeValue.second);
112         case KernelConfigType::TRISTATE:
113             return os << to_string(kctv.mTristateValue);
114     }
115 }
116 
parse(const std::string & s,Level * l)117 bool parse(const std::string& s, Level* l) {
118     if (s.empty()) {
119         *l = Level::UNSPECIFIED;
120         return true;
121     }
122     if (s == "legacy") {
123         *l = Level::LEGACY;
124         return true;
125     }
126     size_t value;
127     if (!ParseUint(s, &value)) {
128         return false;
129     }
130     *l = static_cast<Level>(value);
131     if (!IsValid(*l)) {
132         return false;
133     }
134     return true;
135 }
136 
operator <<(std::ostream & os,Level l)137 std::ostream& operator<<(std::ostream& os, Level l) {
138     if (l == Level::UNSPECIFIED) {
139         return os;
140     }
141     if (l == Level::LEGACY) {
142         return os << "legacy";
143     }
144     return os << static_cast<size_t>(l);
145 }
146 
147 // Notice that strtoull is used even though KernelConfigIntValue is signed int64_t,
148 // because strtoull can accept negative values as well.
149 // Notice that according to man strtoul, strtoull can actually accept
150 // -2^64 + 1 to 2^64 - 1, with the 65th bit truncated.
151 // ParseInt / ParseUint are not used because they do not handle signed hex very well.
152 template <typename T>
parseKernelConfigIntHelper(const std::string & s,T * i)153 bool parseKernelConfigIntHelper(const std::string &s, T *i) {
154     char *end;
155     errno = 0;
156     unsigned long long int ulli = strtoull(s.c_str(), &end, 0 /* base */);
157     // It is implementation defined that what value will be returned by strtoull
158     // in the error case, so we are checking errno directly here.
159     if (errno == 0 && s.c_str() != end && *end == '\0') {
160         *i = static_cast<T>(ulli);
161         return true;
162     }
163     return false;
164 }
165 
parseKernelConfigInt(const std::string & s,int64_t * i)166 bool parseKernelConfigInt(const std::string &s, int64_t *i) {
167     return parseKernelConfigIntHelper(s, i);
168 }
169 
parseKernelConfigInt(const std::string & s,uint64_t * i)170 bool parseKernelConfigInt(const std::string &s, uint64_t *i) {
171     return parseKernelConfigIntHelper(s, i);
172 }
173 
parseRange(const std::string & s,KernelConfigRangeValue * range)174 bool parseRange(const std::string &s, KernelConfigRangeValue *range) {
175     auto pos = s.find('-');
176     if (pos == std::string::npos) {
177         return false;
178     }
179     return parseKernelConfigInt(s.substr(0, pos),  &range->first)
180         && parseKernelConfigInt(s.substr(pos + 1), &range->second);
181 }
182 
parse(const std::string & s,KernelConfigKey * key)183 bool parse(const std::string &s, KernelConfigKey *key) {
184     *key = s;
185     return true;
186 }
187 
parseKernelConfigValue(const std::string & s,KernelConfigTypedValue * kctv)188 bool parseKernelConfigValue(const std::string &s, KernelConfigTypedValue *kctv) {
189     switch (kctv->mType) {
190         case KernelConfigType::STRING:
191             kctv->mStringValue = s;
192             return true;
193         case KernelConfigType::INTEGER:
194             return parseKernelConfigInt(s, &kctv->mIntegerValue);
195         case KernelConfigType::RANGE:
196             return parseRange(s, &kctv->mRangeValue);
197         case KernelConfigType::TRISTATE:
198             return parse(s, &kctv->mTristateValue);
199     }
200 }
201 
parseKernelConfigTypedValue(const std::string & s,KernelConfigTypedValue * kctv)202 bool parseKernelConfigTypedValue(const std::string& s, KernelConfigTypedValue* kctv) {
203     if (s.size() > 1 && s[0] == '"' && s.back() == '"') {
204         kctv->mType = KernelConfigType::STRING;
205         kctv->mStringValue = s.substr(1, s.size()-2);
206         return true;
207     }
208     if (parseKernelConfigInt(s, &kctv->mIntegerValue)) {
209         kctv->mType = KernelConfigType::INTEGER;
210         return true;
211     }
212     if (parse(s, &kctv->mTristateValue)) {
213         kctv->mType = KernelConfigType::TRISTATE;
214         return true;
215     }
216     // Do not test for KernelConfigType::RANGE.
217     return false;
218 }
219 
parse(const std::string & s,Version * ver)220 bool parse(const std::string &s, Version *ver) {
221     std::vector<std::string> v = SplitString(s, '.');
222     if (v.size() != 2) {
223         return false;
224     }
225     size_t major, minor;
226     if (!ParseUint(v[0], &major)) {
227         return false;
228     }
229     if (!ParseUint(v[1], &minor)) {
230         return false;
231     }
232     *ver = Version(major, minor);
233     return true;
234 }
235 
parse(const std::string & s,SepolicyVersion * sepolicyVer)236 bool parse(const std::string& s, SepolicyVersion* sepolicyVer) {
237     size_t major;
238     // vFRC versioning
239     if (ParseUint(s, &major)) {
240         *sepolicyVer = SepolicyVersion(major, std::nullopt);
241         return true;
242     }
243     // fall back to normal Version
244     Version ver;
245     if (!parse(s, &ver)) return false;
246     *sepolicyVer = SepolicyVersion(ver.majorVer, ver.minorVer);
247     return true;
248 }
249 
operator <<(std::ostream & os,const Version & ver)250 std::ostream &operator<<(std::ostream &os, const Version &ver) {
251     if (ver.majorVer == details::kFakeAidlMajorVersion) {
252         return os << ver.minorVer;
253     } else {
254         return os << ver.majorVer << "." << ver.minorVer;
255     }
256 }
257 
operator <<(std::ostream & os,const SepolicyVersion & ver)258 std::ostream& operator<<(std::ostream& os, const SepolicyVersion& ver) {
259     os << ver.majorVer;
260     if (ver.minorVer.has_value()) os << "." << ver.minorVer.value();
261     return os;
262 }
263 
264 // Helper for parsing a VersionRange object. versionParser defines how the first half
265 // (before the '-' character) of the string is parsed.
parseVersionRange(const std::string & s,VersionRange * vr,const std::function<bool (const std::string &,Version *)> & versionParser)266 static bool parseVersionRange(
267     const std::string& s, VersionRange* vr,
268     const std::function<bool(const std::string&, Version*)>& versionParser) {
269     std::vector<std::string> v = SplitString(s, '-');
270     if (v.size() != 1 && v.size() != 2) {
271         return false;
272     }
273     Version minVer;
274     if (!versionParser(v[0], &minVer)) {
275         return false;
276     }
277     if (v.size() == 1) {
278         *vr = VersionRange(minVer.majorVer, minVer.minorVer);
279     } else {
280         size_t maxMinor;
281         if (!ParseUint(v[1], &maxMinor)) {
282             return false;
283         }
284         *vr = VersionRange(minVer.majorVer, minVer.minorVer, maxMinor);
285     }
286     return true;
287 }
288 
parse(const std::string & s,VersionRange * vr)289 bool parse(const std::string& s, VersionRange* vr) {
290     bool (*versionParser)(const std::string&, Version*) = parse;
291     return parseVersionRange(s, vr, versionParser);
292 }
293 
294 // TODO(b/314010177): Add unit tests for this function.
parse(const std::string & s,SepolicyVersionRange * svr)295 bool parse(const std::string& s, SepolicyVersionRange* svr) {
296     SepolicyVersion sepolicyVersion;
297     if (parse(s, &sepolicyVersion)) {
298         *svr = SepolicyVersionRange(sepolicyVersion.majorVer, sepolicyVersion.minorVer);
299         return true;
300     }
301     // fall back to normal VersionRange
302     VersionRange vr;
303     if (parse(s, &vr)) {
304         *svr = SepolicyVersionRange(vr.majorVer, vr.minMinor, vr.maxMinor);
305         return true;
306     }
307     return false;
308 }
309 
operator <<(std::ostream & os,const VersionRange & vr)310 std::ostream &operator<<(std::ostream &os, const VersionRange &vr) {
311     if (vr.isSingleVersion()) {
312         return os << vr.minVer();
313     }
314     return os << vr.minVer() << "-" << vr.maxMinor;
315 }
316 
operator <<(std::ostream & os,const SepolicyVersionRange & svr)317 std::ostream& operator<<(std::ostream& os, const SepolicyVersionRange& svr) {
318     if (svr.maxMinor.has_value()) {
319         return os << VersionRange(svr.majorVer, svr.minMinor.value_or(0), svr.maxMinor.value());
320     }
321 
322     return os << SepolicyVersion(svr.majorVer, svr.minMinor);
323 }
324 
325 #pragma clang diagnostic push
326 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
parse(const std::string & s,VndkVersionRange * vr)327 bool parse(const std::string &s, VndkVersionRange *vr) {
328     std::vector<std::string> v = SplitString(s, '-');
329     if (v.size() != 1 && v.size() != 2) {
330         return false;
331     }
332     std::vector<std::string> minVector = SplitString(v[0], '.');
333     if (minVector.size() != 3) {
334         return false;
335     }
336     if (!ParseUint(minVector[0], &vr->sdk) ||
337         !ParseUint(minVector[1], &vr->vndk) ||
338         !ParseUint(minVector[2], &vr->patchMin)) {
339         return false;
340     }
341     if (v.size() == 1) {
342         vr->patchMax = vr->patchMin;
343         return true;
344     } else {
345         return ParseUint(v[1], &vr->patchMax);
346     }
347 }
348 
operator <<(std::ostream & os,const VndkVersionRange & vr)349 std::ostream &operator<<(std::ostream &os, const VndkVersionRange &vr) {
350     os << vr.sdk << "." << vr.vndk << "." << vr.patchMin;
351     if (!vr.isSingleVersion()) {
352         os << "-" << vr.patchMax;
353     }
354     return os;
355 }
356 #pragma clang diagnostic pop
357 
parse(const std::string & s,KernelVersion * kernelVersion)358 bool parse(const std::string &s, KernelVersion *kernelVersion) {
359     std::vector<std::string> v = SplitString(s, '.');
360     if (v.size() != 3) {
361         return false;
362     }
363     size_t version, major, minor;
364     if (!ParseUint(v[0], &version)) {
365         return false;
366     }
367     if (!ParseUint(v[1], &major)) {
368         return false;
369     }
370     if (!ParseUint(v[2], &minor)) {
371         return false;
372     }
373     *kernelVersion = KernelVersion(version, major, minor);
374     return true;
375 }
376 
operator <<(std::ostream & os,const TransportArch & ta)377 std::ostream &operator<<(std::ostream &os, const TransportArch &ta) {
378     return os << to_string(ta.transport) << to_string(ta.arch);
379 }
380 
operator <<(std::ostream & os,const KernelVersion & ver)381 std::ostream &operator<<(std::ostream &os, const KernelVersion &ver) {
382     return os << ver.version << "." << ver.majorRev << "." << ver.minorRev;
383 }
384 
operator <<(std::ostream & os,const ManifestHal & hal)385 std::ostream &operator<<(std::ostream &os, const ManifestHal &hal) {
386     return os << hal.format << "/"
387               << hal.name << "/"
388               << hal.transportArch << "/"
389               << hal.versions;
390 }
391 
expandInstances(const MatrixHal & req,const VersionRange & vr,bool brace)392 std::string expandInstances(const MatrixHal& req, const VersionRange& vr, bool brace) {
393     std::string s;
394     size_t count = 0;
395     req.forEachInstance(vr, [&](const auto& matrixInstance) {
396         if (count > 0) s += " AND ";
397         auto instance = matrixInstance.isRegex() ? matrixInstance.regexPattern()
398                                                  : matrixInstance.exactInstance();
399         switch (req.format) {
400             case HalFormat::AIDL: {
401                 s += toFQNameString(matrixInstance.interface(), instance) + " (@" +
402                      aidlVersionRangeToString(vr) + ")";
403             } break;
404             case HalFormat::HIDL:
405                 [[fallthrough]];
406             case HalFormat::NATIVE: {
407                 s += toFQNameString(vr, matrixInstance.interface(), instance);
408             } break;
409         }
410         count++;
411         return true;
412     });
413     if (count == 0) {
414         s += "@" + to_string(vr);
415     }
416     if (count >= 2 && brace) {
417         s = "(" + s + ")";
418     }
419     return s;
420 }
421 
expandInstances(const MatrixHal & req)422 std::vector<std::string> expandInstances(const MatrixHal& req) {
423     size_t count = req.instancesCount();
424     if (count == 0) {
425         return {};
426     }
427     if (count == 1) {
428         return {expandInstances(req, req.versionRanges.front(), false /* brace */)};
429     }
430     std::vector<std::string> ss;
431     for (const auto& vr : req.versionRanges) {
432         if (!ss.empty()) {
433             ss.back() += " OR";
434         }
435         ss.push_back(expandInstances(req, vr, true /* brace */));
436     }
437     return ss;
438 }
439 
operator <<(std::ostream & os,KernelSepolicyVersion ksv)440 std::ostream &operator<<(std::ostream &os, KernelSepolicyVersion ksv){
441     return os << ksv.value;
442 }
443 
parse(const std::string & s,KernelSepolicyVersion * ksv)444 bool parse(const std::string &s, KernelSepolicyVersion *ksv){
445     return ParseUint(s, &ksv->value);
446 }
447 
dump(const HalManifest & vm)448 std::string dump(const HalManifest &vm) {
449     std::ostringstream oss;
450     bool first = true;
451     for (const auto &hal : vm.getHals()) {
452         if (!first) {
453             oss << ":";
454         }
455         oss << hal;
456         first = false;
457     }
458     return oss.str();
459 }
460 
dump(const RuntimeInfo & ki,bool verbose)461 std::string dump(const RuntimeInfo& ki, bool verbose) {
462     std::ostringstream oss;
463 
464     oss << "kernel = " << ki.osName() << "/" << ki.nodeName() << "/" << ki.osRelease() << "/"
465         << ki.osVersion() << "/" << ki.hardwareId() << ";" << ki.mBootAvbVersion << "/"
466         << ki.mBootVbmetaAvbVersion << ";"
467         << "kernelSepolicyVersion = " << ki.kernelSepolicyVersion() << ";";
468 
469     if (verbose) {
470         oss << "\n\ncpu info:\n" << ki.cpuInfo();
471     }
472 
473     oss << "\n#CONFIG's loaded = " << ki.kernelConfigs().size() << ";\n";
474 
475     if (verbose) {
476         for (const auto& pair : ki.kernelConfigs()) {
477             oss << pair.first << "=" << pair.second << "\n";
478         }
479     }
480 
481     return oss.str();
482 }
483 
toFQNameString(const std::string & package,const std::string & version,const std::string & interface,const std::string & instance)484 std::string toFQNameString(const std::string& package, const std::string& version,
485                            const std::string& interface, const std::string& instance) {
486     std::stringstream ss;
487     ss << package << "@" << version;
488     if (!interface.empty()) {
489         ss << "::" << interface;
490     }
491     if (!instance.empty()) {
492         ss << "/" << instance;
493     }
494     return ss.str();
495 }
496 
toFQNameString(const std::string & package,const Version & version,const std::string & interface,const std::string & instance)497 std::string toFQNameString(const std::string& package, const Version& version,
498                            const std::string& interface, const std::string& instance) {
499     return toFQNameString(package, to_string(version), interface, instance);
500 }
501 
toFQNameString(const Version & version,const std::string & interface,const std::string & instance)502 std::string toFQNameString(const Version& version, const std::string& interface,
503                            const std::string& instance) {
504     return toFQNameString("", version, interface, instance);
505 }
506 
507 // android.hardware.foo@1.0-1::IFoo/default.
508 // Note that the format is extended to support a range of versions.
toFQNameString(const std::string & package,const VersionRange & range,const std::string & interface,const std::string & instance)509 std::string toFQNameString(const std::string& package, const VersionRange& range,
510                            const std::string& interface, const std::string& instance) {
511     return toFQNameString(package, to_string(range), interface, instance);
512 }
513 
toFQNameString(const VersionRange & range,const std::string & interface,const std::string & instance)514 std::string toFQNameString(const VersionRange& range, const std::string& interface,
515                            const std::string& instance) {
516     return toFQNameString("", range, interface, instance);
517 }
518 
toFQNameString(const std::string & interface,const std::string & instance)519 std::string toFQNameString(const std::string& interface, const std::string& instance) {
520     return interface + "/" + instance;
521 }
522 
operator <<(std::ostream & os,const FqInstance & fqInstance)523 std::ostream& operator<<(std::ostream& os, const FqInstance& fqInstance) {
524     return os << fqInstance.string();
525 }
526 
parse(const std::string & s,FqInstance * fqInstance)527 bool parse(const std::string& s, FqInstance* fqInstance) {
528     return fqInstance->setTo(s);
529 }
530 
toAidlFqnameString(const std::string & package,const std::string & interface,const std::string & instance)531 std::string toAidlFqnameString(const std::string& package, const std::string& interface,
532                                const std::string& instance) {
533     std::stringstream ss;
534     ss << package << "." << interface;
535     if (!instance.empty()) {
536         ss << "/" << instance;
537     }
538     return ss.str();
539 }
540 
aidlVersionToString(const Version & v)541 std::string aidlVersionToString(const Version& v) {
542     return to_string(v.minorVer);
543 }
parseAidlVersion(const std::string & s,Version * version)544 bool parseAidlVersion(const std::string& s, Version* version) {
545     version->majorVer = details::kFakeAidlMajorVersion;
546     return android::base::ParseUint(s, &version->minorVer);
547 }
548 
aidlVersionRangeToString(const VersionRange & vr)549 std::string aidlVersionRangeToString(const VersionRange& vr) {
550     if (vr.isSingleVersion()) {
551         return to_string(vr.minMinor);
552     }
553     return to_string(vr.minMinor) + "-" + to_string(vr.maxMinor);
554 }
555 
parseAidlVersionRange(const std::string & s,VersionRange * vr)556 bool parseAidlVersionRange(const std::string& s, VersionRange* vr) {
557     return parseVersionRange(s, vr, parseAidlVersion);
558 }
559 
parseApexName(std::string_view path)560 std::string_view parseApexName(std::string_view path) {
561     if (base::ConsumePrefix(&path, "/apex/")) {
562         return path.substr(0, path.find('/'));
563     }
564     return {};
565 }
566 
567 } // namespace vintf
568 } // namespace android
569