AssembleVintf.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  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. #include <stdlib.h>
  17. #include <unistd.h>
  18. #include <fstream>
  19. #include <iostream>
  20. #include <sstream>
  21. #include <string>
  22. #include <unordered_map>
  23. #include <android-base/file.h>
  24. #include <android-base/parseint.h>
  25. #include <android-base/strings.h>
  26. #include <vintf/AssembleVintf.h>
  27. #include <vintf/KernelConfigParser.h>
  28. #include <vintf/parse_string.h>
  29. #include <vintf/parse_xml.h>
  30. #include "utils.h"
  31. #define BUFFER_SIZE sysconf(_SC_PAGESIZE)
  32. namespace android {
  33. namespace vintf {
  34. static const std::string gConfigPrefix = "android-base-";
  35. static const std::string gConfigSuffix = ".config";
  36. static const std::string gBaseConfig = "android-base.config";
  37. // An input stream with a name.
  38. // The input stream may be an actual file, or a stringstream for testing.
  39. // It takes ownership on the istream.
  40. class NamedIstream {
  41. public:
  42. NamedIstream(const std::string& name, std::unique_ptr<std::istream>&& stream)
  43. : mName(name), mStream(std::move(stream)) {}
  44. const std::string& name() const { return mName; }
  45. std::istream& stream() { return *mStream; }
  46. private:
  47. std::string mName;
  48. std::unique_ptr<std::istream> mStream;
  49. };
  50. /**
  51. * Slurps the device manifest file and add build time flag to it.
  52. */
  53. class AssembleVintfImpl : public AssembleVintf {
  54. using Condition = std::unique_ptr<KernelConfig>;
  55. using ConditionedConfig = std::pair<Condition, std::vector<KernelConfig> /* configs */>;
  56. public:
  57. void setFakeEnv(const std::string& key, const std::string& value) { mFakeEnv[key] = value; }
  58. std::string getEnv(const std::string& key) const {
  59. auto it = mFakeEnv.find(key);
  60. if (it != mFakeEnv.end()) {
  61. return it->second;
  62. }
  63. const char* envValue = getenv(key.c_str());
  64. return envValue != nullptr ? std::string(envValue) : std::string();
  65. }
  66. // Get environment variable and split with space.
  67. std::vector<std::string> getEnvList(const std::string& key) const {
  68. std::vector<std::string> ret;
  69. for (auto&& v : base::Split(getEnv(key), " ")) {
  70. v = base::Trim(v);
  71. if (!v.empty()) {
  72. ret.push_back(v);
  73. }
  74. }
  75. return ret;
  76. }
  77. template <typename T>
  78. bool getFlag(const std::string& key, T* value, bool log = true) const {
  79. std::string envValue = getEnv(key);
  80. if (envValue.empty()) {
  81. if (log) {
  82. std::cerr << "Warning: " << key << " is missing, defaulted to " << (*value) << "."
  83. << std::endl;
  84. }
  85. return true;
  86. }
  87. if (!parse(envValue, value)) {
  88. std::cerr << "Cannot parse " << envValue << "." << std::endl;
  89. return false;
  90. }
  91. return true;
  92. }
  93. /**
  94. * Set *out to environment variable only if *out is a dummy value (i.e. default constructed).
  95. * Return true if *out is set to environment variable, otherwise false.
  96. */
  97. template <typename T>
  98. bool getFlagIfUnset(const std::string& envKey, T* out, bool log = true) const {
  99. bool hasExistingValue = !(*out == T{});
  100. bool hasEnvValue = false;
  101. T envValue;
  102. std::string envStrValue = getEnv(envKey);
  103. if (!envStrValue.empty()) {
  104. if (!parse(envStrValue, &envValue)) {
  105. if (log) {
  106. std::cerr << "Cannot parse " << envValue << "." << std::endl;
  107. }
  108. return false;
  109. }
  110. hasEnvValue = true;
  111. }
  112. if (hasExistingValue) {
  113. if (hasEnvValue && log) {
  114. std::cerr << "Warning: cannot override existing value " << *out << " with "
  115. << envKey << " (which is " << envValue << ")." << std::endl;
  116. }
  117. return false;
  118. }
  119. if (!hasEnvValue) {
  120. if (log) {
  121. std::cerr << "Warning: " << envKey << " is not specified. Default to " << T{} << "."
  122. << std::endl;
  123. }
  124. return false;
  125. }
  126. *out = envValue;
  127. return true;
  128. }
  129. bool getBooleanFlag(const std::string& key) const { return getEnv(key) == std::string("true"); }
  130. size_t getIntegerFlag(const std::string& key, size_t defaultValue = 0) const {
  131. std::string envValue = getEnv(key);
  132. if (envValue.empty()) {
  133. return defaultValue;
  134. }
  135. size_t value;
  136. if (!base::ParseUint(envValue, &value)) {
  137. std::cerr << "Error: " << key << " must be a number." << std::endl;
  138. return defaultValue;
  139. }
  140. return value;
  141. }
  142. static std::string read(std::basic_istream<char>& is) {
  143. std::stringstream ss;
  144. ss << is.rdbuf();
  145. return ss.str();
  146. }
  147. static bool isCommonConfig(const std::string& path) {
  148. return ::android::base::Basename(path) == gBaseConfig;
  149. }
  150. // nullptr on any error, otherwise the condition.
  151. static Condition generateCondition(const std::string& path) {
  152. std::string fname = ::android::base::Basename(path);
  153. if (fname.size() <= gConfigPrefix.size() + gConfigSuffix.size() ||
  154. !std::equal(gConfigPrefix.begin(), gConfigPrefix.end(), fname.begin()) ||
  155. !std::equal(gConfigSuffix.rbegin(), gConfigSuffix.rend(), fname.rbegin())) {
  156. return nullptr;
  157. }
  158. std::string sub = fname.substr(gConfigPrefix.size(),
  159. fname.size() - gConfigPrefix.size() - gConfigSuffix.size());
  160. if (sub.empty()) {
  161. return nullptr; // should not happen
  162. }
  163. for (size_t i = 0; i < sub.size(); ++i) {
  164. if (sub[i] == '-') {
  165. sub[i] = '_';
  166. continue;
  167. }
  168. if (isalnum(sub[i])) {
  169. sub[i] = toupper(sub[i]);
  170. continue;
  171. }
  172. std::cerr << "'" << fname << "' (in " << path
  173. << ") is not a valid kernel config file name. Must match regex: "
  174. << "android-base(-[0-9a-zA-Z-]+)?\\" << gConfigSuffix
  175. << std::endl;
  176. return nullptr;
  177. }
  178. sub.insert(0, "CONFIG_");
  179. return std::make_unique<KernelConfig>(std::move(sub), Tristate::YES);
  180. }
  181. static bool parseFileForKernelConfigs(std::basic_istream<char>& stream,
  182. std::vector<KernelConfig>* out) {
  183. KernelConfigParser parser(true /* processComments */, true /* relaxedFormat */);
  184. status_t err = parser.processAndFinish(read(stream));
  185. if (err != OK) {
  186. std::cerr << parser.error();
  187. return false;
  188. }
  189. for (auto& configPair : parser.configs()) {
  190. out->push_back({});
  191. KernelConfig& config = out->back();
  192. config.first = std::move(configPair.first);
  193. if (!parseKernelConfigTypedValue(configPair.second, &config.second)) {
  194. std::cerr << "Unknown value type for key = '" << config.first << "', value = '"
  195. << configPair.second << "'\n";
  196. return false;
  197. }
  198. }
  199. return true;
  200. }
  201. static bool parseFilesForKernelConfigs(std::vector<NamedIstream>* streams,
  202. std::vector<ConditionedConfig>* out) {
  203. out->clear();
  204. ConditionedConfig commonConfig;
  205. bool foundCommonConfig = false;
  206. bool ret = true;
  207. for (auto& namedStream : *streams) {
  208. if (isCommonConfig(namedStream.name())) {
  209. ret &= parseFileForKernelConfigs(namedStream.stream(), &commonConfig.second);
  210. foundCommonConfig = true;
  211. } else {
  212. Condition condition = generateCondition(namedStream.name());
  213. ret &= (condition != nullptr);
  214. std::vector<KernelConfig> kernelConfigs;
  215. if ((ret &= parseFileForKernelConfigs(namedStream.stream(), &kernelConfigs)))
  216. out->emplace_back(std::move(condition), std::move(kernelConfigs));
  217. }
  218. }
  219. if (!foundCommonConfig) {
  220. std::cerr << "No " << gBaseConfig << " is found in these paths:" << std::endl;
  221. for (auto& namedStream : *streams) {
  222. std::cerr << " " << namedStream.name() << std::endl;
  223. }
  224. }
  225. ret &= foundCommonConfig;
  226. // first element is always common configs (no conditions).
  227. out->insert(out->begin(), std::move(commonConfig));
  228. return ret;
  229. }
  230. std::basic_ostream<char>& out() const { return mOutRef == nullptr ? std::cout : *mOutRef; }
  231. // If -c is provided, check it.
  232. bool checkDualFile(const HalManifest& manifest, const CompatibilityMatrix& matrix) {
  233. if (getBooleanFlag("PRODUCT_ENFORCE_VINTF_MANIFEST")) {
  234. std::string error;
  235. if (!manifest.checkCompatibility(matrix, &error)) {
  236. std::cerr << "Not compatible: " << error << std::endl;
  237. return false;
  238. }
  239. }
  240. // Check HALs in device manifest that are not in framework matrix.
  241. if (getBooleanFlag("VINTF_ENFORCE_NO_UNUSED_HALS")) {
  242. auto unused = manifest.checkUnusedHals(matrix);
  243. if (!unused.empty()) {
  244. std::cerr << "Error: The following instances are in the device manifest but "
  245. << "not specified in framework compatibility matrix: " << std::endl
  246. << " " << android::base::Join(unused, "\n ") << std::endl
  247. << "Suggested fix:" << std::endl
  248. << "1. Check for any typos in device manifest or framework compatibility "
  249. << "matrices with FCM version >= " << matrix.level() << "." << std::endl
  250. << "2. Add them to any framework compatibility matrix with FCM "
  251. << "version >= " << matrix.level() << " where applicable." << std::endl
  252. << "3. Add them to DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE "
  253. << "or DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE." << std::endl;
  254. return false;
  255. }
  256. }
  257. return true;
  258. }
  259. template <typename S>
  260. using Schemas = std::vector<Named<S>>;
  261. using HalManifests = Schemas<HalManifest>;
  262. using CompatibilityMatrices = Schemas<CompatibilityMatrix>;
  263. template <typename M>
  264. void outputInputs(const Schemas<M>& inputs) {
  265. out() << "<!--" << std::endl;
  266. out() << " Input:" << std::endl;
  267. for (const auto& e : inputs) {
  268. if (!e.name.empty()) {
  269. out() << " " << base::Basename(e.name) << std::endl;
  270. }
  271. }
  272. out() << "-->" << std::endl;
  273. }
  274. // Parse --kernel arguments and write to output manifest.
  275. bool setDeviceManifestKernel(HalManifest* manifest) {
  276. if (mKernels.empty()) {
  277. return true;
  278. }
  279. if (mKernels.size() > 1) {
  280. std::cerr << "Warning: multiple --kernel is specified when building device manifest. "
  281. << "Only the first one will be used." << std::endl;
  282. }
  283. auto& kernelArg = *mKernels.begin();
  284. const auto& kernelVer = kernelArg.first;
  285. auto& kernelConfigFiles = kernelArg.second;
  286. // addKernel() guarantees that !kernelConfigFiles.empty().
  287. if (kernelConfigFiles.size() > 1) {
  288. std::cerr << "Warning: multiple config files are specified in --kernel when building "
  289. << "device manfiest. Only the first one will be used." << std::endl;
  290. }
  291. KernelConfigParser parser(true /* processComments */, false /* relaxedFormat */);
  292. status_t err = parser.processAndFinish(read(kernelConfigFiles[0].stream()));
  293. if (err != OK) {
  294. std::cerr << parser.error();
  295. return false;
  296. }
  297. manifest->device.mKernel = std::make_optional<KernelInfo>();
  298. manifest->device.mKernel->mVersion = kernelVer;
  299. manifest->device.mKernel->mConfigs = parser.configs();
  300. return true;
  301. }
  302. bool assembleHalManifest(HalManifests* halManifests) {
  303. std::string error;
  304. HalManifest* halManifest = &halManifests->front().object;
  305. for (auto it = halManifests->begin() + 1; it != halManifests->end(); ++it) {
  306. const std::string& path = it->name;
  307. HalManifest& manifestToAdd = it->object;
  308. if (manifestToAdd.level() != Level::UNSPECIFIED) {
  309. if (halManifest->level() == Level::UNSPECIFIED) {
  310. halManifest->mLevel = manifestToAdd.level();
  311. } else if (halManifest->level() != manifestToAdd.level()) {
  312. std::cerr << "Inconsistent FCM Version in HAL manifests:" << std::endl
  313. << " File '" << halManifests->front().name << "' has level "
  314. << halManifest->level() << std::endl
  315. << " File '" << path << "' has level " << manifestToAdd.level()
  316. << std::endl;
  317. return false;
  318. }
  319. }
  320. if (!halManifest->addAll(&manifestToAdd, &error)) {
  321. std::cerr << "File \"" << path << "\" cannot be added: " << error << std::endl;
  322. return false;
  323. }
  324. }
  325. if (halManifest->mType == SchemaType::DEVICE) {
  326. (void)getFlagIfUnset("BOARD_SEPOLICY_VERS", &halManifest->device.mSepolicyVersion);
  327. if (!setDeviceFcmVersion(halManifest)) {
  328. return false;
  329. }
  330. if (!setDeviceManifestKernel(halManifest)) {
  331. return false;
  332. }
  333. }
  334. if (halManifest->mType == SchemaType::FRAMEWORK) {
  335. for (auto&& v : getEnvList("PROVIDED_VNDK_VERSIONS")) {
  336. halManifest->framework.mVendorNdks.emplace_back(std::move(v));
  337. }
  338. for (auto&& v : getEnvList("PLATFORM_SYSTEMSDK_VERSIONS")) {
  339. halManifest->framework.mSystemSdk.mVersions.emplace(std::move(v));
  340. }
  341. }
  342. outputInputs(*halManifests);
  343. if (mOutputMatrix) {
  344. CompatibilityMatrix generatedMatrix = halManifest->generateCompatibleMatrix();
  345. if (!halManifest->checkCompatibility(generatedMatrix, &error)) {
  346. std::cerr << "FATAL ERROR: cannot generate a compatible matrix: " << error
  347. << std::endl;
  348. }
  349. out() << "<!-- \n"
  350. " Autogenerated skeleton compatibility matrix. \n"
  351. " Use with caution. Modify it to suit your needs.\n"
  352. " All HALs are set to optional.\n"
  353. " Many entries other than HALs are zero-filled and\n"
  354. " require human attention. \n"
  355. "-->\n"
  356. << gCompatibilityMatrixConverter(generatedMatrix, mSerializeFlags);
  357. } else {
  358. out() << gHalManifestConverter(*halManifest, mSerializeFlags);
  359. }
  360. out().flush();
  361. if (mCheckFile != nullptr) {
  362. CompatibilityMatrix checkMatrix;
  363. if (!gCompatibilityMatrixConverter(&checkMatrix, read(*mCheckFile), &error)) {
  364. std::cerr << "Cannot parse check file as a compatibility matrix: " << error
  365. << std::endl;
  366. return false;
  367. }
  368. if (!checkDualFile(*halManifest, checkMatrix)) {
  369. return false;
  370. }
  371. }
  372. return true;
  373. }
  374. // Parse --kernel arguments and write to output matrix.
  375. bool assembleFrameworkCompatibilityMatrixKernels(CompatibilityMatrix* matrix) {
  376. for (auto& pair : mKernels) {
  377. std::vector<ConditionedConfig> conditionedConfigs;
  378. if (!parseFilesForKernelConfigs(&pair.second, &conditionedConfigs)) {
  379. return false;
  380. }
  381. for (ConditionedConfig& conditionedConfig : conditionedConfigs) {
  382. MatrixKernel kernel(KernelVersion{pair.first}, std::move(conditionedConfig.second));
  383. if (conditionedConfig.first != nullptr)
  384. kernel.mConditions.push_back(std::move(*conditionedConfig.first));
  385. std::string error;
  386. if (!matrix->addKernel(std::move(kernel), &error)) {
  387. std::cerr << "Error:" << error << std::endl;
  388. return false;
  389. };
  390. }
  391. }
  392. return true;
  393. }
  394. bool setDeviceFcmVersion(HalManifest* manifest) {
  395. // Not needed for generating empty manifest for DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE.
  396. if (getBooleanFlag("VINTF_IGNORE_TARGET_FCM_VERSION")) {
  397. return true;
  398. }
  399. size_t shippingApiLevel = getIntegerFlag("PRODUCT_SHIPPING_API_LEVEL");
  400. if (manifest->level() != Level::UNSPECIFIED) {
  401. return true;
  402. }
  403. if (!getBooleanFlag("PRODUCT_ENFORCE_VINTF_MANIFEST")) {
  404. manifest->mLevel = Level::LEGACY;
  405. return true;
  406. }
  407. // TODO(b/70628538): Do not infer from Shipping API level.
  408. if (shippingApiLevel) {
  409. std::cerr << "Warning: Shipping FCM Version is inferred from Shipping API level. "
  410. << "Declare Shipping FCM Version in device manifest directly." << std::endl;
  411. manifest->mLevel = details::convertFromApiLevel(shippingApiLevel);
  412. if (manifest->mLevel == Level::UNSPECIFIED) {
  413. std::cerr << "Error: Shipping FCM Version cannot be inferred from Shipping API "
  414. << "level " << shippingApiLevel << "."
  415. << "Declare Shipping FCM Version in device manifest directly."
  416. << std::endl;
  417. return false;
  418. }
  419. return true;
  420. }
  421. // TODO(b/69638851): should be an error if Shipping API level is not defined.
  422. // For now, just leave it empty; when framework compatibility matrix is built,
  423. // lowest FCM Version is assumed.
  424. std::cerr << "Warning: Shipping FCM Version cannot be inferred, because:" << std::endl
  425. << " (1) It is not explicitly declared in device manifest;" << std::endl
  426. << " (2) PRODUCT_ENFORCE_VINTF_MANIFEST is set to true;" << std::endl
  427. << " (3) PRODUCT_SHIPPING_API_LEVEL is undefined." << std::endl
  428. << "Assuming 'unspecified' Shipping FCM Version. " << std::endl
  429. << "To remove this warning, define 'level' attribute in device manifest."
  430. << std::endl;
  431. return true;
  432. }
  433. Level getLowestFcmVersion(const CompatibilityMatrices& matrices) {
  434. Level ret = Level::UNSPECIFIED;
  435. for (const auto& e : matrices) {
  436. if (ret == Level::UNSPECIFIED || ret > e.object.level()) {
  437. ret = e.object.level();
  438. }
  439. }
  440. return ret;
  441. }
  442. bool assembleCompatibilityMatrix(CompatibilityMatrices* matrices) {
  443. std::string error;
  444. CompatibilityMatrix* matrix = nullptr;
  445. std::unique_ptr<HalManifest> checkManifest;
  446. std::unique_ptr<CompatibilityMatrix> builtMatrix;
  447. if (mCheckFile != nullptr) {
  448. checkManifest = std::make_unique<HalManifest>();
  449. if (!gHalManifestConverter(checkManifest.get(), read(*mCheckFile), &error)) {
  450. std::cerr << "Cannot parse check file as a HAL manifest: " << error << std::endl;
  451. return false;
  452. }
  453. }
  454. if (matrices->front().object.mType == SchemaType::DEVICE) {
  455. builtMatrix = CompatibilityMatrix::combineDeviceMatrices(matrices, &error);
  456. matrix = builtMatrix.get();
  457. if (matrix == nullptr) {
  458. std::cerr << error << std::endl;
  459. return false;
  460. }
  461. auto vndkVersion = base::Trim(getEnv("REQUIRED_VNDK_VERSION"));
  462. if (!vndkVersion.empty()) {
  463. auto& valueInMatrix = matrix->device.mVendorNdk;
  464. if (!valueInMatrix.version().empty() && valueInMatrix.version() != vndkVersion) {
  465. std::cerr << "Hard-coded <vendor-ndk> version in device compatibility matrix ("
  466. << matrices->front().name << "), '" << valueInMatrix.version()
  467. << "', does not match value inferred "
  468. << "from BOARD_VNDK_VERSION '" << vndkVersion << "'" << std::endl;
  469. return false;
  470. }
  471. valueInMatrix = VendorNdk{std::move(vndkVersion)};
  472. }
  473. for (auto&& v : getEnvList("BOARD_SYSTEMSDK_VERSIONS")) {
  474. matrix->device.mSystemSdk.mVersions.emplace(std::move(v));
  475. }
  476. }
  477. if (matrices->front().object.mType == SchemaType::FRAMEWORK) {
  478. Level deviceLevel =
  479. checkManifest != nullptr ? checkManifest->level() : Level::UNSPECIFIED;
  480. if (deviceLevel == Level::UNSPECIFIED) {
  481. deviceLevel = getLowestFcmVersion(*matrices);
  482. if (checkManifest != nullptr && deviceLevel != Level::UNSPECIFIED) {
  483. std::cerr << "Warning: No Target FCM Version for device. Assuming \""
  484. << to_string(deviceLevel)
  485. << "\" when building final framework compatibility matrix."
  486. << std::endl;
  487. }
  488. }
  489. builtMatrix = CompatibilityMatrix::combine(deviceLevel, matrices, &error);
  490. matrix = builtMatrix.get();
  491. if (matrix == nullptr) {
  492. std::cerr << error << std::endl;
  493. return false;
  494. }
  495. if (!assembleFrameworkCompatibilityMatrixKernels(matrix)) {
  496. return false;
  497. }
  498. // Add PLATFORM_SEPOLICY_* to sepolicy.sepolicy-version. Remove dupes.
  499. std::set<Version> sepolicyVersions;
  500. auto sepolicyVersionStrings = getEnvList("PLATFORM_SEPOLICY_COMPAT_VERSIONS");
  501. auto currentSepolicyVersionString = getEnv("PLATFORM_SEPOLICY_VERSION");
  502. if (!currentSepolicyVersionString.empty()) {
  503. sepolicyVersionStrings.push_back(currentSepolicyVersionString);
  504. }
  505. for (auto&& s : sepolicyVersionStrings) {
  506. Version v;
  507. if (!parse(s, &v)) {
  508. std::cerr << "Error: unknown sepolicy version '" << s << "' specified by "
  509. << (s == currentSepolicyVersionString
  510. ? "PLATFORM_SEPOLICY_VERSION"
  511. : "PLATFORM_SEPOLICY_COMPAT_VERSIONS")
  512. << ".";
  513. return false;
  514. }
  515. sepolicyVersions.insert(v);
  516. }
  517. for (auto&& v : sepolicyVersions) {
  518. matrix->framework.mSepolicy.mSepolicyVersionRanges.emplace_back(v.majorVer,
  519. v.minorVer);
  520. }
  521. getFlagIfUnset("POLICYVERS", &matrix->framework.mSepolicy.mKernelSepolicyVersion,
  522. false /* log */);
  523. getFlagIfUnset("FRAMEWORK_VBMETA_VERSION", &matrix->framework.mAvbMetaVersion,
  524. false /* log */);
  525. // Hard-override existing AVB version
  526. getFlag("FRAMEWORK_VBMETA_VERSION_OVERRIDE", &matrix->framework.mAvbMetaVersion,
  527. false /* log */);
  528. }
  529. outputInputs(*matrices);
  530. out() << gCompatibilityMatrixConverter(*matrix, mSerializeFlags);
  531. out().flush();
  532. if (checkManifest != nullptr && !checkDualFile(*checkManifest, *matrix)) {
  533. return false;
  534. }
  535. return true;
  536. }
  537. enum AssembleStatus { SUCCESS, FAIL_AND_EXIT, TRY_NEXT };
  538. template <typename Schema, typename AssembleFunc>
  539. AssembleStatus tryAssemble(const XmlConverter<Schema>& converter, const std::string& schemaName,
  540. AssembleFunc assemble, std::string* error) {
  541. Schemas<Schema> schemas;
  542. Schema schema;
  543. if (!converter(&schema, read(mInFiles.front().stream()), error)) {
  544. return TRY_NEXT;
  545. }
  546. auto firstType = schema.type();
  547. schemas.emplace_back(mInFiles.front().name(), std::move(schema));
  548. for (auto it = mInFiles.begin() + 1; it != mInFiles.end(); ++it) {
  549. Schema additionalSchema;
  550. const std::string& fileName = it->name();
  551. if (!converter(&additionalSchema, read(it->stream()), error)) {
  552. std::cerr << "File \"" << fileName << "\" is not a valid " << firstType << " "
  553. << schemaName << " (but the first file is a valid " << firstType << " "
  554. << schemaName << "). Error: " << *error << std::endl;
  555. return FAIL_AND_EXIT;
  556. }
  557. if (additionalSchema.type() != firstType) {
  558. std::cerr << "File \"" << fileName << "\" is a " << additionalSchema.type() << " "
  559. << schemaName << " (but a " << firstType << " " << schemaName
  560. << " is expected)." << std::endl;
  561. return FAIL_AND_EXIT;
  562. }
  563. schemas.emplace_back(fileName, std::move(additionalSchema));
  564. }
  565. return assemble(&schemas) ? SUCCESS : FAIL_AND_EXIT;
  566. }
  567. bool assemble() override {
  568. using std::placeholders::_1;
  569. if (mInFiles.empty()) {
  570. std::cerr << "Missing input file." << std::endl;
  571. return false;
  572. }
  573. std::string manifestError;
  574. auto status = tryAssemble(gHalManifestConverter, "manifest",
  575. std::bind(&AssembleVintfImpl::assembleHalManifest, this, _1),
  576. &manifestError);
  577. if (status == SUCCESS) return true;
  578. if (status == FAIL_AND_EXIT) return false;
  579. resetInFiles();
  580. std::string matrixError;
  581. status = tryAssemble(gCompatibilityMatrixConverter, "compatibility matrix",
  582. std::bind(&AssembleVintfImpl::assembleCompatibilityMatrix, this, _1),
  583. &matrixError);
  584. if (status == SUCCESS) return true;
  585. if (status == FAIL_AND_EXIT) return false;
  586. std::cerr << "Input file has unknown format." << std::endl
  587. << "Error when attempting to convert to manifest: " << manifestError << std::endl
  588. << "Error when attempting to convert to compatibility matrix: " << matrixError
  589. << std::endl;
  590. return false;
  591. }
  592. std::ostream& setOutputStream(Ostream&& out) override {
  593. mOutRef = std::move(out);
  594. return *mOutRef;
  595. }
  596. std::istream& addInputStream(const std::string& name, Istream&& in) override {
  597. auto it = mInFiles.emplace(mInFiles.end(), name, std::move(in));
  598. return it->stream();
  599. }
  600. std::istream& setCheckInputStream(Istream&& in) override {
  601. mCheckFile = std::move(in);
  602. return *mCheckFile;
  603. }
  604. bool hasKernelVersion(const KernelVersion& kernelVer) const override {
  605. return mKernels.find(kernelVer) != mKernels.end();
  606. }
  607. std::istream& addKernelConfigInputStream(const KernelVersion& kernelVer,
  608. const std::string& name, Istream&& in) override {
  609. auto&& kernel = mKernels[kernelVer];
  610. auto it = kernel.emplace(kernel.end(), name, std::move(in));
  611. return it->stream();
  612. }
  613. void resetInFiles() {
  614. for (auto& inFile : mInFiles) {
  615. inFile.stream().clear();
  616. inFile.stream().seekg(0);
  617. }
  618. }
  619. void setOutputMatrix() override { mOutputMatrix = true; }
  620. bool setHalsOnly() override {
  621. if (mHasSetHalsOnlyFlag) {
  622. std::cerr << "Error: Cannot set --hals-only with --no-hals." << std::endl;
  623. return false;
  624. }
  625. // Just override it with HALS_ONLY because other flags that modify mSerializeFlags
  626. // does not interfere with this (except --no-hals).
  627. mSerializeFlags = SerializeFlags::HALS_ONLY;
  628. mHasSetHalsOnlyFlag = true;
  629. return true;
  630. }
  631. bool setNoHals() override {
  632. if (mHasSetHalsOnlyFlag) {
  633. std::cerr << "Error: Cannot set --hals-only with --no-hals." << std::endl;
  634. return false;
  635. }
  636. mSerializeFlags = mSerializeFlags.disableHals();
  637. mHasSetHalsOnlyFlag = true;
  638. return true;
  639. }
  640. bool setNoKernelRequirements() override {
  641. mSerializeFlags = mSerializeFlags.disableKernelConfigs().disableKernelMinorRevision();
  642. return true;
  643. }
  644. private:
  645. std::vector<NamedIstream> mInFiles;
  646. Ostream mOutRef;
  647. Istream mCheckFile;
  648. bool mOutputMatrix = false;
  649. bool mHasSetHalsOnlyFlag = false;
  650. SerializeFlags::Type mSerializeFlags = SerializeFlags::EVERYTHING;
  651. std::map<KernelVersion, std::vector<NamedIstream>> mKernels;
  652. std::map<std::string, std::string> mFakeEnv;
  653. };
  654. bool AssembleVintf::openOutFile(const std::string& path) {
  655. return static_cast<std::ofstream&>(setOutputStream(std::make_unique<std::ofstream>(path)))
  656. .is_open();
  657. }
  658. bool AssembleVintf::openInFile(const std::string& path) {
  659. return static_cast<std::ifstream&>(addInputStream(path, std::make_unique<std::ifstream>(path)))
  660. .is_open();
  661. }
  662. bool AssembleVintf::openCheckFile(const std::string& path) {
  663. return static_cast<std::ifstream&>(setCheckInputStream(std::make_unique<std::ifstream>(path)))
  664. .is_open();
  665. }
  666. bool AssembleVintf::addKernel(const std::string& kernelArg) {
  667. auto tokens = base::Split(kernelArg, ":");
  668. if (tokens.size() <= 1) {
  669. std::cerr << "Unrecognized --kernel option '" << kernelArg << "'" << std::endl;
  670. return false;
  671. }
  672. KernelVersion kernelVer;
  673. if (!parse(tokens.front(), &kernelVer)) {
  674. std::cerr << "Unrecognized kernel version '" << tokens.front() << "'" << std::endl;
  675. return false;
  676. }
  677. if (hasKernelVersion(kernelVer)) {
  678. std::cerr << "Multiple --kernel for " << kernelVer << " is specified." << std::endl;
  679. return false;
  680. }
  681. for (auto it = tokens.begin() + 1; it != tokens.end(); ++it) {
  682. bool opened =
  683. static_cast<std::ifstream&>(
  684. addKernelConfigInputStream(kernelVer, *it, std::make_unique<std::ifstream>(*it)))
  685. .is_open();
  686. if (!opened) {
  687. std::cerr << "Cannot open file '" << *it << "'." << std::endl;
  688. return false;
  689. }
  690. }
  691. return true;
  692. }
  693. std::unique_ptr<AssembleVintf> AssembleVintf::newInstance() {
  694. return std::make_unique<AssembleVintfImpl>();
  695. }
  696. } // namespace vintf
  697. } // namespace android