1*7594170eSAndroid Build Coastguard Worker# Copyright (C) 2023 The Android Open Source Project 2*7594170eSAndroid Build Coastguard Worker# 3*7594170eSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*7594170eSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*7594170eSAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*7594170eSAndroid Build Coastguard Worker# 7*7594170eSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 8*7594170eSAndroid Build Coastguard Worker# 9*7594170eSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*7594170eSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*7594170eSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*7594170eSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*7594170eSAndroid Build Coastguard Worker# limitations under the License. 14*7594170eSAndroid Build Coastguard Worker 15*7594170eSAndroid Build Coastguard Worker# An API level, can be a finalized (numbered) API, a preview (codenamed) API, or 16*7594170eSAndroid Build Coastguard Worker# the future API level (10000). Can be parsed from a string with 17*7594170eSAndroid Build Coastguard Worker# parse_api_level_with_version. 18*7594170eSAndroid Build Coastguard Worker 19*7594170eSAndroid Build Coastguard Workerload("@bazel_skylib//lib:dicts.bzl", "dicts") 20*7594170eSAndroid Build Coastguard Workerload("@soong_injection//api_levels:platform_versions.bzl", "platform_versions") 21*7594170eSAndroid Build Coastguard Workerload(":api_constants.bzl", "api_levels_released_versions") 22*7594170eSAndroid Build Coastguard Worker 23*7594170eSAndroid Build Coastguard Worker_NONE_API_LEVEL_INT = -1 24*7594170eSAndroid Build Coastguard Worker_PREVIEW_API_LEVEL_BASE = 9000 # Base constant for preview API levels. 25*7594170eSAndroid Build Coastguard Worker_FUTURE_API_LEVEL_INT = 10000 # API Level associated with an arbitrary future release 26*7594170eSAndroid Build Coastguard Worker 27*7594170eSAndroid Build Coastguard Worker# Dict of unfinalized codenames to a placeholder preview API int. 28*7594170eSAndroid Build Coastguard Workerdef _preview_codenames_to_ints(platform_sdk_variables): 29*7594170eSAndroid Build Coastguard Worker return { 30*7594170eSAndroid Build Coastguard Worker codename: _PREVIEW_API_LEVEL_BASE + i 31*7594170eSAndroid Build Coastguard Worker for i, codename in enumerate(platform_sdk_variables.platform_version_active_codenames) 32*7594170eSAndroid Build Coastguard Worker } 33*7594170eSAndroid Build Coastguard Worker 34*7594170eSAndroid Build Coastguard Worker# Returns true if a string or int version is in preview (not finalized). 35*7594170eSAndroid Build Coastguard Workerdef _is_preview(version, platform_sdk_variables): 36*7594170eSAndroid Build Coastguard Worker preview_codenames_to_ints = _preview_codenames_to_ints(platform_sdk_variables) 37*7594170eSAndroid Build Coastguard Worker if type(version) == "string" and version.isdigit(): 38*7594170eSAndroid Build Coastguard Worker # normalize int types internally 39*7594170eSAndroid Build Coastguard Worker version = int(version) 40*7594170eSAndroid Build Coastguard Worker 41*7594170eSAndroid Build Coastguard Worker # Future / current / none is considered as a preview. 42*7594170eSAndroid Build Coastguard Worker if version in ("current", "(no version)", _FUTURE_API_LEVEL_INT, _NONE_API_LEVEL_INT): 43*7594170eSAndroid Build Coastguard Worker return True 44*7594170eSAndroid Build Coastguard Worker 45*7594170eSAndroid Build Coastguard Worker # api can be either the codename or the int level (9000+) 46*7594170eSAndroid Build Coastguard Worker return version in preview_codenames_to_ints or version in preview_codenames_to_ints.values() 47*7594170eSAndroid Build Coastguard Worker 48*7594170eSAndroid Build Coastguard Worker# Return 10000 for unfinalized versions, otherwise return unchanged. 49*7594170eSAndroid Build Coastguard Workerdef _final_or_future(version, platform_sdk_variables): 50*7594170eSAndroid Build Coastguard Worker if _is_preview(version = version, platform_sdk_variables = platform_sdk_variables): 51*7594170eSAndroid Build Coastguard Worker return _FUTURE_API_LEVEL_INT 52*7594170eSAndroid Build Coastguard Worker else: 53*7594170eSAndroid Build Coastguard Worker return version 54*7594170eSAndroid Build Coastguard Worker 55*7594170eSAndroid Build Coastguard Workerdef _api_levels_with_previews(platform_sdk_variables): 56*7594170eSAndroid Build Coastguard Worker return dicts.add( 57*7594170eSAndroid Build Coastguard Worker api_levels_released_versions, 58*7594170eSAndroid Build Coastguard Worker _preview_codenames_to_ints(platform_sdk_variables), 59*7594170eSAndroid Build Coastguard Worker ) 60*7594170eSAndroid Build Coastguard Worker 61*7594170eSAndroid Build Coastguard Worker# @unused 62*7594170eSAndroid Build Coastguard Workerdef _api_levels_with_final_codenames(platform_sdk_variables): 63*7594170eSAndroid Build Coastguard Worker if platform_sdk_variables.platform_sdk_final and platform_sdk_variables.platform_sdk_version: 64*7594170eSAndroid Build Coastguard Worker return api_levels_released_versions 65*7594170eSAndroid Build Coastguard Worker return dicts.add( 66*7594170eSAndroid Build Coastguard Worker api_levels_released_versions, 67*7594170eSAndroid Build Coastguard Worker {"current": _final_or_future( 68*7594170eSAndroid Build Coastguard Worker version = platform_sdk_variables.platform_sdk_version, 69*7594170eSAndroid Build Coastguard Worker platform_sdk_variables = platform_sdk_variables, 70*7594170eSAndroid Build Coastguard Worker )}, 71*7594170eSAndroid Build Coastguard Worker ) 72*7594170eSAndroid Build Coastguard Worker 73*7594170eSAndroid Build Coastguard Worker# parse_api_level_from_version is a Starlark implementation of ApiLevelFromUser 74*7594170eSAndroid Build Coastguard Worker# at https://cs.android.com/android/platform/superproject/+/master:build/soong/android/api_levels.go;l=221-250;drc=5095a6c4b484f34d5c4f55a855d6174e00fb7f5e 75*7594170eSAndroid Build Coastguard Workerdef _parse_api_level_from_version(version, platform_sdk_variables): 76*7594170eSAndroid Build Coastguard Worker """converts the given string `version` to an api level 77*7594170eSAndroid Build Coastguard Worker 78*7594170eSAndroid Build Coastguard Worker Args: 79*7594170eSAndroid Build Coastguard Worker version: must be non-empty. Inputs that are not "current", known 80*7594170eSAndroid Build Coastguard Worker previews, finalized codenames, or convertible to an integer will return 81*7594170eSAndroid Build Coastguard Worker an error. 82*7594170eSAndroid Build Coastguard Worker 83*7594170eSAndroid Build Coastguard Worker Returns: The api level as an int. 84*7594170eSAndroid Build Coastguard Worker """ 85*7594170eSAndroid Build Coastguard Worker if version == "": 86*7594170eSAndroid Build Coastguard Worker fail("API level string must be non-empty") 87*7594170eSAndroid Build Coastguard Worker 88*7594170eSAndroid Build Coastguard Worker if version == "current": 89*7594170eSAndroid Build Coastguard Worker return _FUTURE_API_LEVEL_INT 90*7594170eSAndroid Build Coastguard Worker 91*7594170eSAndroid Build Coastguard Worker if _is_preview(version = version, platform_sdk_variables = platform_sdk_variables): 92*7594170eSAndroid Build Coastguard Worker return _preview_codenames_to_ints(platform_sdk_variables).get(version) or int(version) 93*7594170eSAndroid Build Coastguard Worker 94*7594170eSAndroid Build Coastguard Worker # Not preview nor current. 95*7594170eSAndroid Build Coastguard Worker # 96*7594170eSAndroid Build Coastguard Worker # If the level is the codename of an API level that has been finalized, this 97*7594170eSAndroid Build Coastguard Worker # function returns the API level number associated with that API level. If 98*7594170eSAndroid Build Coastguard Worker # the input is *not* a finalized codename, the input is returned unmodified. 99*7594170eSAndroid Build Coastguard Worker canonical_level = api_levels_released_versions.get(version) 100*7594170eSAndroid Build Coastguard Worker if not canonical_level: 101*7594170eSAndroid Build Coastguard Worker if not version.isdigit(): 102*7594170eSAndroid Build Coastguard Worker fail("version %s could not be parsed as integer and is not a recognized codename" % version) 103*7594170eSAndroid Build Coastguard Worker return int(version) 104*7594170eSAndroid Build Coastguard Worker return canonical_level 105*7594170eSAndroid Build Coastguard Worker 106*7594170eSAndroid Build Coastguard Workerdef _default_app_target_sdk_string(platform_sdk_variables): 107*7594170eSAndroid Build Coastguard Worker if platform_sdk_variables.platform_sdk_final: 108*7594170eSAndroid Build Coastguard Worker return str(platform_sdk_variables.platform_sdk_version) 109*7594170eSAndroid Build Coastguard Worker 110*7594170eSAndroid Build Coastguard Worker if not platform_sdk_variables.platform_sdk_codename: 111*7594170eSAndroid Build Coastguard Worker # soong returns NoneApiLevel here value: "(no version)", number: -1, isPreview: true 112*7594170eSAndroid Build Coastguard Worker # 113*7594170eSAndroid Build Coastguard Worker # fail fast instead of returning an arbitrary value. 114*7594170eSAndroid Build Coastguard Worker fail("Platform_sdk_codename must be set.") 115*7594170eSAndroid Build Coastguard Worker 116*7594170eSAndroid Build Coastguard Worker if platform_sdk_variables.platform_sdk_codename == "REL": 117*7594170eSAndroid Build Coastguard Worker fail("Platform_sdk_codename should not be REL when Platform_sdk_final is false") 118*7594170eSAndroid Build Coastguard Worker 119*7594170eSAndroid Build Coastguard Worker return platform_sdk_variables.platform_sdk_codename 120*7594170eSAndroid Build Coastguard Worker 121*7594170eSAndroid Build Coastguard Worker# Starlark implementation of DefaultAppTargetSDK from build/soong/android/config.go 122*7594170eSAndroid Build Coastguard Worker# https://cs.android.com/android/platform/superproject/+/master:build/soong/android/config.go;l=875-889;drc=b0dc477ef740ec959548fe5517bd92ac4ea0325c 123*7594170eSAndroid Build Coastguard Worker# check what you want returned for codename == "" case before using 124*7594170eSAndroid Build Coastguard Workerdef _default_app_target_sdk(platform_sdk_variables): 125*7594170eSAndroid Build Coastguard Worker """default_app_target_sdk returns the API level that platform apps are targeting. 126*7594170eSAndroid Build Coastguard Worker This converts a codename to the exact ApiLevel it represents. 127*7594170eSAndroid Build Coastguard Worker """ 128*7594170eSAndroid Build Coastguard Worker return _parse_api_level_from_version( 129*7594170eSAndroid Build Coastguard Worker version = _default_app_target_sdk_string(platform_sdk_variables), 130*7594170eSAndroid Build Coastguard Worker platform_sdk_variables = platform_sdk_variables, 131*7594170eSAndroid Build Coastguard Worker ) 132*7594170eSAndroid Build Coastguard Worker 133*7594170eSAndroid Build Coastguard Worker# Starlark implementation of EffectiveVersionString from build/soong/android/api_levels.go 134*7594170eSAndroid Build Coastguard Worker# EffectiveVersionString converts an api level string into the concrete version string that the module 135*7594170eSAndroid Build Coastguard Worker# should use. For modules targeting an unreleased SDK (meaning it does not yet have a number) 136*7594170eSAndroid Build Coastguard Worker# it returns the codename (P, Q, R, etc.) 137*7594170eSAndroid Build Coastguard Workerdef _effective_version_string( 138*7594170eSAndroid Build Coastguard Worker version, 139*7594170eSAndroid Build Coastguard Worker platform_sdk_variables): 140*7594170eSAndroid Build Coastguard Worker if not _is_preview(version, platform_sdk_variables): 141*7594170eSAndroid Build Coastguard Worker return version 142*7594170eSAndroid Build Coastguard Worker default_app_target_sdk_string = _default_app_target_sdk_string(platform_sdk_variables) 143*7594170eSAndroid Build Coastguard Worker if not _is_preview(default_app_target_sdk_string, platform_sdk_variables): 144*7594170eSAndroid Build Coastguard Worker return default_app_target_sdk_string 145*7594170eSAndroid Build Coastguard Worker if version in platform_sdk_variables.platform_version_active_codenames: 146*7594170eSAndroid Build Coastguard Worker return version 147*7594170eSAndroid Build Coastguard Worker return default_app_target_sdk_string 148*7594170eSAndroid Build Coastguard Worker 149*7594170eSAndroid Build Coastguard Workerdef api_from_product(platform_sdk_variables): 150*7594170eSAndroid Build Coastguard Worker """Provides api level-related utility functions from platform variables. 151*7594170eSAndroid Build Coastguard Worker 152*7594170eSAndroid Build Coastguard Worker Args: 153*7594170eSAndroid Build Coastguard Worker platform_sdk_variables: a struct that must provides the 4 154*7594170eSAndroid Build Coastguard Worker product variables: platform_sdk_final (boolean), 155*7594170eSAndroid Build Coastguard Worker platform_sdk_version (int), platform_sdk_codename (string), 156*7594170eSAndroid Build Coastguard Worker platform_version_active_codenames (string list) 157*7594170eSAndroid Build Coastguard Worker 158*7594170eSAndroid Build Coastguard Worker Returns: A struct containing utility functions and constants 159*7594170eSAndroid Build Coastguard Worker around api levels, e.g. for parsing them from user input and for 160*7594170eSAndroid Build Coastguard Worker overriding them based on defaults and the input product variables. 161*7594170eSAndroid Build Coastguard Worker """ 162*7594170eSAndroid Build Coastguard Worker return struct( 163*7594170eSAndroid Build Coastguard Worker NONE_API_LEVEL = _NONE_API_LEVEL_INT, 164*7594170eSAndroid Build Coastguard Worker FUTURE_API_LEVEL = _FUTURE_API_LEVEL_INT, 165*7594170eSAndroid Build Coastguard Worker is_preview = lambda version: _is_preview( 166*7594170eSAndroid Build Coastguard Worker version = version, 167*7594170eSAndroid Build Coastguard Worker platform_sdk_variables = platform_sdk_variables, 168*7594170eSAndroid Build Coastguard Worker ), 169*7594170eSAndroid Build Coastguard Worker final_or_future = lambda version: _final_or_future( 170*7594170eSAndroid Build Coastguard Worker version = version, 171*7594170eSAndroid Build Coastguard Worker platform_sdk_variables = platform_sdk_variables, 172*7594170eSAndroid Build Coastguard Worker ), 173*7594170eSAndroid Build Coastguard Worker default_app_target_sdk_string = lambda: _default_app_target_sdk_string(platform_sdk_variables), 174*7594170eSAndroid Build Coastguard Worker default_app_target_sdk = lambda: _default_app_target_sdk(platform_sdk_variables), 175*7594170eSAndroid Build Coastguard Worker parse_api_level_from_version = lambda version: _parse_api_level_from_version( 176*7594170eSAndroid Build Coastguard Worker version = version, 177*7594170eSAndroid Build Coastguard Worker platform_sdk_variables = platform_sdk_variables, 178*7594170eSAndroid Build Coastguard Worker ), 179*7594170eSAndroid Build Coastguard Worker api_levels = _api_levels_with_previews(platform_sdk_variables), 180*7594170eSAndroid Build Coastguard Worker effective_version_string = lambda version: _effective_version_string( 181*7594170eSAndroid Build Coastguard Worker version = version, 182*7594170eSAndroid Build Coastguard Worker platform_sdk_variables = platform_sdk_variables, 183*7594170eSAndroid Build Coastguard Worker ), 184*7594170eSAndroid Build Coastguard Worker ) 185*7594170eSAndroid Build Coastguard Worker 186*7594170eSAndroid Build Coastguard Worker# TODO(b/300428335): access these variables in a transition friendly way. 187*7594170eSAndroid Build Coastguard Workerapi = api_from_product(platform_versions) 188