Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 125d0b63 authored by Yifan Hong's avatar Yifan Hong
Browse files

Add function to extract timestamp from boot image

Also add toybox to otatools list.

Bug: 169169031
Test: build OTA
Change-Id: Ib14dbf46a8385ccf2a9c5a9c6f4e7fa9399cf0ba
parent e98d29b4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3887,6 +3887,7 @@ INTERNAL_OTATOOLS_MODULES := \
  signapk \
  simg2img \
  sload_f2fs \
  toybox \
  tune2fs \
  unpack_bootimg \
  update_host_simulator \
+3 −0
Original line number Diff line number Diff line
@@ -125,6 +125,9 @@ python_defaults {
    required: [
        "brillo_update_payload",
        "checkvintf",
        "lz4",
        "toybox",
        "unpack_bootimg"
    ],
    target: {
        darwin: {
+9 −0
Original line number Diff line number Diff line
@@ -814,6 +814,15 @@ class PartitionBuildProps(object):
    props._LoadBuildProp(data)
    return props

  @staticmethod
  def FromBuildPropFile(name, build_prop_file):
    """Constructs an instance from a build prop file."""

    props = PartitionBuildProps("unknown", name)
    with open(build_prop_file) as f:
      props._LoadBuildProp(f.read())
    return props

  def _LoadBuildProp(self, data):
    for line in data.split('\n'):
      line = line.strip()
+59 −1
Original line number Diff line number Diff line
@@ -14,14 +14,17 @@

import copy
import itertools
import logging
import os
import zipfile

import ota_metadata_pb2
from common import (ZipDelete, ZipClose, OPTIONS, MakeTempFile,
                    ZipWriteStr, BuildInfo, LoadDictionaryFromFile,
                    SignFile, PARTITIONS_WITH_CARE_MAP, PartitionBuildProps)
                    SignFile, PARTITIONS_WITH_CARE_MAP, PartitionBuildProps,
                    MakeTempDir, RunAndCheckOutput, ExternalError)

logger = logging.getLogger(__name__)

OPTIONS.no_signing = False
OPTIONS.force_non_ab = False
@@ -38,6 +41,9 @@ METADATA_NAME = 'META-INF/com/android/metadata'
METADATA_PROTO_NAME = 'META-INF/com/android/metadata.pb'
UNZIP_PATTERN = ['IMAGES/*', 'META/*', 'OTA/*', 'RADIO/*']

# See sysprop.mk. If file is moved, add new search paths here; don't remove
# existing search paths.
RAMDISK_BUILD_PROP_REL_PATHS = ['system/etc/ramdisk/build.prop']

def FinalizeMetadata(metadata, input_file, output_file, needed_property_files):
  """Finalizes the metadata and signs an A/B OTA package.
@@ -561,3 +567,55 @@ def SignOutput(temp_zip_name, output_zip_name):

  SignFile(temp_zip_name, output_zip_name, OPTIONS.package_key, pw,
           whole_file=True)


def GetBootImageTimestamp(boot_img):
  """
  Get timestamp from ramdisk within the boot image

  Args:
    boot_img: the boot image file. Ramdisk must be compressed with lz4 format.

  Return:
    An integer that corresponds to the timestamp of the boot image, or None
    if file has unknown format. Raise exception if an unexpected error has
    occurred.
  """

  tmp_dir = MakeTempDir('boot_', suffix='.img')
  try:
    RunAndCheckOutput(['unpack_bootimg', '--boot_img', boot_img, '--out', tmp_dir])
    ramdisk = os.path.join(tmp_dir, 'ramdisk')
    if not os.path.isfile(ramdisk):
      logger.warning('Unable to get boot image timestamp: no ramdisk in boot')
      return None
    uncompressed_ramdisk = os.path.join(tmp_dir, 'uncompressed_ramdisk')
    RunAndCheckOutput(['lz4', '-d', ramdisk, uncompressed_ramdisk])

    abs_uncompressed_ramdisk = os.path.abspath(uncompressed_ramdisk)
    extracted_ramdisk = MakeTempDir('extracted_ramdisk')
    # Use "toybox cpio" instead of "cpio" because the latter invokes cpio from
    # the host environment.
    RunAndCheckOutput(['toybox', 'cpio', '-F', abs_uncompressed_ramdisk, '-i'],
               cwd=extracted_ramdisk)

    prop_file = None
    for search_path in RAMDISK_BUILD_PROP_REL_PATHS:
      prop_file = os.path.join(extracted_ramdisk, search_path)
      if os.path.isfile(prop_file):
        break
      logger.warning('Unable to get boot image timestamp: no %s in ramdisk', search_path)

    if not prop_file:
      return None

    props = PartitionBuildProps.FromBuildPropFile('boot', prop_file)
    timestamp = props.GetProp('ro.bootimage.build.date.utc')
    if timestamp:
      return int(timestamp)
    logger.warning('Unable to get boot image timestamp: ro.bootimage.build.date.utc is undefined')
    return None

  except ExternalError as e:
    logger.warning('Unable to get boot image timestamp: %s', e)
    return None