From 3a6e2e61a520ba0dd10b01a2e48142f785f15751 Mon Sep 17 00:00:00 2001 From: Christopher Grant Date: Mon, 25 Nov 2019 16:40:14 +0000 Subject: [PATCH] Android: Support pure-32-bit version codes on 64-bit build configs See the associated bug for reasons why this work is happening. Refactor the version number generator script to be more explicit, and do away with the hack that was in place to support multiple version numbers in 64-bit config. Also, add the new pure 32-bit Mono and Trichrome numbers, as well as an alias 32_64 version number, which is equivalent to the ambiguous "Monochrome" version. Bug: 1027573 Change-Id: Iae270f84ad3cf3c28e9001460a016aa7f75237e8 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1931100 Commit-Queue: Christopher Grant Reviewed-by: Andrew Grieve Cr-Original-Commit-Position: refs/heads/master@{#718671} Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src Cr-Mirrored-Commit: 0c8f086794b4d8183f1094b2a43b0c9fbd41286d --- util/android_chrome_version.py | 158 +++++++++++++++++----------- util/android_chrome_version_test.py | 33 ++++-- util/version.gni | 5 +- 3 files changed, 125 insertions(+), 71 deletions(-) diff --git a/util/android_chrome_version.py b/util/android_chrome_version.py index 986dc2cdb..f46221000 100644 --- a/util/android_chrome_version.py +++ b/util/android_chrome_version.py @@ -1,15 +1,15 @@ # Copyright 2019 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Different build variants of chrome for android have different version codes. -Reason: for targets that have the same package name (e.g. chrome, chome -modern, monochrome, trichrome), Play Store considers them the same app -and will push the supported app with the highest version code to devices. -(note Play Store does not support hosting two different apps with same -version code and package name) +"""Different build variants of Chrome for Android have different version codes. -Each key in this dict represents a unique version code that will be used for -one or more android chrome apks. +For targets that have the same package name (e.g. Chrome, Chrome Modern, +Monochrome, Trichrome), Play Store considers them the same app and will push the +supported app with the highest version code to devices. Note that Play Store +does not support hosting two different apps with same version code and package +name. + +Each version code generated by this script will be used by one or more APKs. Webview channels must have unique version codes for a couple reasons: a) Play Store does not support having the same version code for different @@ -21,23 +21,78 @@ b) Firebase project support (used by official builders) requires unique packages are whitelisted by Android as webview providers. WEBVIEW_STABLE, WEBVIEW_BETA, WEBVIEW_DEV are all used for standalone webview, -whereas the others are used for various chrome apks. +whereas the others are used for various chrome APKs. -Note that a final digit of '3' for webview is reserved for Trichrome Webview. +Note that a final digit of '3' for Webview is reserved for Trichrome Webview. The same versionCode is used for both Trichrome Chrome and Trichrome Webview. """ -ANDROID_CHROME_APK_VERSION_CODE_DIFFS = { + +# Package name version bits. +_PACKAGE_NAMES = { 'CHROME': 0, 'CHROME_MODERN': 1, 'MONOCHROME': 2, 'TRICHROME': 3, - 'NOTOUCH_CHROME': 4, 'WEBVIEW_STABLE': 0, 'WEBVIEW_BETA': 1, 'WEBVIEW_DEV': 2, } +"""List of version numbers to be created for each build configuration. +Tuple format: -"""The architecture preference is encoded into the version_code for devices + (version code name), (package name), (supported ABIs) + +Here, (supported ABIs) is referring to the combination of browser ABI and +webview library ABI present in a particular APK. For example, 64_32 implies a +64-bit browser with an extra 32-bit Webview library. See also +_ABIS_TO_BIT_MASK. +""" +_APKS = { + '32': [ + ('CHROME', 'CHROME', '32'), + ('CHROME_MODERN', 'CHROME_MODERN', '32'), + ('MONOCHROME', 'MONOCHROME', '32'), + ('TRICHROME', 'TRICHROME', '32'), + ('WEBVIEW_STABLE', 'WEBVIEW_STABLE', '32'), + ('WEBVIEW_BETA', 'WEBVIEW_BETA', '32'), + ('WEBVIEW_DEV', 'WEBVIEW_DEV', '32'), + ], + '64': [ + # Pure 64-bit Chrome variants have traditionally used the first + # available 64-bit architecture digit, which is now used for + # Monochrome/Trichrome's "32+64" variant. It could be changed to "64", + # but there's no reason to. + ('CHROME', 'CHROME', '32_64'), + ('CHROME_MODERN', 'CHROME_MODERN', '32_64'), + ('MONOCHROME', 'MONOCHROME', '32_64'), + ('MONOCHROME_32', 'MONOCHROME', '32'), + ('MONOCHROME_32_64', 'MONOCHROME', '32_64'), + ('MONOCHROME_64_32', 'MONOCHROME', '64_32'), + ('MONOCHROME_64', 'MONOCHROME', '64'), + ('TRICHROME', 'TRICHROME', '32_64'), + ('TRICHROME_32', 'TRICHROME', '32'), + ('TRICHROME_32_64', 'TRICHROME', '32_64'), + ('TRICHROME_64_32', 'TRICHROME', '64_32'), + ('TRICHROME_64', 'TRICHROME', '64'), + ('WEBVIEW_STABLE', 'WEBVIEW_STABLE', '32_64'), + ('WEBVIEW_BETA', 'WEBVIEW_BETA', '32_64'), + ('WEBVIEW_DEV', 'WEBVIEW_DEV', '32_64'), + ] +} + +# Splits input build config architecture to manufacturer and bitness. +_ARCH_TO_MFG_AND_BITNESS = { + 'arm': ('arm', '32'), + 'arm64': ('arm', '64'), + 'x86': ('intel', '32'), + 'x64': ('intel', '64'), + 'mipsel': ('mipsel', '32'), +} + +# Expose the available choices to other scripts. +ARCH_CHOICES = _ARCH_TO_MFG_AND_BITNESS.keys() +""" +The architecture preference is encoded into the version_code for devices that support multiple architectures. (exploiting play store logic that pushes apk with highest version code) @@ -77,50 +132,34 @@ things here: - The relative order of mips isn't important, but it needs to be a *distinct* value to the other architectures because all builds need unique version codes. """ -ARCH_VERSION_CODE_DIFF = { - 'arm': 0, - 'x86': 10, - 'mipsel': 20, - 'arm64': 30, - 'x64': 60 +_ABIS_TO_BIT_MASK = { + 'arm': { + '32': 0, + '32_64': 30, + '64_32': 40, + '64': 50, + }, + 'intel': { + '32': 10, + '32_64': 60, + '64_32': 70, + '64': 80, + }, + 'mipsel': { + '32': 20, + } } -ARCH_CHOICES = ARCH_VERSION_CODE_DIFF.keys() - """ "Next" builds get +5 last version code digit. We choose 5 because it won't conflict with values in ANDROID_CHROME_APK_VERSION_CODE_DIFFS """ -NEXT_BUILD_VERSION_CODE_DIFF = 5 - -"""For 64-bit architectures, some packages have multiple targets with version -codes that differ by the second-to-last digit (the architecture digit). This is -for various combinations of 32-bit vs 64-bit chrome and webview. The -default/traditional configuration is 32-bit chrome with 64-bit webview, but we -are adding: -+ 64-bit chrome with 32-bit webview -+ 64-bit combined Chrome and Webview (only one library) -+ (maybe someday 32-bit chrome with 32-bit webview) - -The naming scheme followed here is _, -e.g. 64_32 is 64-bit chrome with 32-bit webview. -""" -ARCH64_APK_VARIANTS = { - '64_32': { - 'PACKAGES': frozenset(['MONOCHROME', 'TRICHROME']), - 'MODIFIER': 10 - }, - '64': { - 'PACKAGES': frozenset(['MONOCHROME', 'TRICHROME']), - 'MODIFIER': 20 - } -} +_NEXT_BUILD_VERSION_CODE_DIFF = 5 def GenerateVersionCodes(version_values, arch, is_next_build): - """Get dict of version codes for chrome-for-android-related targets + """Build dict of version codes for the specified build architecture. Eg: - e.g. { 'CHROME_VERSION_CODE': '378100010', 'MONOCHROME_VERSION_CODE': '378100013', @@ -142,25 +181,22 @@ def GenerateVersionCodes(version_values, arch, is_next_build): Thus, this method is responsible for the final two digits of versionCode. """ - base_version_code = '%s%03d00' % (version_values['BUILD'], - int(version_values['PATCH'])) - new_version_code = int(base_version_code) + base_version_code = int( + '%s%03d00' % (version_values['BUILD'], int(version_values['PATCH']))) - new_version_code += ARCH_VERSION_CODE_DIFF[arch] if is_next_build: - new_version_code += NEXT_BUILD_VERSION_CODE_DIFF + base_version_code += _NEXT_BUILD_VERSION_CODE_DIFF + + mfg, bitness = _ARCH_TO_MFG_AND_BITNESS[arch] version_codes = {} - for apk, diff in ANDROID_CHROME_APK_VERSION_CODE_DIFFS.iteritems(): + + for apk, package, abis in _APKS[bitness]: + abi_bits = _ABIS_TO_BIT_MASK[mfg][abis] + package_bits = _PACKAGE_NAMES[package] + version_code_name = apk + '_VERSION_CODE' - version_code_val = new_version_code + diff + version_code_val = base_version_code + abi_bits + package_bits version_codes[version_code_name] = str(version_code_val) - for variant, config in ARCH64_APK_VARIANTS.iteritems(): - if apk in config['PACKAGES']: - variant_name = apk + '_' + variant + '_VERSION_CODE' - variant_val = version_code_val + config['MODIFIER'] - version_codes[variant_name] = str(variant_val) - - return version_codes diff --git a/util/android_chrome_version_test.py b/util/android_chrome_version_test.py index 529ccd33a..570849715 100644 --- a/util/android_chrome_version_test.py +++ b/util/android_chrome_version_test.py @@ -54,15 +54,6 @@ class _VersionTest(unittest.TestCase): self.assertEqual(trichrome_version_code, '372000003') - def testGenerateVersionCodesAndroidNoTouch(self): - """Assert it gives correct values for standard/example inputs""" - output = GenerateVersionCodes( - self.EXAMPLE_VERSION_VALUES, arch='arm', is_next_build=False) - - notouch_chrome_version_code = output['NOTOUCH_CHROME_VERSION_CODE'] - - self.assertEqual(notouch_chrome_version_code, '372000004') - def testGenerateVersionCodesAndroidWebviewStable(self): """Assert it gives correct values for standard/example inputs""" output = GenerateVersionCodes( @@ -170,13 +161,25 @@ class _VersionTest(unittest.TestCase): """ output = GenerateVersionCodes( self.EXAMPLE_VERSION_VALUES, arch='arm64', is_next_build=False) + arch_monochrome_version_code = output['MONOCHROME_VERSION_CODE'] + arch_monochrome_32_version_code = output['MONOCHROME_32_VERSION_CODE'] + arch_monochrome_32_64_version_code = output['MONOCHROME_32_64_VERSION_CODE'] arch_monochrome_64_32_version_code = output['MONOCHROME_64_32_VERSION_CODE'] arch_monochrome_64_version_code = output['MONOCHROME_64_VERSION_CODE'] + arch_trichrome_version_code = output['TRICHROME_VERSION_CODE'] + arch_trichrome_32_version_code = output['TRICHROME_32_VERSION_CODE'] + arch_trichrome_32_64_version_code = output['TRICHROME_32_64_VERSION_CODE'] arch_trichrome_64_32_version_code = output['TRICHROME_64_32_VERSION_CODE'] arch_trichrome_64_version_code = output['TRICHROME_64_VERSION_CODE'] + self.assertEqual(arch_monochrome_32_version_code, '372000002') + self.assertEqual(arch_monochrome_32_64_version_code, '372000032') + self.assertEqual(arch_monochrome_version_code, '372000032') self.assertEqual(arch_monochrome_64_32_version_code, '372000042') self.assertEqual(arch_monochrome_64_version_code, '372000052') + self.assertEqual(arch_trichrome_32_version_code, '372000003') + self.assertEqual(arch_trichrome_32_64_version_code, '372000033') + self.assertEqual(arch_trichrome_version_code, '372000033') self.assertEqual(arch_trichrome_64_32_version_code, '372000043') self.assertEqual(arch_trichrome_64_version_code, '372000053') @@ -202,13 +205,25 @@ class _VersionTest(unittest.TestCase): """ output = GenerateVersionCodes( self.EXAMPLE_VERSION_VALUES, arch='x64', is_next_build=False) + arch_monochrome_32_version_code = output['MONOCHROME_32_VERSION_CODE'] + arch_monochrome_32_64_version_code = output['MONOCHROME_32_64_VERSION_CODE'] + arch_monochrome_version_code = output['MONOCHROME_VERSION_CODE'] arch_monochrome_64_32_version_code = output['MONOCHROME_64_32_VERSION_CODE'] arch_monochrome_64_version_code = output['MONOCHROME_64_VERSION_CODE'] + arch_trichrome_32_version_code = output['TRICHROME_32_VERSION_CODE'] + arch_trichrome_32_64_version_code = output['TRICHROME_32_64_VERSION_CODE'] + arch_trichrome_version_code = output['TRICHROME_VERSION_CODE'] arch_trichrome_64_32_version_code = output['TRICHROME_64_32_VERSION_CODE'] arch_trichrome_64_version_code = output['TRICHROME_64_VERSION_CODE'] + self.assertEqual(arch_monochrome_32_version_code, '372000012') + self.assertEqual(arch_monochrome_32_64_version_code, '372000062') + self.assertEqual(arch_monochrome_version_code, '372000062') self.assertEqual(arch_monochrome_64_32_version_code, '372000072') self.assertEqual(arch_monochrome_64_version_code, '372000082') + self.assertEqual(arch_trichrome_32_version_code, '372000013') + self.assertEqual(arch_trichrome_32_64_version_code, '372000063') + self.assertEqual(arch_trichrome_version_code, '372000063') self.assertEqual(arch_trichrome_64_32_version_code, '372000073') self.assertEqual(arch_trichrome_64_version_code, '372000083') diff --git a/util/version.gni b/util/version.gni index 56cf536e2..ee774e71b 100644 --- a/util/version.gni +++ b/util/version.gni @@ -78,7 +78,10 @@ _script_arguments += [ _result = exec_script("version.py", _script_arguments, "scope", - [ chrome_version_file ]) + [ + chrome_version_file, + "android_chrome_version.py", + ]) # Full version. For example "45.0.12321.0" chrome_version_full = _result.full