AssembleVintf.cpp revision a59d2567783cad6f675d2fc1f2fcce4bce3e34e3
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
174d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong#include <stdlib.h>
184d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong#include <unistd.h>
194d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong
204d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong#include <fstream>
214d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong#include <iostream>
224d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong#include <unordered_map>
234d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong#include <sstream>
244d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong#include <string>
254d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong
264d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong#include <vintf/parse_string.h>
274d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong#include <vintf/parse_xml.h>
284d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong
294d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hongnamespace android {
304d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hongnamespace vintf {
314d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong
324d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong/**
334d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong * Slurps the device manifest file and add build time flag to it.
344d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong */
354d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hongclass AssembleVintf {
364d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hongpublic:
374d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong    template<typename T>
384d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong    static bool getFlag(const std::string& key, T* value) {
394d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        const char *envValue = getenv(key.c_str());
404d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        if (envValue == NULL) {
414d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong            std::cerr << "Required " << key << " flag." << std::endl;
424d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong            return false;
434d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        }
444d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong
454d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        if (!parse(envValue, value)) {
464d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong            std::cerr << "Cannot parse " << envValue << "." << std::endl;
474d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong            return false;
484d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        }
494d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        return true;
504d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong    }
514d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong
52a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong    static bool assemble(std::basic_istream<char>& inFile,
53a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong                         std::basic_ostream<char>& outFile,
54a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong                         bool isMatrix) {
554d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        std::stringstream ss;
564d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        ss << inFile.rdbuf();
574d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        std::string fileContent = ss.str();
584d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong
594d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        HalManifest halManifest;
604d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        if (!gHalManifestConverter(&halManifest, fileContent)) {
614d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong            std::cerr << "Illformed HAL manifest: " << gHalManifestConverter.lastError()
624d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong                    << std::endl;
634d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong            return false;
644d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        }
654d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong
664d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        if (halManifest.mType == SchemaType::DEVICE) {
674d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong            if (!getFlag("BOARD_SEPOLICY_VERS", &halManifest.device.mSepolicyVersion)) {
684d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong                return false;
694d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong            }
704d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        }
714d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong
72a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong        if (isMatrix) {
73a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong            CompatibilityMatrix mat = halManifest.generateCompatibleMatrix();
74a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong            std::string error;
75a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong            if (!halManifest.checkCompatibility(mat, &error)) {
76a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong                std::cerr << "FATAL ERROR: cannot generate a compatible matrix: "
77a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong                          << error << std::endl;
78a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong            }
79a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong            outFile << "<!-- \n"
80a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong                       "    Autogenerated skeleton compatibility matrix. \n"
81a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong                       "    Use with caution. Modify it to suit your needs.\n"
82a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong                       "    All HALs are set to optional.\n"
83a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong                       "    Many entries other than HALs are zero-filled and\n"
84a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong                       "    require human attention. \n"
85a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong                       "-->\n"
86a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong                    << gCompatibilityMatrixConverter(mat);
87a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong        } else {
88a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong            outFile << gHalManifestConverter(halManifest);
89a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong        }
90a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong
914d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        outFile.flush();
924d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong
934d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        return true;
944d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong    }
954d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong};
964d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong
974d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong}  // namespace vintf
984d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong}  // namespace android
994d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong
1004d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hongvoid help() {
1014d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong    std::cerr <<
1024d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        "assemble_vintf -h\n"
1034d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        "               Display this help text.\n"
104a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong        "assemble_vintf -i <input file> [-o <output file>] [-m]\n"
1054d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        "               Fill in build-time flags into the given manifest.\n"
106a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong        "               If no designated output file, write to stdout.\n"
107a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong        "               If -m is set, a compatible compatibility matrix is\n"
108a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong        "               generated instead.\n";
1094d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong}
1104d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong
1114d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hongint main(int argc, char **argv) {
1124d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong    std::ifstream inFile;
1134d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong    std::ofstream outFile;
1144d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong    std::ostream* outFileRef = &std::cout;
115a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong    bool isMatrix = false;
1164d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong    int res;
117a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong    while((res = getopt(argc, argv, "hi:o:m")) >= 0) {
1184d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        switch (res) {
1194d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong            case 'i': {
1204d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong                inFile.open(optarg);
1214d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong                if (!inFile.is_open()) {
1224d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong                    std::cerr << "Failed to open " << optarg << std::endl;
1234d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong                    return 1;
1244d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong                }
1254d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong            } break;
1264d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong
1274d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong            case 'o': {
1284d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong                outFile.open(optarg);
1294d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong                if (!outFile.is_open()) {
1304d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong                    std::cerr << "Failed to open " << optarg << std::endl;
1314d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong                    return 1;
1324d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong                }
1334d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong                outFileRef = &outFile;
1344d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong            } break;
1354d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong
136a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong            case 'm': {
137a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong                isMatrix = true;
138a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong            } break;
139a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong
1404d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong            case 'h':
1414d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong            default: {
1424d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong                help();
1434d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong                return 1;
1444d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong            } break;
1454d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        }
1464d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong    }
1474d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong
1484d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong    if (!inFile.is_open()) {
1494d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        std::cerr << "Missing input file" << std::endl;
1504d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        help();
1514d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong        return 1;
1524d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong    }
1534d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong
154a59d2567783cad6f675d2fc1f2fcce4bce3e34e3Yifan Hong    return ::android::vintf::AssembleVintf::assemble(inFile, *outFileRef, isMatrix)
1554d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong            ? 0 : 1;
1564d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong}
1574d18bcc9a3de245edb20c2469718f8442c758d97Yifan Hong
158