//
// Copyright (C) 2015 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 "update_engine/boot_control_android.h"

#include <memory>
#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/logging.h>
#include <base/strings/string_util.h>
#include <bootloader_message/bootloader_message.h>
#include <brillo/message_loops/message_loop.h>
#include <fs_mgr.h>

#include "update_engine/common/utils.h"
#include "update_engine/dynamic_partition_control_android.h"

using std::string;

using android::dm::DmDeviceState;
using android::fs_mgr::Partition;
using android::hardware::hidl_string;
using android::hardware::Return;
using android::hardware::boot::V1_0::BoolResult;
using android::hardware::boot::V1_0::CommandResult;
using android::hardware::boot::V1_0::IBootControl;
using Slot = chromeos_update_engine::BootControlInterface::Slot;
using PartitionMetadata =
    chromeos_update_engine::BootControlInterface::PartitionMetadata;

namespace {

auto StoreResultCallback(CommandResult* dest) {
  return [dest](const CommandResult& result) { *dest = result; };
}
}  // namespace

namespace chromeos_update_engine {

namespace boot_control {

// Factory defined in boot_control.h.
std::unique_ptr<BootControlInterface> CreateBootControl() {
  auto boot_control = std::make_unique<BootControlAndroid>();
  if (!boot_control->Init()) {
    return nullptr;
  }
  return std::move(boot_control);
}

}  // namespace boot_control

bool BootControlAndroid::Init() {
  module_ = IBootControl::getService();
  if (module_ == nullptr) {
    LOG(ERROR) << "Error getting bootctrl HIDL module.";
    return false;
  }

  LOG(INFO) << "Loaded boot control hidl hal.";

  dynamic_control_ = std::make_unique<DynamicPartitionControlAndroid>();

  return true;
}

void BootControlAndroid::Cleanup() {
  dynamic_control_->Cleanup();
}

unsigned int BootControlAndroid::GetNumSlots() const {
  return module_->getNumberSlots();
}

BootControlInterface::Slot BootControlAndroid::GetCurrentSlot() const {
  return module_->getCurrentSlot();
}

bool BootControlAndroid::GetSuffix(Slot slot, string* suffix) const {
  auto store_suffix_cb = [&suffix](hidl_string cb_suffix) {
    *suffix = cb_suffix.c_str();
  };
  Return<void> ret = module_->getSuffix(slot, store_suffix_cb);

  if (!ret.isOk()) {
    LOG(ERROR) << "boot_control impl returned no suffix for slot "
               << SlotName(slot);
    return false;
  }
  return true;
}

namespace {

enum class DynamicPartitionDeviceStatus {
  SUCCESS,
  ERROR,
  TRY_STATIC,
};

DynamicPartitionDeviceStatus GetDynamicPartitionDevice(
    DynamicPartitionControlInterface* dynamic_control,
    const string& super_device,
    const string& partition_name_suffix,
    Slot slot,
    string* device) {
  auto builder = dynamic_control->LoadMetadataBuilder(super_device, slot);

  if (builder == nullptr) {
    if (!dynamic_control->IsDynamicPartitionsEnabled()) {
      return DynamicPartitionDeviceStatus::TRY_STATIC;
    }
    LOG(ERROR) << "No metadata in slot "
               << BootControlInterface::SlotName(slot);
    return DynamicPartitionDeviceStatus::ERROR;
  }

  if (builder->FindPartition(partition_name_suffix) == nullptr) {
    LOG(INFO) << partition_name_suffix
              << " is not in super partition metadata.";
    return DynamicPartitionDeviceStatus::TRY_STATIC;
  }

  DmDeviceState state = dynamic_control->GetState(partition_name_suffix);

  if (state == DmDeviceState::ACTIVE) {
    if (dynamic_control->GetDmDevicePathByName(partition_name_suffix, device)) {
      LOG(INFO) << partition_name_suffix
                << " is mapped on device mapper: " << *device;
      return DynamicPartitionDeviceStatus::SUCCESS;
    }
    LOG(ERROR) << partition_name_suffix << " is mapped but path is unknown.";
    return DynamicPartitionDeviceStatus::ERROR;
  }

  // DeltaPerformer calls InitPartitionMetadata before calling
  // InstallPlan::LoadPartitionsFromSlots. After InitPartitionMetadata,
  // the target partition must be re-mapped with force_writable == true.
  // Hence, if it is not mapped, we assume it is a source partition and
  // map it without force_writable.
  if (state == DmDeviceState::INVALID) {
    if (dynamic_control->MapPartitionOnDeviceMapper(super_device,
                                                    partition_name_suffix,
                                                    slot,
                                                    false /* force_writable */,
                                                    device)) {
      return DynamicPartitionDeviceStatus::SUCCESS;
    }
    return DynamicPartitionDeviceStatus::ERROR;
  }

  LOG(ERROR) << partition_name_suffix
             << " is mapped on device mapper but state is unknown: "
             << static_cast<std::underlying_type_t<DmDeviceState>>(state);
  return DynamicPartitionDeviceStatus::ERROR;
}
}  // namespace

bool BootControlAndroid::GetPartitionDevice(const string& partition_name,
                                            Slot slot,
                                            string* device) const {
  string suffix;
  if (!GetSuffix(slot, &suffix)) {
    return false;
  }
  const string partition_name_suffix = partition_name + suffix;

  string device_dir_str;
  if (!dynamic_control_->GetDeviceDir(&device_dir_str)) {
    return false;
  }
  base::FilePath device_dir(device_dir_str);

  string super_device =
      device_dir.Append(fs_mgr_get_super_partition_name()).value();
  switch (GetDynamicPartitionDevice(dynamic_control_.get(),
                                    super_device,
                                    partition_name_suffix,
                                    slot,
                                    device)) {
    case DynamicPartitionDeviceStatus::SUCCESS:
      return true;
    case DynamicPartitionDeviceStatus::TRY_STATIC:
      break;
    case DynamicPartitionDeviceStatus::ERROR:  // fallthrough
    default:
      return false;
  }

  base::FilePath path = device_dir.Append(partition_name_suffix);
  if (!dynamic_control_->DeviceExists(path.value())) {
    LOG(ERROR) << "Device file " << path.value() << " does not exist.";
    return false;
  }

  *device = path.value();
  return true;
}

bool BootControlAndroid::IsSlotBootable(Slot slot) const {
  Return<BoolResult> ret = module_->isSlotBootable(slot);
  if (!ret.isOk()) {
    LOG(ERROR) << "Unable to determine if slot " << SlotName(slot)
               << " is bootable: "
               << ret.description();
    return false;
  }
  if (ret == BoolResult::INVALID_SLOT) {
    LOG(ERROR) << "Invalid slot: " << SlotName(slot);
    return false;
  }
  return ret == BoolResult::TRUE;
}

bool BootControlAndroid::MarkSlotUnbootable(Slot slot) {
  CommandResult result;
  auto ret = module_->setSlotAsUnbootable(slot, StoreResultCallback(&result));
  if (!ret.isOk()) {
    LOG(ERROR) << "Unable to call MarkSlotUnbootable for slot "
               << SlotName(slot) << ": "
               << ret.description();
    return false;
  }
  if (!result.success) {
    LOG(ERROR) << "Unable to mark slot " << SlotName(slot)
               << " as unbootable: " << result.errMsg.c_str();
  }
  return result.success;
}

bool BootControlAndroid::SetActiveBootSlot(Slot slot) {
  CommandResult result;
  auto ret = module_->setActiveBootSlot(slot, StoreResultCallback(&result));
  if (!ret.isOk()) {
    LOG(ERROR) << "Unable to call SetActiveBootSlot for slot " << SlotName(slot)
               << ": " << ret.description();
    return false;
  }
  if (!result.success) {
    LOG(ERROR) << "Unable to set the active slot to slot " << SlotName(slot)
               << ": " << result.errMsg.c_str();
  }
  return result.success;
}

bool BootControlAndroid::MarkBootSuccessfulAsync(
    base::Callback<void(bool)> callback) {
  CommandResult result;
  auto ret = module_->markBootSuccessful(StoreResultCallback(&result));
  if (!ret.isOk()) {
    LOG(ERROR) << "Unable to call MarkBootSuccessful: "
               << ret.description();
    return false;
  }
  if (!result.success) {
    LOG(ERROR) << "Unable to mark boot successful: " << result.errMsg.c_str();
  }
  return brillo::MessageLoop::current()->PostTask(
             FROM_HERE, base::Bind(callback, result.success)) !=
         brillo::MessageLoop::kTaskIdNull;
}

namespace {

bool InitPartitionMetadataInternal(
    DynamicPartitionControlInterface* dynamic_control,
    const string& super_device,
    Slot source_slot,
    Slot target_slot,
    const string& target_suffix,
    const PartitionMetadata& partition_metadata) {
  auto builder =
      dynamic_control->LoadMetadataBuilder(super_device, source_slot);
  if (builder == nullptr) {
    // TODO(elsk): allow reconstructing metadata from partition_metadata
    // in recovery sideload.
    LOG(ERROR) << "No metadata at "
               << BootControlInterface::SlotName(source_slot);
    return false;
  }

  std::vector<string> groups = builder->ListGroups();
  for (const auto& group_name : groups) {
    if (base::EndsWith(
            group_name, target_suffix, base::CompareCase::SENSITIVE)) {
      LOG(INFO) << "Removing group " << group_name;
      builder->RemoveGroupAndPartitions(group_name);
    }
  }

  uint64_t total_size = 0;
  for (const auto& group : partition_metadata.groups) {
    total_size += group.size;
  }

  if (total_size > (builder->AllocatableSpace() / 2)) {
    LOG(ERROR)
        << "The maximum size of all groups with suffix " << target_suffix
        << " (" << total_size
        << ") has exceeded half of allocatable space for dynamic partitions "
        << (builder->AllocatableSpace() / 2) << ".";
    return false;
  }

  for (const auto& group : partition_metadata.groups) {
    auto group_name_suffix = group.name + target_suffix;
    if (!builder->AddGroup(group_name_suffix, group.size)) {
      LOG(ERROR) << "Cannot add group " << group_name_suffix << " with size "
                 << group.size;
      return false;
    }
    LOG(INFO) << "Added group " << group_name_suffix << " with size "
              << group.size;

    for (const auto& partition : group.partitions) {
      auto parition_name_suffix = partition.name + target_suffix;
      Partition* p = builder->AddPartition(
          parition_name_suffix, group_name_suffix, LP_PARTITION_ATTR_READONLY);
      if (!p) {
        LOG(ERROR) << "Cannot add partition " << parition_name_suffix
                   << " to group " << group_name_suffix;
        return false;
      }
      if (!builder->ResizePartition(p, partition.size)) {
        LOG(ERROR) << "Cannot resize partition " << parition_name_suffix
                   << " to size " << partition.size << ". Not enough space?";
        return false;
      }
      LOG(INFO) << "Added partition " << parition_name_suffix << " to group "
                << group_name_suffix << " with size " << partition.size;
    }
  }

  return dynamic_control->StoreMetadata(
      super_device, builder.get(), target_slot);
}

// Unmap all partitions, and remap partitions as writable.
bool Remap(DynamicPartitionControlInterface* dynamic_control,
           const string& super_device,
           Slot target_slot,
           const string& target_suffix,
           const PartitionMetadata& partition_metadata) {
  for (const auto& group : partition_metadata.groups) {
    for (const auto& partition : group.partitions) {
      if (!dynamic_control->UnmapPartitionOnDeviceMapper(
              partition.name + target_suffix, true /* wait */)) {
        return false;
      }
      if (partition.size == 0) {
        continue;
      }
      string map_path;
      if (!dynamic_control->MapPartitionOnDeviceMapper(
              super_device,
              partition.name + target_suffix,
              target_slot,
              true /* force writable */,
              &map_path)) {
        return false;
      }
    }
  }
  return true;
}

}  // namespace

bool BootControlAndroid::InitPartitionMetadata(
    Slot target_slot, const PartitionMetadata& partition_metadata) {
  if (!dynamic_control_->IsDynamicPartitionsEnabled()) {
    return true;
  }

  string device_dir_str;
  if (!dynamic_control_->GetDeviceDir(&device_dir_str)) {
    return false;
  }
  base::FilePath device_dir(device_dir_str);
  string super_device =
      device_dir.Append(fs_mgr_get_super_partition_name()).value();

  Slot current_slot = GetCurrentSlot();
  if (target_slot == current_slot) {
    LOG(ERROR) << "Cannot call InitPartitionMetadata on current slot.";
    return false;
  }

  string target_suffix;
  if (!GetSuffix(target_slot, &target_suffix)) {
    return false;
  }

  if (!InitPartitionMetadataInternal(dynamic_control_.get(),
                                     super_device,
                                     current_slot,
                                     target_slot,
                                     target_suffix,
                                     partition_metadata)) {
    return false;
  }

  if (!Remap(dynamic_control_.get(),
             super_device,
             target_slot,
             target_suffix,
             partition_metadata)) {
    return false;
  }

  return true;
}

}  // namespace chromeos_update_engine
