/*
 * Copyright (C) 2018 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 LOG_TAG "apexd"

#include "apexd.h"
#include "apexd_private.h"

#include "apex_database.h"
#include "apex_file.h"
#include "apex_key.h"
#include "apex_manifest.h"
#include "apex_shim.h"
#include "apexd_checkpoint.h"
#include "apexd_loop.h"
#include "apexd_prepostinstall.h"
#include "apexd_prop.h"
#include "apexd_session.h"
#include "apexd_utils.h"
#include "status_or.h"
#include "string_log.h"

#include <ApexProperties.sysprop.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/macros.h>
#include <android-base/properties.h>
#include <android-base/scopeguard.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <libavb/libavb.h>
#include <libdm/dm.h>
#include <libdm/dm_table.h>
#include <libdm/dm_target.h>
#include <selinux/android.h>

#include <dirent.h>
#include <fcntl.h>
#include <linux/loop.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <algorithm>
#include <array>
#include <filesystem>
#include <fstream>
#include <iomanip>
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>
#include <unordered_set>

using android::base::EndsWith;
using android::base::Join;
using android::base::ReadFullyAtOffset;
using android::base::StartsWith;
using android::base::StringPrintf;
using android::base::unique_fd;
using android::dm::DeviceMapper;
using android::dm::DmDeviceState;
using android::dm::DmTable;
using android::dm::DmTargetVerity;

using apex::proto::SessionState;

namespace android {
namespace apex {

using MountedApexData = MountedApexDatabase::MountedApexData;

namespace {

// These should be in-sync with system/sepolicy/public/property_contexts
static constexpr const char* kApexStatusSysprop = "apexd.status";
static constexpr const char* kApexStatusStarting = "starting";
static constexpr const char* kApexStatusReady = "ready";

static constexpr const char* kApexVerityOnSystemProp =
    "persist.apexd.verity_on_system";
static bool gForceDmVerityOnSystem =
    android::base::GetBoolProperty(kApexVerityOnSystemProp, false);

// This should be in UAPI, but it's not :-(
static constexpr const char* kDmVerityRestartOnCorruption =
    "restart_on_corruption";

MountedApexDatabase gMountedApexes;

CheckpointInterface* gVoldService;
bool gSupportsFsCheckpoints = false;
bool gInFsCheckpointMode = false;

static constexpr size_t kLoopDeviceSetupAttempts = 3u;

static const bool kUpdatable =
    android::sysprop::ApexProperties::updatable().value_or(false);

bool gBootstrap = false;
static const std::vector<const std::string> kBootstrapApexes = {
    "com.android.runtime",
    "com.android.tzdata",
};

static constexpr const int kNumRetriesWhenCheckpointingEnabled = 1;

bool isBootstrapApex(const ApexFile& apex) {
  return std::find(kBootstrapApexes.begin(), kBootstrapApexes.end(),
                   apex.GetManifest().name()) != kBootstrapApexes.end();
}

// Pre-allocate loop devices so that we don't have to wait for them
// later when actually activating APEXes.
Status preAllocateLoopDevices() {
  auto scan = FindApexes(kApexPackageBuiltinDirs);
  if (!scan.Ok()) {
    return scan.ErrorStatus();
  }

  auto size = 0;
  for (const auto& path : *scan) {
    auto apexFile = ApexFile::Open(path);
    if (!apexFile.Ok() || apexFile->IsFlattened()) {
      continue;
    }
    size++;
    // bootstrap Apexes may be activated on separate namespaces.
    if (isBootstrapApex(*apexFile)) {
      size++;
    }
  }

  // note: do not call preAllocateLoopDevices() if size == 0
  // or the device does not support updatable APEX.
  // For devices (e.g. ARC) which doesn't support loop-control
  // preAllocateLoopDevices() can cause problem when it tries
  // to access /dev/loop-control.
  if (size == 0 || !kUpdatable) {
    return Status::Success();
  }
  return loop::preAllocateLoopDevices(size);
}

std::unique_ptr<DmTable> createVerityTable(const ApexVerityData& verity_data,
                                           const std::string& loop,
                                           bool restart_on_corruption) {
  AvbHashtreeDescriptor* desc = verity_data.desc.get();
  auto table = std::make_unique<DmTable>();

  std::ostringstream hash_algorithm;
  hash_algorithm << desc->hash_algorithm;

  auto target = std::make_unique<DmTargetVerity>(
      0, desc->image_size / 512, desc->dm_verity_version, loop, loop,
      desc->data_block_size, desc->hash_block_size,
      desc->image_size / desc->data_block_size,
      desc->tree_offset / desc->hash_block_size, hash_algorithm.str(),
      verity_data.root_digest, verity_data.salt);

  target->IgnoreZeroBlocks();
  if (restart_on_corruption) {
    target->SetVerityMode(kDmVerityRestartOnCorruption);
  }
  table->AddTarget(std::move(target));

  table->set_readonly(true);

  return table;
}

enum WaitForDeviceMode {
  kWaitToBeCreated = 0,
  kWaitToBeDeleted,
};

Status waitForDevice(const std::string& device, const WaitForDeviceMode& mode) {
  // TODO(b/122059364): Make this more efficient
  // TODO: use std::chrono?

  // Deleting a device might take more time, so wait a little bit longer.
  size_t num_tries = mode == kWaitToBeCreated ? 10u : 15u;

  LOG(DEBUG) << "Waiting for " << device << " to be "
             << (mode == kWaitToBeCreated ? "created" : " deleted");
  for (size_t i = 0; i < num_tries; ++i) {
    StatusOr<bool> status = PathExists(device);
    if (status.Ok()) {
      if (mode == kWaitToBeCreated && *status) {
        return Status::Success();
      }
      if (mode == kWaitToBeDeleted && !*status) {
        return Status::Success();
      }
    }
    if (i + 1 < num_tries) {
      usleep(50000);
    }
  }

  return Status::Fail(StringLog()
                      << "Failed to wait for device " << device << " to be "
                      << (mode == kWaitToBeCreated ? " created" : " deleted"));
}

// Deletes a dm-verity device with a given name and path.
// Synchronizes on the device actually being deleted from userspace.
Status DeleteVerityDevice(const std::string& name, const std::string& path) {
  DeviceMapper& dm = DeviceMapper::Instance();
  if (!dm.DeleteDevice(name)) {
    return Status::Fail(StringLog() << "Failed to delete device " << name
                                    << " with path " << path);
  }
  // Block until device is deleted from userspace.
  return waitForDevice(path, kWaitToBeDeleted);
}

// Deletes dm-verity device with a given name.
// See function above.
Status DeleteVerityDevice(const std::string& name) {
  DeviceMapper& dm = DeviceMapper::Instance();
  std::string path;
  if (!dm.GetDmDevicePathByName(name, &path)) {
    return Status::Fail(StringLog()
                        << "Unable to get path for dm-verity device " << name);
  }
  return DeleteVerityDevice(name, path);
}

class DmVerityDevice {
 public:
  DmVerityDevice() : cleared_(true) {}
  explicit DmVerityDevice(const std::string& name)
      : name_(name), cleared_(false) {}
  DmVerityDevice(const std::string& name, const std::string& dev_path)
      : name_(name), dev_path_(dev_path), cleared_(false) {}

  DmVerityDevice(DmVerityDevice&& other) noexcept
      : name_(std::move(other.name_)),
        dev_path_(std::move(other.dev_path_)),
        cleared_(other.cleared_) {
    other.cleared_ = true;
  }

  DmVerityDevice& operator=(DmVerityDevice&& other) noexcept {
    name_ = other.name_;
    dev_path_ = other.dev_path_;
    cleared_ = other.cleared_;
    other.cleared_ = true;
    return *this;
  }

  ~DmVerityDevice() {
    if (!cleared_) {
      Status ret = DeleteVerityDevice(name_, dev_path_);
      if (!ret.Ok()) {
        LOG(ERROR) << ret.ErrorMessage();
      }
    }
  }

  const std::string& GetName() const { return name_; }
  const std::string& GetDevPath() const { return dev_path_; }
  void SetDevPath(const std::string& dev_path) { dev_path_ = dev_path; }

  void Release() { cleared_ = true; }

 private:
  std::string name_;
  std::string dev_path_;
  bool cleared_;
};

StatusOr<DmVerityDevice> createVerityDevice(const std::string& name,
                                            const DmTable& table) {
  DeviceMapper& dm = DeviceMapper::Instance();

  if (dm.GetState(name) != DmDeviceState::INVALID) {
    // TODO: since apexd tears down devices during unmount, can this happen?
    LOG(WARNING) << "Deleting existing dm device " << name;
    const Status& status = DeleteVerityDevice(name);
    if (!status.Ok()) {
      // TODO: should we fail instead?
      LOG(ERROR) << "Failed to delete device " << name << " : "
                 << status.ErrorMessage();
    }
  }

  if (!dm.CreateDevice(name, table)) {
    return StatusOr<DmVerityDevice>::MakeError(
        "Couldn't create verity device.");
  }
  DmVerityDevice dev(name);

  std::string dev_path;
  if (!dm.GetDmDevicePathByName(name, &dev_path)) {
    return StatusOr<DmVerityDevice>::MakeError(
        "Couldn't get verity device path!");
  }
  dev.SetDevPath(dev_path);

  return StatusOr<DmVerityDevice>(std::move(dev));
}

Status RemovePreviouslyActiveApexFiles(
    const std::unordered_set<std::string>& affected_packages,
    const std::unordered_set<std::string>& files_to_keep) {
  auto all_active_apex_files =
      FindApexFilesByName(kActiveApexPackagesDataDir, false /* include_dirs */);

  if (!all_active_apex_files.Ok()) {
    return all_active_apex_files.ErrorStatus();
  }

  for (const std::string& path : *all_active_apex_files) {
    StatusOr<ApexFile> apex_file = ApexFile::Open(path);
    if (!apex_file.Ok()) {
      return apex_file.ErrorStatus();
    }

    const std::string& package_name = apex_file->GetManifest().name();
    if (affected_packages.find(package_name) == affected_packages.end()) {
      // This apex belongs to a package that wasn't part of this stage sessions,
      // hence it should be kept.
      continue;
    }

    if (files_to_keep.find(apex_file->GetPath()) != files_to_keep.end()) {
      // This is a path that was staged and should be kept.
      continue;
    }

    LOG(DEBUG) << "Deleting previously active apex " << apex_file->GetPath();
    if (unlink(apex_file->GetPath().c_str()) != 0) {
      return Status::Fail(PStringLog()
                          << "Failed to unlink " << apex_file->GetPath());
    }
  }

  return Status::Success();
}

// Reads the entire device to verify the image is authenticatic
Status readVerityDevice(const std::string& verity_device,
                        uint64_t device_size) {
  static constexpr int kBlockSize = 4096;
  static constexpr size_t kBufSize = 1024 * kBlockSize;
  std::vector<uint8_t> buffer(kBufSize);

  unique_fd fd(TEMP_FAILURE_RETRY(open(verity_device.c_str(), O_RDONLY)));
  if (fd.get() == -1) {
    return Status::Fail(PStringLog() << "Can't open " << verity_device);
  }

  size_t bytes_left = device_size;
  while (bytes_left > 0) {
    size_t to_read = std::min(bytes_left, kBufSize);
    if (!android::base::ReadFully(fd.get(), buffer.data(), to_read)) {
      return Status::Fail(PStringLog() << "Can't verify " << verity_device
                                       << "; corrupted?");
    }
    bytes_left -= to_read;
  }

  return Status::Success();
}

Status VerifyMountedImage(const ApexFile& apex,
                          const std::string& mount_point) {
  auto status = apex.VerifyManifestMatches(mount_point);
  if (!status.Ok()) {
    return status;
  }
  if (shim::IsShimApex(apex)) {
    return shim::ValidateShimApex(mount_point, apex);
  }
  return Status::Success();
}

StatusOr<MountedApexData> mountNonFlattened(const ApexFile& apex,
                                            const std::string& mountPoint,
                                            const std::string& device_name,
                                            bool verifyImage) {
  using StatusM = StatusOr<MountedApexData>;
  const std::string& full_path = apex.GetPath();

  if (!kUpdatable) {
    return StatusM::Fail(StringLog()
                         << "Unable to mount non-flattened apex package "
                         << full_path << " because device doesn't support it");
  }

  loop::LoopbackDeviceUniqueFd loopbackDevice;
  for (size_t attempts = 1;; ++attempts) {
    StatusOr<loop::LoopbackDeviceUniqueFd> ret = loop::createLoopDevice(
        full_path, apex.GetImageOffset(), apex.GetImageSize());
    if (ret.Ok()) {
      loopbackDevice = std::move(*ret);
      break;
    }
    if (attempts >= kLoopDeviceSetupAttempts) {
      return StatusM::Fail(StringLog()
                           << "Could not create loop device for " << full_path
                           << ": " << ret.ErrorMessage());
    }
  }
  LOG(VERBOSE) << "Loopback device created: " << loopbackDevice.name;

  auto verityData = apex.VerifyApexVerity();
  if (!verityData.Ok()) {
    return StatusM::Fail(StringLog()
                         << "Failed to verify Apex Verity data for "
                         << full_path << ": " << verityData.ErrorMessage());
  }
  std::string blockDevice = loopbackDevice.name;
  MountedApexData apex_data(loopbackDevice.name, apex.GetPath(), mountPoint,
                            device_name);

  // for APEXes in immutable partitions, we don't need to mount them on
  // dm-verity because they are already in the dm-verity protected partition;
  // system. However, note that we don't skip verification to ensure that APEXes
  // are correctly signed.
  const bool mountOnVerity =
      gForceDmVerityOnSystem || !isPathForBuiltinApexes(full_path);
  DmVerityDevice verityDev;
  if (mountOnVerity) {
    auto verityTable =
        createVerityTable(*verityData, loopbackDevice.name,
                          /* restart_on_corruption = */ !verifyImage);
    StatusOr<DmVerityDevice> verityDevRes =
        createVerityDevice(device_name, *verityTable);
    if (!verityDevRes.Ok()) {
      return StatusM::Fail(StringLog()
                           << "Failed to create Apex Verity device "
                           << full_path << ": " << verityDevRes.ErrorMessage());
    }
    verityDev = std::move(*verityDevRes);
    blockDevice = verityDev.GetDevPath();

    Status readAheadStatus = loop::configureReadAhead(verityDev.GetDevPath());
    if (!readAheadStatus.Ok()) {
      return StatusM::MakeError(readAheadStatus);
    }
  }

  // TODO(b/122059364): Even though the kernel has created the verity
  // device, we still depend on ueventd to run to actually create the
  // device node in userspace. To solve this properly we should listen on
  // the netlink socket for uevents, or use inotify. For now, this will
  // have to do.
  Status deviceStatus = waitForDevice(blockDevice, kWaitToBeCreated);
  if (!deviceStatus.Ok()) {
    return StatusM::MakeError(deviceStatus);
  }

  // TODO: consider moving this inside RunVerifyFnInsideTempMount.
  if (mountOnVerity && verifyImage) {
    Status verityStatus =
        readVerityDevice(blockDevice, (*verityData).desc->image_size);
    if (!verityStatus.Ok()) {
      return StatusM::MakeError(verityStatus);
    }
  }

  if (mount(blockDevice.c_str(), mountPoint.c_str(), "ext4",
            MS_NOATIME | MS_NODEV | MS_DIRSYNC | MS_RDONLY, nullptr) == 0) {
    LOG(INFO) << "Successfully mounted package " << full_path << " on "
              << mountPoint;
    auto status = VerifyMountedImage(apex, mountPoint);
    if (!status.Ok()) {
      umount2(mountPoint.c_str(), UMOUNT_NOFOLLOW | MNT_DETACH);
      return StatusM::Fail(StringLog() << "Failed to verify " << full_path
                                       << ": " << status.ErrorMessage());
    }
    // Time to accept the temporaries as good.
    if (mountOnVerity) {
      verityDev.Release();
    }
    loopbackDevice.CloseGood();

    return StatusM(std::move(apex_data));
  } else {
    return StatusM::Fail(StringLog() << "Mounting failed for package "
                                     << full_path << " : " << strerror(errno));
  }
}

StatusOr<MountedApexData> mountFlattened(const ApexFile& apex,
                                         const std::string& mountPoint) {
  using StatusM = StatusOr<MountedApexData>;
  if (!isPathForBuiltinApexes(apex.GetPath())) {
    return StatusM::Fail(StringLog() << "Cannot activate flattened APEX "
                                     << apex.GetPath());
  }

  if (mount(apex.GetPath().c_str(), mountPoint.c_str(), nullptr, MS_BIND,
            nullptr) == 0) {
    LOG(INFO) << "Successfully bind-mounted flattened package "
              << apex.GetPath() << " on " << mountPoint;

    MountedApexData apex_data("" /* loop_name */, apex.GetPath(), mountPoint,
                              "" /* device_name */);
    return StatusM(std::move(apex_data));
  }
  return StatusM::Fail(PStringLog() << "Mounting failed for flattened package "
                                    << apex.GetPath());
}

StatusOr<MountedApexData> MountPackageImpl(const ApexFile& apex,
                                           const std::string& mountPoint,
                                           const std::string& device_name,
                                           bool verifyImage) {
  using StatusM = StatusOr<MountedApexData>;
  LOG(VERBOSE) << "Creating mount point: " << mountPoint;
  // Note: the mount point could exist in case when the APEX was activated
  // during the bootstrap phase (e.g., the runtime or tzdata APEX).
  // Although we have separate mount namespaces to separate the early activated
  // APEXes from the normally activate APEXes, the mount points themselves
  // are shared across the two mount namespaces because /apex (a tmpfs) itself
  // mounted at / which is (and has to be) a shared mount. Therefore, if apexd
  // finds an empty directory under /apex, it's not a problem and apexd can use
  // it.
  auto exists = PathExists(mountPoint);
  if (!exists.Ok()) {
    return StatusM::MakeError(exists.ErrorStatus());
  }
  if (!*exists && mkdir(mountPoint.c_str(), kMkdirMode) != 0) {
    return StatusM::Fail(PStringLog()
                         << "Could not create mount point " << mountPoint);
  }
  auto deleter = [&mountPoint]() {
    if (rmdir(mountPoint.c_str()) != 0) {
      PLOG(WARNING) << "Could not rmdir " << mountPoint;
    }
  };
  auto scope_guard = android::base::make_scope_guard(deleter);
  if (!IsEmptyDirectory(mountPoint)) {
    return StatusM::Fail(PStringLog() << mountPoint << " is not empty");
  }

  StatusOr<MountedApexData> ret;
  if (apex.IsFlattened()) {
    ret = mountFlattened(apex, mountPoint);
  } else {
    ret = mountNonFlattened(apex, mountPoint, device_name, verifyImage);
  }
  if (ret.Ok()) {
    scope_guard.Disable();  // Accept the mount.
  }
  return ret;
}

StatusOr<MountedApexData> VerifyAndTempMountPackage(
    const ApexFile& apex, const std::string& mount_point) {
  const std::string& package_id = GetPackageId(apex.GetManifest());
  LOG(DEBUG) << "Temp mounting " << package_id << " to " << mount_point;
  const std::string& temp_device_name = package_id + ".tmp";
  return MountPackageImpl(apex, mount_point, temp_device_name,
                          /* verifyImage = */ true);
}

Status Unmount(const MountedApexData& data) {
  // Lazily try to umount whatever is mounted.
  if (umount2(data.mount_point.c_str(), UMOUNT_NOFOLLOW | MNT_DETACH) != 0 &&
      errno != EINVAL && errno != ENOENT) {
    return Status::Fail(PStringLog()
                        << "Failed to unmount directory " << data.mount_point);
  }
  // Attempt to delete the folder. If the folder is retained, other
  // data may be incorrect.
  if (rmdir(data.mount_point.c_str()) != 0) {
    PLOG(ERROR) << "Failed to rmdir directory " << data.mount_point;
  }

  // Try to free up the device-mapper device.
  if (!data.device_name.empty()) {
    const auto& status = DeleteVerityDevice(data.device_name);
    if (!status.Ok()) {
      LOG(DEBUG) << "Failed to free device " << data.device_name << " : "
                 << status.ErrorMessage();
    }
  }

  // Try to free up the loop device.
  if (!data.loop_name.empty()) {
    auto log_fn = [](const std::string& path,
                     const std::string& id ATTRIBUTE_UNUSED) {
      LOG(VERBOSE) << "Freeing loop device " << path << "for unmount.";
    };
    loop::DestroyLoopDevice(data.loop_name, log_fn);
  }

  return Status::Success();
}

std::string GetPackageTempMountPoint(const ApexManifest& manifest) {
  return StringPrintf("%s.tmp",
                      apexd_private::GetPackageMountPoint(manifest).c_str());
}

template <typename VerifyFn>
Status RunVerifyFnInsideTempMount(const ApexFile& apex,
                                  const VerifyFn& verify_fn) {
  // Temp mount image of this apex to validate it was properly signed;
  // this will also read the entire block device through dm-verity, so
  // we can be sure there is no corruption.
  const std::string& temp_mount_point =
      GetPackageTempMountPoint(apex.GetManifest());

  StatusOr<MountedApexData> mount_status =
      VerifyAndTempMountPackage(apex, temp_mount_point);
  if (!mount_status.Ok()) {
    LOG(ERROR) << "Failed to temp mount to " << temp_mount_point << " : "
               << mount_status.ErrorMessage();
    return mount_status.ErrorStatus();
  }
  auto cleaner = [&]() {
    LOG(DEBUG) << "Unmounting " << temp_mount_point;
    Status status = Unmount(*mount_status);
    if (!status.Ok()) {
      LOG(WARNING) << "Failed to unmount " << temp_mount_point << " : "
                   << status.ErrorMessage();
    }
  };
  auto scope_guard = android::base::make_scope_guard(cleaner);
  return verify_fn(temp_mount_point);
}

template <typename HookFn, typename HookCall>
Status PrePostinstallPackages(const std::vector<ApexFile>& apexes, HookFn fn,
                              HookCall call) {
  if (apexes.empty()) {
    return Status::Fail("Empty set of inputs");
  }

  // 1) Check whether the APEXes have hooks.
  bool has_hooks = false;
  for (const ApexFile& apex_file : apexes) {
    if (!(apex_file.GetManifest().*fn)().empty()) {
      has_hooks = true;
      break;
    }
  }

  // 2) If we found hooks, run the pre/post-install.
  if (has_hooks) {
    Status install_status = (*call)(apexes);
    if (!install_status.Ok()) {
      return install_status;
    }
  }

  return Status::Success();
}

Status PreinstallPackages(const std::vector<ApexFile>& apexes) {
  return PrePostinstallPackages(apexes, &ApexManifest::preinstallhook,
                                &StagePreInstall);
}

Status PostinstallPackages(const std::vector<ApexFile>& apexes) {
  return PrePostinstallPackages(apexes, &ApexManifest::postinstallhook,
                                &StagePostInstall);
}

template <typename RetType, typename Fn>
RetType HandlePackages(const std::vector<std::string>& paths, Fn fn) {
  // 1) Open all APEXes.
  std::vector<ApexFile> apex_files;
  for (const std::string& path : paths) {
    StatusOr<ApexFile> apex_file = ApexFile::Open(path);
    if (!apex_file.Ok()) {
      return RetType::Fail(apex_file.ErrorMessage());
    }
    apex_files.emplace_back(std::move(*apex_file));
  }

  // 2) Dispatch.
  return fn(apex_files);
}

Status ValidateStagingShimApex(const ApexFile& to) {
  using android::base::StringPrintf;
  auto system_shim = ApexFile::Open(
      StringPrintf("%s/%s", kApexPackageSystemDir, shim::kSystemShimApexName));
  if (!system_shim.Ok()) {
    return system_shim.ErrorStatus();
  }
  auto verify_fn = [&](const std::string& system_apex_path) {
    return shim::ValidateUpdate(system_apex_path, to.GetPath());
  };
  return RunVerifyFnInsideTempMount(*system_shim, verify_fn);
}

// A version of apex verification that happens during boot.
// This function should only verification checks that are necessary to run on
// each boot. Try to avoid putting expensive checks inside this function.
Status VerifyPackageBoot(const ApexFile& apex_file) {
  if (apex_file.IsFlattened()) {
    return Status::Fail("Can't upgrade flattened apex");
  }
  StatusOr<ApexVerityData> verity_or = apex_file.VerifyApexVerity();
  if (!verity_or.Ok()) {
    return Status::Fail(verity_or.ErrorMessage());
  }

  if (shim::IsShimApex(apex_file)) {
    // Validating shim is not a very cheap operation, but it's fine to perform
    // it here since it only runs during CTS tests and will never be triggered
    // during normal flow.
    const auto& status = ValidateStagingShimApex(apex_file);
    if (!status.Ok()) {
      return status;
    }
  }
  return Status::Success();
}

// A version of apex verification that happens on submitStagedSession.
// This function contains checks that might be expensive to perform, e.g. temp
// mounting a package and reading entire dm-verity device, and shouldn't be run
// during boot.
Status VerifyPackageInstall(const ApexFile& apex_file) {
  const auto& verify_package_boot_status = VerifyPackageBoot(apex_file);
  if (!verify_package_boot_status.Ok()) {
    return verify_package_boot_status;
  }
  if (!kUpdatable) {
    return Status::Fail(StringLog() << "Attempted to upgrade apex package "
                                    << apex_file.GetPath()
                                    << " on a device that doesn't support it");
  }
  StatusOr<ApexVerityData> verity_or = apex_file.VerifyApexVerity();

  constexpr const auto kSuccessFn = [](const std::string& _) {
    return Status::Success();
  };
  return RunVerifyFnInsideTempMount(apex_file, kSuccessFn);
}

template <typename VerifyApexFn>
StatusOr<std::vector<ApexFile>> verifyPackages(
    const std::vector<std::string>& paths, const VerifyApexFn& verify_apex_fn) {
  if (paths.empty()) {
    return StatusOr<std::vector<ApexFile>>::MakeError("Empty set of inputs");
  }
  LOG(DEBUG) << "verifyPackages() for " << Join(paths, ',');

  using StatusT = StatusOr<std::vector<ApexFile>>;
  auto verify_fn = [&](std::vector<ApexFile>& apexes) {
    for (const ApexFile& apex_file : apexes) {
      Status status = verify_apex_fn(apex_file);
      if (!status.Ok()) {
        return StatusT::MakeError(status);
      }
    }
    return StatusT(std::move(apexes));
  };
  return HandlePackages<StatusT>(paths, verify_fn);
}

StatusOr<ApexFile> verifySessionDir(const int session_id) {
  std::string sessionDirPath = std::string(kStagedSessionsDir) + "/session_" +
                               std::to_string(session_id);
  LOG(INFO) << "Scanning " << sessionDirPath
            << " looking for packages to be validated";
  StatusOr<std::vector<std::string>> scan =
      FindApexFilesByName(sessionDirPath, /* include_dirs=*/false);
  if (!scan.Ok()) {
    LOG(WARNING) << scan.ErrorMessage();
    return StatusOr<ApexFile>::MakeError(scan.ErrorMessage());
  }

  if (scan->size() > 1) {
    return StatusOr<ApexFile>::MakeError(
        "More than one APEX package found in the same session directory.");
  }

  auto verified = verifyPackages(*scan, VerifyPackageInstall);
  if (!verified.Ok()) {
    return StatusOr<ApexFile>::MakeError(verified.ErrorStatus());
  }
  return StatusOr<ApexFile>(std::move((*verified)[0]));
}

Status ClearSessions() {
  auto sessions = ApexSession::GetSessions();
  int cnt = 0;
  for (ApexSession& session : sessions) {
    Status status = session.DeleteSession();
    if (!status.Ok()) {
      return status;
    }
    cnt++;
  }
  if (cnt > 0) {
    LOG(DEBUG) << "Deleted " << cnt << " sessions";
  }
  return Status::Success();
}

Status DeleteBackup() {
  auto exists = PathExists(std::string(kApexBackupDir));
  if (!exists.Ok()) {
    return Status::Fail(StringLog() << "Can't clean " << kApexBackupDir << " : "
                                    << exists.ErrorMessage());
  }
  if (!*exists) {
    LOG(DEBUG) << kApexBackupDir << " does not exist. Nothing to clean";
    return Status::Success();
  }
  return DeleteDirContent(std::string(kApexBackupDir));
}

Status BackupActivePackages() {
  LOG(DEBUG) << "Initializing  backup of " << kActiveApexPackagesDataDir;

  // Previous restore might've delete backups folder.
  auto create_status = createDirIfNeeded(kApexBackupDir, 0700);
  if (!create_status.Ok()) {
    return Status::Fail(StringLog()
                        << "Backup failed : " << create_status.ErrorMessage());
  }

  auto apex_active_exists = PathExists(std::string(kActiveApexPackagesDataDir));
  if (!apex_active_exists.Ok()) {
    return Status::Fail("Backup failed : " + apex_active_exists.ErrorMessage());
  }
  if (!*apex_active_exists) {
    LOG(DEBUG) << kActiveApexPackagesDataDir
               << " does not exist. Nothing to backup";
    return Status::Success();
  }

  auto active_packages =
      FindApexFilesByName(kActiveApexPackagesDataDir, false /* include_dirs */);
  if (!active_packages.Ok()) {
    return Status::Fail(StringLog() << "Backup failed : "
                                    << active_packages.ErrorMessage());
  }

  auto cleanup_status = DeleteBackup();
  if (!cleanup_status.Ok()) {
    return Status::Fail(StringLog()
                        << "Backup failed : " << cleanup_status.ErrorMessage());
  }

  auto backup_path_fn = [](const ApexFile& apex_file) {
    return StringPrintf("%s/%s%s", kApexBackupDir,
                        GetPackageId(apex_file.GetManifest()).c_str(),
                        kApexPackageSuffix);
  };

  auto deleter = []() {
    auto status = DeleteDirContent(std::string(kApexBackupDir));
    if (!status.Ok()) {
      LOG(ERROR) << "Failed to cleanup " << kApexBackupDir << " : "
                 << status.ErrorMessage();
    }
  };
  auto scope_guard = android::base::make_scope_guard(deleter);

  for (const std::string& path : *active_packages) {
    StatusOr<ApexFile> apex_file = ApexFile::Open(path);
    if (!apex_file.Ok()) {
      return Status::Fail("Backup failed : " + apex_file.ErrorMessage());
    }
    const auto& dest_path = backup_path_fn(*apex_file);
    if (link(apex_file->GetPath().c_str(), dest_path.c_str()) != 0) {
      return Status::Fail(PStringLog()
                          << "Failed to backup " << apex_file->GetPath());
    }
  }

  scope_guard.Disable();  // Accept the backup.
  return Status::Success();
}

Status DoRollback(ApexSession& session) {
  if (gInFsCheckpointMode) {
    // We will roll back automatically when we reboot
    return Status::Success();
  }
  auto scope_guard = android::base::make_scope_guard([&]() {
    auto st = session.UpdateStateAndCommit(SessionState::ROLLBACK_FAILED);
    LOG(DEBUG) << "Marking " << session << " as failed to rollback";
    if (!st.Ok()) {
      LOG(WARNING) << "Failed to mark session " << session
                   << " as failed to rollback : " << st.ErrorMessage();
    }
  });

  auto backup_exists = PathExists(std::string(kApexBackupDir));
  if (!backup_exists.Ok()) {
    return backup_exists.ErrorStatus();
  }
  if (!*backup_exists) {
    return Status::Fail(StringLog() << kApexBackupDir << " does not exist");
  }

  struct stat stat_data;
  if (stat(kActiveApexPackagesDataDir, &stat_data) != 0) {
    return Status::Fail(PStringLog()
                        << "Failed to access " << kActiveApexPackagesDataDir);
  }

  LOG(DEBUG) << "Deleting existing packages in " << kActiveApexPackagesDataDir;
  auto delete_status =
      DeleteDirContent(std::string(kActiveApexPackagesDataDir));
  if (!delete_status.Ok()) {
    return delete_status;
  }

  LOG(DEBUG) << "Renaming " << kApexBackupDir << " to "
             << kActiveApexPackagesDataDir;
  if (rename(kApexBackupDir, kActiveApexPackagesDataDir) != 0) {
    return Status::Fail(PStringLog() << "Failed to rename " << kApexBackupDir
                                     << " to " << kActiveApexPackagesDataDir);
  }

  LOG(DEBUG) << "Restoring original permissions for "
             << kActiveApexPackagesDataDir;
  if (chmod(kActiveApexPackagesDataDir, stat_data.st_mode & ALLPERMS) != 0) {
    // TODO: should we wipe out /data/apex/active if chmod fails?
    return Status::Fail(PStringLog()
                        << "Failed to restore original permissions for "
                        << kActiveApexPackagesDataDir);
  }

  scope_guard.Disable();  // Rollback succeeded. Accept state.
  return Status::Success();
}

Status RollbackStagedSession(ApexSession& session) {
  // If the session is staged, it hasn't been activated yet, and we just need
  // to update its state to prevent it from being activated later.
  return session.UpdateStateAndCommit(SessionState::ROLLED_BACK);
}

Status RollbackActivatedSession(ApexSession& session) {
  if (gInFsCheckpointMode) {
    LOG(DEBUG) << "Checkpoint mode is enabled";
    // On checkpointing devices, our modifications on /data will be
    // automatically rolled back when we abort changes. Updating the session
    // state is pointless here, as it will be rolled back as well.
    return Status::Success();
  }

  auto status =
      session.UpdateStateAndCommit(SessionState::ROLLBACK_IN_PROGRESS);
  if (!status.Ok()) {
    // TODO: should we continue with a rollback?
    return Status::Fail(StringLog() << "Rollback of session " << session
                                    << " failed : " << status.ErrorMessage());
  }

  status = DoRollback(session);
  if (!status.Ok()) {
    return Status::Fail(StringLog() << "Rollback of session " << session
                                    << " failed : " << status.ErrorMessage());
  }

  status = session.UpdateStateAndCommit(SessionState::ROLLED_BACK);
  if (!status.Ok()) {
    LOG(WARNING) << "Failed to mark session " << session
                 << " as rolled back : " << status.ErrorMessage();
  }

  return Status::Success();
}

Status RollbackSession(ApexSession& session) {
  LOG(DEBUG) << "Initializing rollback of " << session;

  switch (session.GetState()) {
    case SessionState::ROLLBACK_IN_PROGRESS:
      [[clang::fallthrough]];
    case SessionState::ROLLED_BACK:
      return Status::Success();
    case SessionState::STAGED:
      return RollbackStagedSession(session);
    case SessionState::ACTIVATED:
      return RollbackActivatedSession(session);
    default:
      return Status::Fail(StringLog() << "Can't restore session " << session
                                      << " : session is in a wrong state");
  }
}

Status ResumeRollback(ApexSession& session) {
  auto backup_exists = PathExists(std::string(kApexBackupDir));
  if (!backup_exists.Ok()) {
    return backup_exists.ErrorStatus();
  }
  if (*backup_exists) {
    auto rollback_status = DoRollback(session);
    if (!rollback_status.Ok()) {
      return rollback_status;
    }
  }
  auto status = session.UpdateStateAndCommit(SessionState::ROLLED_BACK);
  if (!status.Ok()) {
    LOG(WARNING) << "Failed to mark session " << session
                 << " as rolled back : " << status.ErrorMessage();
  }
  return Status::Success();
}

Status UnmountPackage(const ApexFile& apex, bool allow_latest) {
  LOG(VERBOSE) << "Unmounting " << GetPackageId(apex.GetManifest());

  const ApexManifest& manifest = apex.GetManifest();

  std::optional<MountedApexData> data;
  bool latest = false;

  auto fn = [&](const MountedApexData& d, bool l) {
    if (d.full_path == apex.GetPath()) {
      data.emplace(d);
      latest = l;
    }
  };
  gMountedApexes.ForallMountedApexes(manifest.name(), fn);

  if (!data.has_value()) {
    return Status::Fail(StringLog() << "Did not find " << apex.GetPath());
  }

  if (latest) {
    if (!allow_latest) {
      return Status::Fail(StringLog()
                          << "Package " << apex.GetPath() << " is active");
    }
    std::string mount_point = apexd_private::GetActiveMountPoint(manifest);
    LOG(VERBOSE) << "Unmounting and deleting " << mount_point;
    if (umount2(mount_point.c_str(), UMOUNT_NOFOLLOW | MNT_DETACH) != 0) {
      return Status::Fail(PStringLog() << "Failed to unmount " << mount_point);
    }
    if (rmdir(mount_point.c_str()) != 0) {
      PLOG(ERROR) << "Could not rmdir " << mount_point;
      // Continue here.
    }
  }

  // Clean up gMountedApexes now, even though we're not fully done.
  gMountedApexes.RemoveMountedApex(manifest.name(), apex.GetPath());
  return Unmount(*data);
}

}  // namespace

namespace apexd_private {

Status MountPackage(const ApexFile& apex, const std::string& mountPoint) {
  auto ret =
      MountPackageImpl(apex, mountPoint, GetPackageId(apex.GetManifest()),
                       /* verifyImage = */ false);
  if (!ret.Ok()) {
    return ret.ErrorStatus();
  }

  gMountedApexes.AddMountedApex(apex.GetManifest().name(), false,
                                std::move(*ret));
  return Status::Success();
}

Status UnmountPackage(const ApexFile& apex) {
  return android::apex::UnmountPackage(apex, /* allow_latest= */ false);
}

bool IsMounted(const std::string& name, const std::string& full_path) {
  bool found_mounted = false;
  gMountedApexes.ForallMountedApexes(
      name, [&](const MountedApexData& data, bool latest ATTRIBUTE_UNUSED) {
        if (full_path == data.full_path) {
          found_mounted = true;
        }
      });
  return found_mounted;
}

std::string GetPackageMountPoint(const ApexManifest& manifest) {
  return StringPrintf("%s/%s", kApexRoot, GetPackageId(manifest).c_str());
}

std::string GetActiveMountPoint(const ApexManifest& manifest) {
  return StringPrintf("%s/%s", kApexRoot, manifest.name().c_str());
}

}  // namespace apexd_private

Status resumeRollbackIfNeeded() {
  auto session = ApexSession::GetActiveSession();
  if (!session.Ok()) {
    return session.ErrorStatus();
  }
  if (!session->has_value()) {
    return Status::Success();
  }
  if ((**session).GetState() == SessionState::ROLLBACK_IN_PROGRESS) {
    // This means that phone was rebooted during the rollback. Resuming it.
    return ResumeRollback(**session);
  }
  return Status::Success();
}

Status activatePackageImpl(const ApexFile& apex_file) {
  const ApexManifest& manifest = apex_file.GetManifest();

  if (gBootstrap && !isBootstrapApex(apex_file)) {
    LOG(INFO) << "Skipped when bootstrapping";
    return Status::Success();
  } else if (!kUpdatable && !gBootstrap && isBootstrapApex(apex_file)) {
    LOG(INFO) << "Package already activated in bootstrap";
    return Status::Success();
  }

  // See whether we think it's active, and do not allow to activate the same
  // version. Also detect whether this is the highest version.
  // We roll this into a single check.
  bool is_newest_version = true;
  bool found_other_version = false;
  bool version_found_mounted = false;
  {
    uint64_t new_version = manifest.version();
    bool version_found_active = false;
    gMountedApexes.ForallMountedApexes(
        manifest.name(), [&](const MountedApexData& data, bool latest) {
          StatusOr<ApexFile> otherApex = ApexFile::Open(data.full_path);
          if (!otherApex.Ok()) {
            return;
          }
          found_other_version = true;
          if (static_cast<uint64_t>(otherApex->GetManifest().version()) ==
              new_version) {
            version_found_mounted = true;
            version_found_active = latest;
          }
          if (static_cast<uint64_t>(otherApex->GetManifest().version()) >
              new_version) {
            is_newest_version = false;
          }
        });
    if (version_found_active) {
      LOG(DEBUG) << "Package " << manifest.name() << " with version "
                 << manifest.version() << " already active";
      return Status::Success();
    }
  }

  const std::string& mountPoint = apexd_private::GetPackageMountPoint(manifest);

  if (!version_found_mounted) {
    Status mountStatus = apexd_private::MountPackage(apex_file, mountPoint);
    if (!mountStatus.Ok()) {
      return mountStatus;
    }
  }

  bool mounted_latest = false;
  if (is_newest_version) {
    const Status& update_st = apexd_private::BindMount(
        apexd_private::GetActiveMountPoint(manifest), mountPoint);
    mounted_latest = update_st.Ok();
    if (!update_st.Ok()) {
      return Status::Fail(StringLog()
                          << "Failed to update package " << manifest.name()
                          << " to version " << manifest.version() << " : "
                          << update_st.ErrorMessage());
    }
  }
  if (mounted_latest) {
    gMountedApexes.SetLatest(manifest.name(), apex_file.GetPath());
  }

  LOG(DEBUG) << "Successfully activated " << apex_file.GetPath()
             << " package_name: " << manifest.name()
             << " version: " << manifest.version();
  return Status::Success();
}

Status activatePackage(const std::string& full_path) {
  LOG(INFO) << "Trying to activate " << full_path;

  StatusOr<ApexFile> apex_file = ApexFile::Open(full_path);
  if (!apex_file.Ok()) {
    return apex_file.ErrorStatus();
  }
  return activatePackageImpl(*apex_file);
}

Status deactivatePackage(const std::string& full_path) {
  LOG(INFO) << "Trying to deactivate " << full_path;

  StatusOr<ApexFile> apexFile = ApexFile::Open(full_path);
  if (!apexFile.Ok()) {
    return apexFile.ErrorStatus();
  }

  return UnmountPackage(*apexFile, /* allow_latest= */ true);
}

std::vector<ApexFile> getActivePackages() {
  std::vector<ApexFile> ret;
  gMountedApexes.ForallMountedApexes(
      [&](const std::string&, const MountedApexData& data, bool latest) {
        if (!latest) {
          return;
        }

        StatusOr<ApexFile> apexFile = ApexFile::Open(data.full_path);
        if (!apexFile.Ok()) {
          // TODO: Fail?
          return;
        }
        ret.emplace_back(std::move(*apexFile));
      });

  return ret;
}

namespace {
std::unordered_map<std::string, uint64_t> GetActivePackagesMap() {
  std::vector<ApexFile> active_packages = getActivePackages();
  std::unordered_map<std::string, uint64_t> ret;
  for (const auto& package : active_packages) {
    const ApexManifest& manifest = package.GetManifest();
    ret.insert({manifest.name(), manifest.version()});
  }
  return ret;
}

}  // namespace

std::vector<ApexFile> getFactoryPackages() {
  std::vector<ApexFile> ret;
  for (const auto& dir : kApexPackageBuiltinDirs) {
    auto apex_files = FindApexFilesByName(dir, /* include_dirs=*/false);
    if (!apex_files.Ok()) {
      LOG(ERROR) << apex_files.ErrorMessage();
      continue;
    }
    for (const std::string& path : *apex_files) {
      StatusOr<ApexFile> apex_file = ApexFile::Open(path);
      if (!apex_file.Ok()) {
        LOG(ERROR) << apex_file.ErrorMessage();
      } else {
        ret.emplace_back(std::move(*apex_file));
      }
    }
  }
  return ret;
}

StatusOr<ApexFile> getActivePackage(const std::string& packageName) {
  std::vector<ApexFile> packages = getActivePackages();
  for (ApexFile& apex : packages) {
    if (apex.GetManifest().name() == packageName) {
      return StatusOr<ApexFile>(std::move(apex));
    }
  }

  return StatusOr<ApexFile>::MakeError(
      PStringLog() << "Cannot find matching package for: " << packageName);
}

Status abortActiveSession() {
  auto session_or_none = ApexSession::GetActiveSession();
  if (!session_or_none.Ok()) {
    return session_or_none.ErrorStatus();
  }
  if (session_or_none->has_value()) {
    auto& session = session_or_none->value();
    LOG(DEBUG) << "Aborting active session " << session;
    switch (session.GetState()) {
      case SessionState::VERIFIED:
        [[clang::fallthrough]];
      case SessionState::STAGED:
        return session.DeleteSession();
      case SessionState::ACTIVATED:
        return RollbackActivatedSession(session);
      default:
        return Status::Fail(StringLog()
                            << "Session " << session << " can't be aborted");
    }
  } else {
    LOG(DEBUG) << "There are no active sessions";
    return Status::Success();
  }
}

Status scanPackagesDirAndActivate(const char* apex_package_dir) {
  LOG(INFO) << "Scanning " << apex_package_dir << " looking for APEX packages.";

  const bool scanBuiltinApexes = isPathForBuiltinApexes(apex_package_dir);
  StatusOr<std::vector<std::string>> scan =
      FindApexFilesByName(apex_package_dir, scanBuiltinApexes);
  if (!scan.Ok()) {
    return Status::Fail(StringLog() << "Failed to scan " << apex_package_dir
                                    << " : " << scan.ErrorMessage());
  }

  const auto& packages_with_code = GetActivePackagesMap();

  std::vector<std::string> failed_pkgs;
  size_t activated_cnt = 0;
  size_t skipped_cnt = 0;
  for (const std::string& name : *scan) {
    LOG(INFO) << "Found " << name;

    StatusOr<ApexFile> apex_file = ApexFile::Open(name);
    if (!apex_file.Ok()) {
      LOG(ERROR) << "Failed to activate " << name << " : "
                 << apex_file.ErrorMessage();
      failed_pkgs.push_back(name);
      continue;
    }

    uint64_t new_version =
        static_cast<uint64_t>(apex_file->GetManifest().version());
    const auto& it = packages_with_code.find(apex_file->GetManifest().name());
    if (it != packages_with_code.end() && it->second >= new_version) {
      LOG(INFO) << "Skipping activation of " << name
                << " same package with higher version " << it->second
                << " is already active";
      skipped_cnt++;
      continue;
    }

    if (!kUpdatable && !apex_file->IsFlattened()) {
      LOG(INFO) << "Skipping activation of non-flattened apex package " << name
                << " because device doesn't support it";
      skipped_cnt++;
      continue;
    }

    Status res = activatePackageImpl(*apex_file);
    if (!res.Ok()) {
      LOG(ERROR) << "Failed to activate " << name << " : "
                 << res.ErrorMessage();
      failed_pkgs.push_back(name);
    } else {
      activated_cnt++;
    }
  }

  if (!failed_pkgs.empty()) {
    return Status::Fail(StringLog()
                        << "Failed to activate following packages : "
                        << Join(failed_pkgs, ','));
  }

  LOG(INFO) << "Activated " << activated_cnt
            << " packages. Skipped: " << skipped_cnt;
  return Status::Success();
}

void scanStagedSessionsDirAndStage() {
  LOG(INFO) << "Scanning " << kApexSessionsDir
            << " looking for sessions to be activated.";

  auto stagedSessions = ApexSession::GetSessionsInState(SessionState::STAGED);
  for (auto& session : stagedSessions) {
    auto sessionId = session.GetId();

    auto session_failed_fn = [&]() {
      LOG(WARNING) << "Marking session " << sessionId << " as failed.";
      auto st = session.UpdateStateAndCommit(SessionState::ACTIVATION_FAILED);
      if (!st.Ok()) {
        LOG(WARNING) << "Failed to mark session " << sessionId
                     << " as failed : " << st.ErrorMessage();
      }
    };
    auto scope_guard = android::base::make_scope_guard(session_failed_fn);

    std::vector<std::string> dirsToScan;
    if (session.GetChildSessionIds().empty()) {
      dirsToScan.push_back(std::string(kStagedSessionsDir) + "/session_" +
                           std::to_string(sessionId));
    } else {
      for (auto childSessionId : session.GetChildSessionIds()) {
        dirsToScan.push_back(std::string(kStagedSessionsDir) + "/session_" +
                             std::to_string(childSessionId));
      }
    }

    std::vector<std::string> apexes;
    bool scanSuccessful = true;
    for (const auto& dirToScan : dirsToScan) {
      StatusOr<std::vector<std::string>> scan =
          FindApexFilesByName(dirToScan, /* include_dirs=*/false);
      if (!scan.Ok()) {
        LOG(WARNING) << scan.ErrorMessage();
        scanSuccessful = false;
        break;
      }

      if (scan->size() > 1) {
        LOG(WARNING) << "More than one APEX package found in the same session "
                     << "directory " << dirToScan << ", skipping activation.";
        scanSuccessful = false;
        break;
      }

      if (scan->empty()) {
        LOG(WARNING) << "No APEX packages found while scanning " << dirToScan
                     << " session id: " << sessionId << ".";
        scanSuccessful = false;
        break;
      }
      apexes.push_back(std::move((*scan)[0]));
    }

    if (!scanSuccessful) {
      continue;
    }

    // Run postinstall, if necessary.
    Status postinstall_status = postinstallPackages(apexes);
    if (!postinstall_status.Ok()) {
      LOG(ERROR) << "Postinstall failed for session "
                 << std::to_string(sessionId) << ": "
                 << postinstall_status.ErrorMessage();
      continue;
    }

    const Status result = stagePackages(apexes);
    if (!result.Ok()) {
      LOG(ERROR) << "Activation failed for packages " << Join(apexes, ',')
                 << ": " << result.ErrorMessage();
      continue;
    }

    // Session was OK, release scopeguard.
    scope_guard.Disable();

    auto st = session.UpdateStateAndCommit(SessionState::ACTIVATED);
    if (!st.Ok()) {
      LOG(ERROR) << "Failed to mark " << session
                 << " as activated : " << st.ErrorMessage();
    }
  }
}

Status preinstallPackages(const std::vector<std::string>& paths) {
  if (paths.empty()) {
    return Status::Fail("Empty set of inputs");
  }
  LOG(DEBUG) << "preinstallPackages() for " << Join(paths, ',');
  return HandlePackages<Status>(paths, PreinstallPackages);
}

Status postinstallPackages(const std::vector<std::string>& paths) {
  if (paths.empty()) {
    return Status::Fail("Empty set of inputs");
  }
  LOG(DEBUG) << "postinstallPackages() for " << Join(paths, ',');
  return HandlePackages<Status>(paths, PostinstallPackages);
}

namespace {
std::string StageDestPath(const ApexFile& apex_file) {
  return StringPrintf("%s/%s%s", kActiveApexPackagesDataDir,
                      GetPackageId(apex_file.GetManifest()).c_str(),
                      kApexPackageSuffix);
}

std::vector<std::string> FilterUnnecessaryStagingPaths(
    const std::vector<std::string>& tmp_paths) {
  const auto& packages_with_code = GetActivePackagesMap();

  auto filter_fn = [&packages_with_code](const std::string& path) {
    auto apex_file = ApexFile::Open(path);
    if (!apex_file.Ok()) {
      // Pretend that apex should be staged, so that stagePackages will fail
      // trying to open it.
      return true;
    }
    std::string dest_path = StageDestPath(*apex_file);
    if (access(dest_path.c_str(), F_OK) == 0) {
      LOG(DEBUG) << dest_path << " already exists. Skipping";
      return false;
    }
    const ApexManifest& manifest = apex_file->GetManifest();
    const auto& it = packages_with_code.find(manifest.name());
    uint64_t new_version = static_cast<uint64_t>(manifest.version());
    if (it != packages_with_code.end() && it->second == new_version) {
      LOG(DEBUG) << GetPackageId(manifest) << " is already active. Skipping";
      return false;
    }
    return true;
  };

  std::vector<std::string> ret;
  std::copy_if(tmp_paths.begin(), tmp_paths.end(), std::back_inserter(ret),
               filter_fn);
  return ret;
}

}  // namespace

Status stagePackages(const std::vector<std::string>& tmpPaths) {
  if (tmpPaths.empty()) {
    return Status::Fail("Empty set of inputs");
  }
  LOG(DEBUG) << "stagePackages() for " << Join(tmpPaths, ',');

  // Note: this function is temporary. As such the code is not optimized, e.g.,
  //       it will open ApexFiles multiple times.

  // 1) Verify all packages.
  auto verify_status = verifyPackages(tmpPaths, VerifyPackageBoot);
  if (!verify_status.Ok()) {
    return Status::Fail(verify_status.ErrorMessage());
  }

  // 2) Now stage all of them.

  // Make sure that kActiveApexPackagesDataDir exists.
  auto create_dir_status =
      createDirIfNeeded(std::string(kActiveApexPackagesDataDir), 0750);
  if (!create_dir_status.Ok()) {
    return Status::Fail(create_dir_status.ErrorMessage());
  }

  // 2) Filter out packages that do not require staging, e.g.:
  //    a) Their /data/apex/active/package.apex@version already exists.
  //    b) Such package is already active
  std::vector<std::string> paths_to_stage =
      FilterUnnecessaryStagingPaths(tmpPaths);
  if (paths_to_stage.empty()) {
    // Finish early if nothing to stage. Since stagePackages fails in case
    // tmpPaths is empty, it's fine to return Success here.
    return Status::Success();
  }

  // 3) Now stage all of them.

  // Ensure the APEX gets removed on failure.
  std::unordered_set<std::string> staged_files;
  auto deleter = [&staged_files]() {
    for (const std::string& staged_path : staged_files) {
      if (TEMP_FAILURE_RETRY(unlink(staged_path.c_str())) != 0) {
        PLOG(ERROR) << "Unable to unlink " << staged_path;
      }
    }
  };
  auto scope_guard = android::base::make_scope_guard(deleter);

  std::unordered_set<std::string> staged_packages;
  for (const std::string& path : paths_to_stage) {
    StatusOr<ApexFile> apex_file = ApexFile::Open(path);
    if (!apex_file.Ok()) {
      return apex_file.ErrorStatus();
    }
    std::string dest_path = StageDestPath(*apex_file);

    if (link(apex_file->GetPath().c_str(), dest_path.c_str()) != 0) {
      // TODO: Get correct binder error status.
      return Status::Fail(PStringLog()
                          << "Unable to link " << apex_file->GetPath() << " to "
                          << dest_path);
    }
    staged_files.insert(dest_path);
    staged_packages.insert(apex_file->GetManifest().name());

    LOG(DEBUG) << "Success linking " << apex_file->GetPath() << " to "
               << dest_path;
  }

  scope_guard.Disable();  // Accept the state.

  return RemovePreviouslyActiveApexFiles(staged_packages, staged_files);
}

Status unstagePackages(const std::vector<std::string>& paths) {
  if (paths.empty()) {
    return Status::Fail("Empty set of inputs");
  }
  LOG(DEBUG) << "unstagePackages() for " << Join(paths, ',');

  // TODO: to make unstage safer, we can copy to be unstaged packages to a
  // temporary folder and restore state from it in case unstagePackages fails.

  for (const std::string& path : paths) {
    if (access(path.c_str(), F_OK) != 0) {
      return Status::Fail(PStringLog() << "Can't access " << path);
    }
  }

  for (const std::string& path : paths) {
    if (unlink(path.c_str()) != 0) {
      return Status::Fail(PStringLog() << "Can't unlink " << path);
    }
  }

  return Status::Success();
}

Status rollbackStagedSessionIfAny() {
  auto session = ApexSession::GetActiveSession();
  if (!session.Ok()) {
    return session.ErrorStatus();
  }
  if (!session->has_value()) {
    LOG(WARNING) << "No session to rollback";
    return Status::Success();
  }
  if ((*session)->GetState() == SessionState::STAGED) {
    LOG(INFO) << "Rolling back session " << **session;
    return RollbackStagedSession(**session);
  }
  return Status::Fail(StringLog() << "Can't rollback " << **session
                                  << " because it is not in STAGED state");
}

Status rollbackActiveSession() {
  auto session = ApexSession::GetActiveSession();
  if (!session.Ok()) {
    return Status::Fail(StringLog() << "Failed to get active session : "
                                    << session.ErrorMessage());
  } else if (!session->has_value()) {
    return Status::Fail(
        "Rollback requested, when there are no active sessions.");
  } else {
    return RollbackSession(*(*session));
  }
}

Status rollbackActiveSessionAndReboot() {
  auto status = rollbackActiveSession();
  if (!status.Ok()) {
    return status;
  }
  LOG(ERROR) << "Successfully rolled back. Time to reboot device.";
  if (gInFsCheckpointMode) {
    Status res = gVoldService->AbortChanges("apexd_initiated" /* message */,
                                            false /* retry */);
    if (!res.Ok()) {
      LOG(ERROR) << res.ErrorMessage();
    }
  }
  Reboot();
  return Status::Success();
}

int onBootstrap() {
  gBootstrap = true;

  Status preAllocate = preAllocateLoopDevices();
  if (!preAllocate.Ok()) {
    LOG(ERROR) << "Failed to pre-allocate loop devices : "
               << preAllocate.ErrorMessage();
  }

  Status status = collectApexKeys();
  if (!status.Ok()) {
    LOG(ERROR) << "Failed to collect APEX keys : " << status.ErrorMessage();
    return 1;
  }

  // Activate built-in APEXes for processes launched before /data is mounted.
  status = scanPackagesDirAndActivate(kApexPackageSystemDir);
  if (!status.Ok()) {
    LOG(ERROR) << "Failed to activate APEX files in " << kApexPackageSystemDir
               << " : " << status.ErrorMessage();
    return 1;
  }
  LOG(INFO) << "Bootstrapping done";
  return 0;
}

void onStart(CheckpointInterface* checkpoint_service) {
  LOG(INFO) << "Marking APEXd as starting";
  if (!android::base::SetProperty(kApexStatusSysprop, kApexStatusStarting)) {
    PLOG(ERROR) << "Failed to set " << kApexStatusSysprop << " to "
                << kApexStatusStarting;
  }

  if (checkpoint_service != nullptr) {
    gVoldService = checkpoint_service;
    StatusOr<bool> supports_fs_checkpoints =
        gVoldService->SupportsFsCheckpoints();
    if (supports_fs_checkpoints.Ok()) {
      gSupportsFsCheckpoints = *supports_fs_checkpoints;
    } else {
      LOG(ERROR) << "Failed to check if filesystem checkpoints are supported: "
                 << supports_fs_checkpoints.ErrorMessage();
    }
    if (gSupportsFsCheckpoints) {
      StatusOr<bool> needs_checkpoint = gVoldService->NeedsCheckpoint();
      if (needs_checkpoint.Ok()) {
        gInFsCheckpointMode = *needs_checkpoint;
      } else {
        LOG(ERROR) << "Failed to check if we're in filesystem checkpoint mode: "
                   << needs_checkpoint.ErrorMessage();
      }
    }
  }

  // Ask whether we should roll back any staged sessions; this can happen if
  // we've exceeded the retry count on a device that supports filesystem
  // checkpointing.
  if (gSupportsFsCheckpoints) {
    StatusOr<bool> needs_rollback = gVoldService->NeedsRollback();
    if (!needs_rollback.Ok()) {
      LOG(ERROR) << "Failed to check if we need a rollback: "
                 << needs_rollback.ErrorMessage();
    } else if (*needs_rollback) {
      LOG(INFO) << "Exceeded number of session retries ("
                << kNumRetriesWhenCheckpointingEnabled
                << "). Starting a rollback";
      Status status = rollbackStagedSessionIfAny();
      if (!status.Ok()) {
        LOG(ERROR)
            << "Failed to roll back (as requested by fs checkpointing) : "
            << status.ErrorMessage();
      }
    }
  }

  Status status = collectApexKeys();
  if (!status.Ok()) {
    LOG(ERROR) << "Failed to collect APEX keys : " << status.ErrorMessage();
    return;
  }

  gMountedApexes.PopulateFromMounts();

  // Activate APEXes from /data/apex. If one in the directory is newer than the
  // system one, the new one will eclipse the old one.
  scanStagedSessionsDirAndStage();
  status = resumeRollbackIfNeeded();
  if (!status.Ok()) {
    LOG(ERROR) << "Failed to resume rollback : " << status.ErrorMessage();
  }

  status = scanPackagesDirAndActivate(kActiveApexPackagesDataDir);
  if (!status.Ok()) {
    LOG(ERROR) << "Failed to activate packages from "
               << kActiveApexPackagesDataDir << " : " << status.ErrorMessage();
    Status rollback_status = rollbackActiveSessionAndReboot();
    if (!rollback_status.Ok()) {
      // TODO: should we kill apexd in this case?
      LOG(ERROR) << "Failed to rollback : " << rollback_status.ErrorMessage();
    }
  }

  for (const auto& dir : kApexPackageBuiltinDirs) {
    // TODO(b/123622800): if activation failed, rollback and reboot.
    status = scanPackagesDirAndActivate(dir.c_str());
    if (!status.Ok()) {
      // This should never happen. Like **really** never.
      // TODO: should we kill apexd in this case?
      LOG(ERROR) << "Failed to activate packages from " << dir << " : "
                 << status.ErrorMessage();
    }
  }
}

void onAllPackagesReady() {
  // Set a system property to let other components to know that APEXs are
  // correctly mounted and ready to be used. Before using any file from APEXs,
  // they can query this system property to ensure that they are okay to
  // access. Or they may have a on-property trigger to delay a task until
  // APEXs become ready.
  LOG(INFO) << "Marking APEXd as ready";
  if (!android::base::SetProperty(kApexStatusSysprop, kApexStatusReady)) {
    PLOG(ERROR) << "Failed to set " << kApexStatusSysprop << " to "
                << kApexStatusReady;
  }
}

StatusOr<std::vector<ApexFile>> submitStagedSession(
    const int session_id, const std::vector<int>& child_session_ids) {
  bool needsBackup = true;
  Status cleanup_status = ClearSessions();
  if (!cleanup_status.Ok()) {
    return StatusOr<std::vector<ApexFile>>::MakeError(cleanup_status);
  }

  if (gSupportsFsCheckpoints) {
    Status checkpoint_status =
        gVoldService->StartCheckpoint(kNumRetriesWhenCheckpointingEnabled);
    if (!checkpoint_status.Ok()) {
      // The device supports checkpointing, but we could not start it;
      // log a warning, but do continue, since we can live without it.
      LOG(WARNING) << "Failed to start filesystem checkpoint on device that "
                      "should support it: "
                   << checkpoint_status.ErrorMessage();
    } else {
      needsBackup = false;
    }
  }

  if (needsBackup) {
    Status backup_status = BackupActivePackages();
    if (!backup_status.Ok()) {
      return StatusOr<std::vector<ApexFile>>::MakeError(backup_status);
    }
  }

  std::vector<int> ids_to_scan;
  if (!child_session_ids.empty()) {
    ids_to_scan = child_session_ids;
  } else {
    ids_to_scan = {session_id};
  }

  std::vector<ApexFile> ret;
  for (int id_to_scan : ids_to_scan) {
    auto verified = verifySessionDir(id_to_scan);
    if (!verified.Ok()) {
      return StatusOr<std::vector<ApexFile>>::MakeError(verified.ErrorStatus());
    }
    ret.push_back(std::move(*verified));
  }

  // Run preinstall, if necessary.
  Status preinstall_status = PreinstallPackages(ret);
  if (!preinstall_status.Ok()) {
    return StatusOr<std::vector<ApexFile>>::MakeError(preinstall_status);
  }

  auto session = ApexSession::CreateSession(session_id);
  if (!session.Ok()) {
    return StatusOr<std::vector<ApexFile>>::MakeError(session.ErrorMessage());
  }
  (*session).SetChildSessionIds(child_session_ids);
  Status commit_status =
      (*session).UpdateStateAndCommit(SessionState::VERIFIED);
  if (!commit_status.Ok()) {
    return StatusOr<std::vector<ApexFile>>::MakeError(commit_status);
  }

  return StatusOr<std::vector<ApexFile>>(std::move(ret));
}

Status markStagedSessionReady(const int session_id) {
  auto session = ApexSession::GetSession(session_id);
  if (!session.Ok()) {
    return session.ErrorStatus();
  }
  // We should only accept sessions in SessionState::VERIFIED or
  // SessionState::STAGED state. In the SessionState::STAGED case, this
  // function is effectively a no-op.
  auto session_state = (*session).GetState();
  if (session_state == SessionState::STAGED) {
    return Status::Success();
  }
  if (session_state == SessionState::VERIFIED) {
    return (*session).UpdateStateAndCommit(SessionState::STAGED);
  }
  return Status::Fail(StringLog() << "Invalid state for session " << session_id
                                  << ". Cannot mark it as ready.");
}

Status markStagedSessionSuccessful(const int session_id) {
  auto session = ApexSession::GetSession(session_id);
  if (!session.Ok()) {
    return session.ErrorStatus();
  }
  // Only SessionState::ACTIVATED or SessionState::SUCCESS states are accepted.
  // In the SessionState::SUCCESS state, this function is a no-op.
  if (session->GetState() == SessionState::SUCCESS) {
    return Status::Success();
  } else if (session->GetState() == SessionState::ACTIVATED) {
    auto cleanup_status = DeleteBackup();
    if (!cleanup_status.Ok()) {
      return Status::Fail(StringLog() << "Failed to mark session " << *session
                                      << " as successful : "
                                      << cleanup_status.ErrorMessage());
    }
    return session->UpdateStateAndCommit(SessionState::SUCCESS);
  } else {
    return Status::Fail(StringLog() << "Session " << *session
                                    << " can not be marked successful");
  }
}

// Find dangling mounts and unmount them.
// If one is on /data/apex/active, remove it.
void unmountDanglingMounts() {
  std::multimap<std::string, MountedApexData> danglings;
  gMountedApexes.ForallMountedApexes([&](const std::string& package,
                                         const MountedApexData& data,
                                         bool latest) {
    if (!latest) {
      danglings.insert({package, data});
    }
  });

  for (const auto& [package, data] : danglings) {
    const std::string& path = data.full_path;
    LOG(VERBOSE) << "Unmounting " << data.mount_point;
    gMountedApexes.RemoveMountedApex(package, path);
    if (auto st = Unmount(data); !st.Ok()) {
      LOG(ERROR) << st.ErrorMessage();
    }
    if (StartsWith(path, kActiveApexPackagesDataDir)) {
      LOG(VERBOSE) << "Deleting old APEX " << path;
      if (unlink(path.c_str()) != 0) {
        PLOG(ERROR) << "Failed to delete " << path;
      }
    }
  }
}

}  // namespace apex
}  // namespace android
