# pylint: disable=g-direct-third-party-import
# pylint: disable=g-bad-file-header
# Copyright 2015 The Bazel Authors. All rights reserved.
#
# 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.

"""Installs an Android application, possibly in an incremental way."""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import collections
from concurrent import futures
import hashlib
import logging
import os
import posixpath
import re
import shutil
import subprocess
import sys
import tempfile
import time
import zipfile

# Do not edit this line. Copybara replaces it with PY2 migration helper.
from absl import app
from absl import flags
import six

flags.DEFINE_string("split_main_apk", None, "The main APK for split install")
flags.DEFINE_multi_string("split_apk", [], "Split APKs to install")
flags.DEFINE_string("dexmanifest", None, "The .dex manifest")
flags.DEFINE_multi_string("native_lib", None, "Native libraries to install")
flags.DEFINE_string("resource_apk", None, "The resource .apk")
flags.DEFINE_string(
    "apk", None, "The app .apk. If not specified, "
    "do incremental deployment")
flags.DEFINE_string("adb", None, "ADB to use")
flags.DEFINE_string("stub_datafile", None, "The stub data file")
flags.DEFINE_string("output_marker", None, "The output marker file")
flags.DEFINE_multi_string("extra_adb_arg", [], "Extra arguments to adb")
flags.DEFINE_string("execroot", ".", "The exec root")
flags.DEFINE_integer(
    "adb_jobs",
    2, "The number of instances of adb to use in parallel to "
    "update files on the device",
    lower_bound=1)
flags.DEFINE_enum(
    "start", "no", ["no", "cold", "warm", "debug"],
    "Whether/how to start the app after installing it. 'cold' "
    "and 'warm' will both cause the app to be started, 'warm' "
    "will start it with previously saved application state, "
    "'debug' will wait for the debugger before a clean start.")
flags.DEFINE_boolean("start_app", False, "Deprecated, use 'start'.")
flags.DEFINE_string("user_home_dir", None, "Path to the user's home directory")
flags.DEFINE_string("flagfile", None,
                    "Path to a file to read additional flags from")

FLAGS = flags.FLAGS

DEVICE_DIRECTORY = "/data/local/tmp/incrementaldeployment"

# Some devices support ABIs other than those reported by getprop. In this case,
# if the most specific ABI is not available in the .apk, we push the more
# general ones.
COMPATIBLE_ABIS = {
    "armeabi-v7a": ["armeabi"],
    "arm64-v8a": ["armeabi-v7a", "armeabi"]
}


class AdbError(Exception):
  """An exception class signaling an error in an adb invocation."""

  def __init__(self, args, returncode, stdout, stderr):
    self.args = args
    self.returncode = returncode
    self.stdout = stdout
    self.stderr = stderr
    details = "\n".join([
        "adb command: %s" % args,
        "return code: %s" % returncode,
        "stdout: %s" % stdout,
        "stderr: %s" % stderr,
    ])
    super(AdbError, self).__init__(details)


class DeviceNotFoundError(Exception):
  """Raised when the device could not be found."""


class MultipleDevicesError(Exception):
  """Raised when > 1 device is attached and no device serial was given."""

  @staticmethod
  def CheckError(s):
    return re.search("more than one (device and emulator|device|emulator)", s)


class DeviceUnauthorizedError(Exception):
  """Raised when the local machine is not authorized to the device."""


class TimestampException(Exception):
  """Raised when there is a problem with timestamp reading/writing."""


class OldSdkException(Exception):
  """Raised when the SDK on the target device is older than the app allows."""


class EnvvarError(Exception):
  """Raised when a required environment variable is not set."""


hostpath = os.path
targetpath = posixpath


class Adb(object):
  """A class to handle interaction with adb."""

  def __init__(self, adb_path, temp_dir, adb_jobs, user_home_dir,
               extra_adb_args):
    self._adb_path = adb_path
    self._temp_dir = temp_dir
    self._user_home_dir = user_home_dir
    self._file_counter = 1
    self._executor = futures.ThreadPoolExecutor(max_workers=adb_jobs)
    self._extra_adb_args = extra_adb_args or []

  def _Exec(self, adb_args):
    """Executes the given adb command + args."""
    args = [self._adb_path] + self._extra_adb_args + adb_args
    # TODO(ahumesky): Because multiple instances of adb are executed in
    # parallel, these debug logging lines will get interleaved.
    logging.debug("Executing: %s", " ".join(args))

    # adb sometimes requires the user's home directory to access things in
    # $HOME/.android (e.g. keys to authorize with the device). To avoid any
    # potential problems with python picking up things in the user's home
    # directory, HOME is not set in the environment around python and is instead
    # passed explicitly as a flag.
    env = {}
    if self._user_home_dir:
      env["HOME"] = self._user_home_dir

    # On Windows, adb requires the SystemRoot environment variable.
    if Adb._IsHostOsWindows():
      value = os.getenv("SYSTEMROOT")
      if not value:
        raise EnvvarError(("The %SYSTEMROOT% environment variable must "
                           "be set or Adb won't work"))
      env["SYSTEMROOT"] = value

    adb = subprocess.Popen(
        args,
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        env=env)
    stdout, stderr = adb.communicate()
    stdout = stdout.strip()
    stderr = stderr.strip()
    logging.debug("adb ret: %s", adb.returncode)
    logging.debug("adb out: %s", stdout)
    logging.debug("adb err: %s", stderr)

    # Check these first so that the more specific error gets raised instead of
    # the more generic AdbError.
    stdout = six.ensure_str(stdout)
    stderr = six.ensure_str(stderr)
    if "device not found" in stderr:
      raise DeviceNotFoundError()
    elif "device unauthorized" in stderr:
      raise DeviceUnauthorizedError()
    elif MultipleDevicesError.CheckError(stderr):
      # The error messages are from adb's transport.c, but something adds
      # "error: " to the beginning, so take it off so that we don't end up
      # printing "Error: error: ..."
      raise MultipleDevicesError(re.sub("^error: ", "", stderr))
    elif "INSTALL_FAILED_OLDER_SDK" in stdout:
      raise OldSdkException()

    if adb.returncode != 0:
      raise AdbError(args, adb.returncode, stdout, stderr)

    return adb.returncode, stdout, stderr, args

  def _ExecParallel(self, adb_args):
    return self._executor.submit(self._Exec, adb_args)

  def _CreateLocalFile(self):
    """Returns a path to a temporary local file in the temp directory."""
    local = hostpath.join(self._temp_dir, "adbfile_%d" % self._file_counter)
    self._file_counter += 1
    return local

  def GetInstallTime(self, package):
    """Get the installation time of a package."""
    _, stdout, _, _ = self._Shell("dumpsys package %s" % package)
    match = re.search("firstInstallTime=(.*)$", six.ensure_str(stdout),
                      re.MULTILINE)
    if match:
      return match.group(1)
    else:
      return None

  def GetAbi(self):
    """Returns the ABI the device supports."""
    _, stdout, _, _ = self._Shell("getprop ro.product.cpu.abi")
    return stdout

  def Push(self, local, remote):
    """Invoke 'adb push' in parallel."""
    return self._ExecParallel(["push", local, remote])

  def PushString(self, contents, remote):
    """Push a given string to a given path on the device in parallel."""
    local = self._CreateLocalFile()
    with open(local, "wb") as f:
      f.write(contents.encode("utf-8"))
    return self.Push(local, remote)

  def Pull(self, remote):
    """Invoke 'adb pull'.

    Args:
      remote: The path to the remote file to pull.

    Returns:
      The contents of a file or None if the file didn't exist.
    """
    local = self._CreateLocalFile()
    try:
      self._Exec(["pull", remote, local])
      with open(local, "rb") as f:
        return six.ensure_str(f.read(), "utf-8")
    except (AdbError, IOError):
      return None

  def InstallMultiple(self, apk, pkg=None):
    """Invoke 'adb install-multiple'."""

    pkg_args = ["-p", pkg] if pkg else []
    ret, stdout, stderr, args = self._Exec(
        ["install-multiple", "-r"] + pkg_args + [apk])
    if "FAILED" in stdout or "FAILED" in stderr:
      raise AdbError(args, ret, stdout, stderr)

  def Install(self, apk):
    """Invoke 'adb install'."""
    ret, stdout, stderr, args = self._Exec(["install", "-r", apk])

    # adb install could fail with a message on stdout like this:
    #
    #   pkg: /data/local/tmp/Gmail_dev_sharded_incremental.apk
    #   Failure [INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES]
    #
    # and yet it will still have a return code of 0. At least for the install
    # command, it will print "Success" if it succeeded, so check for that in
    # standard out instead of relying on the return code.
    if "FAILED" in stdout or "FAILED" in stderr:
      raise AdbError(args, ret, stdout, stderr)

  def Uninstall(self, pkg):
    """Invoke 'adb uninstall'."""
    self._Exec(["uninstall", pkg])
    # No error checking. If this fails, we assume that the app was not installed
    # in the first place.

  def Delete(self, remote):
    """Delete the given file (or directory) on the device."""
    self.DeleteMultiple([remote])

  def DeleteMultiple(self, remote_files):
    """Delete the given files (or directories) on the device."""
    files_str = " ".join(remote_files)
    if files_str:
      self._Shell("rm -fr %s" % files_str)

  def Mkdir(self, d):
    """Invokes mkdir with the specified directory on the device."""
    self._Shell("mkdir -p %s" % d)

  def StopApp(self, package):
    """Force stops the app with the given package."""
    self._Shell("am force-stop %s" % package)

  def StopAppAndSaveState(self, package):
    """Stops the app with the given package, saving state for the next run."""
    # 'am kill' will only kill processes in the background, so we must make sure
    # our process is in the background first. We accomplish this by bringing up
    # the app switcher.
    self._Shell("input keyevent KEYCODE_APP_SWITCH")
    self._Shell("am kill %s" % package)

  def StartApp(self, package, start_type):
    """Starts the app with the given package."""
    if start_type == "debug":
      self._Shell("am set-debug-app -w --persistent %s" % package)
    else:
      self._Shell("am clear-debug-app %s" % package)
    self._Shell("monkey -p %s -c android.intent.category.LAUNCHER 1" % package)

  def _Shell(self, cmd):
    """Invoke 'adb shell'."""
    return self._Exec(["shell", cmd])

  @staticmethod
  def _IsHostOsWindows():
    return os.name == "nt"


ManifestEntry = collections.namedtuple(
    "ManifestEntry", ["input_file", "zippath", "installpath", "sha256"])


def ParseManifest(contents):
  """Parses a dexmanifest file.

  Args:
    contents: the contents of the manifest file to be parsed.

  Returns:
    A dict of install path -> ManifestEntry.
  """
  result = {}

  for l in contents.split("\n"):
    entry = ManifestEntry(*(l.strip().split(" ")))
    result[entry.installpath] = entry

  return result


def GetAppPackage(stub_datafile):
  """Returns the app package specified in a stub data file."""
  with open(stub_datafile, "rb") as f:
    return six.ensure_str(f.readlines()[1], "utf-8").strip()


def UploadDexes(adb, execroot, app_dir, temp_dir, dexmanifest, full_install):
  """Uploads dexes to the device so that the state.

  Does the minimum amount of work necessary to make the state of the device
  consistent with what was built.

  Args:
    adb: the Adb instance representing the device to install to
    execroot: the execroot
    app_dir: the directory things should be installed under on the device
    temp_dir: a local temporary directory
    dexmanifest: contents of the dex manifest
    full_install: whether to do a full install

  Returns:
    None.
  """

  # Fetch the manifest on the device
  dex_dir = targetpath.join(app_dir, "dex")
  adb.Mkdir(dex_dir)

  old_manifest = None

  if not full_install:
    logging.info("Fetching dex manifest from device...")
    old_manifest_contents = adb.Pull(targetpath.join(dex_dir, "manifest"))
    if old_manifest_contents:
      old_manifest = ParseManifest(old_manifest_contents)
    else:
      logging.info("Dex manifest not found on device")

  if old_manifest is None:
    # If the manifest is not found, maybe a previous installation attempt
    # was interrupted. Wipe the slate clean. Do this also in case we do a full
    # installation.
    old_manifest = {}
    adb.Delete(targetpath.join(dex_dir, "*"))

  new_manifest = ParseManifest(dexmanifest)
  dexes_to_delete = set(old_manifest) - set(new_manifest)

  # Figure out which dexes to upload: those that are present in the new manifest
  # but not in the old one and those whose checksum was changed
  common_dexes = set(new_manifest).intersection(old_manifest)
  dexes_to_upload = set(d for d in common_dexes
                        if new_manifest[d].sha256 != old_manifest[d].sha256)
  dexes_to_upload.update(set(new_manifest) - set(old_manifest))

  if not dexes_to_delete and not dexes_to_upload:
    # If we have nothing to do, don't bother removing and rewriting the manifest
    logging.info("Application dexes up-to-date")
    return

  # Delete the manifest so that we know how to get back to a consistent state
  # if we are interrupted.
  adb.Delete(targetpath.join(dex_dir, "manifest"))

  # Tuple of (local, remote) files to push to the device.
  files_to_push = []

  # Sort dexes to be uploaded by the zip file they are in so that we only need
  # to open each zip only once.
  dexzips_in_upload = set(new_manifest[d].input_file for d in dexes_to_upload
                          if new_manifest[d].zippath != "-")
  for i, dexzip_name in enumerate(dexzips_in_upload):
    zip_dexes = [
        d for d in dexes_to_upload if new_manifest[d].input_file == dexzip_name]
    dexzip_tempdir = hostpath.join(temp_dir, "dex", str(i))
    with zipfile.ZipFile(hostpath.join(execroot, dexzip_name)) as dexzip:
      for dex in zip_dexes:
        zippath = new_manifest[dex].zippath
        dexzip.extract(zippath, dexzip_tempdir)
        files_to_push.append((hostpath.join(dexzip_tempdir, zippath),
                              targetpath.join(dex_dir, dex)))

  # Now gather all the dexes that are not within a .zip file.
  dexes_to_upload = set(
      d for d in dexes_to_upload if new_manifest[d].zippath == "-")
  for dex in dexes_to_upload:
    files_to_push.append((new_manifest[dex].input_file, targetpath.join(
        dex_dir, dex)))

  num_files = len(dexes_to_delete) + len(files_to_push)
  logging.info("Updating %d dex%s...", num_files, "es" if num_files > 1 else "")

  # Delete the dexes that are not in the new manifest
  adb.DeleteMultiple(targetpath.join(dex_dir, dex) for dex in dexes_to_delete)

  # Upload all the files.
  upload_walltime_start = time.time()
  fs = [adb.Push(local, remote) for local, remote in files_to_push]
  done, not_done = futures.wait(fs, return_when=futures.FIRST_EXCEPTION)
  upload_walltime = time.time() - upload_walltime_start
  logging.debug("Dex upload walltime: %s seconds", upload_walltime)

  # If there is anything in not_done, then some adb call failed and we
  # can cancel the rest.
  if not_done:
    for f in not_done:
      f.cancel()

  # If any adb call resulted in an exception, re-raise it.
  for f in done:
    f.result()

  # If no dex upload failed, upload the manifest. If any upload failed, the
  # exception should have been re-raised above.
  # Call result() to raise the exception if there was one.
  adb.PushString(dexmanifest, targetpath.join(dex_dir, "manifest")).result()


def Checksum(filename):
  """Compute the SHA-256 checksum of a file."""
  h = hashlib.sha256()
  with open(filename, "rb") as f:
    while True:
      data = f.read(65536)
      if not data:
        break

      h.update(data)

  return h.hexdigest()


def UploadResources(adb, resource_apk, app_dir):
  """Uploads resources to the device.

  Args:
    adb: The Adb instance representing the device to install to.
    resource_apk: Path to the resource apk.
    app_dir: The directory things should be installed under on the device.

  Returns:
    None.
  """

  # Compute the checksum of the new resources file
  new_checksum = Checksum(resource_apk)

  # Fetch the checksum of the resources file on the device, if it exists
  device_checksum_file = targetpath.join(app_dir, "resources_checksum")
  old_checksum = adb.Pull(device_checksum_file)
  if old_checksum == new_checksum:
    logging.info("Application resources up-to-date")
    return
  logging.info("Updating application resources...")

  # Remove the checksum file on the device so that if the transfer is
  # interrupted, we know how to get the device back to a consistent state.
  adb.Delete(device_checksum_file)
  adb.Push(resource_apk, targetpath.join(app_dir, "resources.ap_")).result()

  # Write the new checksum to the device.
  adb.PushString(new_checksum, device_checksum_file).result()


def ConvertNativeLibs(args):
  """Converts the --native_libs command line argument to an arch -> libs map."""
  native_libs = {}
  if args is not None:
    for native_lib in args:
      abi, path = six.ensure_str(native_lib).split(":")
      if abi not in native_libs:
        native_libs[abi] = set()

      native_libs[abi].add(path)

  return native_libs


def FindAbi(device_abi, app_abis):
  """Selects which ABI native libs should be installed for."""
  if device_abi in app_abis:
    return device_abi

  if device_abi in COMPATIBLE_ABIS:
    for abi in COMPATIBLE_ABIS[device_abi]:
      if abi in app_abis:
        logging.warn("App does not have native libs for ABI '%s'. Using ABI "
                     "'%s'.", device_abi, abi)
        return abi

  logging.warn("No native libs for device ABI '%s'. App has native libs for "
               "ABIs: %s", device_abi, ", ".join(app_abis))
  return None


def UploadNativeLibs(adb, native_lib_args, app_dir, full_install):
  """Uploads native libraries to the device."""

  native_libs = ConvertNativeLibs(native_lib_args)
  libs = set()
  if native_libs:
    abi = FindAbi(adb.GetAbi(), list(native_libs.keys()))
    if abi:
      libs = native_libs[abi]

  basename_to_path = {}
  install_checksums = {}
  for lib in sorted(libs):
    install_checksums[os.path.basename(lib)] = Checksum(lib)
    basename_to_path[os.path.basename(lib)] = lib

  device_manifest = None
  if not full_install:
    device_manifest = adb.Pull(
        targetpath.join(app_dir, "native", "native_manifest"))

  device_checksums = {}
  if device_manifest is None:
    # If we couldn't fetch the device manifest or if this is a non-incremental
    # install, wipe the slate clean
    adb.Delete(targetpath.join(app_dir, "native"))

    # From Android 28 onwards, `adb push` creates directories with insufficient
    # permissions, resulting in errors when pushing files. `adb shell mkdir`
    # works correctly however, so we create the directory here.
    # See https://github.com/bazelbuild/examples/issues/77 for more information.
    adb.Mkdir(targetpath.join(app_dir, "native"))
  else:
    # Otherwise, parse the manifest. Note that this branch is also taken if the
    # manifest is empty.
    for manifest_line in device_manifest.split("\n"):
      if manifest_line:
        name, checksum = manifest_line.split(" ")
        device_checksums[name] = checksum

  libs_to_delete = set(device_checksums) - set(install_checksums)
  libs_to_upload = set(install_checksums) - set(device_checksums)
  common_libs = set(install_checksums).intersection(set(device_checksums))
  libs_to_upload.update([l for l in common_libs
                         if install_checksums[l] != device_checksums[l]])

  libs_to_push = [(basename_to_path[lib], targetpath.join(
      app_dir, "native", lib)) for lib in libs_to_upload]

  if not libs_to_delete and not libs_to_push and device_manifest is not None:
    logging.info("Native libs up-to-date")
    return

  num_files = len(libs_to_delete) + len(libs_to_push)
  logging.info("Updating %d native lib%s...",
               num_files, "s" if num_files != 1 else "")

  adb.Delete(targetpath.join(app_dir, "native", "native_manifest"))

  if libs_to_delete:
    adb.DeleteMultiple(
        [targetpath.join(app_dir, "native", lib) for lib in libs_to_delete])

  upload_walltime_start = time.time()
  fs = [adb.Push(local, remote) for local, remote in libs_to_push]
  done, not_done = futures.wait(fs, return_when=futures.FIRST_EXCEPTION)
  upload_walltime = time.time() - upload_walltime_start
  logging.debug("Native library upload walltime: %s seconds", upload_walltime)

  # If there is anything in not_done, then some adb call failed and we
  # can cancel the rest.
  if not_done:
    for f in not_done:
      f.cancel()

  # If any adb call resulted in an exception, re-raise it.
  for f in done:
    f.result()

  install_manifest = [
      six.ensure_str(name) + " " + checksum
      for name, checksum in install_checksums.items()
  ]
  adb.PushString("\n".join(install_manifest),
                 targetpath.join(app_dir, "native",
                                 "native_manifest")).result()


def VerifyInstallTimestamp(adb, app_package):
  """Verifies that the app is unchanged since the last mobile-install."""
  expected_timestamp = adb.Pull(
      targetpath.join(DEVICE_DIRECTORY, app_package, "install_timestamp"))
  if not expected_timestamp:
    raise TimestampException(
        "Cannot verify last mobile install. At least one non-incremental "
        "'mobile-install' must precede incremental installs")

  actual_timestamp = adb.GetInstallTime(app_package)
  if actual_timestamp is None:
    raise TimestampException(
        "Package '%s' is not installed on the device. At least one "
        "non-incremental 'mobile-install' must precede incremental "
        "installs." % app_package)

  if actual_timestamp != expected_timestamp:
    raise TimestampException("Installed app '%s' has an unexpected timestamp. "
                             "Did you last install the app in a way other than "
                             "'mobile-install'?" % app_package)


def SplitIncrementalInstall(adb, app_package, execroot, split_main_apk,
                            split_apks):
  """Does incremental installation using split packages."""
  app_dir = targetpath.join(DEVICE_DIRECTORY, app_package)
  device_manifest_path = targetpath.join(app_dir, "split_manifest")
  device_manifest = adb.Pull(device_manifest_path)
  expected_timestamp = adb.Pull(targetpath.join(app_dir, "install_timestamp"))
  actual_timestamp = adb.GetInstallTime(app_package)
  device_checksums = {}
  if device_manifest is not None:
    for manifest_line in device_manifest.split("\n"):
      if manifest_line:
        name, checksum = manifest_line.split(" ")
        device_checksums[name] = checksum

  install_checksums = {}
  install_checksums["__MAIN__"] = Checksum(
      hostpath.join(execroot, split_main_apk))
  for apk in split_apks:
    install_checksums[apk] = Checksum(hostpath.join(execroot, apk))

  reinstall_main = False
  if (device_manifest is None or actual_timestamp is None or
      actual_timestamp != expected_timestamp or
      install_checksums["__MAIN__"] != device_checksums["__MAIN__"] or
      set(device_checksums.keys()) != set(install_checksums.keys())):
    # The main app is not up to date or not present or something happened
    # with the on-device manifest. Start from scratch. Notably, we cannot
    # uninstall a split package, so if the set of packages changes, we also
    # need to do a full reinstall.
    reinstall_main = True
    device_checksums = {}

  apks_to_update = [
      apk for apk in split_apks if
      apk not in device_checksums or
      device_checksums[apk] != install_checksums[apk]]

  if not apks_to_update and not reinstall_main:
    # Nothing to do
    return

  # Delete the device manifest so that if something goes wrong, we do a full
  # reinstall next time
  adb.Delete(device_manifest_path)

  if reinstall_main:
    logging.info("Installing main APK...")
    adb.Uninstall(app_package)
    adb.InstallMultiple(targetpath.join(execroot, split_main_apk))
    adb.PushString(
        adb.GetInstallTime(app_package),
        targetpath.join(app_dir, "install_timestamp")).result()

  logging.info("Reinstalling %s APKs...", len(apks_to_update))

  for apk in apks_to_update:
    adb.InstallMultiple(targetpath.join(execroot, apk), app_package)

  install_manifest = [
      six.ensure_str(name) + " " + checksum
      for name, checksum in install_checksums.items()
  ]
  adb.PushString("\n".join(install_manifest),
                 targetpath.join(app_dir, "split_manifest")).result()


def IncrementalInstall(adb_path,
                       execroot,
                       stub_datafile,
                       output_marker,
                       adb_jobs,
                       start_type,
                       dexmanifest=None,
                       apk=None,
                       native_libs=None,
                       resource_apk=None,
                       split_main_apk=None,
                       split_apks=None,
                       user_home_dir=None,
                       extra_adb_args=None):
  """Performs an incremental install.

  Args:
    adb_path: Path to the adb executable.
    execroot: Exec root.
    stub_datafile: The stub datafile containing the app's package name.
    output_marker: Path to the output marker file.
    adb_jobs: The number of instances of adb to use in parallel.
    start_type: A string describing whether/how to start the app after
                installing it. Can be 'no', 'cold', or 'warm'.
    dexmanifest: Path to the .dex manifest file.
    apk: Path to the .apk file. May be None to perform an incremental install.
    native_libs: Native libraries to install.
    resource_apk: Path to the apk containing the app's resources.
    split_main_apk: the split main .apk if split installation is desired.
    split_apks: the list of split .apks to be installed.
    user_home_dir: Path to the user's home directory.
    extra_adb_args: Extra arguments that will always be passed to adb.
  """
  temp_dir = tempfile.mkdtemp()
  try:
    adb = Adb(adb_path, temp_dir, adb_jobs, user_home_dir, extra_adb_args)
    app_package = GetAppPackage(hostpath.join(execroot, stub_datafile))
    app_dir = targetpath.join(DEVICE_DIRECTORY, app_package)
    if split_main_apk:
      SplitIncrementalInstall(adb, app_package, execroot, split_main_apk,
                              split_apks)
    else:
      if not apk:
        VerifyInstallTimestamp(adb, app_package)

      with open(hostpath.join(execroot, dexmanifest), "rb") as f:
        dexmanifest = six.ensure_str(f.read(), "utf-8")
      UploadDexes(adb, execroot, app_dir, temp_dir, dexmanifest, bool(apk))
      # TODO(ahumesky): UploadDexes waits for all the dexes to be uploaded, and
      # then UploadResources is called. We could instead enqueue everything
      # onto the threadpool so that uploading resources happens sooner.
      UploadResources(adb, hostpath.join(execroot, resource_apk), app_dir)
      UploadNativeLibs(adb, native_libs, app_dir, bool(apk))
      if apk:
        apk_path = targetpath.join(execroot, apk)
        adb.Install(apk_path)
        future = adb.PushString(
            adb.GetInstallTime(app_package),
            targetpath.join(DEVICE_DIRECTORY, app_package, "install_timestamp"))
        future.result()
      else:
        if start_type == "warm":
          adb.StopAppAndSaveState(app_package)
        else:
          adb.StopApp(app_package)

    if start_type in ["cold", "warm", "debug"]:
      logging.info("Starting application %s", app_package)
      adb.StartApp(app_package, start_type)

    with open(output_marker, "wb") as _:
      pass
  except DeviceNotFoundError:
    sys.exit("Error: Device not found")
  except DeviceUnauthorizedError:
    sys.exit("Error: Device unauthorized. Please check the confirmation "
             "dialog on your device.")
  except MultipleDevicesError as e:
    sys.exit("Error: " + str(e) + "\nTry specifying a device serial with "
             "\"bazel mobile-install --adb_arg=-s --adb_arg=$ANDROID_SERIAL\"")
  except OldSdkException as e:
    sys.exit("Error: The device does not support the API level specified in "
             "the application's manifest. Check minSdkVersion in "
             "AndroidManifest.xml")
  except TimestampException as e:
    sys.exit("Error:\n%s" % str(e))
  except AdbError as e:
    sys.exit("Error:\n%s" % str(e))
  finally:
    shutil.rmtree(temp_dir, True)


def main(unused_argv):
  if FLAGS.verbosity == "1":  # 'verbosity' flag is defined in absl.logging
    level = logging.DEBUG
    fmt = "%(levelname)-5s %(asctime)s %(module)s:%(lineno)3d] %(message)s"
  else:
    level = logging.INFO
    fmt = "%(message)s"
  logging.basicConfig(stream=sys.stdout, level=level, format=fmt)

  start_type = FLAGS.start
  if FLAGS.start_app and start_type == "no":
    start_type = "cold"

  IncrementalInstall(
      adb_path=FLAGS.adb,
      adb_jobs=FLAGS.adb_jobs,
      execroot=FLAGS.execroot,
      stub_datafile=FLAGS.stub_datafile,
      output_marker=FLAGS.output_marker,
      start_type=start_type,
      native_libs=FLAGS.native_lib,
      split_main_apk=FLAGS.split_main_apk,
      split_apks=FLAGS.split_apk,
      dexmanifest=FLAGS.dexmanifest,
      apk=FLAGS.apk,
      resource_apk=FLAGS.resource_apk,
      user_home_dir=FLAGS.user_home_dir,
      extra_adb_args=FLAGS.extra_adb_arg)


if __name__ == "__main__":
  FLAGS(sys.argv)
  # process any additional flags in --flagfile
  if FLAGS.flagfile:
    with open(FLAGS.flagfile, "rb") as flagsfile:
      FLAGS.Reset()
      FLAGS(sys.argv + [line.strip() for line in flagsfile.readlines()])

  app.run(main)
