AssembleVintf.cpp revision ea25dd45961fc0b23ae9ba602c6d090590aa8241
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 279a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong#include <android-base/file.h> 28dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong#include <android-base/parseint.h> 299a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong 3079efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong#include <vintf/KernelConfigParser.h> 314d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong#include <vintf/parse_string.h> 324d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong#include <vintf/parse_xml.h> 334d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 3479efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong#define BUFFER_SIZE sysconf(_SC_PAGESIZE) 3579efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong 364d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hongnamespace android { 374d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hongnamespace vintf { 384d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 399a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hongstatic const std::string gConfigPrefix = "android-base-"; 409a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hongstatic const std::string gConfigSuffix = ".cfg"; 419a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hongstatic const std::string gBaseConfig = "android-base.cfg"; 429a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong 434d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong/** 444d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong * Slurps the device manifest file and add build time flag to it. 454d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong */ 464d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hongclass AssembleVintf { 479a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong using Condition = std::unique_ptr<KernelConfig>; 489a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong using ConditionedConfig = std::pair<Condition, std::vector<KernelConfig> /* configs */>; 499a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong 509a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong public: 514d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong template<typename T> 524d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong static bool getFlag(const std::string& key, T* value) { 534d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong const char *envValue = getenv(key.c_str()); 544d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong if (envValue == NULL) { 55488e16a67311194f0fb9aa4a33219af170e6316bYifan Hong std::cerr << "Warning: " << key << " is missing, defaulted to " << (*value) 56488e16a67311194f0fb9aa4a33219af170e6316bYifan Hong << std::endl; 57488e16a67311194f0fb9aa4a33219af170e6316bYifan Hong return true; 584d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } 594d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 604d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong if (!parse(envValue, value)) { 614d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong std::cerr << "Cannot parse " << envValue << "." << std::endl; 624d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong return false; 634d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } 644d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong return true; 654d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } 664d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 67dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong static bool getBooleanFlag(const char* key) { 68dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong const char* envValue = getenv(key); 69dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return envValue != nullptr && strcmp(envValue, "true") == 0; 70dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 71dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong 72dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong static size_t getIntegerFlag(const char* key, size_t defaultValue = 0) { 73dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong std::string envValue = getenv(key); 74dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (envValue.empty()) { 75dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return defaultValue; 76dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 77dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong size_t value; 78dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (!base::ParseUint(envValue, &value)) { 79dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong std::cerr << "Error: " << key << " must be a number." << std::endl; 80dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return defaultValue; 81dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 82dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return value; 83dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 84dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong 854650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong static std::string read(std::basic_istream<char>& is) { 864650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong std::stringstream ss; 874650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong ss << is.rdbuf(); 884650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong return ss.str(); 894650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong } 904650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong 919a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong static bool isCommonConfig(const std::string& path) { 929a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong return ::android::base::Basename(path) == gBaseConfig; 939a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong } 949a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong 95dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong static Level convertFromApiLevel(size_t apiLevel) { 96dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (apiLevel < 26) { 97dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return Level::LEGACY; 98dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } else if (apiLevel == 26) { 99dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return Level::O; 100dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } else if (apiLevel == 27) { 101dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return Level::O_MR1; 102dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } else { 103dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return Level::UNSPECIFIED; 104dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 105dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 106dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong 107079ec2492c275b9041584f2f07605982682c559cYifan Hong // nullptr on any error, otherwise the condition. 108079ec2492c275b9041584f2f07605982682c559cYifan Hong static Condition generateCondition(const std::string& path) { 109079ec2492c275b9041584f2f07605982682c559cYifan Hong std::string fname = ::android::base::Basename(path); 110079ec2492c275b9041584f2f07605982682c559cYifan Hong if (fname.size() <= gConfigPrefix.size() + gConfigSuffix.size() || 111079ec2492c275b9041584f2f07605982682c559cYifan Hong !std::equal(gConfigPrefix.begin(), gConfigPrefix.end(), fname.begin()) || 112079ec2492c275b9041584f2f07605982682c559cYifan Hong !std::equal(gConfigSuffix.rbegin(), gConfigSuffix.rend(), fname.rbegin())) { 113079ec2492c275b9041584f2f07605982682c559cYifan Hong return nullptr; 114079ec2492c275b9041584f2f07605982682c559cYifan Hong } 115079ec2492c275b9041584f2f07605982682c559cYifan Hong 116079ec2492c275b9041584f2f07605982682c559cYifan Hong std::string sub = fname.substr(gConfigPrefix.size(), 117079ec2492c275b9041584f2f07605982682c559cYifan Hong fname.size() - gConfigPrefix.size() - gConfigSuffix.size()); 118079ec2492c275b9041584f2f07605982682c559cYifan Hong if (sub.empty()) { 119079ec2492c275b9041584f2f07605982682c559cYifan Hong return nullptr; // should not happen 120079ec2492c275b9041584f2f07605982682c559cYifan Hong } 121079ec2492c275b9041584f2f07605982682c559cYifan Hong for (size_t i = 0; i < sub.size(); ++i) { 122079ec2492c275b9041584f2f07605982682c559cYifan Hong if (sub[i] == '-') { 123079ec2492c275b9041584f2f07605982682c559cYifan Hong sub[i] = '_'; 124079ec2492c275b9041584f2f07605982682c559cYifan Hong continue; 125079ec2492c275b9041584f2f07605982682c559cYifan Hong } 126079ec2492c275b9041584f2f07605982682c559cYifan Hong if (isalnum(sub[i])) { 127079ec2492c275b9041584f2f07605982682c559cYifan Hong sub[i] = toupper(sub[i]); 128079ec2492c275b9041584f2f07605982682c559cYifan Hong continue; 129079ec2492c275b9041584f2f07605982682c559cYifan Hong } 130079ec2492c275b9041584f2f07605982682c559cYifan Hong std::cerr << "'" << fname << "' (in " << path 131079ec2492c275b9041584f2f07605982682c559cYifan Hong << ") is not a valid kernel config file name. Must match regex: " 132079ec2492c275b9041584f2f07605982682c559cYifan Hong << "android-base(-[0-9a-zA-Z-]+)?\\.cfg" << std::endl; 133079ec2492c275b9041584f2f07605982682c559cYifan Hong return nullptr; 134079ec2492c275b9041584f2f07605982682c559cYifan Hong } 135079ec2492c275b9041584f2f07605982682c559cYifan Hong sub.insert(0, "CONFIG_"); 136079ec2492c275b9041584f2f07605982682c559cYifan Hong return std::make_unique<KernelConfig>(std::move(sub), Tristate::YES); 137079ec2492c275b9041584f2f07605982682c559cYifan Hong } 138079ec2492c275b9041584f2f07605982682c559cYifan Hong 13979efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong static bool parseFileForKernelConfigs(const std::string& path, std::vector<KernelConfig>* out) { 14079efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong std::ifstream ifs{path}; 14179efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong if (!ifs.is_open()) { 14279efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong std::cerr << "File '" << path << "' does not exist or cannot be read." << std::endl; 14379efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong return false; 14479efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong } 14502e94004a6d35d20af7df1ea9c66c5b65e4bd9c6Yifan Hong KernelConfigParser parser(true /* processComments */, true /* relaxedFormat */); 14679efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong std::string content = read(ifs); 14779efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong status_t err = parser.process(content.c_str(), content.size()); 14879efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong if (err != OK) { 149ae53a0e6d3f605cc124009cb0172f152f69417a4Yifan Hong std::cerr << parser.error(); 15079efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong return false; 15179efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong } 15279efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong err = parser.finish(); 15379efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong if (err != OK) { 154ae53a0e6d3f605cc124009cb0172f152f69417a4Yifan Hong std::cerr << parser.error(); 15579efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong return false; 15679efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong } 15779efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong 15879efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong for (auto& configPair : parser.configs()) { 15979efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong out->push_back({}); 16079efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong KernelConfig& config = out->back(); 16179efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong config.first = std::move(configPair.first); 16279efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong if (!parseKernelConfigTypedValue(configPair.second, &config.second)) { 16379efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong std::cerr << "Unknown value type for key = '" << config.first << "', value = '" 16479efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong << configPair.second << "'\n"; 16579efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong return false; 16679efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong } 16779efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong } 16879efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong return true; 16979efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong } 17079efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong 1719a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong static bool parseFilesForKernelConfigs(const std::string& path, 1729a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong std::vector<ConditionedConfig>* out) { 1739a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong out->clear(); 1749a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong ConditionedConfig commonConfig; 1759a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong bool foundCommonConfig = false; 1760bef86826065d9cfdad3139ea186a98524cf2eddSteve Muckle bool ret = true; 1770bef86826065d9cfdad3139ea186a98524cf2eddSteve Muckle char *pathIter; 1780bef86826065d9cfdad3139ea186a98524cf2eddSteve Muckle char *modPath = new char[path.length() + 1]; 1790bef86826065d9cfdad3139ea186a98524cf2eddSteve Muckle strcpy(modPath, path.c_str()); 1800bef86826065d9cfdad3139ea186a98524cf2eddSteve Muckle pathIter = strtok(modPath, ":"); 1810bef86826065d9cfdad3139ea186a98524cf2eddSteve Muckle while (ret && pathIter != NULL) { 1829a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong if (isCommonConfig(pathIter)) { 1839a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong ret &= parseFileForKernelConfigs(pathIter, &commonConfig.second); 1849a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong foundCommonConfig = true; 1859a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong } else { 186079ec2492c275b9041584f2f07605982682c559cYifan Hong Condition condition = generateCondition(pathIter); 187079ec2492c275b9041584f2f07605982682c559cYifan Hong ret &= (condition != nullptr); 188079ec2492c275b9041584f2f07605982682c559cYifan Hong 1899a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong std::vector<KernelConfig> kernelConfigs; 1909a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong if ((ret &= parseFileForKernelConfigs(pathIter, &kernelConfigs))) 191079ec2492c275b9041584f2f07605982682c559cYifan Hong out->emplace_back(std::move(condition), std::move(kernelConfigs)); 1929a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong } 1930bef86826065d9cfdad3139ea186a98524cf2eddSteve Muckle pathIter = strtok(NULL, ":"); 1940bef86826065d9cfdad3139ea186a98524cf2eddSteve Muckle } 19582266ae07e00e0b90bc7f13d3ce77ff10291d346Luis A. Lozano delete[] modPath; 1969a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong 1979a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong if (!foundCommonConfig) { 1989a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong std::cerr << "No android-base.cfg is found in these paths: '" << path << "'" 1999a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong << std::endl; 2009a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong } 2019a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong ret &= foundCommonConfig; 2029a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong // first element is always common configs (no conditions). 2039a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong out->insert(out->begin(), std::move(commonConfig)); 2040bef86826065d9cfdad3139ea186a98524cf2eddSteve Muckle return ret; 2050bef86826065d9cfdad3139ea186a98524cf2eddSteve Muckle } 2060bef86826065d9cfdad3139ea186a98524cf2eddSteve Muckle 207dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong static std::string getFileNameFromPath(std::string path) { 208dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong auto idx = path.find_last_of("\\/"); 209dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (idx != std::string::npos) { 210dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong path.erase(0, idx + 1); 211dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 212dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return path; 213dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 214dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong 2159aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong std::basic_ostream<char>& out() const { 2169aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return mOutFileRef == nullptr ? std::cout : *mOutFileRef; 2179aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 2189aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 219dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong template <typename S> 220dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong using Schemas = std::vector<std::pair<std::string, S>>; 221dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong using HalManifests = Schemas<HalManifest>; 222dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong using CompatibilityMatrices = Schemas<CompatibilityMatrix>; 223dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong 224dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong bool assembleHalManifest(HalManifests* halManifests) { 2254650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong std::string error; 226dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong HalManifest* halManifest = &halManifests->front().second; 227dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong for (auto it = halManifests->begin() + 1; it != halManifests->end(); ++it) { 228dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong const std::string& path = it->first; 229dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong HalManifest& halToAdd = it->second; 230dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong 231dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (halToAdd.level() != Level::UNSPECIFIED) { 232dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (halManifest->level() == Level::UNSPECIFIED) { 233dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong halManifest->mLevel = halToAdd.level(); 234dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } else if (halManifest->level() != halToAdd.level()) { 235dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong std::cerr << "Inconsistent FCM Version in HAL manifests:" << std::endl 236dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << " File '" << halManifests->front().first << "' has level " 237dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << halManifest->level() << std::endl 238dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << " File '" << path << "' has level " << halToAdd.level() 239dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << std::endl; 240dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return false; 241dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 242dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 243dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong 244ea25dd45961fc0b23ae9ba602c6d090590aa8241Yifan Hong if (!halManifest->addAllHals(&halToAdd, &error)) { 245dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong std::cerr << "File \"" << path << "\" cannot be added: conflict on HAL \"" << error 246dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << "\" with an existing HAL. See <hal> with the same name " 247dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << "in previously parsed files or previously declared in this file." 248dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << std::endl; 249dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return false; 250dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 251dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 2524d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 2539aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (halManifest->mType == SchemaType::DEVICE) { 2549aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (!getFlag("BOARD_SEPOLICY_VERS", &halManifest->device.mSepolicyVersion)) { 2559aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return false; 2564d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } 257dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (!setDeviceFcmVersion(halManifest)) { 258dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return false; 259dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 2609aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 2614d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 2629aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (mOutputMatrix) { 2639aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong CompatibilityMatrix generatedMatrix = halManifest->generateCompatibleMatrix(); 2649aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (!halManifest->checkCompatibility(generatedMatrix, &error)) { 2659aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong std::cerr << "FATAL ERROR: cannot generate a compatible matrix: " << error 2669aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong << std::endl; 267a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong } 2689aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong out() << "<!-- \n" 2699aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " Autogenerated skeleton compatibility matrix. \n" 2709aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " Use with caution. Modify it to suit your needs.\n" 2719aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " All HALs are set to optional.\n" 2729aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " Many entries other than HALs are zero-filled and\n" 2739aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " require human attention. \n" 2749aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong "-->\n" 275a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong << gCompatibilityMatrixConverter(generatedMatrix, mSerializeFlags); 2769aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } else { 277a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong out() << gHalManifestConverter(*halManifest, mSerializeFlags); 2789aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 2799aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong out().flush(); 2809aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 2819aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (mCheckFile.is_open()) { 2829aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong CompatibilityMatrix checkMatrix; 2839aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (!gCompatibilityMatrixConverter(&checkMatrix, read(mCheckFile))) { 2849aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong std::cerr << "Cannot parse check file as a compatibility matrix: " 2859aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong << gCompatibilityMatrixConverter.lastError() << std::endl; 2869aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return false; 2874650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong } 2889aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (!halManifest->checkCompatibility(checkMatrix, &error)) { 2899aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong std::cerr << "Not compatible: " << error << std::endl; 2909aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return false; 2919aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 2929aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 2934650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong 2949aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return true; 2959aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 2969aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 297e88e16721117aaf97548bebbffd6c8ea81b681efYifan Hong bool assembleFrameworkCompatibilityMatrixKernels(CompatibilityMatrix* matrix) { 2984c34fee9175766bf69b53c4d75ea251ef976185bYifan Hong if (!matrix->framework.mKernels.empty()) { 2994c34fee9175766bf69b53c4d75ea251ef976185bYifan Hong // Remove hard-coded <kernel version="x.y.z" /> in legacy files. 3004c34fee9175766bf69b53c4d75ea251ef976185bYifan Hong std::cerr << "WARNING: framework compatibility matrix has hard-coded kernel" 3014c34fee9175766bf69b53c4d75ea251ef976185bYifan Hong << " requirements for version"; 3024c34fee9175766bf69b53c4d75ea251ef976185bYifan Hong for (const auto& kernel : matrix->framework.mKernels) { 3034c34fee9175766bf69b53c4d75ea251ef976185bYifan Hong std::cerr << " " << kernel.minLts(); 3044c34fee9175766bf69b53c4d75ea251ef976185bYifan Hong } 3054c34fee9175766bf69b53c4d75ea251ef976185bYifan Hong std::cerr << ". Hard-coded requirements are removed." << std::endl; 3064c34fee9175766bf69b53c4d75ea251ef976185bYifan Hong matrix->framework.mKernels.clear(); 3074c34fee9175766bf69b53c4d75ea251ef976185bYifan Hong } 308e88e16721117aaf97548bebbffd6c8ea81b681efYifan Hong for (const auto& pair : mKernels) { 3099a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong std::vector<ConditionedConfig> conditionedConfigs; 3109a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong if (!parseFilesForKernelConfigs(pair.second, &conditionedConfigs)) { 311e88e16721117aaf97548bebbffd6c8ea81b681efYifan Hong return false; 312e88e16721117aaf97548bebbffd6c8ea81b681efYifan Hong } 3139a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong for (ConditionedConfig& conditionedConfig : conditionedConfigs) { 31448602dfa0ef4a40b58c6376bab82c6e46d6f6a0bYifan Hong MatrixKernel kernel(KernelVersion{pair.first.majorVer, pair.first.minorVer, 0u}, 31548602dfa0ef4a40b58c6376bab82c6e46d6f6a0bYifan Hong std::move(conditionedConfig.second)); 316079ec2492c275b9041584f2f07605982682c559cYifan Hong if (conditionedConfig.first != nullptr) 317079ec2492c275b9041584f2f07605982682c559cYifan Hong kernel.mConditions.push_back(std::move(*conditionedConfig.first)); 318079ec2492c275b9041584f2f07605982682c559cYifan Hong matrix->framework.mKernels.push_back(std::move(kernel)); 3199a8b1a7cec9f39953001a2f113cb976ae73eb211Yifan Hong } 320e88e16721117aaf97548bebbffd6c8ea81b681efYifan Hong } 321e88e16721117aaf97548bebbffd6c8ea81b681efYifan Hong return true; 322e88e16721117aaf97548bebbffd6c8ea81b681efYifan Hong } 323e88e16721117aaf97548bebbffd6c8ea81b681efYifan Hong 324dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong bool setDeviceFcmVersion(HalManifest* manifest) { 325dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong size_t shippingApiLevel = getIntegerFlag("PRODUCT_SHIPPING_API_LEVEL"); 326dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong 327dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (manifest->level() != Level::UNSPECIFIED) { 328dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return true; 329dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 330dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (!getBooleanFlag("PRODUCT_ENFORCE_VINTF_MANIFEST")) { 331dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong manifest->mLevel = Level::LEGACY; 332dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return true; 333dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 334dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong // TODO(b/70628538): Do not infer from Shipping API level. 335dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (shippingApiLevel) { 336dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong std::cerr << "Warning: Shipping FCM Version is inferred from Shipping API level. " 337dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << "Declare Shipping FCM Version in device manifest directly." << std::endl; 338dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong manifest->mLevel = convertFromApiLevel(shippingApiLevel); 339dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (manifest->mLevel == Level::UNSPECIFIED) { 340dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong std::cerr << "Error: Shipping FCM Version cannot be inferred from Shipping API " 341dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << "level " << shippingApiLevel << "." 342dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << "Declare Shipping FCM Version in device manifest directly." 343dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << std::endl; 344dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return false; 345dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 346dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return true; 347dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 348dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong // TODO(b/69638851): should be an error if Shipping API level is not defined. 349dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong // For now, just leave it empty; when framework compatibility matrix is built, 350dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong // lowest FCM Version is assumed. 351dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong std::cerr << "Warning: Shipping FCM Version cannot be inferred, because:" << std::endl 352dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << " (1) It is not explicitly declared in device manifest;" << std::endl 353dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << " (2) PRODUCT_ENFORCE_VINTF_MANIFEST is set to true;" << std::endl 354dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << " (3) PRODUCT_SHIPPING_API_LEVEL is undefined." << std::endl 355dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << "Assuming 'unspecified' Shipping FCM Version. " << std::endl 356dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << "To remove this warning, define 'level' attribute in device manifest." 357dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << std::endl; 358dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return true; 359dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 3609aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 361dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong Level getLowestFcmVersion(const CompatibilityMatrices& matrices) { 362dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong Level ret = Level::UNSPECIFIED; 363dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong for (const auto& e : matrices) { 364dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (ret == Level::UNSPECIFIED || ret > e.second.level()) { 365dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong ret = e.second.level(); 366dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 367dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 368dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return ret; 369dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 370dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong 371dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong bool assembleCompatibilityMatrix(CompatibilityMatrices* matrices) { 372dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong std::string error; 373dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong CompatibilityMatrix* matrix = nullptr; 3749aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong KernelSepolicyVersion kernelSepolicyVers; 3759aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong Version sepolicyVers; 376dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong std::unique_ptr<HalManifest> checkManifest; 377dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (matrices->front().second.mType == SchemaType::DEVICE) { 378dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong matrix = &matrices->front().second; 379dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 380dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong 381dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (matrices->front().second.mType == SchemaType::FRAMEWORK) { 382dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong Level deviceLevel = Level::UNSPECIFIED; 383dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong std::vector<std::string> fileList; 384dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (mCheckFile.is_open()) { 385dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong checkManifest = std::make_unique<HalManifest>(); 386dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (!gHalManifestConverter(checkManifest.get(), read(mCheckFile))) { 387dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong std::cerr << "Cannot parse check file as a HAL manifest: " 388dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << gHalManifestConverter.lastError() << std::endl; 389dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return false; 390dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 391dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong deviceLevel = checkManifest->level(); 392dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 393dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong 394dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (deviceLevel == Level::UNSPECIFIED) { 395dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong // For GSI build, legacy devices that do not have a HAL manifest, 396dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong // and devices in development, merge all compatibility matrices. 397dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong deviceLevel = getLowestFcmVersion(*matrices); 398dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 399dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong 400dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong for (auto& e : *matrices) { 401dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (e.second.level() == deviceLevel) { 402dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong fileList.push_back(e.first); 403dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong matrix = &e.second; 404dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 405dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 406dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (matrix == nullptr) { 407dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong std::cerr << "FATAL ERROR: cannot find matrix with level '" << deviceLevel << "'" 408dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << std::endl; 409dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return false; 410dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 411dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong for (auto& e : *matrices) { 412dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (e.second.level() <= deviceLevel) { 413dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong continue; 414dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 415dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong fileList.push_back(e.first); 416dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (!matrix->addAllHalsAsOptional(&e.second, &error)) { 417dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong std::cerr << "File \"" << e.first << "\" cannot be added: " << error 418dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << ". See <hal> with the same name " 419dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << "in previously parsed files or previously declared in this file." 420dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << std::endl; 421dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return false; 422dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 423dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 424dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong 4259aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (!getFlag("BOARD_SEPOLICY_VERS", &sepolicyVers)) { 4269aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return false; 4279aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 4289aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (!getFlag("POLICYVERS", &kernelSepolicyVers)) { 4299aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return false; 4309aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 431e88e16721117aaf97548bebbffd6c8ea81b681efYifan Hong 432e88e16721117aaf97548bebbffd6c8ea81b681efYifan Hong if (!assembleFrameworkCompatibilityMatrixKernels(matrix)) { 433e88e16721117aaf97548bebbffd6c8ea81b681efYifan Hong return false; 43479efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong } 435e88e16721117aaf97548bebbffd6c8ea81b681efYifan Hong 4369aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong matrix->framework.mSepolicy = 4379aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong Sepolicy(kernelSepolicyVers, {{sepolicyVers.majorVer, sepolicyVers.minorVer}}); 4387f6c00c77c755f4efef49e5371058470a461193fYifan Hong 4397f6c00c77c755f4efef49e5371058470a461193fYifan Hong Version avbMetaVersion; 4407f6c00c77c755f4efef49e5371058470a461193fYifan Hong if (!getFlag("FRAMEWORK_VBMETA_VERSION", &avbMetaVersion)) { 4417f6c00c77c755f4efef49e5371058470a461193fYifan Hong return false; 4427f6c00c77c755f4efef49e5371058470a461193fYifan Hong } 4437f6c00c77c755f4efef49e5371058470a461193fYifan Hong matrix->framework.mAvbMetaVersion = avbMetaVersion; 444dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong 445dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong out() << "<!--" << std::endl; 446dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong out() << " Input:" << std::endl; 447dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong for (const auto& path : fileList) { 448dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong out() << " " << getFileNameFromPath(path) << std::endl; 449dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong } 450dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong out() << "-->" << std::endl; 451a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong } 452a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong out() << gCompatibilityMatrixConverter(*matrix, mSerializeFlags); 4539aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong out().flush(); 454a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong 455dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong if (checkManifest != nullptr && getBooleanFlag("PRODUCT_ENFORCE_VINTF_MANIFEST") && 456dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong !checkManifest->checkCompatibility(*matrix, &error)) { 457dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong std::cerr << "Not compatible: " << error << std::endl; 458dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return false; 4599aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 4609aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 4619aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return true; 4629aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 4639aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 464bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong enum AssembleStatus { SUCCESS, FAIL_AND_EXIT, TRY_NEXT }; 465bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong template <typename Schema, typename AssembleFunc> 466bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong AssembleStatus tryAssemble(const XmlConverter<Schema>& converter, const std::string& schemaName, 467bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong AssembleFunc assemble) { 468dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong Schemas<Schema> schemas; 469bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong Schema schema; 470bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong if (!converter(&schema, read(mInFiles.front()))) { 471bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong return TRY_NEXT; 472bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong } 473bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong auto firstType = schema.type(); 474dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong schemas.emplace_back(mInFilePaths.front(), std::move(schema)); 475dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong 476bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong for (auto it = mInFiles.begin() + 1; it != mInFiles.end(); ++it) { 477bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong Schema additionalSchema; 478dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong const std::string fileName = mInFilePaths[std::distance(mInFiles.begin(), it)]; 479bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong if (!converter(&additionalSchema, read(*it))) { 480dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong std::cerr << "File \"" << fileName << "\" is not a valid " << firstType << " " 481dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << schemaName << " (but the first file is a valid " << firstType << " " 482dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << schemaName << "). Error: " << converter.lastError() << std::endl; 483bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong return FAIL_AND_EXIT; 484bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong } 485bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong if (additionalSchema.type() != firstType) { 486dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong std::cerr << "File \"" << fileName << "\" is a " << additionalSchema.type() << " " 487dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << schemaName << " (but a " << firstType << " " << schemaName 488dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong << " is expected)." << std::endl; 489eb14e3013ea11b3d47d40fa860f16345c607fef6Yifan Hong return FAIL_AND_EXIT; 490eb14e3013ea11b3d47d40fa860f16345c607fef6Yifan Hong } 491dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong 492dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong schemas.emplace_back(fileName, std::move(additionalSchema)); 493bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong } 494dbe9db35fe506f6547d33b44ec5e20b70bf343c2Yifan Hong return assemble(&schemas) ? SUCCESS : FAIL_AND_EXIT; 495bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong } 496bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong 4979aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong bool assemble() { 498bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong using std::placeholders::_1; 499bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong if (mInFiles.empty()) { 5009aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong std::cerr << "Missing input file." << std::endl; 5019aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return false; 5029aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 5039aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 504bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong auto status = tryAssemble(gHalManifestConverter, "manifest", 505bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong std::bind(&AssembleVintf::assembleHalManifest, this, _1)); 506bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong if (status == SUCCESS) return true; 507bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong if (status == FAIL_AND_EXIT) return false; 5089aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 509bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong resetInFiles(); 5104650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong 511bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong status = tryAssemble(gCompatibilityMatrixConverter, "compatibility matrix", 512bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong std::bind(&AssembleVintf::assembleCompatibilityMatrix, this, _1)); 513bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong if (status == SUCCESS) return true; 514bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong if (status == FAIL_AND_EXIT) return false; 5154d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 516959ee1bf8b922980542f72ce9ad1929fc7d8b55cYifan Hong std::cerr << "Input file has unknown format." << std::endl 517959ee1bf8b922980542f72ce9ad1929fc7d8b55cYifan Hong << "Error when attempting to convert to manifest: " 518959ee1bf8b922980542f72ce9ad1929fc7d8b55cYifan Hong << gHalManifestConverter.lastError() << std::endl 519959ee1bf8b922980542f72ce9ad1929fc7d8b55cYifan Hong << "Error when attempting to convert to compatibility matrix: " 520959ee1bf8b922980542f72ce9ad1929fc7d8b55cYifan Hong << gCompatibilityMatrixConverter.lastError() << std::endl; 521959ee1bf8b922980542f72ce9ad1929fc7d8b55cYifan Hong return false; 5224d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } 5239aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 5249aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong bool openOutFile(const char* path) { 5259aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong mOutFileRef = std::make_unique<std::ofstream>(); 5269aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong mOutFileRef->open(path); 5279aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return mOutFileRef->is_open(); 5289aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 5299aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 5309aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong bool openInFile(const char* path) { 531bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong mInFilePaths.push_back(path); 532bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong mInFiles.push_back({}); 533bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong mInFiles.back().open(path); 534bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong return mInFiles.back().is_open(); 5359aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 5369aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 5379aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong bool openCheckFile(const char* path) { 5389aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong mCheckFile.open(path); 5399aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong return mCheckFile.is_open(); 5409aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong } 5419aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 542bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong void resetInFiles() { 543bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong for (auto& inFile : mInFiles) { 544bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong inFile.clear(); 545bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong inFile.seekg(0); 546bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong } 547bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong } 548bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong 5499aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong void setOutputMatrix() { mOutputMatrix = true; } 5509aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 551a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong bool setHalsOnly() { 552a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong if (mSerializeFlags) return false; 553a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong mSerializeFlags |= SerializeFlag::HALS_ONLY; 554a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong return true; 555a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong } 556a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong 557a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong bool setNoHals() { 558a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong if (mSerializeFlags) return false; 559a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong mSerializeFlags |= SerializeFlag::NO_HALS; 560a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong return true; 561a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong } 562a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong 56379efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong bool addKernel(const std::string& kernelArg) { 56479efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong auto ind = kernelArg.find(':'); 56579efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong if (ind == std::string::npos) { 56679efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong std::cerr << "Unrecognized --kernel option '" << kernelArg << "'" << std::endl; 56779efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong return false; 56879efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong } 56979efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong std::string kernelVerStr{kernelArg.begin(), kernelArg.begin() + ind}; 57079efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong std::string kernelConfigPath{kernelArg.begin() + ind + 1, kernelArg.end()}; 57179efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong Version kernelVer; 57279efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong if (!parse(kernelVerStr, &kernelVer)) { 57379efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong std::cerr << "Unrecognized kernel version '" << kernelVerStr << "'" << std::endl; 57479efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong return false; 57579efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong } 57648602dfa0ef4a40b58c6376bab82c6e46d6f6a0bYifan Hong if (mKernels.find(kernelVer) != mKernels.end()) { 57748602dfa0ef4a40b58c6376bab82c6e46d6f6a0bYifan Hong std::cerr << "Multiple --kernel for " << kernelVer << " is specified." << std::endl; 57848602dfa0ef4a40b58c6376bab82c6e46d6f6a0bYifan Hong return false; 57948602dfa0ef4a40b58c6376bab82c6e46d6f6a0bYifan Hong } 58048602dfa0ef4a40b58c6376bab82c6e46d6f6a0bYifan Hong mKernels[kernelVer] = kernelConfigPath; 58179efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong return true; 58279efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong } 58379efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong 5849aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong private: 585bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong std::vector<std::string> mInFilePaths; 586bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong std::vector<std::ifstream> mInFiles; 5879aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong std::unique_ptr<std::ofstream> mOutFileRef; 5889aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong std::ifstream mCheckFile; 5899aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong bool mOutputMatrix = false; 590a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong SerializeFlags mSerializeFlags = SerializeFlag::EVERYTHING; 59148602dfa0ef4a40b58c6376bab82c6e46d6f6a0bYifan Hong std::map<Version, std::string> mKernels; 5924d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong}; 5934d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 5944d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong} // namespace vintf 5954d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong} // namespace android 5964d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 5974d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hongvoid help() { 5989aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong std::cerr << "assemble_vintf: Checks if a given manifest / matrix file is valid and \n" 5999aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " fill in build-time flags into the given file.\n" 6009aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong "assemble_vintf -h\n" 6019aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " Display this help text.\n" 602bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong "assemble_vintf -i <input file>[:<input file>[...]] [-o <output file>] [-m]\n" 603bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong " [-c [<check file>]]\n" 6049aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " Fill in build-time flags into the given file.\n" 605bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong " -i <input file>[:<input file>[...]]\n" 606bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong " A list of input files. Format is automatically detected for the\n" 607bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong " first file, and the remaining files must have the same format.\n" 608bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong " Files other than the first file should only have <hal> defined;\n" 609bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong " other entries are ignored.\n" 6109aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " -o <output file>\n" 6119aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " Optional output file. If not specified, write to stdout.\n" 6129aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " -m\n" 6139aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " a compatible compatibility matrix is\n" 6149aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " generated instead; for example, given a device manifest,\n" 6159aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " a framework compatibility matrix is generated. This flag\n" 6169aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " is ignored when input is a compatibility matrix.\n" 6179aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " -c [<check file>]\n" 6189aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " After writing the output file, check compatibility between\n" 6199aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " output file and check file.\n" 6209aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " If -c is set but the check file is not specified, a warning\n" 6219aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " message is written to stderr. Return 0.\n" 6229aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong " If the check file is specified but is not compatible, an error\n" 62379efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong " message is written to stderr. Return 1.\n" 6240bef86826065d9cfdad3139ea186a98524cf2eddSteve Muckle " --kernel=<version>:<android-base.cfg>[:<android-base-arch.cfg>[...]]\n" 62579efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong " Add a kernel entry to framework compatibility matrix.\n" 62679efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong " Ignored for other input format.\n" 62779efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong " <version> has format: 3.18\n" 6280bef86826065d9cfdad3139ea186a98524cf2eddSteve Muckle " <android-base.cfg> is the location of android-base.cfg\n" 6290bef86826065d9cfdad3139ea186a98524cf2eddSteve Muckle " <android-base-arch.cfg> is the location of an optional\n" 630a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong " arch-specific config fragment, more than one may be specified\n" 631a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong " -l, --hals-only\n" 632a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong " Output has only <hal> entries. Cannot be used with -n.\n" 633a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong " -n, --no-hals\n" 634a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong " Output has no <hal> entries (but all other entries).\n" 635a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong " Cannot be used with -l.\n"; 6364d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong} 6374d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 6384d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hongint main(int argc, char **argv) { 639a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong const struct option longopts[] = {{"kernel", required_argument, NULL, 'k'}, 640a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong {"hals-only", no_argument, NULL, 'l'}, 641a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong {"no-hals", no_argument, NULL, 'n'}, 642a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong {0, 0, 0, 0}}; 6439aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong 644bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong std::string outFilePath; 6459aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong ::android::vintf::AssembleVintf assembleVintf; 6464d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong int res; 6479aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong int optind; 648a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong while ((res = getopt_long(argc, argv, "hi:o:mc:nl", longopts, &optind)) >= 0) { 6494d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong switch (res) { 6504d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong case 'i': { 651bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong char* inFilePath = strtok(optarg, ":"); 652bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong while (inFilePath != NULL) { 653bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong if (!assembleVintf.openInFile(inFilePath)) { 654bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong std::cerr << "Failed to open " << optarg << std::endl; 655bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong return 1; 656bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong } 657bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong inFilePath = strtok(NULL, ":"); 6584d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } 6594d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } break; 6604d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 6614d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong case 'o': { 662bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong outFilePath = optarg; 6639aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (!assembleVintf.openOutFile(optarg)) { 6644d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong std::cerr << "Failed to open " << optarg << std::endl; 6654d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong return 1; 6664d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } 6674d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } break; 6684d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 669a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong case 'm': { 6709aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong assembleVintf.setOutputMatrix(); 671a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong } break; 672a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong 6734650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong case 'c': { 6744650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong if (strlen(optarg) != 0) { 6759aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong if (!assembleVintf.openCheckFile(optarg)) { 6764650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong std::cerr << "Failed to open " << optarg << std::endl; 6774650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong return 1; 6784650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong } 6794650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong } else { 6804650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong std::cerr << "WARNING: no compatibility check is done on " 681bfb3c1dc59144dd784d1d81af3ce81c97ea2e45aYifan Hong << (outFilePath.empty() ? "output" : outFilePath) << std::endl; 6824650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong } 6834650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong } break; 6844650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong 68579efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong case 'k': { 68679efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong if (!assembleVintf.addKernel(optarg)) { 68779efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong std::cerr << "ERROR: Unrecognized --kernel argument." << std::endl; 68879efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong return 1; 68979efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong } 69079efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong } break; 69179efa8a35e677cb8ac79041737e2700b0e50de15Yifan Hong 692a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong case 'l': { 693a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong if (!assembleVintf.setHalsOnly()) { 694a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong return 1; 695a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong } 696a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong } break; 697a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong 698a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong case 'n': { 699a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong if (!assembleVintf.setNoHals()) { 700a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong return 1; 701a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong } 702a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong } break; 703a2635c418cdc039d582a50fa91f8dbaa85ce7b02Yifan Hong 7044d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong case 'h': 7054d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong default: { 7064d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong help(); 7074d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong return 1; 7084d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } break; 7094d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } 7104d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong } 7114d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong 7129aa6370fa16fa1c04a15677d1c22401fa94dc4e7Yifan Hong bool success = assembleVintf.assemble(); 7134650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong 7144650ad8e0353ee4404a85300937f66a8c92d7f98Yifan Hong return success ? 0 : 1; 7154d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong} 716