• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (C) 2023 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15# An API level, can be a finalized (numbered) API, a preview (codenamed) API, or
16# the future API level (10000). Can be parsed from a string with
17# parse_api_level_with_version.
18
19load("@bazel_skylib//lib:dicts.bzl", "dicts")
20load("@soong_injection//api_levels:api_levels.bzl", "api_levels_released_versions")
21load("@soong_injection//api_levels:platform_versions.bzl", "platform_versions")
22
23_NONE_API_LEVEL_INT = -1
24_PREVIEW_API_LEVEL_BASE = 9000  # Base constant for preview API levels.
25_FUTURE_API_LEVEL_INT = 10000  # API Level associated with an arbitrary future release
26
27# TODO(b/271280342): access these variables in a transition friendly way.
28_PLATFORM_SDK_FINAL = platform_versions.platform_sdk_final
29_PLATFORM_SDK_VERSION = platform_versions.platform_sdk_version
30_PLATFORM_SDK_CODENAME = platform_versions.platform_sdk_codename
31_PLATFORM_VERSION_ACTIVE_CODENAMES = platform_versions.platform_version_active_codenames
32
33# Dict of unfinalized codenames to a placeholder preview API int.
34_preview_codenames_to_ints = {
35    codename: _PREVIEW_API_LEVEL_BASE + i
36    for i, codename in enumerate(_PLATFORM_VERSION_ACTIVE_CODENAMES)
37}
38
39# Returns true if a string or int version is in preview (not finalized).
40def _is_preview(version):
41    if type(version) == "string" and version.isdigit():
42        # normalize int types internally
43        version = int(version)
44
45    # Future / current is considered as a preview.
46    if version == "current" or version == _FUTURE_API_LEVEL_INT:
47        return True
48
49    # api can be either the codename or the int level (9000+)
50    return version in _preview_codenames_to_ints or version in _preview_codenames_to_ints.values()
51
52# Return 10000 for unfinalized versions, otherwise return unchanged.
53def _final_or_future(version):
54    if _is_preview(version):
55        return _FUTURE_API_LEVEL_INT
56    else:
57        return version
58
59_final_codename = {
60    "current": _final_or_future(_PLATFORM_SDK_VERSION),
61} if _PLATFORM_SDK_FINAL and _PLATFORM_SDK_VERSION else {}
62
63_api_levels_with_previews = dicts.add(api_levels_released_versions, _preview_codenames_to_ints)
64_api_levels_with_final_codenames = dicts.add(api_levels_released_versions, _final_codename)  # @unused
65
66# parse_api_level_from_version is a Starlark implementation of ApiLevelFromUser
67# at https://cs.android.com/android/platform/superproject/+/master:build/soong/android/api_levels.go;l=221-250;drc=5095a6c4b484f34d5c4f55a855d6174e00fb7f5e
68def _parse_api_level_from_version(version):
69    """converts the given string `version` to an api level
70
71    Args:
72        version: must be non-empty. Inputs that are not "current", known
73        previews, finalized codenames, or convertible to an integer will return
74        an error.
75
76    Returns: The api level as an int.
77    """
78    if version == "":
79        fail("API level string must be non-empty")
80
81    if version == "current":
82        return _FUTURE_API_LEVEL_INT
83
84    if _is_preview(version):
85        return _preview_codenames_to_ints.get(version) or int(version)
86
87    # Not preview nor current.
88    #
89    # If the level is the codename of an API level that has been finalized, this
90    # function returns the API level number associated with that API level. If
91    # the input is *not* a finalized codename, the input is returned unmodified.
92    canonical_level = api_levels_released_versions.get(version)
93    if not canonical_level:
94        if not version.isdigit():
95            fail("version %s could not be parsed as integer and is not a recognized codename" % version)
96        return int(version)
97    return canonical_level
98
99# Starlark implementation of DefaultAppTargetSDK from build/soong/android/config.go
100# https://cs.android.com/android/platform/superproject/+/master:build/soong/android/config.go;l=875-889;drc=b0dc477ef740ec959548fe5517bd92ac4ea0325c
101# check what you want returned for codename == "" case before using
102def _default_app_target_sdk():
103    """default_app_target_sdk returns the API level that platform apps are targeting.
104       This converts a codename to the exact ApiLevel it represents.
105    """
106    if _PLATFORM_SDK_FINAL:
107        return _PLATFORM_SDK_VERSION
108
109    codename = _PLATFORM_SDK_CODENAME
110    if not codename:
111        # soong returns NoneApiLevel here value: "(no version)", number: -1, isPreview: true
112        #
113        # fail fast instead of returning an arbitrary value.
114        fail("Platform_sdk_codename must be set.")
115
116    if codename == "REL":
117        fail("Platform_sdk_codename should not be REL when Platform_sdk_final is false")
118
119    return _parse_api_level_from_version(codename)
120
121api = struct(
122    NONE_API_LEVEL = _NONE_API_LEVEL_INT,
123    FUTURE_API_LEVEL = _FUTURE_API_LEVEL_INT,
124    is_preview = _is_preview,
125    final_or_future = _final_or_future,
126    default_app_target_sdk = _default_app_target_sdk,
127    parse_api_level_from_version = _parse_api_level_from_version,
128    api_levels = _api_levels_with_previews,
129)
130