New priority scripts + critical updates to fonts. am: cbb0b54b12

Change-Id: Ifddcec2a5582ac3943b588c07141ddd24979655f
diff --git a/boot_control/Android.bp b/boot_control/Android.bp
deleted file mode 100644
index b2e68df..0000000
--- a/boot_control/Android.bp
+++ /dev/null
@@ -1,61 +0,0 @@
-//
-// 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.
-//
-
-cc_defaults {
-    name: "libboot_control_defaults",
-    vendor: true,
-    recovery_available: true,
-    relative_install_path: "hw",
-
-    cflags: [
-        "-D_FILE_OFFSET_BITS=64",
-        "-Werror",
-        "-Wall",
-        "-Wextra",
-    ],
-
-    shared_libs: [
-        "android.hardware.boot@1.1",
-        "libbase",
-        "liblog",
-    ],
-    static_libs: [
-        "libbootloader_message_vendor",
-        "libfstab",
-    ],
-}
-
-cc_library_static {
-    name: "libboot_control",
-    defaults: ["libboot_control_defaults"],
-    export_include_dirs: ["include"],
-
-    srcs: ["libboot_control.cpp"],
-}
-
-cc_library_shared {
-    name: "bootctrl.default",
-    defaults: ["libboot_control_defaults"],
-
-    srcs: ["legacy_boot_control.cpp"],
-
-    static_libs: [
-        "libboot_control",
-    ],
-    shared_libs: [
-        "libhardware",
-    ],
-}
diff --git a/boot_control/include/libboot_control/libboot_control.h b/boot_control/include/libboot_control/libboot_control.h
deleted file mode 100644
index 5468658..0000000
--- a/boot_control/include/libboot_control/libboot_control.h
+++ /dev/null
@@ -1,89 +0,0 @@
-//
-// Copyright (C) 2019 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.
-//
-
-#pragma once
-
-#include <string>
-
-#include <android/hardware/boot/1.1/IBootControl.h>
-
-namespace android {
-namespace bootable {
-
-// Helper library to implement the IBootControl HAL using the misc partition.
-class BootControl {
-  using MergeStatus = ::android::hardware::boot::V1_1::MergeStatus;
-
- public:
-  bool Init();
-  unsigned int GetNumberSlots();
-  unsigned int GetCurrentSlot();
-  bool MarkBootSuccessful();
-  bool SetActiveBootSlot(unsigned int slot);
-  bool SetSlotAsUnbootable(unsigned int slot);
-  bool SetSlotBootable(unsigned int slot);
-  bool IsSlotBootable(unsigned int slot);
-  const char* GetSuffix(unsigned int slot);
-  bool IsSlotMarkedSuccessful(unsigned int slot);
-  bool SetSnapshotMergeStatus(MergeStatus status);
-  MergeStatus GetSnapshotMergeStatus();
-
-  bool IsValidSlot(unsigned int slot);
-
-  const std::string& misc_device() const {
-    return misc_device_;
-  }
-
- private:
-  // Whether this object was initialized with data from the bootloader message
-  // that doesn't change until next reboot.
-  bool initialized_ = false;
-
-  // The path to the misc_device as reported in the fstab.
-  std::string misc_device_;
-
-  // The number of slots present on the device.
-  unsigned int num_slots_ = 0;
-
-  // The slot where we are running from.
-  unsigned int current_slot_ = 0;
-};
-
-// Helper functions to write the Virtual A/B merge status message. These are
-// separate because BootControl uses bootloader_control_ab in vendor space,
-// whereas the Virtual A/B merge status is in system space. A HAL might not
-// use bootloader_control_ab, but may want to use the AOSP method of maintaining
-// the merge status.
-
-// If the Virtual A/B message has not yet been initialized, then initialize it.
-// This should be called when the BootControl HAL first loads.
-//
-// If the Virtual A/B message in misc was already initialized, true is returned.
-// If initialization was attempted, but failed, false is returned, and the HAL
-// should fail to load.
-bool InitMiscVirtualAbMessageIfNeeded();
-
-// Save the current merge status as well as the current slot.
-bool SetMiscVirtualAbMergeStatus(unsigned int current_slot,
-                                 android::hardware::boot::V1_1::MergeStatus status);
-
-// Return the current merge status. If the saved status is SNAPSHOTTED but the
-// slot hasn't changed, the status returned will be NONE.
-bool GetMiscVirtualAbMergeStatus(unsigned int current_slot,
-                                 android::hardware::boot::V1_1::MergeStatus* status);
-
-}  // namespace bootable
-}  // namespace android
diff --git a/boot_control/legacy_boot_control.cpp b/boot_control/legacy_boot_control.cpp
deleted file mode 100644
index 73d3a58..0000000
--- a/boot_control/legacy_boot_control.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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 <string>
-
-#include <hardware/boot_control.h>
-#include <hardware/hardware.h>
-
-#include <libboot_control/libboot_control.h>
-
-using android::bootable::BootControl;
-
-struct boot_control_private_t {
-  // The base struct needs to be first in the list.
-  boot_control_module_t base;
-
-  BootControl impl;
-};
-
-namespace {
-
-void BootControl_init(boot_control_module_t* module) {
-  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
-  impl.Init();
-}
-
-unsigned int BootControl_getNumberSlots(boot_control_module_t* module) {
-  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
-  return impl.GetNumberSlots();
-}
-
-unsigned int BootControl_getCurrentSlot(boot_control_module_t* module) {
-  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
-  return impl.GetCurrentSlot();
-}
-
-int BootControl_markBootSuccessful(boot_control_module_t* module) {
-  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
-  return impl.MarkBootSuccessful() ? 0 : -1;
-}
-
-int BootControl_setActiveBootSlot(boot_control_module_t* module, unsigned int slot) {
-  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
-  return impl.SetActiveBootSlot(slot) ? 0 : -1;
-}
-
-int BootControl_setSlotAsUnbootable(struct boot_control_module* module, unsigned int slot) {
-  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
-  return impl.SetSlotAsUnbootable(slot) ? 0 : -1;
-}
-
-int BootControl_isSlotBootable(struct boot_control_module* module, unsigned int slot) {
-  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
-  return impl.IsSlotBootable(slot) ? 0 : -1;
-}
-
-int BootControl_isSlotMarkedSuccessful(struct boot_control_module* module, unsigned int slot) {
-  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
-  return impl.IsSlotMarkedSuccessful(slot) ? 0 : -1;
-}
-
-const char* BootControl_getSuffix(boot_control_module_t* module, unsigned int slot) {
-  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
-  return impl.GetSuffix(slot);
-}
-
-static int BootControl_open(const hw_module_t* module __unused, const char* id __unused,
-                            hw_device_t** device __unused) {
-  /* Nothing to do currently. */
-  return 0;
-}
-
-struct hw_module_methods_t BootControl_methods = {
-  .open = BootControl_open,
-};
-
-}  // namespace
-
-boot_control_private_t HAL_MODULE_INFO_SYM = {
-  .base =
-      {
-          .common =
-              {
-                  .tag = HARDWARE_MODULE_TAG,
-                  .module_api_version = BOOT_CONTROL_MODULE_API_VERSION_0_1,
-                  .hal_api_version = HARDWARE_HAL_API_VERSION,
-                  .id = BOOT_CONTROL_HARDWARE_MODULE_ID,
-                  .name = "AOSP reference bootctrl HAL",
-                  .author = "The Android Open Source Project",
-                  .methods = &BootControl_methods,
-              },
-          .init = BootControl_init,
-          .getNumberSlots = BootControl_getNumberSlots,
-          .getCurrentSlot = BootControl_getCurrentSlot,
-          .markBootSuccessful = BootControl_markBootSuccessful,
-          .setActiveBootSlot = BootControl_setActiveBootSlot,
-          .setSlotAsUnbootable = BootControl_setSlotAsUnbootable,
-          .isSlotBootable = BootControl_isSlotBootable,
-          .getSuffix = BootControl_getSuffix,
-          .isSlotMarkedSuccessful = BootControl_isSlotMarkedSuccessful,
-      },
-};
diff --git a/boot_control/libboot_control.cpp b/boot_control/libboot_control.cpp
deleted file mode 100644
index ab9ce97..0000000
--- a/boot_control/libboot_control.cpp
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * 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 <libboot_control/libboot_control.h>
-
-#include <endian.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-
-#include <string>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android-base/stringprintf.h>
-#include <android-base/unique_fd.h>
-
-#include <bootloader_message/bootloader_message.h>
-
-namespace android {
-namespace bootable {
-
-using ::android::hardware::boot::V1_1::MergeStatus;
-
-// The number of boot attempts that should be made from a new slot before
-// rolling back to the previous slot.
-constexpr unsigned int kDefaultBootAttempts = 7;
-static_assert(kDefaultBootAttempts < 8, "tries_remaining field only has 3 bits");
-
-constexpr unsigned int kMaxNumSlots =
-    sizeof(bootloader_control::slot_info) / sizeof(bootloader_control::slot_info[0]);
-constexpr const char* kSlotSuffixes[kMaxNumSlots] = { "_a", "_b", "_c", "_d" };
-constexpr off_t kBootloaderControlOffset = offsetof(bootloader_message_ab, slot_suffix);
-
-static uint32_t CRC32(const uint8_t* buf, size_t size) {
-  static uint32_t crc_table[256];
-
-  // Compute the CRC-32 table only once.
-  if (!crc_table[1]) {
-    for (uint32_t i = 0; i < 256; ++i) {
-      uint32_t crc = i;
-      for (uint32_t j = 0; j < 8; ++j) {
-        uint32_t mask = -(crc & 1);
-        crc = (crc >> 1) ^ (0xEDB88320 & mask);
-      }
-      crc_table[i] = crc;
-    }
-  }
-
-  uint32_t ret = -1;
-  for (size_t i = 0; i < size; ++i) {
-    ret = (ret >> 8) ^ crc_table[(ret ^ buf[i]) & 0xFF];
-  }
-
-  return ~ret;
-}
-
-// Return the little-endian representation of the CRC-32 of the first fields
-// in |boot_ctrl| up to the crc32_le field.
-uint32_t BootloaderControlLECRC(const bootloader_control* boot_ctrl) {
-  return htole32(
-      CRC32(reinterpret_cast<const uint8_t*>(boot_ctrl), offsetof(bootloader_control, crc32_le)));
-}
-
-bool LoadBootloaderControl(const std::string& misc_device, bootloader_control* buffer) {
-  android::base::unique_fd fd(open(misc_device.c_str(), O_RDONLY));
-  if (fd.get() == -1) {
-    PLOG(ERROR) << "failed to open " << misc_device;
-    return false;
-  }
-  if (lseek(fd, kBootloaderControlOffset, SEEK_SET) != kBootloaderControlOffset) {
-    PLOG(ERROR) << "failed to lseek " << misc_device;
-    return false;
-  }
-  if (!android::base::ReadFully(fd.get(), buffer, sizeof(bootloader_control))) {
-    PLOG(ERROR) << "failed to read " << misc_device;
-    return false;
-  }
-  return true;
-}
-
-bool UpdateAndSaveBootloaderControl(const std::string& misc_device, bootloader_control* buffer) {
-  buffer->crc32_le = BootloaderControlLECRC(buffer);
-  android::base::unique_fd fd(open(misc_device.c_str(), O_WRONLY | O_SYNC));
-  if (fd.get() == -1) {
-    PLOG(ERROR) << "failed to open " << misc_device;
-    return false;
-  }
-  if (lseek(fd.get(), kBootloaderControlOffset, SEEK_SET) != kBootloaderControlOffset) {
-    PLOG(ERROR) << "failed to lseek " << misc_device;
-    return false;
-  }
-  if (!android::base::WriteFully(fd.get(), buffer, sizeof(bootloader_control))) {
-    PLOG(ERROR) << "failed to write " << misc_device;
-    return false;
-  }
-  return true;
-}
-
-void InitDefaultBootloaderControl(BootControl* control, bootloader_control* boot_ctrl) {
-  memset(boot_ctrl, 0, sizeof(*boot_ctrl));
-
-  unsigned int current_slot = control->GetCurrentSlot();
-  if (current_slot < kMaxNumSlots) {
-    strlcpy(boot_ctrl->slot_suffix, kSlotSuffixes[current_slot], sizeof(boot_ctrl->slot_suffix));
-  }
-  boot_ctrl->magic = BOOT_CTRL_MAGIC;
-  boot_ctrl->version = BOOT_CTRL_VERSION;
-
-  // Figure out the number of slots by checking if the partitions exist,
-  // otherwise assume the maximum supported by the header.
-  boot_ctrl->nb_slot = kMaxNumSlots;
-  std::string base_path = control->misc_device();
-  size_t last_path_sep = base_path.rfind('/');
-  if (last_path_sep != std::string::npos) {
-    // We test the existence of the "boot" partition on each possible slot,
-    // which is a partition required by Android Bootloader Requirements.
-    base_path = base_path.substr(0, last_path_sep + 1) + "boot";
-    int last_existing_slot = -1;
-    int first_missing_slot = -1;
-    for (unsigned int slot = 0; slot < kMaxNumSlots; ++slot) {
-      std::string partition_path = base_path + kSlotSuffixes[slot];
-      struct stat part_stat;
-      int err = stat(partition_path.c_str(), &part_stat);
-      if (!err) {
-        last_existing_slot = slot;
-        LOG(INFO) << "Found slot: " << kSlotSuffixes[slot];
-      } else if (err < 0 && errno == ENOENT && first_missing_slot == -1) {
-        first_missing_slot = slot;
-      }
-    }
-    // We only declare that we found the actual number of slots if we found all
-    // the boot partitions up to the number of slots, and no boot partition
-    // after that. Not finding any of the boot partitions implies a problem so
-    // we just leave the number of slots in the maximum value.
-    if ((last_existing_slot != -1 && last_existing_slot + 1 == first_missing_slot) ||
-        (first_missing_slot == -1 && last_existing_slot + 1 == kMaxNumSlots)) {
-      boot_ctrl->nb_slot = last_existing_slot + 1;
-      LOG(INFO) << "Found a system with " << last_existing_slot + 1 << " slots.";
-    }
-  }
-
-  for (unsigned int slot = 0; slot < kMaxNumSlots; ++slot) {
-    slot_metadata entry = {};
-
-    if (slot < boot_ctrl->nb_slot) {
-      entry.priority = 7;
-      entry.tries_remaining = kDefaultBootAttempts;
-      entry.successful_boot = 0;
-    } else {
-      entry.priority = 0;  // Unbootable
-    }
-
-    // When the boot_control stored on disk is invalid, we assume that the
-    // current slot is successful. The bootloader should repair this situation
-    // before booting and write a valid boot_control slot, so if we reach this
-    // stage it means that the misc partition was corrupted since boot.
-    if (current_slot == slot) {
-      entry.successful_boot = 1;
-    }
-
-    boot_ctrl->slot_info[slot] = entry;
-  }
-  boot_ctrl->recovery_tries_remaining = 0;
-
-  boot_ctrl->crc32_le = BootloaderControlLECRC(boot_ctrl);
-}
-
-// Return the index of the slot suffix passed or -1 if not a valid slot suffix.
-int SlotSuffixToIndex(const char* suffix) {
-  for (unsigned int slot = 0; slot < kMaxNumSlots; ++slot) {
-    if (!strcmp(kSlotSuffixes[slot], suffix)) return slot;
-  }
-  return -1;
-}
-
-// Initialize the boot_control_private struct with the information from
-// the bootloader_message buffer stored in |boot_ctrl|. Returns whether the
-// initialization succeeded.
-bool BootControl::Init() {
-  if (initialized_) return true;
-
-  // Initialize the current_slot from the read-only property. If the property
-  // was not set (from either the command line or the device tree), we can later
-  // initialize it from the bootloader_control struct.
-  std::string suffix_prop = android::base::GetProperty("ro.boot.slot_suffix", "");
-  if (suffix_prop.empty()) {
-    LOG(ERROR) << "Slot suffix property is not set";
-    return false;
-  }
-  current_slot_ = SlotSuffixToIndex(suffix_prop.c_str());
-
-  std::string err;
-  std::string device = get_bootloader_message_blk_device(&err);
-  if (device.empty()) {
-    LOG(ERROR) << "Could not find bootloader message block device: " << err;
-    return false;
-  }
-
-  bootloader_control boot_ctrl;
-  if (!LoadBootloaderControl(device.c_str(), &boot_ctrl)) {
-    LOG(ERROR) << "Failed to load bootloader control block";
-    return false;
-  }
-
-  // Note that since there isn't a module unload function this memory is leaked.
-  // We use `device` below sometimes, so it's not moved out of here.
-  misc_device_ = device;
-  initialized_ = true;
-
-  // Validate the loaded data, otherwise we will destroy it and re-initialize it
-  // with the current information.
-  uint32_t computed_crc32 = BootloaderControlLECRC(&boot_ctrl);
-  if (boot_ctrl.crc32_le != computed_crc32) {
-    LOG(WARNING) << "Invalid boot control found, expected CRC-32 0x" << std::hex << computed_crc32
-                 << " but found 0x" << std::hex << boot_ctrl.crc32_le << ". Re-initializing.";
-    InitDefaultBootloaderControl(this, &boot_ctrl);
-    UpdateAndSaveBootloaderControl(device.c_str(), &boot_ctrl);
-  }
-
-  if (!InitMiscVirtualAbMessageIfNeeded()) {
-    return false;
-  }
-
-  num_slots_ = boot_ctrl.nb_slot;
-  return true;
-}
-
-unsigned int BootControl::GetNumberSlots() {
-  return num_slots_;
-}
-
-unsigned int BootControl::GetCurrentSlot() {
-  return current_slot_;
-}
-
-bool BootControl::MarkBootSuccessful() {
-  bootloader_control bootctrl;
-  if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
-
-  bootctrl.slot_info[current_slot_].successful_boot = 1;
-  // tries_remaining == 0 means that the slot is not bootable anymore, make
-  // sure we mark the current slot as bootable if it succeeds in the last
-  // attempt.
-  bootctrl.slot_info[current_slot_].tries_remaining = 1;
-  return UpdateAndSaveBootloaderControl(misc_device_, &bootctrl);
-}
-
-bool BootControl::SetActiveBootSlot(unsigned int slot) {
-  if (slot >= kMaxNumSlots || slot >= num_slots_) {
-    // Invalid slot number.
-    return false;
-  }
-
-  bootloader_control bootctrl;
-  if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
-
-  // Set every other slot with a lower priority than the new "active" slot.
-  const unsigned int kActivePriority = 15;
-  const unsigned int kActiveTries = 6;
-  for (unsigned int i = 0; i < num_slots_; ++i) {
-    if (i != slot) {
-      if (bootctrl.slot_info[i].priority >= kActivePriority)
-        bootctrl.slot_info[i].priority = kActivePriority - 1;
-    }
-  }
-
-  // Note that setting a slot as active doesn't change the successful bit.
-  // The successful bit will only be changed by setSlotAsUnbootable().
-  bootctrl.slot_info[slot].priority = kActivePriority;
-  bootctrl.slot_info[slot].tries_remaining = kActiveTries;
-
-  // Setting the current slot as active is a way to revert the operation that
-  // set *another* slot as active at the end of an updater. This is commonly
-  // used to cancel the pending update. We should only reset the verity_corrpted
-  // bit when attempting a new slot, otherwise the verity bit on the current
-  // slot would be flip.
-  if (slot != current_slot_) bootctrl.slot_info[slot].verity_corrupted = 0;
-
-  return UpdateAndSaveBootloaderControl(misc_device_, &bootctrl);
-}
-
-bool BootControl::SetSlotAsUnbootable(unsigned int slot) {
-  if (slot >= kMaxNumSlots || slot >= num_slots_) {
-    // Invalid slot number.
-    return false;
-  }
-
-  bootloader_control bootctrl;
-  if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
-
-  // The only way to mark a slot as unbootable, regardless of the priority is to
-  // set the tries_remaining to 0.
-  bootctrl.slot_info[slot].successful_boot = 0;
-  bootctrl.slot_info[slot].tries_remaining = 0;
-  return UpdateAndSaveBootloaderControl(misc_device_, &bootctrl);
-}
-
-bool BootControl::IsSlotBootable(unsigned int slot) {
-  if (slot >= kMaxNumSlots || slot >= num_slots_) {
-    // Invalid slot number.
-    return false;
-  }
-
-  bootloader_control bootctrl;
-  if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
-
-  return bootctrl.slot_info[slot].tries_remaining != 0;
-}
-
-bool BootControl::IsSlotMarkedSuccessful(unsigned int slot) {
-  if (slot >= kMaxNumSlots || slot >= num_slots_) {
-    // Invalid slot number.
-    return false;
-  }
-
-  bootloader_control bootctrl;
-  if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
-
-  return bootctrl.slot_info[slot].successful_boot && bootctrl.slot_info[slot].tries_remaining;
-}
-
-bool BootControl::IsValidSlot(unsigned int slot) {
-  return slot < kMaxNumSlots && slot < num_slots_;
-}
-
-bool BootControl::SetSnapshotMergeStatus(MergeStatus status) {
-  return SetMiscVirtualAbMergeStatus(current_slot_, status);
-}
-
-MergeStatus BootControl::GetSnapshotMergeStatus() {
-  MergeStatus status;
-  if (!GetMiscVirtualAbMergeStatus(current_slot_, &status)) {
-    return MergeStatus::UNKNOWN;
-  }
-  return status;
-}
-
-const char* BootControl::GetSuffix(unsigned int slot) {
-  if (slot >= kMaxNumSlots || slot >= num_slots_) {
-    return nullptr;
-  }
-  return kSlotSuffixes[slot];
-}
-
-bool InitMiscVirtualAbMessageIfNeeded() {
-  std::string err;
-  misc_virtual_ab_message message;
-  if (!ReadMiscVirtualAbMessage(&message, &err)) {
-    LOG(ERROR) << "Could not read merge status: " << err;
-    return false;
-  }
-
-  if (message.version == MISC_VIRTUAL_AB_MESSAGE_VERSION &&
-      message.magic == MISC_VIRTUAL_AB_MAGIC_HEADER) {
-    // Already initialized.
-    return true;
-  }
-
-  message = {};
-  message.version = MISC_VIRTUAL_AB_MESSAGE_VERSION;
-  message.magic = MISC_VIRTUAL_AB_MAGIC_HEADER;
-  if (!WriteMiscVirtualAbMessage(message, &err)) {
-    LOG(ERROR) << "Could not write merge status: " << err;
-    return false;
-  }
-  return true;
-}
-
-bool SetMiscVirtualAbMergeStatus(unsigned int current_slot,
-                                 android::hardware::boot::V1_1::MergeStatus status) {
-  std::string err;
-  misc_virtual_ab_message message;
-
-  if (!ReadMiscVirtualAbMessage(&message, &err)) {
-    LOG(ERROR) << "Could not read merge status: " << err;
-    return false;
-  }
-
-  message.merge_status = static_cast<uint8_t>(status);
-  message.source_slot = current_slot;
-  if (!WriteMiscVirtualAbMessage(message, &err)) {
-    LOG(ERROR) << "Could not write merge status: " << err;
-    return false;
-  }
-  return true;
-}
-
-bool GetMiscVirtualAbMergeStatus(unsigned int current_slot,
-                                 android::hardware::boot::V1_1::MergeStatus* status) {
-  std::string err;
-  misc_virtual_ab_message message;
-
-  if (!ReadMiscVirtualAbMessage(&message, &err)) {
-    LOG(ERROR) << "Could not read merge status: " << err;
-    return false;
-  }
-
-  // If the slot reverted after having created a snapshot, then the snapshot will
-  // be thrown away at boot. Thus we don't count this as being in a snapshotted
-  // state.
-  *status = static_cast<MergeStatus>(message.merge_status);
-  if (*status == MergeStatus::SNAPSHOTTED && current_slot == message.source_slot) {
-    *status = MergeStatus::NONE;
-  }
-  return true;
-}
-
-}  // namespace bootable
-}  // namespace android
diff --git a/bootloader_message/include/bootloader_message/bootloader_message.h b/bootloader_message/include/bootloader_message/bootloader_message.h
index 9a482d4..e4cf09b 100644
--- a/bootloader_message/include/bootloader_message/bootloader_message.h
+++ b/bootloader_message/include/bootloader_message/bootloader_message.h
@@ -83,108 +83,6 @@
     char reserved[1184];
 };
 
-/**
- * We must be cautious when changing the bootloader_message struct size,
- * because A/B-specific fields may end up with different offsets.
- */
-#if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus)
-static_assert(sizeof(struct bootloader_message) == 2048,
-              "struct bootloader_message size changes, which may break A/B devices");
-#endif
-
-/**
- * The A/B-specific bootloader message structure (4-KiB).
- *
- * We separate A/B boot control metadata from the regular bootloader
- * message struct and keep it here. Everything that's A/B-specific
- * stays after struct bootloader_message, which should be managed by
- * the A/B-bootloader or boot control HAL.
- *
- * The slot_suffix field is used for A/B implementations where the
- * bootloader does not set the androidboot.ro.boot.slot_suffix kernel
- * commandline parameter. This is used by fs_mgr to mount /system and
- * other partitions with the slotselect flag set in fstab. A/B
- * implementations are free to use all 32 bytes and may store private
- * data past the first NUL-byte in this field. It is encouraged, but
- * not mandatory, to use 'struct bootloader_control' described below.
- *
- * The update_channel field is used to store the Omaha update channel
- * if update_engine is compiled with Omaha support.
- */
-struct bootloader_message_ab {
-    struct bootloader_message message;
-    char slot_suffix[32];
-    char update_channel[128];
-
-    // Round up the entire struct to 4096-byte.
-    char reserved[1888];
-};
-
-/**
- * Be cautious about the struct size change, in case we put anything post
- * bootloader_message_ab struct (b/29159185).
- */
-#if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus)
-static_assert(sizeof(struct bootloader_message_ab) == 4096,
-              "struct bootloader_message_ab size changes");
-#endif
-
-#define BOOT_CTRL_MAGIC   0x42414342 /* Bootloader Control AB */
-#define BOOT_CTRL_VERSION 1
-
-struct slot_metadata {
-    // Slot priority with 15 meaning highest priority, 1 lowest
-    // priority and 0 the slot is unbootable.
-    uint8_t priority : 4;
-    // Number of times left attempting to boot this slot.
-    uint8_t tries_remaining : 3;
-    // 1 if this slot has booted successfully, 0 otherwise.
-    uint8_t successful_boot : 1;
-    // 1 if this slot is corrupted from a dm-verity corruption, 0
-    // otherwise.
-    uint8_t verity_corrupted : 1;
-    // Reserved for further use.
-    uint8_t reserved : 7;
-} __attribute__((packed));
-
-/* Bootloader Control AB
- *
- * This struct can be used to manage A/B metadata. It is designed to
- * be put in the 'slot_suffix' field of the 'bootloader_message'
- * structure described above. It is encouraged to use the
- * 'bootloader_control' structure to store the A/B metadata, but not
- * mandatory.
- */
-struct bootloader_control {
-    // NUL terminated active slot suffix.
-    char slot_suffix[4];
-    // Bootloader Control AB magic number (see BOOT_CTRL_MAGIC).
-    uint32_t magic;
-    // Version of struct being used (see BOOT_CTRL_VERSION).
-    uint8_t version;
-    // Number of slots being managed.
-    uint8_t nb_slot : 3;
-    // Number of times left attempting to boot recovery.
-    uint8_t recovery_tries_remaining : 3;
-    // Status of any pending snapshot merge of dynamic partitions.
-    uint8_t merge_status : 3;
-    // Ensure 4-bytes alignment for slot_info field.
-    uint8_t reserved0[1];
-    // Per-slot information.  Up to 4 slots.
-    struct slot_metadata slot_info[4];
-    // Reserved for further use.
-    uint8_t reserved1[8];
-    // CRC32 of all 28 bytes preceding this field (little endian
-    // format).
-    uint32_t crc32_le;
-} __attribute__((packed));
-
-#if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus)
-static_assert(sizeof(struct bootloader_control) ==
-              sizeof(((struct bootloader_message_ab *)0)->slot_suffix),
-              "struct bootloader_control has wrong size");
-#endif
-
 // Holds Virtual A/B merge status information. Current version is 1. New fields
 // must be added to the end.
 struct misc_virtual_ab_message {
diff --git a/recovery_ui/screen_ui.cpp b/recovery_ui/screen_ui.cpp
index 087fc0e..6dcb161 100644
--- a/recovery_ui/screen_ui.cpp
+++ b/recovery_ui/screen_ui.cpp
@@ -448,7 +448,9 @@
     int frame_height = gr_get_height(frame);
     int frame_x = (ScreenWidth() - frame_width) / 2;
     int frame_y = GetAnimationBaseline();
-    DrawSurface(frame, 0, 0, frame_width, frame_height, frame_x, frame_y);
+    if (frame_x >= 0 && frame_y >= 0 && (frame_x + frame_width) < ScreenWidth() &&
+        (frame_y + frame_height) < ScreenHeight())
+      DrawSurface(frame, 0, 0, frame_width, frame_height, frame_x, frame_y);
   }
 
   if (progressBarType != EMPTY) {
diff --git a/tests/Android.bp b/tests/Android.bp
index 4c23255..a9a088a 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -95,6 +95,24 @@
     "libc++fs",
 ]
 
+// recovery image for unittests.
+// ========================================================
+genrule {
+    name: "recovery_image",
+    cmd: "cat $(location testdata/recovery_head) <(cat $(location testdata/recovery_body) | $(location minigzip)) $(location testdata/recovery_tail) > $(out)",
+    srcs: [
+        "testdata/recovery_head",
+        "testdata/recovery_body",
+        "testdata/recovery_tail",
+    ],
+    tools: [
+        "minigzip",
+    ],
+    out: [
+        "testdata/recovery.img",
+    ],
+}
+
 cc_test {
     name: "recovery_unit_test",
     isolated: true,
@@ -128,6 +146,7 @@
 
     data: [
         "testdata/*",
+        ":recovery_image",
         ":res-testdata",
     ],
 }
diff --git a/tests/testdata/recovery.img b/tests/testdata/recovery.img
deleted file mode 100644
index b862e6f..0000000
--- a/tests/testdata/recovery.img
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/recovery_body b/tests/testdata/recovery_body
new file mode 100644
index 0000000..48d7c10
--- /dev/null
+++ b/tests/testdata/recovery_body
Binary files differ
diff --git a/tests/testdata/recovery_head b/tests/testdata/recovery_head
new file mode 100644
index 0000000..7f494d0
--- /dev/null
+++ b/tests/testdata/recovery_head
Binary files differ
diff --git a/tests/testdata/recovery_tail b/tests/testdata/recovery_tail
new file mode 100644
index 0000000..7fe2c6c
--- /dev/null
+++ b/tests/testdata/recovery_tail
Binary files differ
diff --git a/updater/Android.bp b/updater/Android.bp
index cbef430..f00a192 100644
--- a/updater/Android.bp
+++ b/updater/Android.bp
@@ -25,6 +25,7 @@
         "libdm",
         "libfec",
         "libfec_rs",
+        "libavb",
         "libverity_tree",
         "libgtest_prod",
         "liblog",
diff --git a/updater/Android.mk b/updater/Android.mk
index 8a4cd86..46300d9 100644
--- a/updater/Android.mk
+++ b/updater/Android.mk
@@ -32,6 +32,7 @@
     libdm \
     libfec \
     libfec_rs \
+    libavb \
     libverity_tree \
     libgtest_prod \
     liblog \