/*
 * 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/misc.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(std::string&& idmap_path,
                         const time_t last_mod_time,
                         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),
       idmap_path_(std::move(idmap_path)),
       idmap_last_mod_time_(last_mod_time) {

  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_path,
                                                     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(idmap_path.to_string(), getFileModDate(idmap_path.data()), header,
                      data_header, target_entries, overlay_entries, idmap_string_pool.release()));

  return std::move(loaded_idmap);
}

bool LoadedIdmap::IsUpToDate() const {
  return idmap_last_mod_time_ == getFileModDate(idmap_path_.c_str());
}

}  // namespace android
