/*
 * Copyright (C) 2021 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 <vector>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/unique_fd.h>
#include <android/api-level.h>
#include <bootimg.h>
#include <fs_avb/fs_avb_util.h>
#include <gtest/gtest.h>
#include <libavb/libavb.h>
#include <storage_literals/storage_literals.h>
#include <vintf/VintfObject.h>
#include <vintf/parse_string.h>

#include "gsi_validation_utils.h"

using namespace std::literals;
using namespace android::storage_literals;

namespace {

std::string GetBlockDevicePath(const std::string &name) {
  return "/dev/block/by-name/" + name + fs_mgr_get_slot_suffix();
}

uint32_t GetBootHeaderVersion(const void *data) {
  return reinterpret_cast<const boot_img_hdr_v0 *>(data)->header_version;
}

class GkiBootImage {
 public:
  GkiBootImage(const uint8_t *data, size_t size) : data_(data, data + size) {}

  const uint8_t *data() const { return data_.data(); }

  size_t size() const { return data_.size(); }

  uint32_t kernel_pages() const { return GetNumberOfPages(kernel_size()); }

  uint32_t ramdisk_pages() const { return GetNumberOfPages(ramdisk_size()); }

  uint32_t kernel_offset() const {
    // The first page must be the boot image header.
    return page_size();
  }

  uint32_t ramdisk_offset() const {
    return kernel_offset() + kernel_pages() * page_size();
  }

  virtual uint32_t page_size() const = 0;
  virtual uint32_t kernel_size() const = 0;
  virtual uint32_t ramdisk_size() const = 0;
  virtual uint32_t signature_size() const = 0;
  virtual uint32_t signature_offset() const = 0;

  uint32_t GetNumberOfPages(uint32_t value) const {
    return (value + page_size() - 1) / page_size();
  }

  std::vector<uint8_t> GetKernel() const {
    return Slice(kernel_offset(), kernel_size());
  }

  std::vector<uint8_t> GetRamdisk() const {
    return Slice(ramdisk_offset(), ramdisk_size());
  }

  std::vector<uint8_t> GetLegacyGki() const {
    return Slice(0, signature_offset());
  }

  // Parse a vector of vbmeta image from the boot signature section.
  std::vector<android::fs_mgr::VBMetaData> GetBootSignatures() const {
    const auto begin_offset = std::clamp<size_t>(signature_offset(), 0, size());
    const uint8_t *buffer = data() + begin_offset;
    // begin_offset + remaining_bytes <= size() because boot_signature must be
    // the last section.
    size_t remaining_bytes =
        std::clamp<size_t>(signature_size(), 0, size() - begin_offset);
    // In case boot_signature is misaligned, shift to the first AVB magic, and
    // treat it as the actual beginning of boot signature.
    while (remaining_bytes >= AVB_MAGIC_LEN) {
      if (!memcmp(buffer, AVB_MAGIC, AVB_MAGIC_LEN)) {
        break;
      }
      ++buffer;
      --remaining_bytes;
    }
    std::vector<android::fs_mgr::VBMetaData> vbmeta_images;
    while (remaining_bytes >= sizeof(AvbVBMetaImageHeader)) {
      if (memcmp(buffer, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
        break;
      }
      // Extract only the header to calculate the vbmeta image size.
      android::fs_mgr::VBMetaData vbmeta_header(
          buffer, sizeof(AvbVBMetaImageHeader), "boot_signature");
      if (!vbmeta_header.GetVBMetaHeader(/* update_vbmeta_size */ true)) {
        GTEST_LOG_(ERROR) << __FUNCTION__
                          << "(): VBMetaData::GetVBMetaHeader() failed.";
        return {};
      }
      const auto vbmeta_image_size = vbmeta_header.size();
      GTEST_LOG_(INFO) << __FUNCTION__ << "(): Found vbmeta image with size "
                       << vbmeta_image_size;
      if (vbmeta_image_size < sizeof(AvbVBMetaImageHeader)) {
        GTEST_LOG_(ERROR) << __FUNCTION__
                          << "(): Impossible-sized vbmeta image: "
                          << vbmeta_image_size;
        return {};
      }

      if (vbmeta_image_size > remaining_bytes) {
        GTEST_LOG_(ERROR)
            << __FUNCTION__
            << "(): Premature EOF when parsing GKI boot signature.";
        return {};
      }

      vbmeta_images.emplace_back(buffer, vbmeta_image_size, "boot_signature");
      buffer += vbmeta_image_size;
      remaining_bytes -= vbmeta_image_size;
    }
    return vbmeta_images;
  }

  virtual ~GkiBootImage() = default;

 protected:
  std::vector<uint8_t> Slice(size_t offset, size_t length) const {
    const auto begin_offset = std::clamp<size_t>(offset, 0, size());
    const auto end_offset =
        std::clamp<size_t>(begin_offset + length, begin_offset, size());
    const auto begin = data() + begin_offset;
    const auto end = data() + end_offset;
    return {begin, end};
  }

 private:
  std::vector<uint8_t> data_;
};

class GkiBootImageV2 : public GkiBootImage {
 public:
  static constexpr uint32_t kBootSignatureSize = 16_KiB;

  GkiBootImageV2(const uint8_t *data, size_t size) : GkiBootImage(data, size) {}

  const boot_img_hdr_v2 *boot_header() const {
    return reinterpret_cast<const boot_img_hdr_v2 *>(data());
  }

  uint32_t page_size() const override { return boot_header()->page_size; }

  uint32_t kernel_size() const override { return boot_header()->kernel_size; }

  uint32_t ramdisk_size() const override { return boot_header()->ramdisk_size; }

  uint32_t signature_size() const override {
    // Boot v2 header doesn't tell us the size of the boot signature, so we just
    // define the last 16K bytes to be the boot signature for retrofitted GKI.
    return kBootSignatureSize;
  }

  uint32_t signature_offset() const override {
    if (size() < signature_size()) {
      return 0;
    }
    return size() - signature_size();
  }
};

class GkiBootImageV4 : public GkiBootImage {
 public:
  static constexpr uint32_t kPageSize = 4096;

  GkiBootImageV4(const uint8_t *data, size_t size) : GkiBootImage(data, size) {}

  const boot_img_hdr_v4 *boot_header() const {
    return reinterpret_cast<const boot_img_hdr_v4 *>(data());
  }

  uint32_t page_size() const override { return kPageSize; }

  uint32_t kernel_size() const override { return boot_header()->kernel_size; }

  uint32_t ramdisk_size() const override { return boot_header()->ramdisk_size; }

  uint32_t signature_size() const override {
    return boot_header()->signature_size;
  }

  uint32_t signature_offset() const override {
    return ramdisk_offset() + ramdisk_pages() * page_size();
  }
};

// As strange as it sounds we let V3 inherit V4 as they share mostly the same
// header format and image layout. The only difference is that V3 doesn't have
// the |signature_size| field, so we would have to improvise.
class GkiBootImageV3 : public GkiBootImageV4 {
 public:
  static constexpr uint32_t kBootSignatureSize = 16_KiB;

  GkiBootImageV3(const uint8_t *data, size_t size)
      : GkiBootImageV4(data, size) {}

  uint32_t signature_size() const override {
    // boot_header() here is actually a |boot_img_hdr_v4*|.
    // If |signature_size| is non-zero then this is actually a boot v4 image
    // wearing a boot v3 camouflage, else use the same heuristic as boot v2.
    const uint32_t value = GkiBootImageV4::boot_header()->signature_size;
    return value ? value : kBootSignatureSize;
  }
};

std::string GetAvbProperty(
    const std::string &name,
    const std::vector<android::fs_mgr::VBMetaData> &vbmeta_images) {
  const std::string prop_name = "com.android.build." + name;
  return android::fs_mgr::GetAvbPropertyDescriptor(prop_name, vbmeta_images);
}

std::unique_ptr<GkiBootImage> LoadAndVerifyGkiBootImage(
    const std::string &name,
    std::vector<android::fs_mgr::VBMetaData> *boot_signature_images) {
  const std::string block_device_path = GetBlockDevicePath(name);
  const std::string TAG = __FUNCTION__ + "("s + block_device_path + ")";
  SCOPED_TRACE(TAG);

  std::string block_device_data;
  if (!android::base::ReadFileToString(block_device_path, &block_device_data,
                                       /* follow_symlinks */ true)) {
    ADD_FAILURE() << "Failed to read '" << block_device_path
                  << "': " << strerror(errno);
    return nullptr;
  }
  if (block_device_data.size() <= 4096) {
    ADD_FAILURE() << "Size of '" << block_device_path
                  << "' is impossibly small: " << block_device_data.size();
    return nullptr;
  }

  if (block_device_data.substr(0, BOOT_MAGIC_SIZE) != BOOT_MAGIC) {
    ADD_FAILURE() << "Device has invalid boot magic: " << block_device_path;
    return nullptr;
  }

  // Remove the AVB footer and chained vbmeta image if there is any.
  if (block_device_data.size() > AVB_FOOTER_SIZE) {
    const uint8_t *footer_address =
        reinterpret_cast<const uint8_t *>(block_device_data.data()) +
        block_device_data.size() - AVB_FOOTER_SIZE;
    AvbFooter vbmeta_footer;
    if (avb_footer_validate_and_byteswap(
            reinterpret_cast<const AvbFooter *>(footer_address),
            &vbmeta_footer)) {
      block_device_data.resize(vbmeta_footer.original_image_size);
    }
  }

  std::unique_ptr<GkiBootImage> boot_image;
  const auto boot_header_version =
      GetBootHeaderVersion(block_device_data.data());
  if (boot_header_version == 4) {
    boot_image = std::make_unique<GkiBootImageV4>(
        reinterpret_cast<const uint8_t *>(block_device_data.data()),
        block_device_data.size());
  } else if (boot_header_version == 3) {
    boot_image = std::make_unique<GkiBootImageV3>(
        reinterpret_cast<const uint8_t *>(block_device_data.data()),
        block_device_data.size());
  } else if (boot_header_version == 2) {
    boot_image = std::make_unique<GkiBootImageV2>(
        reinterpret_cast<const uint8_t *>(block_device_data.data()),
        block_device_data.size());
  } else {
    ADD_FAILURE() << "Unexpected boot header version: " << boot_header_version;
    return nullptr;
  }

  *boot_signature_images = boot_image->GetBootSignatures();
  if (boot_signature_images->empty()) {
    ADD_FAILURE() << "Failed to load the boot signature.";
    return nullptr;
  }

  // Verify that the vbmeta images in boot_signature are certified.
  for (const auto &vbmeta_image : *boot_signature_images) {
    size_t pk_len;
    const uint8_t *pk_data;
    const auto vbmeta_verify_result = avb_vbmeta_image_verify(
        vbmeta_image.data(), vbmeta_image.size(), &pk_data, &pk_len);
    if (vbmeta_verify_result != AVB_VBMETA_VERIFY_RESULT_OK) {
      ADD_FAILURE() << "Failed to verify boot_signature: "
                    << avb_vbmeta_verify_result_to_string(vbmeta_verify_result);
      return nullptr;
    }
    const std::string out_public_key_data(
        reinterpret_cast<const char *>(pk_data), pk_len);
    if (out_public_key_data.empty()) {
      ADD_FAILURE() << "The GKI image descriptor is not signed.";
      continue;
    }
    if (!ValidatePublicKeyBlob(out_public_key_data)) {
      ADD_FAILURE()
          << "The GKI image descriptor is not signed by an official key.";
      continue;
    }
  }

  // Verify the AVB property descriptors in boot_signature matches property
  // descriptors in the end-of-partition chained vbmeta.
  std::unique_ptr<android::fs_mgr::VBMetaData> vbmeta =
      android::fs_mgr::LoadAndVerifyVbmetaByPath(
          block_device_path, name, /* expected_key_blob */ "",
          /* allow verification error */ true, /* rollback_protection */ false,
          /* is_chained_vbmeta */ false, /* out_public_key_data */ nullptr,
          /* out_verification_disabled */ nullptr,
          /* out_verify_result */ nullptr);
  if (!vbmeta) {
    ADD_FAILURE() << "Failed to load chained vbmeta of: " << block_device_path;
  } else {
    std::vector<android::fs_mgr::VBMetaData> vbmeta_image;
    vbmeta_image.push_back(std::move(*vbmeta));
    vbmeta.reset();

    for (const auto &prop :
         {"boot.security_patch"s, "init_boot.security_patch"s}) {
      const auto expected_value = GetAvbProperty(prop, *boot_signature_images);
      if (!expected_value.empty()) {
        const auto value = GetAvbProperty(prop, vbmeta_image);
        if (value != expected_value) {
          ADD_FAILURE()
              << "Boot signature and vbmeta footer property mismatch '" << prop
              << "': expect '" << expected_value << "', actual '" << value
              << "'.";
        }
      }
    }
  }

  GTEST_LOG_(INFO) << TAG << ": " + name + ".fingerprint: "
                   << GetAvbProperty(name + ".fingerprint",
                                     *boot_signature_images);
  GTEST_LOG_(INFO) << TAG << ": header version: " << boot_header_version
                   << ", kernel size: " << boot_image->kernel_size()
                   << ", ramdisk size: " << boot_image->ramdisk_size()
                   << ", signature size: " << boot_image->signature_size();

  return boot_image;
}

// Verify image data integrity with an AVB hash descriptor.
void VerifyImageDescriptor(
    const std::vector<uint8_t> &image,
    const android::fs_mgr::FsAvbHashDescriptor &descriptor) {
  const std::string TAG = __FUNCTION__ + "("s + descriptor.partition_name + ")";
  SCOPED_TRACE(TAG);

  ASSERT_EQ(image.size(), descriptor.image_size);

  const std::string &salt_str = descriptor.salt;
  const std::string &expected_digest_str = descriptor.digest;

  const std::string hash_algorithm(
      reinterpret_cast<const char *>(descriptor.hash_algorithm));
  GTEST_LOG_(INFO) << TAG << ": hash_algorithm = " << hash_algorithm;

  std::unique_ptr<ShaHasher> hasher = CreateShaHasher(hash_algorithm);
  ASSERT_NE(nullptr, hasher);

  std::vector<uint8_t> salt, expected_digest, out_digest;

  ASSERT_TRUE(HexToBytes(salt_str, &salt))
      << "Invalid salt in descriptor: " << salt_str;
  ASSERT_TRUE(HexToBytes(expected_digest_str, &expected_digest))
      << "Invalid digest in descriptor: " << expected_digest_str;

  ASSERT_EQ(expected_digest.size(), hasher->GetDigestSize());
  out_digest.resize(hasher->GetDigestSize());

  ASSERT_TRUE(hasher->CalculateDigest(image.data(), image.size(), salt.data(),
                                      descriptor.salt_len, out_digest.data()))
      << "Unable to calculate image digest.";

  ASSERT_EQ(out_digest.size(), expected_digest.size())
      << "Calculated digest size does not match expected digest size.";

  ASSERT_EQ(out_digest, expected_digest)
      << "Calculated digest does not match expected digest.";
}

// Returns true iff the device has the specified feature.
bool DeviceSupportsFeature(const char *feature) {
  bool device_supports_feature = false;
  FILE *p = popen("pm list features", "re");
  if (p) {
    char *line = NULL;
    size_t len = 0;
    while (getline(&line, &len, p) > 0) {
      if (strstr(line, feature)) {
        device_supports_feature = true;
        break;
      }
    }
    pclose(p);
  }
  return device_supports_feature;
}

}  // namespace

class GkiComplianceTest : public testing::Test {
 protected:
  void SetUp() override {
    // Fetch device runtime information.
    runtime_info = android::vintf::VintfObject::GetRuntimeInfo();
    ASSERT_NE(nullptr, runtime_info);

    product_first_api_level =
        android::base::GetIntProperty("ro.product.first_api_level", 0);
    ASSERT_NE(0, product_first_api_level)
        << "ro.product.first_api_level is undefined.";

    /* Skip for non arm64 that do not mandate GKI yet. */
    if (runtime_info->hardwareId() != "aarch64") {
      GTEST_SKIP() << "Exempt from GKI test on non-arm64 devices";
    }

    /* Skip for form factors that do not mandate GKI yet */
    const static bool tv_device =
        DeviceSupportsFeature("android.software.leanback");
    const static bool auto_device =
        DeviceSupportsFeature("android.hardware.type.automotive");
    if (tv_device || auto_device) {
      GTEST_SKIP() << "Exempt from GKI test on TV/Auto devices";
    }

    GTEST_LOG_(INFO) << runtime_info->osName() << " "
                     << runtime_info->osRelease();
    GTEST_LOG_(INFO) << "ro.product.first_api_level: "
                     << product_first_api_level;
  }

  std::shared_ptr<const android::vintf::RuntimeInfo> runtime_info;
  int product_first_api_level;
};

TEST_F(GkiComplianceTest, GkiComplianceV1) {
  if (product_first_api_level < __ANDROID_API_R__) {
    GTEST_SKIP() << "Exempt from GKI 1.0 test: ro.product.first_api_level ("
                 << product_first_api_level << ") < " << __ANDROID_API_R__;
  }
  /* Skip for devices if the kernel version is not 5.4. */
  if (runtime_info->kernelVersion().dropMinor() !=
      android::vintf::Version{5, 4}) {
    GTEST_SKIP() << "Exempt from GKI 1.0 test on kernel version: "
                 << runtime_info->kernelVersion();
  }

  /* load vbmeta struct from boot, verify struct integrity */
  std::string out_public_key_data;
  android::fs_mgr::VBMetaVerifyResult out_verify_result;
  const std::string boot_path = GetBlockDevicePath("boot");
  std::unique_ptr<android::fs_mgr::VBMetaData> vbmeta =
      android::fs_mgr::LoadAndVerifyVbmetaByPath(
          boot_path, "boot", "" /* expected_key_blob */,
          true /* allow verification error */, false /* rollback_protection */,
          false /* is_chained_vbmeta */, &out_public_key_data,
          nullptr /* out_verification_disabled */, &out_verify_result);

  ASSERT_TRUE(vbmeta) << "Verification of GKI vbmeta fails.";
  ASSERT_FALSE(out_public_key_data.empty()) << "The GKI image is not signed.";
  EXPECT_TRUE(ValidatePublicKeyBlob(out_public_key_data))
      << "The GKI image is not signed by an official key.";
  EXPECT_EQ(out_verify_result, android::fs_mgr::VBMetaVerifyResult::kSuccess)
      << "Verification of the GKI vbmeta structure failed.";

  /* verify boot partition according to vbmeta structure */
  std::unique_ptr<android::fs_mgr::FsAvbHashDescriptor> descriptor =
      android::fs_mgr::GetHashDescriptor("boot", std::move(*vbmeta));
  ASSERT_TRUE(descriptor)
      << "Failed to load hash descriptor from boot.img vbmeta";

  android::base::unique_fd fd(open(boot_path.c_str(), O_RDONLY));
  ASSERT_TRUE(fd.ok()) << "Fail to open boot partition. Try 'adb root'.";

  std::vector<uint8_t> boot_partition_vector;
  boot_partition_vector.resize(descriptor->image_size);
  ASSERT_TRUE(android::base::ReadFully(fd, boot_partition_vector.data(),
                                       descriptor->image_size))
      << "Could not read boot partition to vector.";

  ASSERT_NO_FATAL_FAILURE(
      VerifyImageDescriptor(boot_partition_vector, *descriptor));
}

TEST_F(GkiComplianceTest, GkiComplianceV2) {
  /* Skip for devices if the kernel version is not >= 5.10. */
  if (runtime_info->kernelVersion().dropMinor() <
      android::vintf::Version{5, 10}) {
    GTEST_SKIP() << "Exempt from GKI 2.0 test on kernel version: "
                 << runtime_info->kernelVersion();
  }

  // GKI 2.0 ensures getKernelLevel() to return valid value.
  std::string error_msg;
  const auto kernel_level =
      android::vintf::VintfObject::GetInstance()->getKernelLevel(&error_msg);
  ASSERT_NE(android::vintf::Level::UNSPECIFIED, kernel_level) << error_msg;

  std::vector<android::fs_mgr::VBMetaData> boot_signature_images;
  std::unique_ptr<GkiBootImage> boot_image =
      LoadAndVerifyGkiBootImage("boot", &boot_signature_images);
  ASSERT_NE(nullptr, boot_image);

  if (kernel_level <= android::vintf::Level::S) {
    // R, S kernel
    // Legacy scheme, verify the GKI 2.0 boot.img against the "boot" descriptor.
    EXPECT_EQ(4, GetBootHeaderVersion(boot_image->data()));
    EXPECT_EQ(1, boot_signature_images.size());

    std::unique_ptr<android::fs_mgr::FsAvbHashDescriptor>
        legacy_boot_descriptor =
            android::fs_mgr::GetHashDescriptor("boot", boot_signature_images);

    ASSERT_NE(nullptr, legacy_boot_descriptor)
        << "Failed to load hash descriptor from the boot signature.";
    ASSERT_NO_FATAL_FAILURE(VerifyImageDescriptor(boot_image->GetLegacyGki(),
                                                  *legacy_boot_descriptor));
  } else {
    // T+ kernel
    std::unique_ptr<android::fs_mgr::FsAvbHashDescriptor>
        generic_kernel_descriptor = android::fs_mgr::GetHashDescriptor(
            "generic_kernel", boot_signature_images);
    std::unique_ptr<android::fs_mgr::FsAvbHashDescriptor>
        generic_ramdisk_descriptor = android::fs_mgr::GetHashDescriptor(
            "generic_ramdisk", boot_signature_images);

    // TODO: Verify the header fields.
    ASSERT_NE(nullptr, generic_kernel_descriptor)
        << "Failed to load the 'generic_kernel' hash descriptor.";
    ASSERT_NO_FATAL_FAILURE(VerifyImageDescriptor(boot_image->GetKernel(),
                                                  *generic_kernel_descriptor));

    if (generic_ramdisk_descriptor) {
      GTEST_LOG_(INFO) << "Retrofitted scheme, checking the ramdisk image from "
                          "the 'boot' partition.";
      auto ramdisk = boot_image->GetRamdisk();
      if (GetBootHeaderVersion(boot_image->data()) == 2) {
        // For [.begin() + offset, .end()) to be a well-defined range,
        // |.begin() + offset| must be within [.begin(), .end()], thus
        // |offset| must be within [0, ramdisk.size()].
        const auto offset = std::clamp<size_t>(
            ramdisk.size() - generic_ramdisk_descriptor->image_size, 0,
            ramdisk.size());
        ramdisk = {ramdisk.begin() + offset, ramdisk.end()};
      }
      ASSERT_NO_FATAL_FAILURE(
          VerifyImageDescriptor(ramdisk, *generic_ramdisk_descriptor));
    } else {
      GTEST_LOG_(INFO) << "T+ verification scheme, the 'boot' partition must "
                          "contain only the generic kernel and the 'init_boot' "
                          "partition must contain only the generic ramdisk.";
      EXPECT_EQ(4, GetBootHeaderVersion(boot_image->data()));
      EXPECT_EQ(1, boot_signature_images.size());
      EXPECT_EQ(0, boot_image->ramdisk_size())
          << "'boot' partition mustn't include a ramdisk image.";

      std::vector<android::fs_mgr::VBMetaData> init_boot_signature_images;
      std::unique_ptr<GkiBootImage> init_boot_image =
          LoadAndVerifyGkiBootImage("init_boot", &init_boot_signature_images);
      ASSERT_NE(nullptr, init_boot_image);
      EXPECT_EQ(4, GetBootHeaderVersion(init_boot_image->data()));
      EXPECT_EQ(1, init_boot_signature_images.size());
      EXPECT_EQ(0, init_boot_image->kernel_size())
          << "'init_boot' partition mustn't include a kernel image.";

      generic_ramdisk_descriptor = android::fs_mgr::GetHashDescriptor(
          "generic_ramdisk", init_boot_signature_images);
      ASSERT_NE(nullptr, generic_ramdisk_descriptor)
          << "Failed to load the 'generic_ramdisk' hash descriptor.";
      ASSERT_NO_FATAL_FAILURE(VerifyImageDescriptor(
          init_boot_image->GetRamdisk(), *generic_ramdisk_descriptor));
    }
  }
}

int main(int argc, char *argv[]) {
  ::testing::InitGoogleTest(&argc, argv);
  android::base::InitLogging(argv, android::base::StderrLogger);
  return RUN_ALL_TESTS();
}
