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

#define ATRACE_TAG ATRACE_TAG_GRAPHICS

#include "layers_extensions.h"

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

#include <memory>
#include <mutex>
#include <string>
#include <vector>

#include <android/dlext.h>
#include <android-base/strings.h>
#include <cutils/properties.h>
#include <graphicsenv/GraphicsEnv.h>
#include <log/log.h>
#include <nativebridge/native_bridge.h>
#include <nativeloader/native_loader.h>
#include <utils/Trace.h>
#include <ziparchive/zip_archive.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:
    explicit LayerLibrary(const std::string& path,
                          const std::string& filename)
        : path_(path),
          filename_(filename),
          dlhandle_(nullptr),
          native_bridge_(false),
          refcount_(0) {}

    LayerLibrary(LayerLibrary&& other) noexcept
        : path_(std::move(other.path_)),
          filename_(std::move(other.filename_)),
          dlhandle_(other.dlhandle_),
          native_bridge_(other.native_bridge_),
          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 std::string_view gpa_name) const;

    const std::string GetFilename() { return filename_; }

   private:
    // TODO(b/79940628): remove that adapter when we could use NativeBridgeGetTrampoline
    // for native libraries.
    template<typename Func = void*>
    Func GetTrampoline(const char* name) const {
        if (native_bridge_) {
            return reinterpret_cast<Func>(android::NativeBridgeGetTrampoline(
                dlhandle_, name, nullptr, 0));
        }
        return reinterpret_cast<Func>(dlsym(dlhandle_, name));
    }

    const std::string path_;

    // Track the filename alone so we can detect duplicates
    const std::string filename_;

    std::mutex mutex_;
    void* dlhandle_;
    bool native_bridge_;
    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 = android::GraphicsEnv::getInstance().getAppNamespace();
        if (app_namespace &&
            !android::base::StartsWith(path_, kSystemLayerLibraryDir)) {
            char* error_msg = nullptr;
            dlhandle_ = OpenNativeLibraryInNamespace(
                app_namespace, path_.c_str(), &native_bridge_, &error_msg);
            if (!dlhandle_) {
                ALOGE("failed to load layer library '%s': %s", path_.c_str(), error_msg);
                android::NativeLoaderFreeErrorMessage(error_msg);
                refcount_ = 0;
                return false;
            }
        } 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());
        char* error_msg = nullptr;
        if (!android::CloseNativeLibrary(dlhandle_, native_bridge_, &error_msg)) {
            ALOGE("failed to unload library '%s': %s", path_.c_str(), error_msg);
            android::NativeLoaderFreeErrorMessage(error_msg);
            refcount_++;
        } else {
           dlhandle_ = nullptr;
        }
    }
}

bool LayerLibrary::EnumerateLayers(size_t library_idx,
                                   std::vector<Layer>& instance_layers) const {
    PFN_vkEnumerateInstanceLayerProperties enumerate_instance_layers =
        GetTrampoline<PFN_vkEnumerateInstanceLayerProperties>(
            "vkEnumerateInstanceLayerProperties");
    PFN_vkEnumerateInstanceExtensionProperties enumerate_instance_extensions =
        GetTrampoline<PFN_vkEnumerateInstanceExtensionProperties>(
            "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 =
        GetTrampoline<PFN_vkEnumerateDeviceLayerProperties>(
            "vkEnumerateDeviceLayerProperties");
    PFN_vkEnumerateDeviceExtensionProperties enumerate_device_extensions =
        GetTrampoline<PFN_vkEnumerateDeviceExtensionProperties>(
            "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
    auto properties = std::make_unique<VkLayerProperties[]>(num_instance_layers + num_device_layers);
    if (num_device_layers > 0) {
        result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
                                         properties.get() + 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 std::string_view gpa_name) const {
    std::string layer_name { layer.properties.layerName };
    if (void* gpa = GetTrampoline((layer_name.append(gpa_name).c_str())))
        return gpa;
    return GetTrampoline((std::string {"vk"}.append(gpa_name)).c_str());
}

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

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

void AddLayerLibrary(const std::string& path, const std::string& filename) {
    LayerLibrary library(path + "/" + filename, filename);
    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 + "/");
    void* iter_cookie = nullptr;
    if ((err = StartIteration(zip, &iter_cookie, prefix, "")) != 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;
    std::string name;
    while (Next(iter_cookie, &entry, &name) == 0) {
        std::string filename(name.substr(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) {
    ATRACE_CALL();

    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")) {

                // Check to ensure we haven't seen this layer already
                // Let the first instance of the shared object be enumerated
                // We're searching for layers in following order:
                // 1. system path
                // 2. libraryPermittedPath (if enabled)
                // 3. libraryPath

                bool duplicate = false;
                for (auto& layer : g_layer_libraries) {
                    if (layer.GetFilename() == filename) {
                        ALOGV("Skipping duplicate layer %s in %s",
                              filename.c_str(), path.c_str());
                        duplicate = true;
                    }
                }

                if (!duplicate)
                    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 std::string_view gpa_name) {
    const LayerLibrary& library = g_layer_libraries[layer.library_idx];
    return library.GetGPA(layer, gpa_name);
}

}  // anonymous namespace

void DiscoverLayers() {
    ATRACE_CALL();

    if (property_get_bool("ro.debuggable", false) &&
        prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
        DiscoverLayersInPathList(kSystemLayerLibraryDir);
    }
    if (!android::GraphicsEnv::getInstance().getLayerPaths().empty())
        DiscoverLayersInPathList(android::GraphicsEnv::getInstance().getLayerPaths());
}

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) noexcept : layer_(other.layer_) {
    other.layer_ = nullptr;
}

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

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

}  // namespace api
}  // namespace vulkan
