• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2#
3# Copyright 2013 The Chromium Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""Installs an APK.
8
9"""
10
11import optparse
12import os
13import re
14import sys
15
16from util import build_device
17from util import build_utils
18from util import md5_check
19
20BUILD_ANDROID_DIR = os.path.join(os.path.dirname(__file__), '..')
21sys.path.append(BUILD_ANDROID_DIR)
22
23from pylib import constants
24from pylib.utils import apk_helper
25
26def GetNewMetadata(device, apk_package):
27  """Gets the metadata on the device for the apk_package apk."""
28  output = device.RunShellCommand('ls -l /data/app/')
29  # Matches lines like:
30  # -rw-r--r-- system   system    7376582 2013-04-19 16:34 \
31  # org.chromium.chrome.shell.apk
32  # -rw-r--r-- system   system    7376582 2013-04-19 16:34 \
33  # org.chromium.chrome.shell-1.apk
34  apk_matcher = lambda s: re.match('.*%s(-[0-9]*)?(.apk)?$' % apk_package, s)
35  matches = filter(apk_matcher, output)
36  return matches[0] if matches else None
37
38def HasInstallMetadataChanged(device, apk_package, metadata_path):
39  """Checks if the metadata on the device for apk_package has changed."""
40  if not os.path.exists(metadata_path):
41    return True
42
43  with open(metadata_path, 'r') as expected_file:
44    return expected_file.read() != device.GetInstallMetadata(apk_package)
45
46
47def RecordInstallMetadata(device, apk_package, metadata_path):
48  """Records the metadata from the device for apk_package."""
49  metadata = GetNewMetadata(device, apk_package)
50  if not metadata:
51    raise Exception('APK install failed unexpectedly.')
52
53  with open(metadata_path, 'w') as outfile:
54    outfile.write(metadata)
55
56
57def main():
58  parser = optparse.OptionParser()
59  parser.add_option('--apk-path',
60      help='Path to .apk to install.')
61  parser.add_option('--install-record',
62      help='Path to install record (touched only when APK is installed).')
63  parser.add_option('--build-device-configuration',
64      help='Path to build device configuration.')
65  parser.add_option('--stamp',
66      help='Path to touch on success.')
67  parser.add_option('--configuration-name',
68      help='The build CONFIGURATION_NAME')
69  options, _ = parser.parse_args()
70
71  device = build_device.GetBuildDeviceFromPath(
72      options.build_device_configuration)
73  if not device:
74    return
75
76  constants.SetBuildType(options.configuration_name)
77
78  serial_number = device.GetSerialNumber()
79  apk_package = apk_helper.GetPackageName(options.apk_path)
80
81  metadata_path = '%s.%s.device.time.stamp' % (options.apk_path, serial_number)
82
83  # If the APK on the device does not match the one that was last installed by
84  # the build, then the APK has to be installed (regardless of the md5 record).
85  force_install = HasInstallMetadataChanged(device, apk_package, metadata_path)
86
87  def Install():
88    device.Install(options.apk_path, reinstall=True)
89    RecordInstallMetadata(device, apk_package, metadata_path)
90    build_utils.Touch(options.install_record)
91
92
93  record_path = '%s.%s.md5.stamp' % (options.apk_path, serial_number)
94  md5_check.CallAndRecordIfStale(
95      Install,
96      record_path=record_path,
97      input_paths=[options.apk_path],
98      force=force_install)
99
100  if options.stamp:
101    build_utils.Touch(options.stamp)
102
103
104if __name__ == '__main__':
105  sys.exit(main())
106