Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 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 | #include <android-base/parseint.h> |
| 21 | |
| 22 | namespace android { |
| 23 | using base::ParseUint; |
| 24 | |
| 25 | namespace vintf { |
| 26 | |
| 27 | static const std::string kRequired("required"); |
| 28 | static const std::string kOptional("optional"); |
| 29 | static const std::string kConfigPrefix("CONFIG_"); |
| 30 | |
| 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> |
| 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> |
| 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> |
| 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 | |
Yifan Hong | c54d32c | 2017-03-07 19:12:26 -0800 | [diff] [blame] | 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 | } \ |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 93 | |
Yifan Hong | c54d32c | 2017-03-07 19:12:26 -0800 | [diff] [blame] | 94 | DEFINE_PARSE_STREAMIN_FOR_ENUM(HalFormat); |
Yifan Hong | c54d32c | 2017-03-07 19:12:26 -0800 | [diff] [blame] | 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); |
Yifan Hong | 7c7d706 | 2017-04-04 16:26:51 -0700 | [diff] [blame] | 99 | DEFINE_PARSE_STREAMIN_FOR_ENUM(SchemaType); |
Yifan Hong | d485790 | 2017-06-13 14:13:56 -0700 | [diff] [blame] | 100 | DEFINE_PARSE_STREAMIN_FOR_ENUM(XmlSchemaFormat); |
Yifan Hong | 3f5489a | 2017-02-08 11:14:21 -0800 | [diff] [blame] | 101 | |
| 102 | std::ostream &operator<<(std::ostream &os, const KernelConfigTypedValue &kctv) { |
| 103 | switch (kctv.mType) { |
| 104 | case KernelConfigType::STRING: |
| 105 | return os << kctv.mStringValue; |
| 106 | case KernelConfigType::INTEGER: |
| 107 | return os << to_string(kctv.mIntegerValue); |
| 108 | case KernelConfigType::RANGE: |
| 109 | return os << to_string(kctv.mRangeValue.first) << "-" |
| 110 | << to_string(kctv.mRangeValue.second); |
| 111 | case KernelConfigType::TRISTATE: |
| 112 | return os << to_string(kctv.mTristateValue); |
| 113 | } |
| 114 | } |
| 115 | |
Yifan Hong | 2027a49 | 2017-12-11 15:21:19 -0800 | [diff] [blame] | 116 | bool parse(const std::string& s, Level* l) { |
| 117 | if (s.empty()) { |
| 118 | *l = Level::UNSPECIFIED; |
| 119 | return true; |
| 120 | } |
| 121 | if (s == "legacy") { |
| 122 | *l = Level::LEGACY; |
| 123 | return true; |
| 124 | } |
| 125 | size_t value; |
| 126 | if (!ParseUint(s, &value)) { |
| 127 | return false; |
| 128 | } |
| 129 | *l = static_cast<Level>(value); |
| 130 | return true; |
| 131 | } |
| 132 | |
| 133 | std::ostream& operator<<(std::ostream& os, Level l) { |
| 134 | if (l == Level::UNSPECIFIED) { |
| 135 | return os; |
| 136 | } |
| 137 | if (l == Level::LEGACY) { |
| 138 | return os << "legacy"; |
| 139 | } |
| 140 | return os << static_cast<size_t>(l); |
| 141 | } |
| 142 | |
Yifan Hong | 3f5489a | 2017-02-08 11:14:21 -0800 | [diff] [blame] | 143 | // Notice that strtoull is used even though KernelConfigIntValue is signed int64_t, |
| 144 | // because strtoull can accept negative values as well. |
| 145 | // Notice that according to man strtoul, strtoull can actually accept |
| 146 | // -2^64 + 1 to 2^64 - 1, with the 65th bit truncated. |
| 147 | // ParseInt / ParseUint are not used because they do not handle signed hex very well. |
| 148 | template <typename T> |
| 149 | bool parseKernelConfigIntHelper(const std::string &s, T *i) { |
| 150 | char *end; |
| 151 | errno = 0; |
| 152 | unsigned long long int ulli = strtoull(s.c_str(), &end, 0 /* base */); |
| 153 | // It is implementation defined that what value will be returned by strtoull |
| 154 | // in the error case, so we are checking errno directly here. |
| 155 | if (errno == 0 && s.c_str() != end && *end == '\0') { |
| 156 | *i = static_cast<T>(ulli); |
| 157 | return true; |
| 158 | } |
| 159 | return false; |
| 160 | } |
| 161 | |
| 162 | bool parseKernelConfigInt(const std::string &s, int64_t *i) { |
| 163 | return parseKernelConfigIntHelper(s, i); |
| 164 | } |
| 165 | |
| 166 | bool parseKernelConfigInt(const std::string &s, uint64_t *i) { |
| 167 | return parseKernelConfigIntHelper(s, i); |
| 168 | } |
| 169 | |
| 170 | bool parseRange(const std::string &s, KernelConfigRangeValue *range) { |
| 171 | auto pos = s.find('-'); |
| 172 | if (pos == std::string::npos) { |
| 173 | return false; |
| 174 | } |
| 175 | return parseKernelConfigInt(s.substr(0, pos), &range->first) |
| 176 | && parseKernelConfigInt(s.substr(pos + 1), &range->second); |
| 177 | } |
| 178 | |
| 179 | bool parse(const std::string &s, KernelConfigKey *key) { |
| 180 | *key = s; |
| 181 | return true; |
| 182 | } |
| 183 | |
| 184 | bool parseKernelConfigValue(const std::string &s, KernelConfigTypedValue *kctv) { |
| 185 | switch (kctv->mType) { |
| 186 | case KernelConfigType::STRING: |
| 187 | kctv->mStringValue = s; |
| 188 | return true; |
| 189 | case KernelConfigType::INTEGER: |
| 190 | return parseKernelConfigInt(s, &kctv->mIntegerValue); |
| 191 | case KernelConfigType::RANGE: |
| 192 | return parseRange(s, &kctv->mRangeValue); |
| 193 | case KernelConfigType::TRISTATE: |
| 194 | return parse(s, &kctv->mTristateValue); |
| 195 | } |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 196 | } |
| 197 | |
Yifan Hong | 8fac3f3 | 2017-07-06 14:06:54 -0700 | [diff] [blame] | 198 | bool parseKernelConfigTypedValue(const std::string& s, KernelConfigTypedValue* kctv) { |
| 199 | if (parseKernelConfigInt(s, &kctv->mIntegerValue)) { |
| 200 | kctv->mType = KernelConfigType::INTEGER; |
| 201 | return true; |
| 202 | } |
| 203 | if (parse(s, &kctv->mTristateValue)) { |
| 204 | kctv->mType = KernelConfigType::TRISTATE; |
| 205 | return true; |
| 206 | } |
| 207 | // Do not test for KernelConfigType::RANGE. |
| 208 | kctv->mType = KernelConfigType::STRING; |
| 209 | kctv->mStringValue = s; |
| 210 | return true; |
| 211 | } |
| 212 | |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 213 | bool parse(const std::string &s, Version *ver) { |
| 214 | std::vector<std::string> v = SplitString(s, '.'); |
| 215 | if (v.size() != 2) { |
| 216 | return false; |
| 217 | } |
| 218 | size_t major, minor; |
| 219 | if (!ParseUint(v[0], &major)) { |
| 220 | return false; |
| 221 | } |
| 222 | if (!ParseUint(v[1], &minor)) { |
| 223 | return false; |
| 224 | } |
| 225 | *ver = Version(major, minor); |
| 226 | return true; |
| 227 | } |
| 228 | |
| 229 | std::ostream &operator<<(std::ostream &os, const Version &ver) { |
| 230 | return os << ver.majorVer << "." << ver.minorVer; |
| 231 | } |
| 232 | |
| 233 | bool parse(const std::string &s, VersionRange *vr) { |
| 234 | std::vector<std::string> v = SplitString(s, '-'); |
| 235 | if (v.size() != 1 && v.size() != 2) { |
| 236 | return false; |
| 237 | } |
| 238 | Version minVer; |
| 239 | if (!parse(v[0], &minVer)) { |
| 240 | return false; |
| 241 | } |
| 242 | if (v.size() == 1) { |
| 243 | *vr = VersionRange(minVer.majorVer, minVer.minorVer); |
| 244 | } else { |
| 245 | size_t maxMinor; |
| 246 | if (!ParseUint(v[1], &maxMinor)) { |
| 247 | return false; |
| 248 | } |
| 249 | *vr = VersionRange(minVer.majorVer, minVer.minorVer, maxMinor); |
| 250 | } |
| 251 | return true; |
| 252 | } |
| 253 | |
| 254 | std::ostream &operator<<(std::ostream &os, const VersionRange &vr) { |
| 255 | if (vr.isSingleVersion()) { |
| 256 | return os << vr.minVer(); |
| 257 | } |
| 258 | return os << vr.minVer() << "-" << vr.maxMinor; |
| 259 | } |
| 260 | |
Yifan Hong | 0f529fa | 2018-01-10 14:51:59 -0800 | [diff] [blame] | 261 | #pragma clang diagnostic push |
| 262 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
Yifan Hong | a04e147 | 2017-04-05 13:15:34 -0700 | [diff] [blame] | 263 | bool parse(const std::string &s, VndkVersionRange *vr) { |
| 264 | std::vector<std::string> v = SplitString(s, '-'); |
| 265 | if (v.size() != 1 && v.size() != 2) { |
| 266 | return false; |
| 267 | } |
| 268 | std::vector<std::string> minVector = SplitString(v[0], '.'); |
| 269 | if (minVector.size() != 3) { |
| 270 | return false; |
| 271 | } |
| 272 | if (!ParseUint(minVector[0], &vr->sdk) || |
| 273 | !ParseUint(minVector[1], &vr->vndk) || |
| 274 | !ParseUint(minVector[2], &vr->patchMin)) { |
| 275 | return false; |
| 276 | } |
| 277 | if (v.size() == 1) { |
| 278 | vr->patchMax = vr->patchMin; |
| 279 | return true; |
| 280 | } else { |
| 281 | return ParseUint(v[1], &vr->patchMax); |
| 282 | } |
| 283 | } |
| 284 | |
| 285 | std::ostream &operator<<(std::ostream &os, const VndkVersionRange &vr) { |
| 286 | os << vr.sdk << "." << vr.vndk << "." << vr.patchMin; |
| 287 | if (!vr.isSingleVersion()) { |
| 288 | os << "-" << vr.patchMax; |
| 289 | } |
| 290 | return os; |
| 291 | } |
Yifan Hong | 0f529fa | 2018-01-10 14:51:59 -0800 | [diff] [blame] | 292 | #pragma clang diagnostic pop |
Yifan Hong | a04e147 | 2017-04-05 13:15:34 -0700 | [diff] [blame] | 293 | |
Yifan Hong | 3f5489a | 2017-02-08 11:14:21 -0800 | [diff] [blame] | 294 | bool parse(const std::string &s, KernelVersion *kernelVersion) { |
| 295 | std::vector<std::string> v = SplitString(s, '.'); |
| 296 | if (v.size() != 3) { |
| 297 | return false; |
| 298 | } |
| 299 | size_t version, major, minor; |
| 300 | if (!ParseUint(v[0], &version)) { |
| 301 | return false; |
| 302 | } |
| 303 | if (!ParseUint(v[1], &major)) { |
| 304 | return false; |
| 305 | } |
| 306 | if (!ParseUint(v[2], &minor)) { |
| 307 | return false; |
| 308 | } |
| 309 | *kernelVersion = KernelVersion(version, major, minor); |
| 310 | return true; |
| 311 | } |
| 312 | |
Yifan Hong | c54d32c | 2017-03-07 19:12:26 -0800 | [diff] [blame] | 313 | std::ostream &operator<<(std::ostream &os, const TransportArch &ta) { |
| 314 | return os << to_string(ta.transport) << to_string(ta.arch); |
| 315 | } |
| 316 | |
| 317 | bool parse(const std::string &s, TransportArch *ta) { |
| 318 | bool transportSet = false; |
| 319 | bool archSet = false; |
| 320 | for (size_t i = 0; i < gTransportStrings.size(); ++i) { |
| 321 | if (s.find(gTransportStrings.at(i)) != std::string::npos) { |
| 322 | ta->transport = static_cast<Transport>(i); |
| 323 | transportSet = true; |
| 324 | break; |
| 325 | } |
| 326 | } |
| 327 | if (!transportSet) { |
| 328 | return false; |
| 329 | } |
| 330 | for (size_t i = 0; i < gArchStrings.size(); ++i) { |
| 331 | if (s.find(gArchStrings.at(i)) != std::string::npos) { |
| 332 | ta->arch = static_cast<Arch>(i); |
| 333 | archSet = true; |
| 334 | break; |
| 335 | } |
| 336 | } |
| 337 | if (!archSet) { |
| 338 | return false; |
| 339 | } |
| 340 | return ta->isValid(); |
| 341 | } |
| 342 | |
Yifan Hong | 3f5489a | 2017-02-08 11:14:21 -0800 | [diff] [blame] | 343 | std::ostream &operator<<(std::ostream &os, const KernelVersion &ver) { |
| 344 | return os << ver.version << "." << ver.majorRev << "." << ver.minorRev; |
| 345 | } |
| 346 | |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 347 | bool parse(const std::string &s, ManifestHal *hal) { |
| 348 | std::vector<std::string> v = SplitString(s, '/'); |
Yifan Hong | 974ad9c | 2017-04-04 15:37:39 -0700 | [diff] [blame] | 349 | if (v.size() != 4) { |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 350 | return false; |
| 351 | } |
| 352 | if (!parse(v[0], &hal->format)) { |
| 353 | return false; |
| 354 | } |
| 355 | hal->name = v[1]; |
Yifan Hong | c54d32c | 2017-03-07 19:12:26 -0800 | [diff] [blame] | 356 | if (!parse(v[2], &hal->transportArch)) { |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 357 | return false; |
| 358 | } |
Yifan Hong | 974ad9c | 2017-04-04 15:37:39 -0700 | [diff] [blame] | 359 | if (!parse(v[3], &hal->versions)) { |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 360 | return false; |
| 361 | } |
Yifan Hong | 5a06ef7 | 2017-01-24 19:54:24 -0800 | [diff] [blame] | 362 | return hal->isValid(); |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 363 | } |
| 364 | |
| 365 | std::ostream &operator<<(std::ostream &os, const ManifestHal &hal) { |
| 366 | return os << hal.format << "/" |
| 367 | << hal.name << "/" |
Yifan Hong | c54d32c | 2017-03-07 19:12:26 -0800 | [diff] [blame] | 368 | << hal.transportArch << "/" |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 369 | << hal.versions; |
| 370 | } |
| 371 | |
| 372 | bool parse(const std::string &s, MatrixHal *req) { |
| 373 | std::vector<std::string> v = SplitString(s, '/'); |
| 374 | if (v.size() != 4) { |
| 375 | return false; |
| 376 | } |
| 377 | if (!parse(v[0], &req->format)) { |
| 378 | return false; |
| 379 | } |
| 380 | req->name = v[1]; |
| 381 | if (!parse(v[2], &req->versionRanges)) { |
| 382 | return false; |
| 383 | } |
| 384 | if (v[3] != kRequired || v[3] != kOptional) { |
| 385 | return false; |
| 386 | } |
| 387 | req->optional = (v[3] == kOptional); |
| 388 | return true; |
| 389 | } |
| 390 | |
| 391 | std::ostream &operator<<(std::ostream &os, const MatrixHal &req) { |
| 392 | return os << req.format << "/" |
| 393 | << req.name << "/" |
| 394 | << req.versionRanges << "/" |
| 395 | << (req.optional ? kOptional : kRequired); |
| 396 | } |
| 397 | |
Yifan Hong | 6e82b11 | 2018-03-20 13:06:00 -0700 | [diff] [blame] | 398 | std::string expandInstances(const MatrixHal& req, const VersionRange& vr, bool brace) { |
Yifan Hong | de3aec2 | 2018-02-12 15:39:47 -0800 | [diff] [blame] | 399 | std::string s; |
Yifan Hong | 8d8264e | 2018-03-14 16:03:11 -0700 | [diff] [blame] | 400 | size_t count = 0; |
Yifan Hong | 6e82b11 | 2018-03-20 13:06:00 -0700 | [diff] [blame] | 401 | req.forEachInstance(vr, [&](const auto& matrixInstance) { |
| 402 | if (count > 0) s += " AND "; |
| 403 | s += toFQNameString(vr, matrixInstance.interface(), |
| 404 | matrixInstance.isRegex() ? matrixInstance.regexPattern() |
| 405 | : matrixInstance.exactInstance()); |
| 406 | count++; |
| 407 | return true; |
| 408 | }); |
Yifan Hong | 8d8264e | 2018-03-14 16:03:11 -0700 | [diff] [blame] | 409 | if (count == 0) { |
| 410 | s += "@" + to_string(vr); |
| 411 | } |
| 412 | if (count >= 2 && brace) { |
| 413 | s = "(" + s + ")"; |
| 414 | } |
Yifan Hong | de3aec2 | 2018-02-12 15:39:47 -0800 | [diff] [blame] | 415 | return s; |
| 416 | } |
| 417 | |
| 418 | std::vector<std::string> expandInstances(const MatrixHal& req) { |
Yifan Hong | 6e82b11 | 2018-03-20 13:06:00 -0700 | [diff] [blame] | 419 | size_t count = req.instancesCount(); |
| 420 | if (count == 0) { |
Yifan Hong | de3aec2 | 2018-02-12 15:39:47 -0800 | [diff] [blame] | 421 | return {}; |
| 422 | } |
Yifan Hong | 6e82b11 | 2018-03-20 13:06:00 -0700 | [diff] [blame] | 423 | if (count == 1) { |
Yifan Hong | 8d8264e | 2018-03-14 16:03:11 -0700 | [diff] [blame] | 424 | return {expandInstances(req, req.versionRanges.front(), false /* brace */)}; |
Yifan Hong | de3aec2 | 2018-02-12 15:39:47 -0800 | [diff] [blame] | 425 | } |
| 426 | std::vector<std::string> ss; |
| 427 | for (const auto& vr : req.versionRanges) { |
| 428 | if (!ss.empty()) { |
| 429 | ss.back() += " OR"; |
| 430 | } |
Yifan Hong | 8d8264e | 2018-03-14 16:03:11 -0700 | [diff] [blame] | 431 | ss.push_back(expandInstances(req, vr, true /* brace */)); |
Yifan Hong | de3aec2 | 2018-02-12 15:39:47 -0800 | [diff] [blame] | 432 | } |
| 433 | return ss; |
| 434 | } |
Yifan Hong | 558380a | 2017-02-09 15:37:32 -0800 | [diff] [blame] | 435 | |
| 436 | std::ostream &operator<<(std::ostream &os, KernelSepolicyVersion ksv){ |
| 437 | return os << ksv.value; |
| 438 | } |
| 439 | |
| 440 | bool parse(const std::string &s, KernelSepolicyVersion *ksv){ |
| 441 | return ParseUint(s, &ksv->value); |
| 442 | } |
| 443 | |
Yifan Hong | d2b7e64 | 2017-02-17 10:15:32 -0800 | [diff] [blame] | 444 | std::string dump(const HalManifest &vm) { |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 445 | std::ostringstream oss; |
| 446 | bool first = true; |
Yifan Hong | ef6d4d3 | 2017-01-23 14:12:28 -0800 | [diff] [blame] | 447 | for (const auto &hal : vm.getHals()) { |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 448 | if (!first) { |
| 449 | oss << ":"; |
| 450 | } |
| 451 | oss << hal; |
| 452 | first = false; |
| 453 | } |
| 454 | return oss.str(); |
| 455 | } |
| 456 | |
Yifan Hong | e3a9234 | 2018-01-25 17:00:16 -0800 | [diff] [blame] | 457 | std::string dump(const RuntimeInfo& ki, bool verbose) { |
Yifan Hong | ccf967b | 2017-01-18 11:04:19 -0800 | [diff] [blame] | 458 | std::ostringstream oss; |
| 459 | |
Yifan Hong | e3a9234 | 2018-01-25 17:00:16 -0800 | [diff] [blame] | 460 | oss << "kernel = " << ki.osName() << "/" << ki.nodeName() << "/" << ki.osRelease() << "/" |
| 461 | << ki.osVersion() << "/" << ki.hardwareId() << ";" << ki.mBootAvbVersion << "/" |
Yifan Hong | 881a9e45 | 2017-04-27 19:31:13 -0700 | [diff] [blame] | 462 | << ki.mBootVbmetaAvbVersion << ";" |
Yifan Hong | e3a9234 | 2018-01-25 17:00:16 -0800 | [diff] [blame] | 463 | << "kernelSepolicyVersion = " << ki.kernelSepolicyVersion() << ";"; |
| 464 | |
| 465 | if (verbose) { |
| 466 | oss << "\n\ncpu info:\n" << ki.cpuInfo(); |
| 467 | } |
| 468 | |
| 469 | oss << "\n#CONFIG's loaded = " << ki.mKernelConfigs.size() << ";\n"; |
| 470 | |
| 471 | if (verbose) { |
| 472 | for (const auto& pair : ki.mKernelConfigs) { |
| 473 | oss << pair.first << "=" << pair.second << "\n"; |
| 474 | } |
Yifan Hong | ccf967b | 2017-01-18 11:04:19 -0800 | [diff] [blame] | 475 | } |
| 476 | |
| 477 | return oss.str(); |
| 478 | } |
| 479 | |
Yifan Hong | b6c7f49 | 2018-02-27 14:07:57 -0800 | [diff] [blame] | 480 | std::string toFQNameString(const std::string& package, const std::string& version, |
| 481 | const std::string& interface, const std::string& instance) { |
| 482 | std::stringstream ss; |
| 483 | ss << package << "@" << version; |
| 484 | if (!interface.empty()) { |
| 485 | ss << "::" << interface; |
| 486 | if (!instance.empty()) { |
| 487 | ss << "/" << instance; |
| 488 | } |
| 489 | } |
| 490 | return ss.str(); |
| 491 | } |
| 492 | |
| 493 | std::string toFQNameString(const std::string& package, const Version& version, |
| 494 | const std::string& interface, const std::string& instance) { |
| 495 | return toFQNameString(package, to_string(version), interface, instance); |
| 496 | } |
| 497 | |
| 498 | std::string toFQNameString(const Version& version, const std::string& interface, |
| 499 | const std::string& instance) { |
| 500 | return toFQNameString("", version, interface, instance); |
| 501 | } |
| 502 | |
| 503 | // android.hardware.foo@1.0-1::IFoo/default. |
| 504 | // Note that the format is extended to support a range of versions. |
| 505 | std::string toFQNameString(const std::string& package, const VersionRange& range, |
| 506 | const std::string& interface, const std::string& instance) { |
| 507 | return toFQNameString(package, to_string(range), interface, instance); |
| 508 | } |
| 509 | |
| 510 | std::string toFQNameString(const VersionRange& range, const std::string& interface, |
| 511 | const std::string& instance) { |
| 512 | return toFQNameString("", range, interface, instance); |
| 513 | } |
| 514 | |
Yifan Hong | a1fae89 | 2018-03-13 12:36:38 -0700 | [diff] [blame] | 515 | std::ostream& operator<<(std::ostream& os, const FqInstance& fqInstance) { |
| 516 | return os << fqInstance.string(); |
| 517 | } |
| 518 | |
| 519 | bool parse(const std::string& s, FqInstance* fqInstance) { |
| 520 | return fqInstance->setTo(s); |
| 521 | } |
| 522 | |
Yifan Hong | 676447a | 2016-11-15 12:57:23 -0800 | [diff] [blame] | 523 | } // namespace vintf |
| 524 | } // namespace android |