AssembleVintf.cpp revision bfb3c1dc59144dd784d1d81af3ce81c97ea2e45a
14d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong/* 24d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong * Copyright (C) 2017 The Android Open Source Project 34d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong * 44d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong * Licensed under the Apache License, Version 2.0 (the "License"); 54d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong * you may not use this file except in compliance with the License. 64d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong * You may obtain a copy of the License at 74d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong * 84d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong * http://www.apache.org/licenses/LICENSE-2.0 94d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong * 104d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong * Unless required by applicable law or agreed to in writing, software 114d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong * distributed under the License is distributed on an "AS IS" BASIS, 124d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong * See the License for the specific language governing permissions and 144d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong * limitations under the License. 154d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong */ 164d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 179aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong#include <getopt.h> 184d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong#include <stdlib.h> 194d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong#include <unistd.h> 204d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 214d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong#include <fstream> 224d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong#include <iostream> 234d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong#include <unordered_map> 244d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong#include <sstream> 254d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong#include <string> 264d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 274d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong#include <vintf/parse_string.h> 284d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong#include <vintf/parse_xml.h> 294d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 304d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hongnamespace android { 314d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hongnamespace vintf { 324d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 334d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong/** 344d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong * Slurps the device manifest file and add build time flag to it. 354d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong */ 364d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hongclass AssembleVintf { 374d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hongpublic: 384d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong template<typename T> 394d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong static bool getFlag(const std::string& key, T* value) { 404d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong const char *envValue = getenv(key.c_str()); 414d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong if (envValue == NULL) { 424d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong std::cerr << "Required " << key << " flag." << std::endl; 434d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong return false; 444d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } 454d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 464d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong if (!parse(envValue, value)) { 474d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong std::cerr << "Cannot parse " << envValue << "." << std::endl; 484d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong return false; 494d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } 504d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong return true; 514d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } 524d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 534650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong static std::string read(std::basic_istream<char>& is) { 544650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong std::stringstream ss; 554650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong ss << is.rdbuf(); 564650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong return ss.str(); 574650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong } 584650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong 599aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong std::basic_ostream<char>& out() const { 609aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return mOutFileRef == nullptr ? std::cout : *mOutFileRef; 619aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 629aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 639aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong bool assembleHalManifest(HalManifest* halManifest) { 644650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong std::string error; 654d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 669aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (halManifest->mType == SchemaType::DEVICE) { 679aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (!getFlag("BOARD_SEPOLICY_VERS", &halManifest->device.mSepolicyVersion)) { 689aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return false; 694d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } 709aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 714d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 729aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (mOutputMatrix) { 739aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong CompatibilityMatrix generatedMatrix = halManifest->generateCompatibleMatrix(); 749aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (!halManifest->checkCompatibility(generatedMatrix, &error)) { 759aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong std::cerr << "FATAL ERROR: cannot generate a compatible matrix: " << error 769aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong << std::endl; 77a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong } 789aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong out() << "<!-- \n" 799aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " Autogenerated skeleton compatibility matrix. \n" 809aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " Use with caution. Modify it to suit your needs.\n" 819aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " All HALs are set to optional.\n" 829aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " Many entries other than HALs are zero-filled and\n" 839aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " require human attention. \n" 849aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong "-->\n" 859aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong << gCompatibilityMatrixConverter(generatedMatrix); 869aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } else { 879aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong out() << gHalManifestConverter(*halManifest); 889aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 899aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong out().flush(); 909aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 919aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (mCheckFile.is_open()) { 929aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong CompatibilityMatrix checkMatrix; 939aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (!gCompatibilityMatrixConverter(&checkMatrix, read(mCheckFile))) { 949aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong std::cerr << "Cannot parse check file as a compatibility matrix: " 959aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong << gCompatibilityMatrixConverter.lastError() << std::endl; 969aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return false; 974650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong } 989aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (!halManifest->checkCompatibility(checkMatrix, &error)) { 999aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong std::cerr << "Not compatible: " << error << std::endl; 1009aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return false; 1019aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 1029aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 1034650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong 1049aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return true; 1059aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 1069aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 1079aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong bool assembleCompatibilityMatrix(CompatibilityMatrix* matrix) { 1089aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong std::string error; 1099aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 1109aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong KernelSepolicyVersion kernelSepolicyVers; 1119aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong Version sepolicyVers; 1129aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (matrix->mType == SchemaType::FRAMEWORK) { 1139aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (!getFlag("BOARD_SEPOLICY_VERS", &sepolicyVers)) { 1149aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return false; 1159aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 1169aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (!getFlag("POLICYVERS", &kernelSepolicyVers)) { 1179aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return false; 1189aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 1199aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong matrix->framework.mSepolicy = 1209aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong Sepolicy(kernelSepolicyVers, {{sepolicyVers.majorVer, sepolicyVers.minorVer}}); 121a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong } 1229aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong out() << gCompatibilityMatrixConverter(*matrix); 1239aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong out().flush(); 124a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong 1259aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (mCheckFile.is_open()) { 1269aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong HalManifest checkManifest; 1279aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (!gHalManifestConverter(&checkManifest, read(mCheckFile))) { 1289aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong std::cerr << "Cannot parse check file as a HAL manifest: " 1299aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong << gHalManifestConverter.lastError() << std::endl; 1309aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return false; 1311e5a054a0c3790364428dbfbe8625836a3087776Yifan Hong } 1329aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (!checkManifest.checkCompatibility(*matrix, &error)) { 1339aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong std::cerr << "Not compatible: " << error << std::endl; 1349aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return false; 1359aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 1369aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 1379aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 1389aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return true; 1399aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 1409aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 141bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong enum AssembleStatus { SUCCESS, FAIL_AND_EXIT, TRY_NEXT }; 142bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong template <typename Schema, typename AssembleFunc> 143bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong AssembleStatus tryAssemble(const XmlConverter<Schema>& converter, const std::string& schemaName, 144bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong AssembleFunc assemble) { 145bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong Schema schema; 146bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong if (!converter(&schema, read(mInFiles.front()))) { 147bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong return TRY_NEXT; 148bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong } 149bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong auto firstType = schema.type(); 150bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong for (auto it = mInFiles.begin() + 1; it != mInFiles.end(); ++it) { 151bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong Schema additionalSchema; 152bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong if (!converter(&additionalSchema, read(*it))) { 153bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong std::cerr << "File \"" << mInFilePaths[std::distance(mInFiles.begin(), it)] 154bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong << "\" is not a valid " << firstType << " " << schemaName 155bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong << " (but the first file is a valid " << firstType << " " << schemaName 156bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong << "). Error: " << converter.lastError() << std::endl; 157bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong return FAIL_AND_EXIT; 158bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong } 159bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong if (additionalSchema.type() != firstType) { 160bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong std::cerr << "File \"" << mInFilePaths[std::distance(mInFiles.begin(), it)] 161bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong << "\" is a " << additionalSchema.type() << " " << schemaName 162bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong << " (but a " << firstType << " " << schemaName << " is expected)." 163bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong << std::endl; 164bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong return FAIL_AND_EXIT; 165bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong } 166bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong schema.addAll(std::move(additionalSchema)); 167bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong } 168bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong return assemble(&schema) ? SUCCESS : FAIL_AND_EXIT; 169bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong } 170bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong 1719aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong bool assemble() { 172bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong using std::placeholders::_1; 173bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong if (mInFiles.empty()) { 1749aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong std::cerr << "Missing input file." << std::endl; 1759aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return false; 1769aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 1779aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 178bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong auto status = tryAssemble(gHalManifestConverter, "manifest", 179bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong std::bind(&AssembleVintf::assembleHalManifest, this, _1)); 180bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong if (status == SUCCESS) return true; 181bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong if (status == FAIL_AND_EXIT) return false; 1829aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 183bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong resetInFiles(); 1844650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong 185bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong status = tryAssemble(gCompatibilityMatrixConverter, "compatibility matrix", 186bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong std::bind(&AssembleVintf::assembleCompatibilityMatrix, this, _1)); 187bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong if (status == SUCCESS) return true; 188bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong if (status == FAIL_AND_EXIT) return false; 1894d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 190959ee1bf8b922980542f72ce9ad1929fc7d8b55cYifan Hong std::cerr << "Input file has unknown format." << std::endl 191959ee1bf8b922980542f72ce9ad1929fc7d8b55cYifan Hong << "Error when attempting to convert to manifest: " 192959ee1bf8b922980542f72ce9ad1929fc7d8b55cYifan Hong << gHalManifestConverter.lastError() << std::endl 193959ee1bf8b922980542f72ce9ad1929fc7d8b55cYifan Hong << "Error when attempting to convert to compatibility matrix: " 194959ee1bf8b922980542f72ce9ad1929fc7d8b55cYifan Hong << gCompatibilityMatrixConverter.lastError() << std::endl; 195959ee1bf8b922980542f72ce9ad1929fc7d8b55cYifan Hong return false; 1964d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } 1979aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 1989aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong bool openOutFile(const char* path) { 1999aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong mOutFileRef = std::make_unique<std::ofstream>(); 2009aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong mOutFileRef->open(path); 2019aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return mOutFileRef->is_open(); 2029aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 2039aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 2049aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong bool openInFile(const char* path) { 205bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong mInFilePaths.push_back(path); 206bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong mInFiles.push_back({}); 207bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong mInFiles.back().open(path); 208bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong return mInFiles.back().is_open(); 2099aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 2109aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 2119aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong bool openCheckFile(const char* path) { 2129aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong mCheckFile.open(path); 2139aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return mCheckFile.is_open(); 2149aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 2159aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 216bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong void resetInFiles() { 217bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong for (auto& inFile : mInFiles) { 218bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong inFile.clear(); 219bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong inFile.seekg(0); 220bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong } 221bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong } 222bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong 2239aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong void setOutputMatrix() { mOutputMatrix = true; } 2249aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 2259aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong private: 226bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong std::vector<std::string> mInFilePaths; 227bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong std::vector<std::ifstream> mInFiles; 2289aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong std::unique_ptr<std::ofstream> mOutFileRef; 2299aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong std::ifstream mCheckFile; 2309aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong bool mOutputMatrix = false; 2314d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong}; 2324d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 2334d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong} // namespace vintf 2344d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong} // namespace android 2354d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 2364d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hongvoid help() { 2379aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong std::cerr << "assemble_vintf: Checks if a given manifest / matrix file is valid and \n" 2389aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " fill in build-time flags into the given file.\n" 2399aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong "assemble_vintf -h\n" 2409aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " Display this help text.\n" 241bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong "assemble_vintf -i <input file>[:<input file>[...]] [-o <output file>] [-m]\n" 242bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong " [-c [<check file>]]\n" 2439aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " Fill in build-time flags into the given file.\n" 244bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong " -i <input file>[:<input file>[...]]\n" 245bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong " A list of input files. Format is automatically detected for the\n" 246bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong " first file, and the remaining files must have the same format.\n" 247bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong " Files other than the first file should only have <hal> defined;\n" 248bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong " other entries are ignored.\n" 2499aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " -o <output file>\n" 2509aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " Optional output file. If not specified, write to stdout.\n" 2519aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " -m\n" 2529aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " a compatible compatibility matrix is\n" 2539aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " generated instead; for example, given a device manifest,\n" 2549aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " a framework compatibility matrix is generated. This flag\n" 2559aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " is ignored when input is a compatibility matrix.\n" 2569aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " -c [<check file>]\n" 2579aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " After writing the output file, check compatibility between\n" 2589aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " output file and check file.\n" 2599aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " If -c is set but the check file is not specified, a warning\n" 2609aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " message is written to stderr. Return 0.\n" 2619aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " If the check file is specified but is not compatible, an error\n" 2629aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " message is written to stderr. Return 1.\n"; 2634d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong} 2644d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 2654d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hongint main(int argc, char **argv) { 2669aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong const struct option longopts[] = {{0, 0, 0, 0}}; 2679aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 268bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong std::string outFilePath; 2699aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong ::android::vintf::AssembleVintf assembleVintf; 2704d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong int res; 2719aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong int optind; 2729aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong while ((res = getopt_long(argc, argv, "hi:o:mc:", longopts, &optind)) >= 0) { 2734d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong switch (res) { 2744d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong case 'i': { 275bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong char* inFilePath = strtok(optarg, ":"); 276bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong while (inFilePath != NULL) { 277bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong if (!assembleVintf.openInFile(inFilePath)) { 278bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong std::cerr << "Failed to open " << optarg << std::endl; 279bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong return 1; 280bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong } 281bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong inFilePath = strtok(NULL, ":"); 2824d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } 2834d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } break; 2844d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 2854d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong case 'o': { 286bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong outFilePath = optarg; 2879aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (!assembleVintf.openOutFile(optarg)) { 2884d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong std::cerr << "Failed to open " << optarg << std::endl; 2894d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong return 1; 2904d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } 2914d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } break; 2924d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 293a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong case 'm': { 2949aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong assembleVintf.setOutputMatrix(); 295a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong } break; 296a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong 2974650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong case 'c': { 2984650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong if (strlen(optarg) != 0) { 2999aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (!assembleVintf.openCheckFile(optarg)) { 3004650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong std::cerr << "Failed to open " << optarg << std::endl; 3014650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong return 1; 3024650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong } 3034650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong } else { 3044650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong std::cerr << "WARNING: no compatibility check is done on " 305bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong << (outFilePath.empty() ? "output" : outFilePath) << std::endl; 3064650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong } 3074650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong } break; 3084650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong 3094d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong case 'h': 3104d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong default: { 3114d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong help(); 3124d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong return 1; 3134d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } break; 3144d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } 3154d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } 3164d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 3179aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong bool success = assembleVintf.assemble(); 3184650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong 3194650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong return success ? 0 : 1; 3204d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong} 3214d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 322