/*
 * 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.
 */

#define LOG_TAG "libvintf"
#include <android-base/logging.h>

#include "HalManifest.h"

#include <dirent.h>

#include <mutex>
#include <set>

#include "parse_string.h"
#include "parse_xml.h"
#include "utils.h"
#include "CompatibilityMatrix.h"

namespace android {
namespace vintf {

constexpr Version HalManifest::kVersion;

// Check <version> tag for all <hal> with the same name.
bool HalManifest::shouldAdd(const ManifestHal& hal) const {
    if (!hal.isValid()) {
        return false;
    }
    auto existingHals = mHals.equal_range(hal.name);
    std::set<size_t> existingMajorVersions;
    for (auto it = existingHals.first; it != existingHals.second; ++it) {
        for (const auto& v : it->second.versions) {
            // Assume integrity on existingHals, so no check on emplace().second
            existingMajorVersions.insert(v.majorVer);
        }
    }
    for (const auto& v : hal.versions) {
        if (!existingMajorVersions.emplace(v.majorVer).second /* no insertion */) {
            return false;
        }
    }
    return true;
}

std::set<std::string> HalManifest::getHalNames() const {
    std::set<std::string> names{};
    for (const auto &hal : mHals) {
        names.insert(hal.first);
    }
    return names;
}

std::set<std::string> HalManifest::getHalNamesAndVersions() const {
    std::set<std::string> names{};
    for (const auto &hal : getHals()) {
        for (const auto &version : hal.versions) {
            names.insert(hal.name + "@" + to_string(version));
        }
    }
    return names;
}

std::set<std::string> HalManifest::getInterfaceNames(const std::string &name) const {
    std::set<std::string> interfaceNames{};
    for (const ManifestHal *hal : getHals(name)) {
        for (const auto &iface : hal->interfaces) {
            interfaceNames.insert(iface.first);
        }
    }
    return interfaceNames;
}

std::vector<const ManifestHal *> HalManifest::getHals(const std::string &name) const {
    std::vector<const ManifestHal *> ret;
    auto range = mHals.equal_range(name);
    for (auto it = range.first; it != range.second; ++it) {
        ret.push_back(&it->second);
    }
    return ret;
}
std::vector<ManifestHal *> HalManifest::getHals(const std::string &name) {
    std::vector<ManifestHal *> ret;
    auto range = mHals.equal_range(name);
    for (auto it = range.first; it != range.second; ++it) {
        ret.push_back(&it->second);
    }
    return ret;
}

Transport HalManifest::getTransport(const std::string &package, const Version &v,
            const std::string &interfaceName, const std::string &instanceName) const {

    for (const ManifestHal *hal : getHals(package)) {
        bool found = false;
        for (auto& ver : hal->versions) {
            if (ver.majorVer == v.majorVer && ver.minorVer >= v.minorVer) {
                found = true;
                break;
            }
        }
        if (!found) {
            LOG(DEBUG) << "HalManifest::getTransport(" << to_string(mType) << "): Cannot find "
                      << to_string(v) << " in supported versions of " << package;
            continue;
        }
        auto it = hal->interfaces.find(interfaceName);
        if (it == hal->interfaces.end()) {
            LOG(DEBUG) << "HalManifest::getTransport(" << to_string(mType) << "): Cannot find interface '"
                      << interfaceName << "' in " << package << "@" << to_string(v);
            continue;
        }
        const auto &instances = it->second.instances;
        if (instances.find(instanceName) == instances.end()) {
            LOG(DEBUG) << "HalManifest::getTransport(" << to_string(mType) << "): Cannot find instance '"
                      << instanceName << "' in "
                      << package << "@" << to_string(v) << "::" << interfaceName;
            continue;
        }
        return hal->transportArch.transport;
    }
    LOG(DEBUG) << "HalManifest::getTransport(" << to_string(mType) << "): Cannot get transport for "
                 << package << "@" << v << "::" << interfaceName << "/" << instanceName;
    return Transport::EMPTY;

}

ConstMultiMapValueIterable<std::string, ManifestHal> HalManifest::getHals() const {
    return HalGroup<ManifestHal>::getHals();
}

std::set<Version> HalManifest::getSupportedVersions(const std::string &name) const {
    std::set<Version> ret;
    for (const ManifestHal *hal : getHals(name)) {
        ret.insert(hal->versions.begin(), hal->versions.end());
    }
    return ret;
}


std::set<std::string> HalManifest::getInstances(
        const std::string &halName, const std::string &interfaceName) const {
    std::set<std::string> ret;
    for (const ManifestHal *hal : getHals(halName)) {
        auto it = hal->interfaces.find(interfaceName);
        if (it != hal->interfaces.end()) {
            ret.insert(it->second.instances.begin(), it->second.instances.end());
        }
    }
    return ret;
}

bool HalManifest::hasInstance(const std::string &halName,
        const std::string &interfaceName, const std::string &instanceName) const {
    const auto &instances = getInstances(halName, interfaceName);
    return instances.find(instanceName) != instances.end();
}

using InstancesOfVersion = std::map<std::string /* interface */,
                                    std::set<std::string /* instance */>>;
using Instances = std::map<Version, InstancesOfVersion>;

static bool satisfyVersion(const MatrixHal& matrixHal, const Version& manifestHalVersion) {
    for (const VersionRange &matrixVersionRange : matrixHal.versionRanges) {
        // If Compatibility Matrix says 2.5-2.7, the "2.7" is purely informational;
        // the framework can work with all 2.5-2.infinity.
        if (matrixVersionRange.supportedBy(manifestHalVersion)) {
            return true;
        }
    }
    return false;
}

// Check if matrixHal.interfaces is a subset of instancesOfVersion
static bool satisfyAllInstances(const MatrixHal& matrixHal,
        const InstancesOfVersion &instancesOfVersion) {
    for (const auto& matrixHalInterfacePair : matrixHal.interfaces) {
        const std::string& interface = matrixHalInterfacePair.first;
        auto it = instancesOfVersion.find(interface);
        if (it == instancesOfVersion.end()) {
            return false;
        }
        const std::set<std::string>& manifestInterfaceInstances = it->second;
        const std::set<std::string>& matrixInterfaceInstances =
                matrixHalInterfacePair.second.instances;
        if (!std::includes(manifestInterfaceInstances.begin(), manifestInterfaceInstances.end(),
                           matrixInterfaceInstances.begin(), matrixInterfaceInstances.end())) {
            return false;
        }
    }
    return true;
}

bool HalManifest::isCompatible(const MatrixHal& matrixHal) const {
    Instances instances;
    // Do the cross product version x interface x instance and sort them,
    // because interfaces / instances can span in multiple HALs.
    // This is efficient for small <hal> entries.
    for (const ManifestHal* manifestHal : getHals(matrixHal.name)) {
        for (const Version& manifestHalVersion : manifestHal->versions) {
            instances[manifestHalVersion] = {};
            for (const auto& halInterfacePair : manifestHal->interfaces) {
                const std::string& interface = halInterfacePair.first;
                const auto& toAdd = halInterfacePair.second.instances;
                instances[manifestHalVersion][interface].insert(toAdd.begin(), toAdd.end());
            }
        }
    }
    for (const auto& instanceMapPair : instances) {
        const Version& manifestHalVersion = instanceMapPair.first;
        const InstancesOfVersion& instancesOfVersion = instanceMapPair.second;
        if (!satisfyVersion(matrixHal, manifestHalVersion)) {
            continue;
        }
        if (!satisfyAllInstances(matrixHal, instancesOfVersion)) {
            continue;
        }
        return true; // match!
    }
    return false;
}

// For each hal in mat, there must be a hal in manifest that supports this.
std::vector<std::string> HalManifest::checkIncompatibility(const CompatibilityMatrix &mat,
        bool includeOptional) const {
    std::vector<std::string> incompatible;
    for (const MatrixHal &matrixHal : mat.getHals()) {
        if (!includeOptional && matrixHal.optional) {
            continue;
        }
        // don't check optional; put it in the incompatibility list as well.
        if (!isCompatible(matrixHal)) {
            incompatible.push_back(matrixHal.name);
        }
    }
    return incompatible;
}

bool HalManifest::checkCompatibility(const CompatibilityMatrix &mat, std::string *error) const {
    if (mType == mat.mType) {
        if (error != nullptr) {
            *error = "Wrong type; checking " + to_string(mType) + " manifest against "
                    + to_string(mat.mType) + " compatibility matrix";
        }
        return false;
    }
    std::vector<std::string> incompatibleHals =
            checkIncompatibility(mat, false /* includeOptional */);
    if (!incompatibleHals.empty()) {
        if (error != nullptr) {
            *error = "HALs incompatible.";
            for (const auto &name : incompatibleHals) {
                *error += " " + name;
            }
        }
        return false;
    }
    if (mType == SchemaType::FRAMEWORK) {
    // TODO(b/36400653) enable this. It is disabled since vndk is not yet defined.
#ifdef VINTF_CHECK_VNDK
        bool match = false;
        const auto &matVndk = mat.device.mVndk;
        for (const auto &vndk : framework.mVndks) {
            if (!vndk.mVersionRange.in(matVndk.mVersionRange)) {
                continue;
            }
            // version matches, check libaries
            std::vector<std::string> diff;
            std::set_difference(matVndk.mLibraries.begin(), matVndk.mLibraries.end(),
                    vndk.mLibraries.begin(), vndk.mLibraries.end(),
                    std::inserter(diff, diff.begin()))
            if (!diff.empty()) {
                if (error != nullptr) {
                    *error = "Vndk libs incompatible.";
                    for (const auto &name : diff) {
                        *error += " " + name;
                    }
                }
                return false;
            }
            match = true;
            break;
        }
        if (!match) {
            if (error != nullptr) {
                *error = "Vndk version " + to_string(matVndk.mVersionRange) + " is not supported.";
            }
        }
#endif
    } else if (mType == SchemaType::DEVICE) {
        bool match = false;
        for (const auto &range : mat.framework.mSepolicy.sepolicyVersions()) {
            if (range.supportedBy(device.mSepolicyVersion)) {
                match = true;
                break;
            }
        }
        if (!match) {
            if (error != nullptr) {
                *error = "Sepolicy version " + to_string(device.mSepolicyVersion)
                        + " doesn't satisify the requirements.";
            }
            return false;
        }
    }

    return true;
}

CompatibilityMatrix HalManifest::generateCompatibleMatrix() const {
    CompatibilityMatrix matrix;

    for (const ManifestHal &manifestHal : getHals()) {
        MatrixHal matrixHal{
            .format = manifestHal.format,
            .name = manifestHal.name,
            .optional = true,
            .interfaces = manifestHal.interfaces
        };
        for (const Version &manifestVersion : manifestHal.versions) {
            matrixHal.versionRanges.push_back({manifestVersion.majorVer, manifestVersion.minorVer});
        }
        matrix.add(std::move(matrixHal));
    }
    if (mType == SchemaType::FRAMEWORK) {
        matrix.mType = SchemaType::DEVICE;
        // VNDK does not need to be added for compatibility
    } else if (mType == SchemaType::DEVICE) {
        matrix.mType = SchemaType::FRAMEWORK;
        matrix.framework.mSepolicy = Sepolicy(0u /* kernelSepolicyVersion */,
                {{device.mSepolicyVersion.majorVer, device.mSepolicyVersion.minorVer}});
    }

    return matrix;
}

status_t HalManifest::fetchAllInformation(const std::string &path) {
    return details::fetchAllInformation(path, gHalManifestConverter, this);
}

SchemaType HalManifest::type() const {
    return mType;
}

const Version &HalManifest::sepolicyVersion() const {
    CHECK(mType == SchemaType::DEVICE);
    return device.mSepolicyVersion;
}

const std::vector<Vndk> &HalManifest::vndks() const {
    CHECK(mType == SchemaType::FRAMEWORK);
    return framework.mVndks;
}

bool operator==(const HalManifest &lft, const HalManifest &rgt) {
    return lft.mType == rgt.mType &&
           lft.mHals == rgt.mHals &&
           (lft.mType != SchemaType::DEVICE || (
                lft.device.mSepolicyVersion == rgt.device.mSepolicyVersion)) &&
           (lft.mType != SchemaType::FRAMEWORK || (
                lft.framework.mVndks == rgt.framework.mVndks));
}

} // namespace vintf
} // namespace android
