| # 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. | |
| 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 | |
| versions of a package. Without unique codes, promoting a beta apk to stable | |
| would require first removing the beta version. | |
| b) Firebase project support (used by official builders) requires unique | |
| [version code + package name]. | |
| We cannot add new webview package names for new channels because webview | |
| packages are allowlisted 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. | |
| Note that a package digit of '3' for Webview is reserved for Trichrome Webview. | |
| The same versionCode is used for both Trichrome Chrome and Trichrome Webview. | |
| Version code values are constructed like this: | |
| {full BUILD number}{3 digits: PATCH}{1 digit: package}{1 digit: ABIs}. | |
| For example: | |
| Build 3721, patch 0, ChromeModern (1), on ARM64 (5): 372100015 | |
| Build 3721, patch 9, Monochrome (2), on ARM (0): 372100920 | |
| """ | |
| # Package name version bits. | |
| _PACKAGE_NAMES = { | |
| 'CHROME': 0, | |
| 'CHROME_MODERN': 10, | |
| 'MONOCHROME': 20, | |
| 'TRICHROME': 30, | |
| 'WEBVIEW_STABLE': 0, | |
| 'WEBVIEW_BETA': 10, | |
| 'WEBVIEW_DEV': 20, | |
| } | |
| """ "Next" builds get +5 on their package version code digit. | |
| We choose 5 because it won't conflict with values in _PACKAGE_NAMES. | |
| """ | |
| _NEXT_BUILD_VERSION_CODE_DIFF = 50 | |
| """List of version numbers to be created for each build configuration. | |
| Tuple format: | |
| (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': [ | |
| ('CHROME', 'CHROME', '64'), | |
| ('CHROME_MODERN', 'CHROME_MODERN', '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'), | |
| ('WEBVIEW_32_STABLE', 'WEBVIEW_STABLE', '32'), | |
| ('WEBVIEW_32_BETA', 'WEBVIEW_BETA', '32'), | |
| ('WEBVIEW_32_DEV', 'WEBVIEW_DEV', '32'), | |
| ] | |
| } | |
| # 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) | |
| Detail: | |
| Many Android devices support multiple architectures, and can run applications | |
| built for any of them; the Play Store considers all of the supported | |
| architectures compatible and does not, itself, have any preference for which | |
| is "better". The common cases here: | |
| - All production arm64 devices can also run arm | |
| - All production x64 devices can also run x86 | |
| - Pretty much all production x86/x64 devices can also run arm (via a binary | |
| translator) | |
| Since the Play Store has no particular preferences, you have to encode your own | |
| preferences into the ordering of the version codes. There's a few relevant | |
| things here: | |
| - For any android app, it's theoretically preferable to ship a 64-bit version to | |
| 64-bit devices if it exists, because the 64-bit architectures are supposed to | |
| be "better" than their 32-bit predecessors (unfortunately this is not always | |
| true due to the effect on memory usage, but we currently deal with this by | |
| simply not shipping a 64-bit version *at all* on the configurations where we | |
| want the 32-bit version to be used). | |
| - For any android app, it's definitely preferable to ship an x86 version to x86 | |
| devices if it exists instead of an arm version, because running things through | |
| the binary translator is a performance hit. | |
| - For WebView, Monochrome, and Trichrome specifically, they are a special class | |
| of APK called "multiarch" which means that they actually need to *use* more | |
| than one architecture at runtime (rather than simply being compatible with | |
| more than one). The 64-bit builds of these multiarch APKs contain both 32-bit | |
| and 64-bit code, so that Webview is available for both ABIs. If you're | |
| multiarch you *must* have a version that supports both 32-bit and 64-bit | |
| version on a 64-bit device, otherwise it won't work properly. So, the 64-bit | |
| version needs to be a higher versionCode, as otherwise a 64-bit device would | |
| prefer the 32-bit version that does not include any 64-bit code, and fail. | |
| - 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. | |
| """ | |
| _ABIS_TO_BIT_MASK = { | |
| 'arm': { | |
| '32': 0, | |
| '32_64': 3, | |
| '64_32': 4, | |
| '64': 5, | |
| }, | |
| 'intel': { | |
| '32': 1, | |
| '32_64': 6, | |
| '64_32': 7, | |
| '64': 8, | |
| }, | |
| 'mipsel': { | |
| '32': 2, | |
| } | |
| } | |
| def GenerateVersionCodes(version_values, arch, is_next_build): | |
| """Build dict of version codes for the specified build architecture. Eg: | |
| { | |
| 'CHROME_VERSION_CODE': '378100010', | |
| 'MONOCHROME_VERSION_CODE': '378100013', | |
| ... | |
| } | |
| versionCode values are built like this: | |
| {full BUILD int}{3 digits: PATCH}{1 digit: package}{1 digit: ABIs}. | |
| MAJOR and MINOR values are not used for generating versionCode. | |
| - MINOR is always 0. It was used for something long ago in Chrome's history | |
| but has not been used since, and has never been nonzero on Android. | |
| - MAJOR is cosmetic and controlled by the release managers. MAJOR and BUILD | |
| always have reasonable sort ordering: for two version codes A and B, it's | |
| always the case that (A.MAJOR < B.MAJOR) implies (A.BUILD < B.BUILD), and | |
| that (A.MAJOR > B.MAJOR) implies (A.BUILD > B.BUILD). This property is just | |
| maintained by the humans who set MAJOR. | |
| Thus, this method is responsible for the final two digits of versionCode. | |
| """ | |
| base_version_code = int( | |
| '%s%03d00' % (version_values['BUILD'], int(version_values['PATCH']))) | |
| if is_next_build: | |
| base_version_code += _NEXT_BUILD_VERSION_CODE_DIFF | |
| mfg, bitness = _ARCH_TO_MFG_AND_BITNESS[arch] | |
| version_codes = {} | |
| 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 = base_version_code + abi_bits + package_bits | |
| version_codes[version_code_name] = str(version_code_val) | |
| return version_codes |