/*
 * Copyright 2016 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 "layers_extensions.h"

#include <alloca.h>
#include <dirent.h>
#include <dlfcn.h>
#include <mutex>
#include <sys/prctl.h>
#include <string>
#include <string.h>
#include <vector>

#include <android-base/strings.h>
#include <android/dlext.h>
#include <cutils/properties.h>
#include <log/log.h>
#include <ziparchive/zip_archive.h>

#include <vulkan/vulkan_loader_data.h>

// TODO(jessehall): The whole way we deal with extensions is pretty hokey, and
// not a good long-term solution. Having a hard-coded enum of extensions is
// bad, of course. Representing sets of extensions (requested, supported, etc.)
// as a bitset isn't necessarily bad, if the mapping from extension to bit were
// dynamic. Need to rethink this completely when there's a little more time.

// TODO(jessehall): This file currently builds up global data structures as it
// loads, and never cleans them up. This means we're doing heap allocations
// without going through an app-provided allocator, but worse, we'll leak those
// allocations if the loader is unloaded.
//
// We should allocate "enough" BSS space, and suballocate from there. Will
// probably want to intern strings, etc., and will need some custom/manual data
// structures.

namespace vulkan {
namespace api {

struct Layer {
    VkLayerProperties properties;
    size_t library_idx;

    // true if the layer intercepts vkCreateDevice and device commands
    bool is_global;

    std::vector<VkExtensionProperties> instance_extensions;
    std::vector<VkExtensionProperties> device_extensions;
};

namespace {

const char kSystemLayerLibraryDir[] = "/data/local/debug/vulkan";

class LayerLibrary {
   public:
    LayerLibrary(const std::string& path)
        : path_(path), dlhandle_(nullptr), refcount_(0) {}

    LayerLibrary(LayerLibrary&& other)
        : path_(std::move(other.path_)),
          dlhandle_(other.dlhandle_),
          refcount_(other.refcount_) {
        other.dlhandle_ = nullptr;
        other.refcount_ = 0;
    }

    LayerLibrary(const LayerLibrary&) = delete;
    LayerLibrary& operator=(const LayerLibrary&) = delete;

    // these are thread-safe
    bool Open();
    void Close();

    bool EnumerateLayers(size_t library_idx,
                         std::vector<Layer>& instance_layers) const;

    void* GetGPA(const Layer& layer,
                 const char* gpa_name,
                 size_t gpa_name_len) const;

   private:
    const std::string path_;

    std::mutex mutex_;
    void* dlhandle_;
    size_t refcount_;
};

bool LayerLibrary::Open() {
    std::lock_guard<std::mutex> lock(mutex_);
    if (refcount_++ == 0) {
        ALOGV("opening layer library '%s'", path_.c_str());
        // Libraries in the system layer library dir can't be loaded into
        // the application namespace. That causes compatibility problems, since
        // any symbol dependencies will be resolved by system libraries. They
        // can't safely use libc++_shared, for example. Which is one reason
        // (among several) we only allow them in non-user builds.
        auto app_namespace = LoaderData::GetInstance().app_namespace;
        if (app_namespace &&
            !android::base::StartsWith(path_, kSystemLayerLibraryDir)) {
            android_dlextinfo dlextinfo = {};
            dlextinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
            dlextinfo.library_namespace = app_namespace;
            dlhandle_ = android_dlopen_ext(path_.c_str(), RTLD_NOW | RTLD_LOCAL,
                                           &dlextinfo);
        } else {
            dlhandle_ = dlopen(path_.c_str(), RTLD_NOW | RTLD_LOCAL);
        }
        if (!dlhandle_) {
            ALOGE("failed to load layer library '%s': %s", path_.c_str(),
                  dlerror());
            refcount_ = 0;
            return false;
        }
    }
    return true;
}

void LayerLibrary::Close() {
    std::lock_guard<std::mutex> lock(mutex_);
    if (--refcount_ == 0) {
        ALOGV("closing layer library '%s'", path_.c_str());
        dlclose(dlhandle_);
        dlhandle_ = nullptr;
    }
}

bool LayerLibrary::EnumerateLayers(size_t library_idx,
                                   std::vector<Layer>& instance_layers) const {
    PFN_vkEnumerateInstanceLayerProperties enumerate_instance_layers =
        reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
            dlsym(dlhandle_, "vkEnumerateInstanceLayerProperties"));
    PFN_vkEnumerateInstanceExtensionProperties enumerate_instance_extensions =
        reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
            dlsym(dlhandle_, "vkEnumerateInstanceExtensionProperties"));
    if (!enumerate_instance_layers || !enumerate_instance_extensions) {
        ALOGE("layer library '%s' missing some instance enumeration functions",
              path_.c_str());
        return false;
    }

    // device functions are optional
    PFN_vkEnumerateDeviceLayerProperties enumerate_device_layers =
        reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(
            dlsym(dlhandle_, "vkEnumerateDeviceLayerProperties"));
    PFN_vkEnumerateDeviceExtensionProperties enumerate_device_extensions =
        reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
            dlsym(dlhandle_, "vkEnumerateDeviceExtensionProperties"));

    // get layer counts
    uint32_t num_instance_layers = 0;
    uint32_t num_device_layers = 0;
    VkResult result = enumerate_instance_layers(&num_instance_layers, nullptr);
    if (result != VK_SUCCESS || !num_instance_layers) {
        if (result != VK_SUCCESS) {
            ALOGE(
                "vkEnumerateInstanceLayerProperties failed for library '%s': "
                "%d",
                path_.c_str(), result);
        }
        return false;
    }
    if (enumerate_device_layers) {
        result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
                                         nullptr);
        if (result != VK_SUCCESS) {
            ALOGE(
                "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
                path_.c_str(), result);
            return false;
        }
    }

    // get layer properties
    VkLayerProperties* properties = static_cast<VkLayerProperties*>(alloca(
        (num_instance_layers + num_device_layers) * sizeof(VkLayerProperties)));
    result = enumerate_instance_layers(&num_instance_layers, properties);
    if (result != VK_SUCCESS) {
        ALOGE("vkEnumerateInstanceLayerProperties failed for library '%s': %d",
              path_.c_str(), result);
        return false;
    }
    if (num_device_layers > 0) {
        result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
                                         properties + num_instance_layers);
        if (result != VK_SUCCESS) {
            ALOGE(
                "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
                path_.c_str(), result);
            return false;
        }
    }

    // append layers to instance_layers
    size_t prev_num_instance_layers = instance_layers.size();
    instance_layers.reserve(prev_num_instance_layers + num_instance_layers);
    for (size_t i = 0; i < num_instance_layers; i++) {
        const VkLayerProperties& props = properties[i];

        Layer layer;
        layer.properties = props;
        layer.library_idx = library_idx;
        layer.is_global = false;

        uint32_t count = 0;
        result =
            enumerate_instance_extensions(props.layerName, &count, nullptr);
        if (result != VK_SUCCESS) {
            ALOGE(
                "vkEnumerateInstanceExtensionProperties(\"%s\") failed for "
                "library '%s': %d",
                props.layerName, path_.c_str(), result);
            instance_layers.resize(prev_num_instance_layers);
            return false;
        }
        layer.instance_extensions.resize(count);
        result = enumerate_instance_extensions(
            props.layerName, &count, layer.instance_extensions.data());
        if (result != VK_SUCCESS) {
            ALOGE(
                "vkEnumerateInstanceExtensionProperties(\"%s\") failed for "
                "library '%s': %d",
                props.layerName, path_.c_str(), result);
            instance_layers.resize(prev_num_instance_layers);
            return false;
        }

        for (size_t j = 0; j < num_device_layers; j++) {
            const auto& dev_props = properties[num_instance_layers + j];
            if (memcmp(&props, &dev_props, sizeof(props)) == 0) {
                layer.is_global = true;
                break;
            }
        }

        if (layer.is_global && enumerate_device_extensions) {
            result = enumerate_device_extensions(
                VK_NULL_HANDLE, props.layerName, &count, nullptr);
            if (result != VK_SUCCESS) {
                ALOGE(
                    "vkEnumerateDeviceExtensionProperties(\"%s\") failed for "
                    "library '%s': %d",
                    props.layerName, path_.c_str(), result);
                instance_layers.resize(prev_num_instance_layers);
                return false;
            }
            layer.device_extensions.resize(count);
            result = enumerate_device_extensions(
                VK_NULL_HANDLE, props.layerName, &count,
                layer.device_extensions.data());
            if (result != VK_SUCCESS) {
                ALOGE(
                    "vkEnumerateDeviceExtensionProperties(\"%s\") failed for "
                    "library '%s': %d",
                    props.layerName, path_.c_str(), result);
                instance_layers.resize(prev_num_instance_layers);
                return false;
            }
        }

        instance_layers.push_back(layer);
        ALOGD("added %s layer '%s' from library '%s'",
              (layer.is_global) ? "global" : "instance", props.layerName,
              path_.c_str());
    }

    return true;
}

void* LayerLibrary::GetGPA(const Layer& layer,
                           const char* gpa_name,
                           size_t gpa_name_len) const {
    void* gpa;
    size_t layer_name_len =
        std::max(size_t{2}, strlen(layer.properties.layerName));
    char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1));
    strcpy(name, layer.properties.layerName);
    strcpy(name + layer_name_len, gpa_name);
    if (!(gpa = dlsym(dlhandle_, name))) {
        strcpy(name, "vk");
        strcpy(name + 2, gpa_name);
        gpa = dlsym(dlhandle_, name);
    }
    return gpa;
}

// ----------------------------------------------------------------------------

std::vector<LayerLibrary> g_layer_libraries;
std::vector<Layer> g_instance_layers;

void AddLayerLibrary(const std::string& path) {
    LayerLibrary library(path);
    if (!library.Open())
        return;

    if (!library.EnumerateLayers(g_layer_libraries.size(), g_instance_layers)) {
        library.Close();
        return;
    }

    library.Close();

    g_layer_libraries.emplace_back(std::move(library));
}

template <typename Functor>
void ForEachFileInDir(const std::string& dirname, Functor functor) {
    auto dir_deleter = [](DIR* handle) { closedir(handle); };
    std::unique_ptr<DIR, decltype(dir_deleter)> dir(opendir(dirname.c_str()),
                                                    dir_deleter);
    if (!dir) {
        // It's normal for some search directories to not exist, especially
        // /data/local/debug/vulkan.
        int err = errno;
        ALOGW_IF(err != ENOENT, "failed to open layer directory '%s': %s",
                 dirname.c_str(), strerror(err));
        return;
    }
    ALOGD("searching for layers in '%s'", dirname.c_str());
    dirent* entry;
    while ((entry = readdir(dir.get())) != nullptr)
        functor(entry->d_name);
}

template <typename Functor>
void ForEachFileInZip(const std::string& zipname,
                      const std::string& dir_in_zip,
                      Functor functor) {
    int32_t err;
    ZipArchiveHandle zip = nullptr;
    if ((err = OpenArchive(zipname.c_str(), &zip)) != 0) {
        ALOGE("failed to open apk '%s': %d", zipname.c_str(), err);
        return;
    }
    std::string prefix(dir_in_zip + "/");
    const ZipString prefix_str(prefix.c_str());
    void* iter_cookie = nullptr;
    if ((err = StartIteration(zip, &iter_cookie, &prefix_str, nullptr)) != 0) {
        ALOGE("failed to iterate entries in apk '%s': %d", zipname.c_str(),
              err);
        CloseArchive(zip);
        return;
    }
    ALOGD("searching for layers in '%s!/%s'", zipname.c_str(),
          dir_in_zip.c_str());
    ZipEntry entry;
    ZipString name;
    while (Next(iter_cookie, &entry, &name) == 0) {
        std::string filename(
            reinterpret_cast<const char*>(name.name) + prefix.length(),
            name.name_length - prefix.length());
        // only enumerate direct entries of the directory, not subdirectories
        if (filename.find('/') != filename.npos)
            continue;
        // Check whether it *may* be possible to load the library directly from
        // the APK. Loading still may fail for other reasons, but this at least
        // lets us avoid failed-to-load log messages in the typical case of
        // compressed and/or unaligned libraries.
        if (entry.method != kCompressStored || entry.offset % PAGE_SIZE != 0)
            continue;
        functor(filename);
    }
    EndIteration(iter_cookie);
    CloseArchive(zip);
}

template <typename Functor>
void ForEachFileInPath(const std::string& path, Functor functor) {
    size_t zip_pos = path.find("!/");
    if (zip_pos == std::string::npos) {
        ForEachFileInDir(path, functor);
    } else {
        ForEachFileInZip(path.substr(0, zip_pos), path.substr(zip_pos + 2),
                         functor);
    }
}

void DiscoverLayersInPathList(const std::string& pathstr) {
    std::vector<std::string> paths = android::base::Split(pathstr, ":");
    for (const auto& path : paths) {
        ForEachFileInPath(path, [&](const std::string& filename) {
            if (android::base::StartsWith(filename, "libVkLayer") &&
                android::base::EndsWith(filename, ".so")) {
                AddLayerLibrary(path + "/" + filename);
            }
        });
    }
}

const VkExtensionProperties* FindExtension(
    const std::vector<VkExtensionProperties>& extensions,
    const char* name) {
    auto it = std::find_if(extensions.cbegin(), extensions.cend(),
                           [=](const VkExtensionProperties& ext) {
                               return (strcmp(ext.extensionName, name) == 0);
                           });
    return (it != extensions.cend()) ? &*it : nullptr;
}

void* GetLayerGetProcAddr(const Layer& layer,
                          const char* gpa_name,
                          size_t gpa_name_len) {
    const LayerLibrary& library = g_layer_libraries[layer.library_idx];
    return library.GetGPA(layer, gpa_name, gpa_name_len);
}

}  // anonymous namespace

void DiscoverLayers() {
    if (property_get_bool("ro.debuggable", false) &&
        prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
        DiscoverLayersInPathList(kSystemLayerLibraryDir);
    }
    if (!LoaderData::GetInstance().layer_path.empty())
        DiscoverLayersInPathList(LoaderData::GetInstance().layer_path);
}

uint32_t GetLayerCount() {
    return static_cast<uint32_t>(g_instance_layers.size());
}

const Layer& GetLayer(uint32_t index) {
    return g_instance_layers[index];
}

const Layer* FindLayer(const char* name) {
    auto layer =
        std::find_if(g_instance_layers.cbegin(), g_instance_layers.cend(),
                     [=](const Layer& entry) {
                         return strcmp(entry.properties.layerName, name) == 0;
                     });
    return (layer != g_instance_layers.cend()) ? &*layer : nullptr;
}

const VkLayerProperties& GetLayerProperties(const Layer& layer) {
    return layer.properties;
}

bool IsLayerGlobal(const Layer& layer) {
    return layer.is_global;
}

const VkExtensionProperties* GetLayerInstanceExtensions(const Layer& layer,
                                                        uint32_t& count) {
    count = static_cast<uint32_t>(layer.instance_extensions.size());
    return layer.instance_extensions.data();
}

const VkExtensionProperties* GetLayerDeviceExtensions(const Layer& layer,
                                                      uint32_t& count) {
    count = static_cast<uint32_t>(layer.device_extensions.size());
    return layer.device_extensions.data();
}

const VkExtensionProperties* FindLayerInstanceExtension(const Layer& layer,
                                                        const char* name) {
    return FindExtension(layer.instance_extensions, name);
}

const VkExtensionProperties* FindLayerDeviceExtension(const Layer& layer,
                                                      const char* name) {
    return FindExtension(layer.device_extensions, name);
}

LayerRef GetLayerRef(const Layer& layer) {
    LayerLibrary& library = g_layer_libraries[layer.library_idx];
    return LayerRef((library.Open()) ? &layer : nullptr);
}

LayerRef::LayerRef(const Layer* layer) : layer_(layer) {}

LayerRef::~LayerRef() {
    if (layer_) {
        LayerLibrary& library = g_layer_libraries[layer_->library_idx];
        library.Close();
    }
}

LayerRef::LayerRef(LayerRef&& other) : layer_(other.layer_) {
    other.layer_ = nullptr;
}

PFN_vkGetInstanceProcAddr LayerRef::GetGetInstanceProcAddr() const {
    return layer_ ? reinterpret_cast<PFN_vkGetInstanceProcAddr>(
                        GetLayerGetProcAddr(*layer_, "GetInstanceProcAddr", 19))
                  : nullptr;
}

PFN_vkGetDeviceProcAddr LayerRef::GetGetDeviceProcAddr() const {
    return layer_ ? reinterpret_cast<PFN_vkGetDeviceProcAddr>(
                        GetLayerGetProcAddr(*layer_, "GetDeviceProcAddr", 17))
                  : nullptr;
}

}  // namespace api
}  // namespace vulkan
