/*
 * 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 ATRACE_TAG ATRACE_TAG_RESOURCES

#include "androidfw/Idmap.h"

#include "android-base/logging.h"
#include "android-base/stringprintf.h"
#include "androidfw/ResourceTypes.h"
#include "androidfw/Util.h"
#include "utils/ByteOrder.h"
#include "utils/Trace.h"

#ifdef _WIN32
#ifdef ERROR
#undef ERROR
#endif
#endif

using ::android::base::StringPrintf;

namespace android {

static bool compare_target_entries(const Idmap_target_entry &e1, const uint32_t target_id) {
  return dtohl(e1.target_id) < target_id;
}

static bool compare_overlay_entries(const Idmap_overlay_entry& e1, const uint32_t overlay_id) {
  return dtohl(e1.overlay_id) < overlay_id;
}

size_t Idmap_header::Size() const {
  return sizeof(Idmap_header) + sizeof(uint8_t) * dtohl(debug_info_size);
}

OverlayStringPool::OverlayStringPool(const LoadedIdmap* loaded_idmap)
    : data_header_(loaded_idmap->data_header_),
      idmap_string_pool_(loaded_idmap->string_pool_.get()) { };

OverlayStringPool::~OverlayStringPool() {
  uninit();
}

const char16_t* OverlayStringPool::stringAt(size_t idx, size_t* outLen) const {
  const size_t offset = dtohl(data_header_->string_pool_index_offset);
  if (idmap_string_pool_ != nullptr && idx >= ResStringPool::size() && idx >= offset) {
    return idmap_string_pool_->stringAt(idx - offset, outLen);
  }

  return ResStringPool::stringAt(idx, outLen);
}

const char* OverlayStringPool::string8At(size_t idx, size_t* outLen) const {
  const size_t offset = dtohl(data_header_->string_pool_index_offset);
  if (idmap_string_pool_ != nullptr && idx >= ResStringPool::size() && idx >= offset) {
    return idmap_string_pool_->string8At(idx - offset, outLen);
  }

  return ResStringPool::string8At(idx, outLen);
}

size_t OverlayStringPool::size() const {
  return ResStringPool::size() + (idmap_string_pool_ != nullptr ? idmap_string_pool_->size() : 0U);
}

OverlayDynamicRefTable::OverlayDynamicRefTable(const Idmap_data_header* data_header,
                                               const Idmap_overlay_entry* entries,
                                               uint8_t target_assigned_package_id)
    : data_header_(data_header),
      entries_(entries),
      target_assigned_package_id_(target_assigned_package_id) { };

status_t OverlayDynamicRefTable::lookupResourceId(uint32_t* resId) const {
  const Idmap_overlay_entry* first_entry = entries_;
  const Idmap_overlay_entry* end_entry = entries_ + dtohl(data_header_->overlay_entry_count);
  auto entry = std::lower_bound(first_entry, end_entry, *resId, compare_overlay_entries);

  if (entry == end_entry || dtohl(entry->overlay_id) != *resId) {
    // A mapping for the target resource id could not be found.
    return DynamicRefTable::lookupResourceId(resId);
  }

  *resId = (0x00FFFFFFU & dtohl(entry->target_id))
      | (((uint32_t) target_assigned_package_id_) << 24);
  return NO_ERROR;
}

status_t OverlayDynamicRefTable::lookupResourceIdNoRewrite(uint32_t* resId) const {
  return DynamicRefTable::lookupResourceId(resId);
}

IdmapResMap::IdmapResMap(const Idmap_data_header* data_header,
                         const Idmap_target_entry* entries,
                         uint8_t target_assigned_package_id,
                         const OverlayDynamicRefTable* overlay_ref_table)
    : data_header_(data_header),
      entries_(entries),
      target_assigned_package_id_(target_assigned_package_id),
      overlay_ref_table_(overlay_ref_table) { };

IdmapResMap::Result IdmapResMap::Lookup(uint32_t target_res_id) const {
  if ((target_res_id >> 24) != target_assigned_package_id_) {
    // The resource id must have the same package id as the target package.
    return {};
  }

  // The resource ids encoded within the idmap are build-time resource ids.
  target_res_id = (0x00FFFFFFU & target_res_id)
      | (((uint32_t) data_header_->target_package_id) << 24);

  const Idmap_target_entry* first_entry = entries_;
  const Idmap_target_entry* end_entry = entries_ + dtohl(data_header_->target_entry_count);
  auto entry = std::lower_bound(first_entry, end_entry, target_res_id, compare_target_entries);

  if (entry == end_entry || dtohl(entry->target_id) != target_res_id) {
    // A mapping for the target resource id could not be found.
    return {};
  }

  // A reference should be treated as an alias of the resource. Instead of returning the table
  // entry, return the alias resource id to look up. The alias resource might not reside within the
  // overlay package, so the resource id must be fixed with the dynamic reference table of the
  // overlay before returning.
  if (entry->type == Res_value::TYPE_REFERENCE
      || entry->type == Res_value::TYPE_DYNAMIC_REFERENCE) {
    uint32_t overlay_resource_id = dtohl(entry->value);

    // Lookup the resource without rewriting the overlay resource id back to the target resource id
    // being looked up.
    overlay_ref_table_->lookupResourceIdNoRewrite(&overlay_resource_id);
    return Result(overlay_resource_id);
  }

  // Copy the type and value into the ResTable_entry structure needed by asset manager.
  uint16_t malloc_size = sizeof(ResTable_entry) + sizeof(Res_value);
  auto table_entry = reinterpret_cast<ResTable_entry*>(malloc(malloc_size));
  memset(table_entry, 0, malloc_size);
  table_entry->size = htods(sizeof(ResTable_entry));

  auto table_value = reinterpret_cast<Res_value*>(reinterpret_cast<uint8_t*>(table_entry)
      + sizeof(ResTable_entry));
  table_value->dataType = entry->type;
  table_value->data = entry->value;

  return Result(ResTable_entry_handle::managed(table_entry));
}

static bool is_word_aligned(const void* data) {
  return (reinterpret_cast<uintptr_t>(data) & 0x03) == 0;
}

static bool IsValidIdmapHeader(const StringPiece& data) {
  if (!is_word_aligned(data.data())) {
    LOG(ERROR) << "Idmap header is not word aligned.";
    return false;
  }

  if (data.size() < sizeof(Idmap_header)) {
    LOG(ERROR) << "Idmap header is too small.";
    return false;
  }

  const Idmap_header* header = reinterpret_cast<const Idmap_header*>(data.data());
  if (dtohl(header->magic) != kIdmapMagic) {
    LOG(ERROR) << StringPrintf("Invalid Idmap file: bad magic value (was 0x%08x, expected 0x%08x)",
                               dtohl(header->magic), kIdmapMagic);
    return false;
  }

  if (dtohl(header->version) != kIdmapCurrentVersion) {
    // We are strict about versions because files with this format are auto-generated and don't need
    // backwards compatibility.
    LOG(ERROR) << StringPrintf("Version mismatch in Idmap (was 0x%08x, expected 0x%08x)",
                               dtohl(header->version), kIdmapCurrentVersion);
    return false;
  }

  return true;
}

LoadedIdmap::LoadedIdmap(const Idmap_header* header,
                         const Idmap_data_header* data_header,
                         const Idmap_target_entry* target_entries,
                         const Idmap_overlay_entry* overlay_entries,
                         ResStringPool* string_pool)
     : header_(header),
       data_header_(data_header),
       target_entries_(target_entries),
       overlay_entries_(overlay_entries),
       string_pool_(string_pool) {

  size_t length = strnlen(reinterpret_cast<const char*>(header_->overlay_path),
                          arraysize(header_->overlay_path));
  overlay_apk_path_.assign(reinterpret_cast<const char*>(header_->overlay_path), length);

  length = strnlen(reinterpret_cast<const char*>(header_->target_path),
                          arraysize(header_->target_path));
  target_apk_path_.assign(reinterpret_cast<const char*>(header_->target_path), length);
}

std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_data) {
  ATRACE_CALL();
  if (!IsValidIdmapHeader(idmap_data)) {
    return {};
  }

  auto header = reinterpret_cast<const Idmap_header*>(idmap_data.data());
  const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(idmap_data.data()) + header->Size();
  size_t data_size = idmap_data.size() - header->Size();

  // Currently idmap2 can only generate one data block.
  auto data_header = reinterpret_cast<const Idmap_data_header*>(data_ptr);
  data_ptr += sizeof(*data_header);
  data_size -= sizeof(*data_header);

  // Make sure there is enough space for the target entries declared in the header.
  const auto target_entries = reinterpret_cast<const Idmap_target_entry*>(data_ptr);
  if (data_size / sizeof(Idmap_target_entry) <
      static_cast<size_t>(dtohl(data_header->target_entry_count))) {
    LOG(ERROR) << StringPrintf("Idmap too small for the number of target entries (%d)",
                               (int)dtohl(data_header->target_entry_count));
    return {};
  }

  // Advance the data pointer past the target entries.
  const size_t target_entry_size_bytes =
      (dtohl(data_header->target_entry_count) * sizeof(Idmap_target_entry));
  data_ptr += target_entry_size_bytes;
  data_size -= target_entry_size_bytes;

  // Make sure there is enough space for the overlay entries declared in the header.
  const auto overlay_entries = reinterpret_cast<const Idmap_overlay_entry*>(data_ptr);
  if (data_size / sizeof(Idmap_overlay_entry) <
      static_cast<size_t>(dtohl(data_header->overlay_entry_count))) {
    LOG(ERROR) << StringPrintf("Idmap too small for the number of overlay entries (%d)",
                               (int)dtohl(data_header->overlay_entry_count));
    return {};
  }

  // Advance the data pointer past the target entries.
  const size_t overlay_entry_size_bytes =
      (dtohl(data_header->overlay_entry_count) * sizeof(Idmap_overlay_entry));
  data_ptr += overlay_entry_size_bytes;
  data_size -= overlay_entry_size_bytes;

  // Read the idmap string pool that holds the value of inline string entries.
  if (data_size < dtohl(data_header->string_pool_length)) {
    LOG(ERROR) << StringPrintf("Idmap too small for string pool (length %d)",
                               (int)dtohl(data_header->string_pool_length));
    return {};
  }

  auto idmap_string_pool = util::make_unique<ResStringPool>();
  if (dtohl(data_header->string_pool_length) > 0) {
    status_t err = idmap_string_pool->setTo(data_ptr, dtohl(data_header->string_pool_length));
    if (err != NO_ERROR) {
      LOG(ERROR) << "idmap string pool corrupt.";
      return {};
    }
  }

  // Can't use make_unique because LoadedIdmap constructor is private.
  std::unique_ptr<LoadedIdmap> loaded_idmap = std::unique_ptr<LoadedIdmap>(
      new LoadedIdmap(header, data_header, target_entries, overlay_entries,
                      idmap_string_pool.release()));

  return std::move(loaded_idmap);
}

}  // namespace android
