Home | History | Annotate | Download | only in gyp
      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 
     11 import optparse
     12 import os
     13 import re
     14 import sys
     15 
     16 from util import build_device
     17 from util import build_utils
     18 from util import md5_check
     19 
     20 BUILD_ANDROID_DIR = os.path.join(os.path.dirname(__file__), '..')
     21 sys.path.append(BUILD_ANDROID_DIR)
     22 
     23 from pylib import constants
     24 from pylib.utils import apk_helper
     25 
     26 def 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 
     38 def 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 
     47 def 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 
     57 def 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 
    104 if __name__ == '__main__':
    105   sys.exit(main())
    106