blob: aafcee79a391c081db53936c9f275dbe29fcdbae [file] [log] [blame]
Jiyong Parkf1691d22021-03-29 20:11:58 +09001// Copyright 2021 Google Inc. All rights reserved.
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
15package android
16
17import (
18 "fmt"
19 "strconv"
20 "strings"
21)
22
23type SdkContext interface {
24 // SdkVersion returns SdkSpec that corresponds to the sdk_version property of the current module
Jiyong Park92315372021-04-02 08:45:46 +090025 SdkVersion(ctx EarlyModuleContext) SdkSpec
Jiyong Parkf1691d22021-03-29 20:11:58 +090026 // SystemModules returns the system_modules property of the current module, or an empty string if it is not set.
27 SystemModules() string
Spandan Das8c9ae7e2023-03-03 21:20:36 +000028 // MinSdkVersion returns ApiLevel that corresponds to the min_sdk_version property of the current module,
Jiyong Parkf1691d22021-03-29 20:11:58 +090029 // or from sdk_version if it is not set.
Spandan Das8c9ae7e2023-03-03 21:20:36 +000030 MinSdkVersion(ctx EarlyModuleContext) ApiLevel
Spandan Dasa26eda72023-03-02 00:56:06 +000031 // ReplaceMaxSdkVersionPlaceholder returns Apilevel to replace the maxSdkVersion property of permission and
William Loh5a082f92022-05-17 20:21:50 +000032 // uses-permission tags if it is set.
Spandan Dasa26eda72023-03-02 00:56:06 +000033 ReplaceMaxSdkVersionPlaceholder(ctx EarlyModuleContext) ApiLevel
Spandan Dasca70fc42023-03-01 23:38:49 +000034 // TargetSdkVersion returns the ApiLevel that corresponds to the target_sdk_version property of the current module,
Jiyong Parkf1691d22021-03-29 20:11:58 +090035 // or from sdk_version if it is not set.
Spandan Dasca70fc42023-03-01 23:38:49 +000036 TargetSdkVersion(ctx EarlyModuleContext) ApiLevel
Jiyong Parkf1691d22021-03-29 20:11:58 +090037}
38
39// SdkKind represents a particular category of an SDK spec like public, system, test, etc.
40type SdkKind int
41
42const (
43 SdkInvalid SdkKind = iota
44 SdkNone
45 SdkCore
46 SdkCorePlatform
Spandan Das0b555e32022-11-28 18:48:51 +000047 SdkIntraCore // API surface provided by one core module to another
Jiyong Parkf1691d22021-03-29 20:11:58 +090048 SdkPublic
49 SdkSystem
50 SdkTest
Mark White9421c4c2023-08-10 00:07:03 +000051 SdkTestFrameworksCore
Jiyong Parkf1691d22021-03-29 20:11:58 +090052 SdkModule
53 SdkSystemServer
54 SdkPrivate
Spandan Das4ac2aed2022-12-28 01:54:29 +000055 SdkToolchain // API surface provided by ART to compile other API domains
Jiyong Parkf1691d22021-03-29 20:11:58 +090056)
57
58// String returns the string representation of this SdkKind
59func (k SdkKind) String() string {
60 switch k {
61 case SdkPrivate:
62 return "private"
63 case SdkNone:
64 return "none"
65 case SdkPublic:
66 return "public"
67 case SdkSystem:
68 return "system"
69 case SdkTest:
70 return "test"
Mark White9421c4c2023-08-10 00:07:03 +000071 case SdkTestFrameworksCore:
72 return "test_frameworks_core"
Jiyong Parkf1691d22021-03-29 20:11:58 +090073 case SdkCore:
74 return "core"
75 case SdkCorePlatform:
76 return "core_platform"
Spandan Das0b555e32022-11-28 18:48:51 +000077 case SdkIntraCore:
78 return "intracore"
Jiyong Parkf1691d22021-03-29 20:11:58 +090079 case SdkModule:
80 return "module-lib"
81 case SdkSystemServer:
82 return "system-server"
Spandan Das4ac2aed2022-12-28 01:54:29 +000083 case SdkToolchain:
84 return "toolchain"
Jiyong Parkf1691d22021-03-29 20:11:58 +090085 default:
86 return "invalid"
87 }
88}
89
Jihoon Kang5b065bb2023-04-05 21:08:08 +000090func (k SdkKind) DefaultJavaLibraryName() string {
Spandan Das626a8ad2023-03-20 18:52:50 +000091 switch k {
92 case SdkPublic:
93 return "android_stubs_current"
94 case SdkSystem:
95 return "android_system_stubs_current"
96 case SdkTest:
97 return "android_test_stubs_current"
Mark White9421c4c2023-08-10 00:07:03 +000098 case SdkTestFrameworksCore:
99 return "android_test_frameworks_core_stubs_current"
Spandan Das626a8ad2023-03-20 18:52:50 +0000100 case SdkCore:
101 return "core.current.stubs"
102 case SdkModule:
103 return "android_module_lib_stubs_current"
104 case SdkSystemServer:
105 return "android_system_server_stubs_current"
106 default:
107 panic(fmt.Errorf("APIs of API surface %v cannot be provided by a single Soong module\n", k))
108 }
109}
110
Jiyong Parkf1691d22021-03-29 20:11:58 +0900111// SdkSpec represents the kind and the version of an SDK for a module to build against
112type SdkSpec struct {
Jiyong Park54105c42021-03-31 18:17:53 +0900113 Kind SdkKind
114 ApiLevel ApiLevel
115 Raw string
Jiyong Parkf1691d22021-03-29 20:11:58 +0900116}
117
118func (s SdkSpec) String() string {
Jiyong Park54105c42021-03-31 18:17:53 +0900119 return fmt.Sprintf("%s_%s", s.Kind, s.ApiLevel)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900120}
121
122// Valid checks if this SdkSpec is well-formed. Note however that true doesn't mean that the
123// specified SDK actually exists.
124func (s SdkSpec) Valid() bool {
125 return s.Kind != SdkInvalid
126}
127
128// Specified checks if this SdkSpec is well-formed and is not "".
129func (s SdkSpec) Specified() bool {
130 return s.Valid() && s.Kind != SdkPrivate
131}
132
133// whether the API surface is managed and versioned, i.e. has .txt file that
134// get frozen on SDK freeze and changes get reviewed by API council.
135func (s SdkSpec) Stable() bool {
136 if !s.Specified() {
137 return false
138 }
139 switch s.Kind {
140 case SdkNone:
141 // there is nothing to manage and version in this case; de facto stable API.
142 return true
143 case SdkCore, SdkPublic, SdkSystem, SdkModule, SdkSystemServer:
144 return true
Mark White9421c4c2023-08-10 00:07:03 +0000145 case SdkCorePlatform, SdkTest, SdkTestFrameworksCore, SdkPrivate:
Jiyong Parkf1691d22021-03-29 20:11:58 +0900146 return false
147 default:
148 panic(fmt.Errorf("unknown SdkKind=%v", s.Kind))
149 }
150 return false
151}
152
satayev0ee2f912021-12-01 17:39:48 +0000153// PrebuiltSdkAvailableForUnbundledBuild tells whether this SdkSpec can have a prebuilt SDK
Jiyong Parkf1691d22021-03-29 20:11:58 +0900154// that can be used for unbundled builds.
155func (s SdkSpec) PrebuiltSdkAvailableForUnbundledBuild() bool {
156 // "", "none", and "core_platform" are not available for unbundled build
157 // as we don't/can't have prebuilt stub for the versions
158 return s.Kind != SdkPrivate && s.Kind != SdkNone && s.Kind != SdkCorePlatform
159}
160
161func (s SdkSpec) ForVendorPartition(ctx EarlyModuleContext) SdkSpec {
162 // If BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES has a numeric value,
163 // use it instead of "current" for the vendor partition.
164 currentSdkVersion := ctx.DeviceConfig().CurrentApiLevelForVendorModules()
165 if currentSdkVersion == "current" {
166 return s
167 }
168
169 if s.Kind == SdkPublic || s.Kind == SdkSystem {
Jiyong Park54105c42021-03-31 18:17:53 +0900170 if s.ApiLevel.IsCurrent() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900171 if i, err := strconv.Atoi(currentSdkVersion); err == nil {
Jiyong Park54105c42021-03-31 18:17:53 +0900172 apiLevel := uncheckedFinalApiLevel(i)
173 return SdkSpec{s.Kind, apiLevel, s.Raw}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900174 }
175 panic(fmt.Errorf("BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES must be either \"current\" or a number, but was %q", currentSdkVersion))
176 }
177 }
178 return s
179}
180
181// UsePrebuilt determines whether prebuilt SDK should be used for this SdkSpec with the given context.
182func (s SdkSpec) UsePrebuilt(ctx EarlyModuleContext) bool {
Jiyong Parkc7022042021-04-15 16:53:05 +0900183 switch s {
184 case SdkSpecNone, SdkSpecCorePlatform, SdkSpecPrivate:
185 return false
186 }
187
Jiyong Park54105c42021-03-31 18:17:53 +0900188 if s.ApiLevel.IsCurrent() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900189 // "current" can be built from source and be from prebuilt SDK
190 return ctx.Config().AlwaysUsePrebuiltSdks()
Jiyong Park54105c42021-03-31 18:17:53 +0900191 } else if !s.ApiLevel.IsPreview() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900192 // validation check
Mark White9421c4c2023-08-10 00:07:03 +0000193 if s.Kind != SdkPublic && s.Kind != SdkSystem && s.Kind != SdkTest &&
194 s.Kind != SdkTestFrameworksCore && s.Kind != SdkModule && s.Kind != SdkSystemServer {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900195 panic(fmt.Errorf("prebuilt SDK is not not available for SdkKind=%q", s.Kind))
196 return false
197 }
198 // numbered SDKs are always from prebuilt
199 return true
200 }
Jiyong Parkf1691d22021-03-29 20:11:58 +0900201 return false
202}
203
Jiyong Park54105c42021-03-31 18:17:53 +0900204// EffectiveVersion converts an SdkSpec into the concrete ApiLevel that the module should use. For
205// modules targeting an unreleased SDK (meaning it does not yet have a number) it returns
206// FutureApiLevel(10000).
207func (s SdkSpec) EffectiveVersion(ctx EarlyModuleContext) (ApiLevel, error) {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900208 if !s.Valid() {
Jiyong Park54105c42021-03-31 18:17:53 +0900209 return s.ApiLevel, fmt.Errorf("invalid sdk version %q", s.Raw)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900210 }
211
212 if ctx.DeviceSpecific() || ctx.SocSpecific() {
213 s = s.ForVendorPartition(ctx)
214 }
Spandan Dasdd7057c2023-01-05 01:03:47 +0000215 return s.ApiLevel.EffectiveVersion(ctx)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900216}
217
218// EffectiveVersionString converts an SdkSpec into the concrete version string that the module
219// should use. For modules targeting an unreleased SDK (meaning it does not yet have a number)
220// it returns the codename (P, Q, R, etc.)
221func (s SdkSpec) EffectiveVersionString(ctx EarlyModuleContext) (string, error) {
Jiyong Park54105c42021-03-31 18:17:53 +0900222 if !s.Valid() {
223 return s.ApiLevel.String(), fmt.Errorf("invalid sdk version %q", s.Raw)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900224 }
Jiyong Park54105c42021-03-31 18:17:53 +0900225
226 if ctx.DeviceSpecific() || ctx.SocSpecific() {
227 s = s.ForVendorPartition(ctx)
228 }
Spandan Dasdd7057c2023-01-05 01:03:47 +0000229 return s.ApiLevel.EffectiveVersionString(ctx)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900230}
231
Jiyong Park92315372021-04-02 08:45:46 +0900232var (
Jiyong Parkc7022042021-04-15 16:53:05 +0900233 SdkSpecNone = SdkSpec{SdkNone, NoneApiLevel, "(no version)"}
Spandan Das15da5882023-03-02 23:36:39 +0000234 SdkSpecPrivate = SdkSpec{SdkPrivate, PrivateApiLevel, ""}
Jiyong Parkc7022042021-04-15 16:53:05 +0900235 SdkSpecCorePlatform = SdkSpec{SdkCorePlatform, FutureApiLevel, "core_platform"}
Jiyong Park92315372021-04-02 08:45:46 +0900236)
237
238func SdkSpecFrom(ctx EarlyModuleContext, str string) SdkSpec {
satayev0ee2f912021-12-01 17:39:48 +0000239 return SdkSpecFromWithConfig(ctx.Config(), str)
240}
241
242func SdkSpecFromWithConfig(config Config, str string) SdkSpec {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900243 switch str {
244 // special cases first
245 case "":
Jiyong Park92315372021-04-02 08:45:46 +0900246 return SdkSpecPrivate
Jiyong Parkf1691d22021-03-29 20:11:58 +0900247 case "none":
Jiyong Park92315372021-04-02 08:45:46 +0900248 return SdkSpecNone
Jiyong Parkf1691d22021-03-29 20:11:58 +0900249 case "core_platform":
Jiyong Park92315372021-04-02 08:45:46 +0900250 return SdkSpecCorePlatform
Jiyong Parkf1691d22021-03-29 20:11:58 +0900251 default:
252 // the syntax is [kind_]version
253 sep := strings.LastIndex(str, "_")
254
255 var kindString string
256 if sep == 0 {
Spandan Das15da5882023-03-02 23:36:39 +0000257 return SdkSpec{SdkInvalid, NewInvalidApiLevel(str), str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900258 } else if sep == -1 {
259 kindString = ""
260 } else {
261 kindString = str[0:sep]
262 }
263 versionString := str[sep+1 : len(str)]
264
265 var kind SdkKind
266 switch kindString {
267 case "":
268 kind = SdkPublic
269 case "core":
270 kind = SdkCore
271 case "system":
272 kind = SdkSystem
273 case "test":
274 kind = SdkTest
Mark White9421c4c2023-08-10 00:07:03 +0000275 case "test_frameworks_core":
276 kind = SdkTestFrameworksCore
Jiyong Parkf1691d22021-03-29 20:11:58 +0900277 case "module":
278 kind = SdkModule
279 case "system_server":
280 kind = SdkSystemServer
281 default:
Jiyong Park54105c42021-03-31 18:17:53 +0900282 return SdkSpec{SdkInvalid, NoneApiLevel, str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900283 }
284
satayev0ee2f912021-12-01 17:39:48 +0000285 apiLevel, err := ApiLevelFromUserWithConfig(config, versionString)
Jiyong Park92315372021-04-02 08:45:46 +0900286 if err != nil {
Spandan Das15da5882023-03-02 23:36:39 +0000287 return SdkSpec{SdkInvalid, NewInvalidApiLevel(versionString), str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900288 }
Jiyong Park54105c42021-03-31 18:17:53 +0900289 return SdkSpec{kind, apiLevel, str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900290 }
291}
292
293func (s SdkSpec) ValidateSystemSdk(ctx EarlyModuleContext) bool {
Sebastian Pickl1f166222024-01-04 17:25:03 +0000294 // Ensures that the specified system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor/product Java module)
295 // Assuming that BOARD_SYSTEMSDK_VERSIONS := 28 29,
296 // sdk_version of the modules in vendor/product that use system sdk must be either system_28, system_29 or system_current
297 if s.Kind != SdkSystem || s.ApiLevel.IsPreview() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900298 return true
299 }
Sebastian Pickl1f166222024-01-04 17:25:03 +0000300 allowedVersions := ctx.DeviceConfig().PlatformSystemSdkVersions()
301 if ctx.DeviceSpecific() || ctx.SocSpecific() || (ctx.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
302 systemSdkVersions := ctx.DeviceConfig().SystemSdkVersions()
303 if len(systemSdkVersions) > 0 {
304 allowedVersions = systemSdkVersions
Jiyong Parkf1691d22021-03-29 20:11:58 +0900305 }
306 }
Sebastian Pickl1f166222024-01-04 17:25:03 +0000307 if len(allowedVersions) > 0 && !InList(s.ApiLevel.String(), allowedVersions) {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900308 ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
Sebastian Pickl1f166222024-01-04 17:25:03 +0000309 s.Raw, allowedVersions)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900310 return false
311 }
312 return true
313}
Spandan Das6b73fcb2023-03-20 20:20:58 +0000314
315func init() {
316 RegisterMakeVarsProvider(pctx, javaSdkMakeVars)
317}
318
319// Export the name of the soong modules representing the various Java API surfaces.
320func javaSdkMakeVars(ctx MakeVarsContext) {
Jihoon Kang91c83952023-05-30 19:12:28 +0000321 ctx.Strict("ANDROID_PUBLIC_STUBS", SdkPublic.DefaultJavaLibraryName())
322 ctx.Strict("ANDROID_SYSTEM_STUBS", SdkSystem.DefaultJavaLibraryName())
323 ctx.Strict("ANDROID_TEST_STUBS", SdkTest.DefaultJavaLibraryName())
324 ctx.Strict("ANDROID_MODULE_LIB_STUBS", SdkModule.DefaultJavaLibraryName())
325 ctx.Strict("ANDROID_SYSTEM_SERVER_STUBS", SdkSystemServer.DefaultJavaLibraryName())
326 ctx.Strict("ANDROID_CORE_STUBS", SdkCore.DefaultJavaLibraryName())
Spandan Das6b73fcb2023-03-20 20:20:58 +0000327}