2017-03-28 23:54:55 +02:00
// Copyright 2017 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package android
import (
"encoding/json"
2020-04-01 18:41:41 +02:00
"fmt"
2018-05-04 00:42:34 +02:00
"strconv"
2023-08-25 20:02:13 +02:00
"strings"
2017-03-28 23:54:55 +02:00
)
func init ( ) {
2023-05-16 02:58:37 +02:00
RegisterParallelSingletonType ( "api_levels" , ApiLevelsSingleton )
2017-03-28 23:54:55 +02:00
}
2021-02-04 18:28:22 +01:00
const previewAPILevelBase = 9000
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
// An API level, which may be a finalized (numbered) API, a preview (codenamed)
// API, or the future API level (10000). Can be parsed from a string with
// ApiLevelFromUser or ApiLevelOrPanic.
//
// The different *types* of API levels are handled separately. Currently only
2021-03-29 13:11:58 +02:00
// Java has these, and they're managed with the SdkKind enum of the SdkSpec. A
// future cleanup should be to migrate SdkSpec to using ApiLevel instead of its
// SdkVersion int, and to move SdkSpec into this package.
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
type ApiLevel struct {
// The string representation of the API level.
value string
// A number associated with the API level. The exact value depends on
// whether this API level is a preview or final API.
//
// For final API levels, this is the assigned version number.
//
// For preview API levels, this value has no meaning except to index known
// previews to determine ordering.
number int
// Identifies this API level as either a preview or final API level.
isPreview bool
}
2022-07-01 21:39:14 +02:00
func ( this ApiLevel ) FinalInt ( ) int {
2023-03-03 00:36:39 +01:00
if this . IsInvalid ( ) {
panic ( fmt . Errorf ( "%v is not a recognized api_level\n" , this ) )
}
2022-07-01 21:39:14 +02:00
if this . IsPreview ( ) {
panic ( "Requested a final int from a non-final ApiLevel" )
} else {
return this . number
}
}
2020-07-23 07:32:17 +02:00
func ( this ApiLevel ) FinalOrFutureInt ( ) int {
2023-03-03 00:36:39 +01:00
if this . IsInvalid ( ) {
panic ( fmt . Errorf ( "%v is not a recognized api_level\n" , this ) )
}
2020-07-23 07:32:17 +02:00
if this . IsPreview ( ) {
2020-07-24 01:43:25 +02:00
return FutureApiLevelInt
2020-07-23 07:32:17 +02:00
} else {
return this . number
}
}
2021-02-04 18:28:22 +01:00
// FinalOrPreviewInt distinguishes preview versions from "current" (future).
// This is for "native" stubs and should be in sync with ndkstubgen/getApiLevelsMap().
// - "current" -> future (10000)
// - preview codenames -> preview base (9000) + index
// - otherwise -> cast to int
func ( this ApiLevel ) FinalOrPreviewInt ( ) int {
2023-03-03 00:36:39 +01:00
if this . IsInvalid ( ) {
panic ( fmt . Errorf ( "%v is not a recognized api_level\n" , this ) )
}
2021-02-04 18:28:22 +01:00
if this . IsCurrent ( ) {
return this . number
}
if this . IsPreview ( ) {
return previewAPILevelBase + this . number
}
return this . number
}
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
// Returns the canonical name for this API level. For a finalized API level
// this will be the API number as a string. For a preview API level this
// will be the codename, or "current".
func ( this ApiLevel ) String ( ) string {
return this . value
}
// Returns true if this is a non-final API level.
func ( this ApiLevel ) IsPreview ( ) bool {
return this . isPreview
}
2023-03-03 00:36:39 +01:00
// Returns true if the raw api level string is invalid
func ( this ApiLevel ) IsInvalid ( ) bool {
return this . EqualTo ( InvalidApiLevel )
}
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
// Returns true if this is the unfinalized "current" API level. This means
// different things across Java and native. Java APIs do not use explicit
// codenames, so all non-final codenames are grouped into "current". For native
// explicit codenames are typically used, and current is the union of all
// non-final APIs, including those that may not yet be in any codename.
//
// Note that in a build where the platform is final, "current" will not be a
// preview API level but will instead be canonicalized to the final API level.
func ( this ApiLevel ) IsCurrent ( ) bool {
return this . value == "current"
}
2021-01-26 03:43:46 +01:00
func ( this ApiLevel ) IsNone ( ) bool {
return this . number == - 1
}
2023-03-03 00:36:39 +01:00
// Returns true if an app is compiling against private apis.
// e.g. if sdk_version = "" in Android.bp, then the ApiLevel of that "sdk" is at PrivateApiLevel.
func ( this ApiLevel ) IsPrivate ( ) bool {
return this . number == PrivateApiLevel . number
}
2023-01-05 02:03:47 +01:00
// EffectiveVersion converts an ApiLevel into the concrete ApiLevel that the module should use. For
// modules targeting an unreleased SDK (meaning it does not yet have a number) it returns
// FutureApiLevel(10000).
func ( l ApiLevel ) EffectiveVersion ( ctx EarlyModuleContext ) ( ApiLevel , error ) {
if l . EqualTo ( InvalidApiLevel ) {
return l , fmt . Errorf ( "invalid version in sdk_version %q" , l . value )
}
if ! l . IsPreview ( ) {
return l , nil
}
ret := ctx . Config ( ) . DefaultAppTargetSdk ( ctx )
if ret . IsPreview ( ) {
return FutureApiLevel , nil
}
return ret , nil
}
// EffectiveVersionString converts an SdkSpec into the concrete version string that the module
// should use. For modules targeting an unreleased SDK (meaning it does not yet have a number)
// it returns the codename (P, Q, R, etc.)
func ( l ApiLevel ) EffectiveVersionString ( ctx EarlyModuleContext ) ( string , error ) {
if l . EqualTo ( InvalidApiLevel ) {
return l . value , fmt . Errorf ( "invalid version in sdk_version %q" , l . value )
}
if ! l . IsPreview ( ) {
return l . String ( ) , nil
}
// Determine the default sdk
ret := ctx . Config ( ) . DefaultAppTargetSdk ( ctx )
if ! ret . IsPreview ( ) {
// If the default sdk has been finalized, return that
return ret . String ( ) , nil
}
// There can be more than one active in-development sdks
// If an app is targeting an active sdk, but not the default one, return the requested active sdk.
// e.g.
// SETUP
// In-development: UpsideDownCake, VanillaIceCream
// Default: VanillaIceCream
// Android.bp
// min_sdk_version: `UpsideDownCake`
// RETURN
// UpsideDownCake and not VanillaIceCream
for _ , preview := range ctx . Config ( ) . PreviewApiLevels ( ) {
if l . String ( ) == preview . String ( ) {
return preview . String ( ) , nil
}
}
// Otherwise return the default one
return ret . String ( ) , nil
}
2023-03-03 22:20:36 +01:00
// Specified returns true if the module is targeting a recognzized api_level.
// It returns false if either
// 1. min_sdk_version is not an int or a recognized codename
// 2. both min_sdk_version and sdk_version are empty. In this case, MinSdkVersion() defaults to SdkSpecPrivate.ApiLevel
func ( this ApiLevel ) Specified ( ) bool {
return ! this . IsInvalid ( ) && ! this . IsPrivate ( )
}
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
// Returns -1 if the current API level is less than the argument, 0 if they
// are equal, and 1 if it is greater than the argument.
func ( this ApiLevel ) CompareTo ( other ApiLevel ) int {
if this . IsPreview ( ) && ! other . IsPreview ( ) {
return 1
} else if ! this . IsPreview ( ) && other . IsPreview ( ) {
return - 1
}
if this . number < other . number {
return - 1
} else if this . number == other . number {
return 0
} else {
return 1
}
}
func ( this ApiLevel ) EqualTo ( other ApiLevel ) bool {
return this . CompareTo ( other ) == 0
}
func ( this ApiLevel ) GreaterThan ( other ApiLevel ) bool {
return this . CompareTo ( other ) > 0
}
func ( this ApiLevel ) GreaterThanOrEqualTo ( other ApiLevel ) bool {
return this . CompareTo ( other ) >= 0
}
func ( this ApiLevel ) LessThan ( other ApiLevel ) bool {
return this . CompareTo ( other ) < 0
}
func ( this ApiLevel ) LessThanOrEqualTo ( other ApiLevel ) bool {
return this . CompareTo ( other ) <= 0
}
func uncheckedFinalApiLevel ( num int ) ApiLevel {
return ApiLevel {
value : strconv . Itoa ( num ) ,
number : num ,
isPreview : false ,
}
}
2023-08-25 20:02:13 +02:00
func uncheckedFinalIncrementalApiLevel ( num int , increment int ) ApiLevel {
return ApiLevel {
value : strconv . Itoa ( num ) + "." + strconv . Itoa ( increment ) ,
number : num ,
isPreview : false ,
}
}
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
var NoneApiLevel = ApiLevel {
value : "(no version)" ,
// Not 0 because we don't want this to compare equal with the first preview.
number : - 1 ,
isPreview : true ,
}
2023-03-03 00:36:39 +01:00
// Sentinel ApiLevel to validate that an apiLevel is either an int or a recognized codename.
var InvalidApiLevel = NewInvalidApiLevel ( "invalid" )
// Returns an apiLevel object at the same level as InvalidApiLevel.
// The object contains the raw string provied in bp file, and can be used for error handling.
func NewInvalidApiLevel ( raw string ) ApiLevel {
return ApiLevel {
value : raw ,
number : - 2 , // One less than NoneApiLevel
isPreview : true ,
}
}
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
// The first version that introduced 64-bit ABIs.
var FirstLp64Version = uncheckedFinalApiLevel ( 21 )
2021-05-14 22:07:32 +02:00
// Android has had various kinds of packed relocations over the years
// (http://b/187907243).
//
// API level 30 is where the now-standard SHT_RELR is available.
var FirstShtRelrVersion = uncheckedFinalApiLevel ( 30 )
// API level 28 introduced SHT_RELR when it was still Android-only, and used an
// Android-specific relocation.
var FirstAndroidRelrVersion = uncheckedFinalApiLevel ( 28 )
// API level 23 was when we first had the Chrome relocation packer, which is
// obsolete and has been removed, but lld can now generate compatible packed
// relocations itself.
var FirstPackedRelocationsVersion = uncheckedFinalApiLevel ( 23 )
2021-10-29 14:50:24 +02:00
// LastWithoutModuleLibCoreSystemModules is the last API level where prebuilts/sdk does not contain
// a core-for-system-modules.jar for the module-lib API scope.
var LastWithoutModuleLibCoreSystemModules = uncheckedFinalApiLevel ( 31 )
2024-02-12 16:00:15 +01:00
var ApiLevelR = uncheckedFinalApiLevel ( 30 )
Add an apex_contributions_defaults module to module sdk
This metadata module will contain a flattened list of all the soong
modules contributed by this module to the rest of the build. This is
supported in V and above.
Bug: 326246905
Test: m art-module-host-exports
Test: unzip -p out/soong/mainline-sdks/art-module-host-exports-current.zip Android.bp | grep -A 15 apex_contributions_defaults
apex_contributions_defaults {
name: "art-module-host-exports.contributions",
contents: [
"prebuilt_art.module.api.annotations",
"prebuilt_dex2oat",
"prebuilt_dex2oatd",
"prebuilt_dexdump",
"prebuilt_hiddenapi",
"prebuilt_oatdump",
"prebuilt_profman",
"prebuilt_veridex",
"prebuilt_libartpalette",
"prebuilt_libartbase",
],
}
Change-Id: Iba43a9da5430adfc0a5fd9b5dc27b5d89c5eacb8
2024-03-06 15:04:36 +01:00
var ApiLevelUpsideDownCake = uncheckedFinalApiLevel ( 34 )
2024-06-07 13:06:57 +02:00
var ApiLevelVanillaIceCream = uncheckedFinalApiLevel ( 35 )
2022-06-24 22:40:11 +02:00
// ReplaceFinalizedCodenames returns the API level number associated with that API level
// if the `raw` input is the codename of an API level has been finalized.
// If the input is *not* a finalized codename, the input is returned unmodified.
2023-04-28 21:32:27 +02:00
func ReplaceFinalizedCodenames ( config Config , raw string ) ( string , error ) {
finalCodenamesMap , err := getFinalCodenamesMap ( config )
if err != nil {
return raw , err
}
num , ok := finalCodenamesMap [ raw ]
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
if ! ok {
2023-04-28 21:32:27 +02:00
return raw , nil
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
}
2023-04-28 21:32:27 +02:00
return strconv . Itoa ( num ) , nil
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
}
2023-03-03 22:20:36 +01:00
// ApiLevelFrom converts the given string `raw` to an ApiLevel.
// If `raw` is invalid (empty string, unrecognized codename etc.) it returns an invalid ApiLevel
func ApiLevelFrom ( ctx PathContext , raw string ) ApiLevel {
ret , err := ApiLevelFromUser ( ctx , raw )
if err != nil {
return NewInvalidApiLevel ( raw )
}
return ret
}
2021-12-01 18:39:48 +01:00
// ApiLevelFromUser converts the given string `raw` to an ApiLevel, possibly returning an error.
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
//
// `raw` must be non-empty. Passing an empty string results in a panic.
//
// "current" will return CurrentApiLevel, which is the ApiLevel associated with
// an arbitrary future release (often referred to as API level 10000).
//
// Finalized codenames will be interpreted as their final API levels, not the
// preview of the associated releases. R is now API 30, not the R preview.
//
// Future codenames return a preview API level that has no associated integer.
//
// Inputs that are not "current", known previews, or convertible to an integer
// will return an error.
2020-10-02 19:26:04 +02:00
func ApiLevelFromUser ( ctx PathContext , raw string ) ( ApiLevel , error ) {
2021-12-01 18:39:48 +01:00
return ApiLevelFromUserWithConfig ( ctx . Config ( ) , raw )
}
// ApiLevelFromUserWithConfig implements ApiLevelFromUser, see comments for
// ApiLevelFromUser for more details.
func ApiLevelFromUserWithConfig ( config Config , raw string ) ( ApiLevel , error ) {
2023-03-02 20:35:02 +01:00
// This logic is replicated in starlark, if changing logic here update starlark code too
2024-01-09 23:02:03 +01:00
// https://cs.android.com/android/platform/superproject/+/main:build/bazel/rules/common/api.bzl;l=42;drc=231c7e8c8038fd478a79eb68aa5b9f5c64e0e061
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
if raw == "" {
panic ( "API level string must be non-empty" )
}
if raw == "current" {
2020-07-24 01:43:25 +02:00
return FutureApiLevel , nil
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
}
2021-12-01 18:39:48 +01:00
for _ , preview := range config . PreviewApiLevels ( ) {
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
if raw == preview . String ( ) {
return preview , nil
}
}
2023-04-28 21:32:27 +02:00
apiLevelsReleasedVersions , err := getApiLevelsMapReleasedVersions ( )
if err != nil {
return NoneApiLevel , err
}
canonical , ok := apiLevelsReleasedVersions [ raw ]
2023-03-06 22:04:30 +01:00
if ! ok {
asInt , err := strconv . Atoi ( raw )
if err != nil {
return NoneApiLevel , fmt . Errorf ( "%q could not be parsed as an integer and is not a recognized codename" , raw )
}
return uncheckedFinalApiLevel ( asInt ) , nil
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
}
2023-03-06 22:04:30 +01:00
return uncheckedFinalApiLevel ( canonical ) , nil
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
}
2021-10-29 14:50:24 +02:00
// ApiLevelForTest returns an ApiLevel constructed from the supplied raw string.
//
// This only supports "current" and numeric levels, code names are not supported.
func ApiLevelForTest ( raw string ) ApiLevel {
if raw == "" {
panic ( "API level string must be non-empty" )
}
if raw == "current" {
return FutureApiLevel
}
2023-08-25 20:02:13 +02:00
if strings . Contains ( raw , "." ) {
// Check prebuilt incremental API format MM.m for major (API level) and minor (incremental) revisions
parts := strings . Split ( raw , "." )
if len ( parts ) != 2 {
panic ( fmt . Errorf ( "Found unexpected version '%s' for incremental API - expect MM.m format for incremental API with both major (MM) an minor (m) revision." , raw ) )
}
sdk , sdk_err := strconv . Atoi ( parts [ 0 ] )
qpr , qpr_err := strconv . Atoi ( parts [ 1 ] )
if sdk_err != nil || qpr_err != nil {
panic ( fmt . Errorf ( "Unable to read version number for incremental api '%s'" , raw ) )
}
apiLevel := uncheckedFinalIncrementalApiLevel ( sdk , qpr )
return apiLevel
}
2021-10-29 14:50:24 +02:00
asInt , err := strconv . Atoi ( raw )
if err != nil {
panic ( fmt . Errorf ( "%q could not be parsed as an integer and is not a recognized codename" , raw ) )
}
apiLevel := uncheckedFinalApiLevel ( asInt )
return apiLevel
}
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
// Converts an API level string `raw` into an ApiLevel in the same method as
// `ApiLevelFromUser`, but the input is assumed to have no errors and any errors
// will panic instead of returning an error.
2020-10-02 19:26:04 +02:00
func ApiLevelOrPanic ( ctx PathContext , raw string ) ApiLevel {
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
value , err := ApiLevelFromUser ( ctx , raw )
if err != nil {
panic ( err . Error ( ) )
}
return value
}
2017-11-29 02:34:01 +01:00
func ApiLevelsSingleton ( ) Singleton {
2017-03-28 23:54:55 +02:00
return & apiLevelsSingleton { }
}
type apiLevelsSingleton struct { }
2017-11-29 02:34:01 +01:00
func createApiLevelsJson ( ctx SingletonContext , file WritablePath ,
2017-03-28 23:54:55 +02:00
apiLevelsMap map [ string ] int ) {
jsonStr , err := json . Marshal ( apiLevelsMap )
if err != nil {
ctx . Errorf ( err . Error ( ) )
}
2020-11-13 20:48:42 +01:00
WriteFileRule ( ctx , file , string ( jsonStr ) )
2017-03-28 23:54:55 +02:00
}
2017-11-29 02:34:01 +01:00
func GetApiLevelsJson ( ctx PathContext ) WritablePath {
2017-03-28 23:54:55 +02:00
return PathForOutput ( ctx , "api_levels.json" )
}
2023-04-28 21:32:27 +02:00
func getApiLevelsMapReleasedVersions ( ) ( map [ string ] int , error ) {
2024-03-07 00:50:53 +01:00
return map [ string ] int {
"G" : 9 ,
"I" : 14 ,
"J" : 16 ,
"J-MR1" : 17 ,
"J-MR2" : 18 ,
"K" : 19 ,
"L" : 21 ,
"L-MR1" : 22 ,
"M" : 23 ,
"N" : 24 ,
"N-MR1" : 25 ,
"O" : 26 ,
"O-MR1" : 27 ,
"P" : 28 ,
"Q" : 29 ,
"R" : 30 ,
"S" : 31 ,
"S-V2" : 32 ,
"Tiramisu" : 33 ,
"UpsideDownCake" : 34 ,
} , nil
2023-02-24 15:46:43 +01:00
}
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
var finalCodenamesMapKey = NewOnceKey ( "FinalCodenamesMap" )
2023-04-28 21:32:27 +02:00
func getFinalCodenamesMap ( config Config ) ( map [ string ] int , error ) {
type resultStruct struct {
result map [ string ] int
err error
}
2023-03-02 20:35:02 +01:00
// This logic is replicated in starlark, if changing logic here update starlark code too
2024-01-09 23:02:03 +01:00
// https://cs.android.com/android/platform/superproject/+/main:build/bazel/rules/common/api.bzl;l=30;drc=231c7e8c8038fd478a79eb68aa5b9f5c64e0e061
2023-04-28 21:32:27 +02:00
result := config . Once ( finalCodenamesMapKey , func ( ) interface { } {
apiLevelsMap , err := getApiLevelsMapReleasedVersions ( )
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
2020-07-23 07:32:17 +02:00
// TODO: Differentiate "current" and "future".
// The code base calls it FutureApiLevel, but the spelling is "current",
// and these are really two different things. When defining APIs it
// means the API has not yet been added to a specific release. When
// choosing an API level to build for it means that the future API level
// should be used, except in the case where the build is finalized in
// which case the platform version should be used. This is *weird*,
// because in the circumstance where API foo was added in R and bar was
// added in S, both of these are usable when building for "current" when
// neither R nor S are final, but the S APIs stop being available in a
// final R build.
2023-04-28 21:32:27 +02:00
if err == nil && Bool ( config . productVariables . Platform_sdk_final ) {
2020-07-24 02:32:15 +02:00
apiLevelsMap [ "current" ] = config . PlatformSdkVersion ( ) . FinalOrFutureInt ( )
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
}
2023-04-28 21:32:27 +02:00
return resultStruct { apiLevelsMap , err }
} ) . ( resultStruct )
return result . result , result . err
Replace stringly-typed API levels.
Handling of API levels within Soong is currently fairly difficult
since it isn't always clear based on context what kind of API level a
given string represents, how much canonicalizing and error checking
the code receiving the string are expected to do, or how those errors
should be treated.
The API level struct does not export its raw data, so as to keep its
"constructor" private to the android package, and to prevent misuse of
the `number` field, which is only an implementation detail for preview
API levels. API levels can be parsed with either
`android.ApiLevelFromUser`, which returns any errors to the caller, or
`android.ApiLevelOrPanic`, which is used in the case where the input
is trusted and any errors in parsing should panic. Even within the
`android` package, these APIs should be preferred over direct
construction.
For cases where there are context specific parsing requirements, such
as handling the "minimum" alias in the cc module,
`nativeApiLevelFromUser` and `nativeApiLevelOrPanic` should be used
instead.
Test: treehugger
Bug: http://b/154667674
Change-Id: Id52921fda32cb437fb1775ac2183299dedc0cf20
2020-07-06 23:49:35 +02:00
}
2019-02-04 20:22:08 +01:00
var apiLevelsMapKey = NewOnceKey ( "ApiLevelsMap" )
2023-02-24 15:46:43 +01:00
// ApiLevelsMap has entries for preview API levels
2023-04-28 21:32:27 +02:00
func GetApiLevelsMap ( config Config ) ( map [ string ] int , error ) {
type resultStruct struct {
result map [ string ] int
err error
}
2023-03-02 20:35:02 +01:00
// This logic is replicated in starlark, if changing logic here update starlark code too
2024-01-09 23:02:03 +01:00
// https://cs.android.com/android/platform/superproject/+/main:build/bazel/rules/common/api.bzl;l=23;drc=231c7e8c8038fd478a79eb68aa5b9f5c64e0e061
2023-04-28 21:32:27 +02:00
result := config . Once ( apiLevelsMapKey , func ( ) interface { } {
apiLevelsMap , err := getApiLevelsMapReleasedVersions ( )
if err == nil {
for i , codename := range config . PlatformVersionAllPreviewCodenames ( ) {
apiLevelsMap [ codename ] = previewAPILevelBase + i
}
2018-05-04 00:42:34 +02:00
}
2023-04-28 21:32:27 +02:00
return resultStruct { apiLevelsMap , err }
} ) . ( resultStruct )
return result . result , result . err
2018-05-04 00:42:34 +02:00
}
func ( a * apiLevelsSingleton ) GenerateBuildActions ( ctx SingletonContext ) {
2023-04-28 21:32:27 +02:00
apiLevelsMap , err := GetApiLevelsMap ( ctx . Config ( ) )
if err != nil {
ctx . Errorf ( "%s\n" , err )
return
}
2017-03-28 23:54:55 +02:00
apiLevelsJson := GetApiLevelsJson ( ctx )
2017-11-29 02:34:01 +01:00
createApiLevelsJson ( ctx , apiLevelsJson , apiLevelsMap )
2017-03-28 23:54:55 +02:00
}