/*
 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
 * Copyright (c) 2011-2021, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of The Linux Foundation nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <log/log.h>
#include <cutils/properties.h>
#include <algorithm>
#include <vector>
#include <string>

#ifndef QMAA
#include <linux/msm_ion.h>
#endif
#include "gr_allocator.h"
#include "gr_utils.h"
#include <QtiGralloc.h>
#include <QtiGrallocPriv.h>
#include <QtiGrallocDefs.h>

#include "qd_utils.h"
#include "gr_alloc_interface.h"

using std::shared_ptr;
using std::vector;

namespace gralloc {

static BufferInfo GetBufferInfo(const BufferDescriptor &descriptor) {
  return BufferInfo(descriptor.GetWidth(), descriptor.GetHeight(), descriptor.GetFormat(),
                    descriptor.GetUsage());
}

void Allocator::SetProperties(gralloc::GrallocProperties props) {
  use_system_heap_for_sensors_ = props.use_system_heap_for_sensors;
}

int Allocator::AllocateMem(AllocData *alloc_data, uint64_t usage, int format) {
  int ret;
  bool is_secure = false;
  alloc_data->uncached = UseUncached(format, usage);

  AllocInterface *alloc_intf = AllocInterface::GetInstance();
  if (!alloc_intf) {
    return -ENOMEM;
  }

  if (!alloc_data->size) {
    ALOGE("%s: Failed to allocate buffer with size 0", __FUNCTION__);
    return -ENOMEM;
  }

  // After this point we should have the right heap set, there is no fallback

  alloc_intf->GetHeapInfo(usage, use_system_heap_for_sensors_, &alloc_data->heap_name,
                          &alloc_data->vm_names, &alloc_data->alloc_type, &alloc_data->flags,
                          &alloc_data->size);

  ret = alloc_intf->AllocBuffer(alloc_data);
  if (ret >= 0) {
    alloc_data->alloc_type |= qtigralloc::PRIV_FLAGS_USES_ION;
  } else {
    ALOGE("%s: Failed to allocate buffer - heap name: %s flags: 0x%x ret: %d", __FUNCTION__,
          alloc_data->heap_name.c_str(), alloc_data->flags, ret);
    return ret;
  }

  if (!alloc_data->vm_names.empty()) {
    ret = alloc_intf->SecureMemPerms(alloc_data);
  }

  if (ret) {
    ALOGE("%s: Failed to modify secure use permissions - heap name: %s flags: 0x%x, err: %d",
          __FUNCTION__, alloc_data->heap_name.c_str(), alloc_data->flags, ret);
  }

  return ret;
}

int Allocator::MapBuffer(void **base, unsigned int size, unsigned int offset, int fd) {
  AllocInterface *alloc_intf = AllocInterface::GetInstance();
  if (!alloc_intf) {
    return -ENOMEM;
  }
  if (alloc_intf) {
    return alloc_intf->MapBuffer(base, size, offset, fd);
  }

  return -EINVAL;
}

int Allocator::ImportBuffer(int fd) {
  AllocInterface *alloc_intf = AllocInterface::GetInstance();
  if (!alloc_intf) {
    return -ENOMEM;
  }
  if (alloc_intf) {
    return alloc_intf->ImportBuffer(fd);
  }

  return -EINVAL;
}

int Allocator::FreeBuffer(void *base, unsigned int size, unsigned int offset, int fd, int handle) {
  AllocInterface *alloc_intf = AllocInterface::GetInstance();
  if (!alloc_intf) {
    return -ENOMEM;
  }
  if (alloc_intf) {
    return alloc_intf->FreeBuffer(base, size, offset, fd, handle);
  }

  return -EINVAL;
}

int Allocator::CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op,
                           int fd) {
  AllocInterface *alloc_intf = AllocInterface::GetInstance();
  if (!alloc_intf) {
    return -ENOMEM;
  }
  if (alloc_intf) {
    return alloc_intf->CleanBuffer(base, size, offset, handle, op, fd);
  }

  return -EINVAL;
}

bool Allocator::CheckForBufferSharing(uint32_t num_descriptors,
                                      const vector<shared_ptr<BufferDescriptor>> &descriptors,
                                      ssize_t *max_index) {
  std::string cur_heap_name = "", prev_heap_name = "";
  std::vector<std::string> cur_vm_names, prev_vm_names;
  unsigned int cur_alloc_type = 0, prev_alloc_type = 0;
  unsigned int cur_flags = 0, prev_flags = 0;
  bool cur_uncached = false, prev_uncached = false;
  unsigned int alignedw, alignedh;
  unsigned int max_size = 0;
  bool is_secure = false;
  unsigned int cur_size = 0, prev_size = 0;

  *max_index = -1;

  AllocInterface *alloc_intf = AllocInterface::GetInstance();
  if (!alloc_intf) {
    return false;
  }

  for (uint32_t i = 0; i < num_descriptors; i++) {
    // Check Cached vs non-cached and all the flags
    cur_uncached = UseUncached(descriptors[i]->GetFormat(), descriptors[i]->GetUsage());
    alloc_intf->GetHeapInfo(descriptors[i]->GetUsage(), use_system_heap_for_sensors_,
                            &cur_heap_name, &cur_vm_names, &cur_alloc_type, &cur_flags, &cur_size);

    if (i > 0 &&
        (cur_heap_name != prev_heap_name || cur_alloc_type != prev_alloc_type ||
         cur_flags != prev_flags || cur_vm_names != prev_vm_names || cur_size != prev_size)) {
      return false;
    }

    // For same format type, find the descriptor with bigger size
    int err = GetAlignedWidthAndHeight(GetBufferInfo(*descriptors[i]), &alignedw, &alignedh);
    if (err) {
      return false;
    }
    unsigned int size = GetSize(GetBufferInfo(*descriptors[i]), alignedw, alignedh);
    if (max_size < size) {
      *max_index = INT(i);
      max_size = size;
    }

    prev_heap_name = cur_heap_name;
    prev_uncached = cur_uncached;
    prev_flags = cur_flags;
    prev_alloc_type = cur_alloc_type;
    prev_vm_names = cur_vm_names;
    prev_size = cur_size;
  }

  return true;
}

int Allocator::SetBufferPermission(int fd, BufferPermission *buffer_perm, int64_t *mem_hdl) {
  AllocInterface *alloc_intf = AllocInterface::GetInstance();
  if (!alloc_intf) {
    return -ENOMEM;
  }
  return alloc_intf->SetBufferPermission(fd, buffer_perm, mem_hdl);
}

}  // namespace gralloc
