Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / build / android / gyp / apk_install.py
blobc9098676f1b67e6486a07666c7c9a7db15181651
1 #!/usr/bin/env python
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.
7 """Installs an APK.
9 """
11 import optparse
12 import os
13 import re
14 import sys
16 from util import build_device
17 from util import build_utils
18 from util import md5_check
20 BUILD_ANDROID_DIR = os.path.join(os.path.dirname(__file__), '..')
21 sys.path.append(BUILD_ANDROID_DIR)
23 from pylib import constants
24 from pylib.utils import apk_helper
26 _DPI_TO_DENSITY = {
27 120: 'ldpi',
28 160: 'mdpi',
29 240: 'hdpi',
30 320: 'xhdpi',
31 480: 'xxhdpi',
35 def RetrieveDeviceConfig(device):
36 """Probes the given device for its split-select config.
38 For example: en-rUS-xhdpi:armeabi-v7a
39 Run "split-select --help" for more info about the format.
40 """
41 language = device.GetProp('persist.sys.language')
42 country = device.GetProp('persist.sys.country')
43 density_dpi = int(device.GetProp('ro.sf.lcd_density'))
44 density = _DPI_TO_DENSITY.get(density_dpi, 'tvdpi')
45 abi = device.product_cpu_abi
46 return '%s-r%s-%s:%s' % (language, country, density, abi)
49 def GetNewMetadata(device, apk_package):
50 """Gets the metadata on the device for the apk_package apk."""
51 output = device.RunShellCommand('ls -l /data/app/')
52 # Matches lines like:
53 # -rw-r--r-- system system 7376582 2013-04-19 16:34 \
54 # org.chromium.chrome.shell.apk
55 # -rw-r--r-- system system 7376582 2013-04-19 16:34 \
56 # org.chromium.chrome.shell-1.apk
57 apk_matcher = lambda s: re.match('.*%s(-[0-9]*)?(.apk)?$' % apk_package, s)
58 matches = filter(apk_matcher, output)
59 return matches[0] if matches else None
61 def HasInstallMetadataChanged(device, apk_package, metadata_path):
62 """Checks if the metadata on the device for apk_package has changed."""
63 if not os.path.exists(metadata_path):
64 return True
66 with open(metadata_path, 'r') as expected_file:
67 return expected_file.read() != device.GetInstallMetadata(apk_package)
70 def RecordInstallMetadata(device, apk_package, metadata_path):
71 """Records the metadata from the device for apk_package."""
72 metadata = GetNewMetadata(device, apk_package)
73 if not metadata:
74 raise Exception('APK install failed unexpectedly.')
76 with open(metadata_path, 'w') as outfile:
77 outfile.write(metadata)
80 def main():
81 parser = optparse.OptionParser()
82 parser.add_option('--apk-path',
83 help='Path to .apk to install.')
84 parser.add_option('--split-apk-path',
85 help='Path to .apk splits (can specify multiple times, causes '
86 '--install-multiple to be used.',
87 action='append')
88 parser.add_option('--android-sdk-tools',
89 help='Path to the Android SDK build tools folder. ' +
90 'Required when using --split-apk-path.')
91 parser.add_option('--install-record',
92 help='Path to install record (touched only when APK is installed).')
93 parser.add_option('--build-device-configuration',
94 help='Path to build device configuration.')
95 parser.add_option('--stamp',
96 help='Path to touch on success.')
97 parser.add_option('--configuration-name',
98 help='The build CONFIGURATION_NAME')
99 options, _ = parser.parse_args()
101 device = build_device.GetBuildDeviceFromPath(
102 options.build_device_configuration)
103 if not device:
104 return
106 constants.SetBuildType(options.configuration_name)
108 serial_number = device.GetSerialNumber()
109 apk_package = apk_helper.GetPackageName(options.apk_path)
111 metadata_path = '%s.%s.device.time.stamp' % (options.apk_path, serial_number)
113 # If the APK on the device does not match the one that was last installed by
114 # the build, then the APK has to be installed (regardless of the md5 record).
115 force_install = HasInstallMetadataChanged(device, apk_package, metadata_path)
117 def SelectSplits(target_config, base_apk, split_apks, android_sdk_tools):
118 cmd = [os.path.join(android_sdk_tools, 'split-select'),
119 '--target', target_config,
120 '--base', base_apk,
122 for split in split_apks:
123 cmd.extend(('--split', split))
125 # split-select outputs one path per line and a blank line at the end.
126 output = build_utils.CheckOutput(cmd)
127 return [x for x in output.split('\n') if x]
129 def Install():
130 if options.split_apk_path:
131 requiredSdkVersion = constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP
132 actualSdkVersion = device.device.build_version_sdk
133 if actualSdkVersion < requiredSdkVersion:
134 raise Exception(('--split-apk-path requires sdk version %s. Device has '
135 'version %s') % (requiredSdkVersion, actualSdkVersion))
136 device_config = RetrieveDeviceConfig(device.device)
137 active_splits = SelectSplits(
138 device_config,
139 options.apk_path,
140 options.split_apk_path,
141 options.android_sdk_tools)
143 all_apks = [options.apk_path] + active_splits
144 device.device.adb.InstallMultiple(all_apks, reinstall=True)
145 else:
146 device.Install(options.apk_path, reinstall=True)
148 RecordInstallMetadata(device, apk_package, metadata_path)
149 build_utils.Touch(options.install_record)
152 record_path = '%s.%s.md5.stamp' % (options.apk_path, serial_number)
153 md5_check.CallAndRecordIfStale(
154 Install,
155 record_path=record_path,
156 input_paths=[options.apk_path],
157 force=force_install)
159 if options.stamp:
160 build_utils.Touch(options.stamp)
163 if __name__ == '__main__':
164 sys.exit(main())