/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "utils.h" using android::kver::KernelRelease; namespace android { namespace vintf { namespace details { // fake sysprops using Properties = std::map; enum Option : int { // Modes HELP, DUMP_FILE_LIST = 1, CHECK_COMPAT, CHECK_ONE, // Options ROOTDIR, PROPERTY, DIR_MAP, KERNEL, }; // command line arguments using Args = std::multimap; class PresetPropertyFetcher : public PropertyFetcher { public: std::string getProperty(const std::string& key, const std::string& defaultValue) const override { auto it = mProps.find(key); if (it == mProps.end()) { LOG(INFO) << "Sysprop " << key << " is missing, default to '" << defaultValue << "'"; return defaultValue; } LOG(INFO) << "Sysprop " << key << "=" << it->second; return it->second; } uint64_t getUintProperty(const std::string& key, uint64_t defaultValue, uint64_t max) const override { uint64_t result; std::string value = getProperty(key, ""); if (!value.empty() && android::base::ParseUint(value, &result, max)) return result; return defaultValue; } bool getBoolProperty(const std::string& key, bool defaultValue) const override { std::string value = getProperty(key, ""); if (value == "1" || value == "true") { return true; } else if (value == "0" || value == "false") { return false; } return defaultValue; } void setProperties(const Properties& props) { mProps.insert(props.begin(), props.end()); } private: std::map mProps; }; struct StaticRuntimeInfo : public RuntimeInfo { KernelVersion kernelVersion; Level kernelLevel = Level::UNSPECIFIED; std::string kernelConfigFile; status_t fetchAllInformation(FetchFlags flags) override { if (flags & RuntimeInfo::FetchFlag::CPU_VERSION) { mKernel.mVersion = kernelVersion; LOG(INFO) << "fetched kernel version " << kernelVersion; } if (flags & RuntimeInfo::FetchFlag::KERNEL_FCM) { mKernel.mLevel = kernelLevel; LOG(INFO) << "fetched kernel level from RuntimeInfo '" << kernelLevel << "'"; } if (flags & RuntimeInfo::FetchFlag::CONFIG_GZ) { std::string content; if (!android::base::ReadFileToString(kernelConfigFile, &content)) { LOG(ERROR) << "Cannot read " << kernelConfigFile; return UNKNOWN_ERROR; } KernelConfigParser parser; auto status = parser.processAndFinish(content); if (status != OK) { return status; } mKernel.mConfigs = std::move(parser.configs()); LOG(INFO) << "read kernel configs from " << kernelConfigFile; } if (flags & RuntimeInfo::FetchFlag::POLICYVERS) { mKernelSepolicyVersion = SIZE_MAX; } return OK; } }; struct StubRuntimeInfo : public RuntimeInfo { status_t fetchAllInformation(FetchFlags) override { return UNKNOWN_ERROR; } }; struct StaticRuntimeInfoFactory : public ObjectFactory { std::shared_ptr info; StaticRuntimeInfoFactory(std::shared_ptr i) : info(i) {} std::shared_ptr make_shared() const override { if (info) return info; return std::make_shared(); } }; // helper functions template std::unique_ptr readObject(FileSystem* fileSystem, const std::string& path) { std::string xml; std::string error; status_t err = fileSystem->fetch(path, &xml, &error); if (err != OK) { LOG(ERROR) << "Cannot read '" << path << "' (" << strerror(-err) << "): " << error; return nullptr; } auto ret = std::make_unique(); ret->setFileName(path); if (!fromXml(ret.get(), xml, &error)) { LOG(ERROR) << "Cannot parse '" << path << "': " << error; return nullptr; } return ret; } int checkCompatibilityForFiles(const std::string& manifestPath, const std::string& matrixPath) { auto fileSystem = std::make_unique(); auto manifest = readObject(fileSystem.get(), manifestPath); auto matrix = readObject(fileSystem.get(), matrixPath); if (manifest == nullptr || matrix == nullptr) { return -1; } std::string error; if (!manifest->checkCompatibility(*matrix, &error)) { LOG(ERROR) << "Incompatible: " << error; std::cout << "false" << std::endl; return 1; } std::cout << "true" << std::endl; return 0; } Args parseArgs(int argc, char** argv) { int longOptFlag; int optionIndex; Args ret; std::vector longopts{ // Modes {"help", no_argument, &longOptFlag, HELP}, {"dump-file-list", no_argument, &longOptFlag, DUMP_FILE_LIST}, {"check-compat", no_argument, &longOptFlag, CHECK_COMPAT}, {"check-one", no_argument, &longOptFlag, CHECK_ONE}, // Options {"rootdir", required_argument, &longOptFlag, ROOTDIR}, {"property", required_argument, &longOptFlag, PROPERTY}, {"dirmap", required_argument, &longOptFlag, DIR_MAP}, {"kernel", required_argument, &longOptFlag, KERNEL}, {0, 0, 0, 0}}; std::map shortopts{ {'h', HELP}, {'D', PROPERTY}, {'c', CHECK_COMPAT}, }; for (;;) { int c = getopt_long(argc, argv, "hcD:", longopts.data(), &optionIndex); if (c == -1) { break; } std::string argValue = optarg ? optarg : std::string{}; if (c == 0) { ret.emplace(static_cast