/*
 * Copyright (C) 2016, 2018-2020 ARM Limited. All rights reserved.
 *
 * Copyright (C) 2008 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 "mali_gralloc_reference.h"

#include <android-base/thread_annotations.h>
#include <hardware/gralloc1.h>

#include <algorithm>
#include <map>
#include <mutex>

#include "allocator/mali_gralloc_ion.h"
#include "mali_gralloc_buffer.h"

class BufferManager {
private:
    // This struct for now is just for validation and reference counting. When we
    // are sure that private_handle_t::bases is not being used outside gralloc, this
    // should become the only place where address mapping is maintained and can be
    // queried from.
    struct MappedData {
        std::array<void *, MAX_BUFFER_FDS> bases;
        size_t alloc_sizes[MAX_BUFFER_FDS] = {};

        void *metadata_vaddr;
        size_t metadata_size;

        uint64_t ref_count = 0;
    };

    BufferManager() = default;

    std::mutex lock;
    std::map<const private_handle_t *, std::unique_ptr<MappedData>> buffer_map GUARDED_BY(lock);

    static off_t get_buffer_size(unsigned int fd) {
        off_t current = lseek(fd, 0, SEEK_CUR);
        off_t size = lseek(fd, 0, SEEK_END);
        lseek(fd, current, SEEK_SET);
        return size;
    }

    // TODO(b/296934447): AION buffers set the size of the buffer themselves. That size exceeds the
    // size of the actual allocated dmabuf.
    static bool dmabuf_sanity_check(buffer_handle_t handle, bool skip_buffer_size_check = false) {
        private_handle_t *hnd =
                static_cast<private_handle_t *>(const_cast<native_handle_t *>(handle));

        int valid_fd_count = std::find(hnd->fds, hnd->fds + MAX_FDS, -1) - hnd->fds;
        // One fd is reserved for metadata which is not accounted for in fd_count
        if (hnd->fd_count != valid_fd_count - 1) {
            MALI_GRALLOC_LOGE("%s failed: count of valid buffer fds does not match fd_count",
                              __func__);
            return false;
        }

        auto check_pid = [&](int fd, uint64_t allocated_size) -> bool {
            auto size = get_buffer_size(fd);
            auto size_padding = size - (off_t)allocated_size;
            if ((size != -1) && ((size_padding < 0) || (size_padding > PAGE_SIZE))) {
                MALI_GRALLOC_LOGE("%s failed: fd (%d) size (%jd) is not within a PAGE_SIZE of "
                                  "expected size (%" PRIx64 ")",
                                  __func__, fd, static_cast<intmax_t>(size), allocated_size);
                return false;
            }
            return true;
        };

        // Check client facing dmabufs
        if (!skip_buffer_size_check) {
            for (auto i = 0; i < hnd->fd_count; i++) {
                if (!check_pid(hnd->fds[i], hnd->alloc_sizes[i])) {
                    MALI_GRALLOC_LOGE("%s failed: Size check failed for alloc_sizes[%d]", __func__,
                                      i);
                    return false;
                }
            }
        }

        // Check metadata dmabuf
        if (!check_pid(hnd->get_share_attr_fd(), hnd->attr_size)) {
            MALI_GRALLOC_LOGE("%s failed: Size check failed for metadata fd", __func__);
            return false;
        }

        return true;
    }

    bool map_buffer_locked(buffer_handle_t handle) REQUIRES(lock) {
        auto data_oe = get_validated_data_locked(handle);
        if (!data_oe.has_value()) {
            return false;
        }
        MappedData &data = data_oe.value();

        // Return early if buffer is already mapped
        if (data.bases[0] != nullptr) {
            return true;
        }

        if (!dmabuf_sanity_check(handle)) {
            return false;
        }

        private_handle_t *hnd =
                reinterpret_cast<private_handle_t *>(const_cast<native_handle *>(handle));
        data.bases = mali_gralloc_ion_map(hnd);
        if (data.bases[0] == nullptr) {
            return false;
        }

        for (auto i = 0; i < MAX_BUFFER_FDS; i++) {
            data.alloc_sizes[i] = hnd->alloc_sizes[i];
        }

        return true;
    }

    bool map_metadata_locked(buffer_handle_t handle) REQUIRES(lock) {
        auto data_oe = get_validated_data_locked(handle);
        if (!data_oe.has_value()) {
            return false;
        }
        MappedData &data = data_oe.value();

        // Return early if buffer is already mapped
        if (data.metadata_vaddr != nullptr) {
            return true;
        }

        if (!dmabuf_sanity_check(handle, /*skip_buffer_size_check=*/true)) {
            return false;
        }

        private_handle_t *hnd =
                reinterpret_cast<private_handle_t *>(const_cast<native_handle *>(handle));
        data.metadata_vaddr = mmap(nullptr, hnd->attr_size, PROT_READ | PROT_WRITE, MAP_SHARED,
                                   hnd->get_share_attr_fd(), 0);
        if (data.metadata_vaddr == nullptr) {
            return false;
        }

        data.metadata_size = hnd->attr_size;
        return true;
    }

    bool validate_locked(buffer_handle_t handle) REQUIRES(lock) {
        if (private_handle_t::validate(handle) < 0) {
            MALI_GRALLOC_LOGE("Reference invalid buffer %p, returning error", handle);
            return false;
        }

        const auto *hnd = reinterpret_cast<private_handle_t *>(const_cast<native_handle *>(handle));
        auto it = buffer_map.find(hnd);
        if (it == buffer_map.end()) {
            MALI_GRALLOC_LOGE("Reference unimported buffer %p, returning error", handle);
            return false;
        }

        auto &data = *(it->second.get());
        if (data.bases[0] != nullptr) {
            for (auto i = 0; i < MAX_BUFFER_FDS; i++) {
                if (data.alloc_sizes[i] != hnd->alloc_sizes[i]) {
                    MALI_GRALLOC_LOGE(
                            "Validation failed: Buffer attributes inconsistent with mapper");
                    return false;
                }
            }
        } else {
            for (auto i = 0; i < MAX_BUFFER_FDS; i++) {
                if (data.bases[i] != nullptr) {
                    MALI_GRALLOC_LOGE("Validation failed: Expected nullptr for unmapped buffer");
                    return false;
                }
            }
        }

        return true;
    }

    std::optional<std::reference_wrapper<MappedData>> get_validated_data_locked(
            buffer_handle_t handle) REQUIRES(lock) {
        if (!validate_locked(handle)) {
            return {};
        }

        private_handle_t *hnd =
                reinterpret_cast<private_handle_t *>(const_cast<native_handle *>(handle));
        auto it = buffer_map.find(hnd);
        if (it == buffer_map.end()) {
            MALI_GRALLOC_LOGE("Trying to release a non-imported buffer");
            return {};
        }

        MappedData &data = *(it->second.get());
        if (data.ref_count == 0) {
            MALI_GRALLOC_LOGE("BUG: Found an imported buffer with ref count 0, expect errors");
        }

        return data;
    }

public:
    static BufferManager &getInstance() {
        static BufferManager instance;
        return instance;
    }

    int retain(buffer_handle_t handle) EXCLUDES(lock) {
        if (private_handle_t::validate(handle) < 0) {
            MALI_GRALLOC_LOGE("Registering/Retaining invalid buffer %p, returning error", handle);
            return -EINVAL;
        }
        std::lock_guard<std::mutex> _l(lock);

        private_handle_t *hnd =
                reinterpret_cast<private_handle_t *>(const_cast<native_handle *>(handle));

        auto it = buffer_map.find(hnd);
        if (it == buffer_map.end()) {
            bool success = false;
            auto _data = std::make_unique<MappedData>();

            std::tie(it, success) = buffer_map.insert({hnd, std::move(_data)});
            if (!success) {
                MALI_GRALLOC_LOGE("Failed to create buffer data mapping");
                return -EINVAL;
            }
        } else if (it->second->ref_count == 0) {
            MALI_GRALLOC_LOGE("BUG: Import counter of an imported buffer is 0, expect errors");
        }
        auto &data = *(it->second.get());

        data.ref_count++;
        return 0;
    }

    int map(buffer_handle_t handle) EXCLUDES(lock) {
        std::lock_guard<std::mutex> _l(lock);
        if (!map_buffer_locked(handle)) {
            return -EINVAL;
        }

        return 0;
    }

    int release(buffer_handle_t handle) EXCLUDES(lock) {
        std::lock_guard<std::mutex> _l(lock);

        auto data_oe = get_validated_data_locked(handle);
        if (!data_oe.has_value()) {
            return -EINVAL;
        }
        MappedData &data = data_oe.value();

        if (data.ref_count == 0) {
            MALI_GRALLOC_LOGE("BUG: Reference held for buffer whose counter is 0");
            return -EINVAL;
        }

        data.ref_count--;
        if (data.ref_count == 0) {
            private_handle_t *hnd =
                    reinterpret_cast<private_handle_t *>(const_cast<native_handle *>(handle));
            auto it = buffer_map.find(hnd);

            if (data.bases[0] != nullptr) {
                mali_gralloc_ion_unmap(hnd, data.bases);
            }

            if (data.metadata_vaddr != nullptr) {
                munmap(data.metadata_vaddr, data.metadata_size);
                data.metadata_vaddr = nullptr;
            }

            buffer_map.erase(it);
        }

        return 0;
    }

    int validate(buffer_handle_t handle) EXCLUDES(lock) {
        std::lock_guard<std::mutex> _l(lock);

        if (!validate_locked(handle)) {
            return -EINVAL;
        }

        return 0;
    }

    std::optional<void *> get_buf_addr(buffer_handle_t handle) {
        std::lock_guard<std::mutex> _l(lock);

        auto data_oe = get_validated_data_locked(handle);
        if (!data_oe.has_value()) {
            return {};
        }
        MappedData &data = data_oe.value();

        if (data.bases[0] == nullptr) {
            MALI_GRALLOC_LOGE("BUG: Called %s for an un-mapped buffer", __FUNCTION__);
            return {};
        }

        return data.bases[0];
    }

    std::optional<void *> get_metadata_addr(buffer_handle_t handle) {
        std::lock_guard<std::mutex> _l(lock);

        auto data_oe = get_validated_data_locked(handle);
        if (!data_oe.has_value()) {
            return {};
        }
        MappedData &data = data_oe.value();

        if (data.metadata_vaddr == nullptr) {
            if (!map_metadata_locked(handle)) {
                return {};
            }
        }

        return data.metadata_vaddr;
    }
};

int mali_gralloc_reference_retain(buffer_handle_t handle) {
    return BufferManager::getInstance().retain(handle);
}

int mali_gralloc_reference_map(buffer_handle_t handle) {
    return BufferManager::getInstance().map(handle);
}

int mali_gralloc_reference_release(buffer_handle_t handle) {
    return BufferManager::getInstance().release(handle);
}

int mali_gralloc_reference_validate(buffer_handle_t handle) {
    return BufferManager::getInstance().validate(handle);
}

std::optional<void *> mali_gralloc_reference_get_buf_addr(buffer_handle_t handle) {
    return BufferManager::getInstance().get_buf_addr(handle);
}

std::optional<void *> mali_gralloc_reference_get_metadata_addr(buffer_handle_t handle) {
    return BufferManager::getInstance().get_metadata_addr(handle);
}
