blob: fa3abaa7caa8409515622545565bb157db2ab327 [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"
Jiyong Park7416d672024-01-04 23:20:42 +000019 "reflect"
Jiyong Parkf1691d22021-03-29 20:11:58 +090020 "strconv"
21 "strings"
22)
23
24type SdkContext interface {
25 // SdkVersion returns SdkSpec that corresponds to the sdk_version property of the current module
Jiyong Park92315372021-04-02 08:45:46 +090026 SdkVersion(ctx EarlyModuleContext) SdkSpec
Jiyong Parkf1691d22021-03-29 20:11:58 +090027 // SystemModules returns the system_modules property of the current module, or an empty string if it is not set.
28 SystemModules() string
Spandan Das8c9ae7e2023-03-03 21:20:36 +000029 // MinSdkVersion returns ApiLevel that corresponds to the min_sdk_version property of the current module,
Jiyong Parkf1691d22021-03-29 20:11:58 +090030 // or from sdk_version if it is not set.
Spandan Das8c9ae7e2023-03-03 21:20:36 +000031 MinSdkVersion(ctx EarlyModuleContext) ApiLevel
Spandan Dasa26eda72023-03-02 00:56:06 +000032 // ReplaceMaxSdkVersionPlaceholder returns Apilevel to replace the maxSdkVersion property of permission and
William Loh5a082f92022-05-17 20:21:50 +000033 // uses-permission tags if it is set.
Spandan Dasa26eda72023-03-02 00:56:06 +000034 ReplaceMaxSdkVersionPlaceholder(ctx EarlyModuleContext) ApiLevel
Spandan Dasca70fc42023-03-01 23:38:49 +000035 // TargetSdkVersion returns the ApiLevel that corresponds to the target_sdk_version property of the current module,
Jiyong Parkf1691d22021-03-29 20:11:58 +090036 // or from sdk_version if it is not set.
Spandan Dasca70fc42023-03-01 23:38:49 +000037 TargetSdkVersion(ctx EarlyModuleContext) ApiLevel
Jiyong Parkf1691d22021-03-29 20:11:58 +090038}
39
40// SdkKind represents a particular category of an SDK spec like public, system, test, etc.
41type SdkKind int
42
Jihoon Kang248cc002024-05-03 23:08:12 +000043// These are generally ordered from the narrower sdk version to the wider sdk version,
44// but not all entries have a strict subset/superset relationship.
45// For example, SdkTest and SdkModule do not have a strict subset/superset relationship but both
46// are supersets of SdkSystem.
47// The general trend should be kept when an additional sdk kind is added.
Jiyong Parkf1691d22021-03-29 20:11:58 +090048const (
49 SdkInvalid SdkKind = iota
50 SdkNone
Jihoon Kang248cc002024-05-03 23:08:12 +000051 SdkToolchain // API surface provided by ART to compile other API domains
Jiyong Parkf1691d22021-03-29 20:11:58 +090052 SdkCore
53 SdkCorePlatform
Spandan Das0b555e32022-11-28 18:48:51 +000054 SdkIntraCore // API surface provided by one core module to another
Jiyong Parkf1691d22021-03-29 20:11:58 +090055 SdkPublic
56 SdkSystem
57 SdkTest
Mark White9421c4c2023-08-10 00:07:03 +000058 SdkTestFrameworksCore
Jiyong Parkf1691d22021-03-29 20:11:58 +090059 SdkModule
60 SdkSystemServer
61 SdkPrivate
62)
63
64// String returns the string representation of this SdkKind
65func (k SdkKind) String() string {
66 switch k {
67 case SdkPrivate:
68 return "private"
69 case SdkNone:
70 return "none"
71 case SdkPublic:
72 return "public"
73 case SdkSystem:
74 return "system"
75 case SdkTest:
76 return "test"
Mark White9421c4c2023-08-10 00:07:03 +000077 case SdkTestFrameworksCore:
78 return "test_frameworks_core"
Jiyong Parkf1691d22021-03-29 20:11:58 +090079 case SdkCore:
80 return "core"
81 case SdkCorePlatform:
82 return "core_platform"
Spandan Das0b555e32022-11-28 18:48:51 +000083 case SdkIntraCore:
84 return "intracore"
Jiyong Parkf1691d22021-03-29 20:11:58 +090085 case SdkModule:
86 return "module-lib"
87 case SdkSystemServer:
88 return "system-server"
Spandan Das4ac2aed2022-12-28 01:54:29 +000089 case SdkToolchain:
90 return "toolchain"
Jiyong Parkf1691d22021-03-29 20:11:58 +090091 default:
92 return "invalid"
93 }
94}
95
Jihoon Kangfa3f0782024-08-21 20:42:18 +000096func ToSdkKind(s string) SdkKind {
97 for kind := SdkNone; kind <= SdkPrivate; kind++ {
98 if s == kind.String() {
99 return kind
100 }
101 }
102 return SdkInvalid
103}
104
Jihoon Kang5b065bb2023-04-05 21:08:08 +0000105func (k SdkKind) DefaultJavaLibraryName() string {
Spandan Das626a8ad2023-03-20 18:52:50 +0000106 switch k {
107 case SdkPublic:
108 return "android_stubs_current"
109 case SdkSystem:
110 return "android_system_stubs_current"
111 case SdkTest:
112 return "android_test_stubs_current"
Mark White9421c4c2023-08-10 00:07:03 +0000113 case SdkTestFrameworksCore:
114 return "android_test_frameworks_core_stubs_current"
Spandan Das626a8ad2023-03-20 18:52:50 +0000115 case SdkCore:
116 return "core.current.stubs"
117 case SdkModule:
118 return "android_module_lib_stubs_current"
119 case SdkSystemServer:
120 return "android_system_server_stubs_current"
121 default:
122 panic(fmt.Errorf("APIs of API surface %v cannot be provided by a single Soong module\n", k))
123 }
124}
125
Jihoon Kang1262e202025-02-07 22:46:09 +0000126func JavaLibraryNameToSdkKind(name string) (SdkKind, bool) {
127 if name == SdkPublic.DefaultJavaLibraryName() {
128 return SdkPublic, true
129 }
130 if name == SdkSystem.DefaultJavaLibraryName() {
131 return SdkSystem, true
132 }
133 if name == SdkTest.DefaultJavaLibraryName() {
134 return SdkTest, true
135 }
136 if name == SdkTestFrameworksCore.DefaultJavaLibraryName() {
137 return SdkTestFrameworksCore, true
138 }
139 if name == SdkCore.DefaultJavaLibraryName() {
140 return SdkCore, true
141 }
142 if name == SdkModule.DefaultJavaLibraryName() {
143 return SdkModule, true
144 }
145 if name == SdkSystemServer.DefaultJavaLibraryName() {
146 return SdkSystemServer, true
147 }
148 return SdkInvalid, false
149}
150
Jihoon Kangbd093452023-12-26 19:08:01 +0000151func (k SdkKind) DefaultExportableJavaLibraryName() string {
152 switch k {
153 case SdkPublic, SdkSystem, SdkTest, SdkModule, SdkSystemServer:
154 return k.DefaultJavaLibraryName() + "_exportable"
155 case SdkCore:
156 return k.DefaultJavaLibraryName() + ".exportable"
157 default:
158 panic(fmt.Errorf("API surface %v does not provide exportable stubs", k))
159 }
160}
161
Jiyong Parkf1691d22021-03-29 20:11:58 +0900162// SdkSpec represents the kind and the version of an SDK for a module to build against
163type SdkSpec struct {
Jiyong Park54105c42021-03-31 18:17:53 +0900164 Kind SdkKind
165 ApiLevel ApiLevel
166 Raw string
Jiyong Parkf1691d22021-03-29 20:11:58 +0900167}
168
169func (s SdkSpec) String() string {
Jiyong Park54105c42021-03-31 18:17:53 +0900170 return fmt.Sprintf("%s_%s", s.Kind, s.ApiLevel)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900171}
172
173// Valid checks if this SdkSpec is well-formed. Note however that true doesn't mean that the
174// specified SDK actually exists.
175func (s SdkSpec) Valid() bool {
176 return s.Kind != SdkInvalid
177}
178
179// Specified checks if this SdkSpec is well-formed and is not "".
180func (s SdkSpec) Specified() bool {
181 return s.Valid() && s.Kind != SdkPrivate
182}
183
184// whether the API surface is managed and versioned, i.e. has .txt file that
185// get frozen on SDK freeze and changes get reviewed by API council.
186func (s SdkSpec) Stable() bool {
187 if !s.Specified() {
188 return false
189 }
190 switch s.Kind {
191 case SdkNone:
192 // there is nothing to manage and version in this case; de facto stable API.
193 return true
194 case SdkCore, SdkPublic, SdkSystem, SdkModule, SdkSystemServer:
195 return true
Mark White9421c4c2023-08-10 00:07:03 +0000196 case SdkCorePlatform, SdkTest, SdkTestFrameworksCore, SdkPrivate:
Jiyong Parkf1691d22021-03-29 20:11:58 +0900197 return false
198 default:
199 panic(fmt.Errorf("unknown SdkKind=%v", s.Kind))
200 }
201 return false
202}
203
satayev0ee2f912021-12-01 17:39:48 +0000204// PrebuiltSdkAvailableForUnbundledBuild tells whether this SdkSpec can have a prebuilt SDK
Jiyong Parkf1691d22021-03-29 20:11:58 +0900205// that can be used for unbundled builds.
206func (s SdkSpec) PrebuiltSdkAvailableForUnbundledBuild() bool {
207 // "", "none", and "core_platform" are not available for unbundled build
208 // as we don't/can't have prebuilt stub for the versions
209 return s.Kind != SdkPrivate && s.Kind != SdkNone && s.Kind != SdkCorePlatform
210}
211
212func (s SdkSpec) ForVendorPartition(ctx EarlyModuleContext) SdkSpec {
213 // If BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES has a numeric value,
214 // use it instead of "current" for the vendor partition.
215 currentSdkVersion := ctx.DeviceConfig().CurrentApiLevelForVendorModules()
Jiyong Park7416d672024-01-04 23:20:42 +0000216 // b/314011075: special case for Java modules in vendor partition. They can no longer use
217 // SDK 35 or later. Their maximum API level is limited to 34 (Android U). This is to
218 // discourage the use of Java APIs in the vendor partition which hasn't been officially
219 // supported since the Project Treble back in Android 10. We would like to eventually
220 // evacuate all Java modules from the partition, but that shall be done progressively.
221 // Note that the check for the availability of SDK 34 is to not break existing tests where
222 // any of the frozen SDK version is unavailable.
223 if isJava(ctx.Module()) && isSdkVersion34AvailableIn(ctx.Config()) {
224 currentSdkVersion = "34"
225 }
226
Jiyong Parkf1691d22021-03-29 20:11:58 +0900227 if currentSdkVersion == "current" {
228 return s
229 }
230
231 if s.Kind == SdkPublic || s.Kind == SdkSystem {
Jiyong Park54105c42021-03-31 18:17:53 +0900232 if s.ApiLevel.IsCurrent() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900233 if i, err := strconv.Atoi(currentSdkVersion); err == nil {
Jiyong Park54105c42021-03-31 18:17:53 +0900234 apiLevel := uncheckedFinalApiLevel(i)
235 return SdkSpec{s.Kind, apiLevel, s.Raw}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900236 }
237 panic(fmt.Errorf("BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES must be either \"current\" or a number, but was %q", currentSdkVersion))
238 }
239 }
240 return s
241}
242
243// UsePrebuilt determines whether prebuilt SDK should be used for this SdkSpec with the given context.
244func (s SdkSpec) UsePrebuilt(ctx EarlyModuleContext) bool {
Jiyong Parkc7022042021-04-15 16:53:05 +0900245 switch s {
246 case SdkSpecNone, SdkSpecCorePlatform, SdkSpecPrivate:
247 return false
248 }
249
Jiyong Park54105c42021-03-31 18:17:53 +0900250 if s.ApiLevel.IsCurrent() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900251 // "current" can be built from source and be from prebuilt SDK
252 return ctx.Config().AlwaysUsePrebuiltSdks()
Jiyong Park54105c42021-03-31 18:17:53 +0900253 } else if !s.ApiLevel.IsPreview() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900254 // validation check
Mark White9421c4c2023-08-10 00:07:03 +0000255 if s.Kind != SdkPublic && s.Kind != SdkSystem && s.Kind != SdkTest &&
256 s.Kind != SdkTestFrameworksCore && s.Kind != SdkModule && s.Kind != SdkSystemServer {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900257 panic(fmt.Errorf("prebuilt SDK is not not available for SdkKind=%q", s.Kind))
258 return false
259 }
260 // numbered SDKs are always from prebuilt
261 return true
262 }
Jiyong Parkf1691d22021-03-29 20:11:58 +0900263 return false
264}
265
Jiyong Park54105c42021-03-31 18:17:53 +0900266// EffectiveVersion converts an SdkSpec into the concrete ApiLevel that the module should use. For
267// modules targeting an unreleased SDK (meaning it does not yet have a number) it returns
268// FutureApiLevel(10000).
269func (s SdkSpec) EffectiveVersion(ctx EarlyModuleContext) (ApiLevel, error) {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900270 if !s.Valid() {
Jiyong Park54105c42021-03-31 18:17:53 +0900271 return s.ApiLevel, fmt.Errorf("invalid sdk version %q", s.Raw)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900272 }
273
274 if ctx.DeviceSpecific() || ctx.SocSpecific() {
275 s = s.ForVendorPartition(ctx)
276 }
Spandan Dasdd7057c2023-01-05 01:03:47 +0000277 return s.ApiLevel.EffectiveVersion(ctx)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900278}
279
280// EffectiveVersionString converts an SdkSpec into the concrete version string that the module
281// should use. For modules targeting an unreleased SDK (meaning it does not yet have a number)
282// it returns the codename (P, Q, R, etc.)
283func (s SdkSpec) EffectiveVersionString(ctx EarlyModuleContext) (string, error) {
Jiyong Park54105c42021-03-31 18:17:53 +0900284 if !s.Valid() {
285 return s.ApiLevel.String(), fmt.Errorf("invalid sdk version %q", s.Raw)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900286 }
Jiyong Park54105c42021-03-31 18:17:53 +0900287
288 if ctx.DeviceSpecific() || ctx.SocSpecific() {
289 s = s.ForVendorPartition(ctx)
290 }
Spandan Dasdd7057c2023-01-05 01:03:47 +0000291 return s.ApiLevel.EffectiveVersionString(ctx)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900292}
293
Jiyong Park92315372021-04-02 08:45:46 +0900294var (
Jiyong Parkc7022042021-04-15 16:53:05 +0900295 SdkSpecNone = SdkSpec{SdkNone, NoneApiLevel, "(no version)"}
Spandan Das15da5882023-03-02 23:36:39 +0000296 SdkSpecPrivate = SdkSpec{SdkPrivate, PrivateApiLevel, ""}
Jiyong Parkc7022042021-04-15 16:53:05 +0900297 SdkSpecCorePlatform = SdkSpec{SdkCorePlatform, FutureApiLevel, "core_platform"}
Jiyong Park92315372021-04-02 08:45:46 +0900298)
299
300func SdkSpecFrom(ctx EarlyModuleContext, str string) SdkSpec {
satayev0ee2f912021-12-01 17:39:48 +0000301 return SdkSpecFromWithConfig(ctx.Config(), str)
302}
303
304func SdkSpecFromWithConfig(config Config, str string) SdkSpec {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900305 switch str {
306 // special cases first
307 case "":
Jiyong Park92315372021-04-02 08:45:46 +0900308 return SdkSpecPrivate
Jiyong Parkf1691d22021-03-29 20:11:58 +0900309 case "none":
Jiyong Park92315372021-04-02 08:45:46 +0900310 return SdkSpecNone
Jiyong Parkf1691d22021-03-29 20:11:58 +0900311 case "core_platform":
Jiyong Park92315372021-04-02 08:45:46 +0900312 return SdkSpecCorePlatform
Jiyong Parkf1691d22021-03-29 20:11:58 +0900313 default:
314 // the syntax is [kind_]version
315 sep := strings.LastIndex(str, "_")
316
317 var kindString string
318 if sep == 0 {
Spandan Das15da5882023-03-02 23:36:39 +0000319 return SdkSpec{SdkInvalid, NewInvalidApiLevel(str), str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900320 } else if sep == -1 {
321 kindString = ""
322 } else {
323 kindString = str[0:sep]
324 }
325 versionString := str[sep+1 : len(str)]
326
327 var kind SdkKind
328 switch kindString {
329 case "":
330 kind = SdkPublic
331 case "core":
332 kind = SdkCore
333 case "system":
334 kind = SdkSystem
335 case "test":
336 kind = SdkTest
Mark White9421c4c2023-08-10 00:07:03 +0000337 case "test_frameworks_core":
338 kind = SdkTestFrameworksCore
Jiyong Parkf1691d22021-03-29 20:11:58 +0900339 case "module":
340 kind = SdkModule
341 case "system_server":
342 kind = SdkSystemServer
343 default:
Jiyong Park54105c42021-03-31 18:17:53 +0900344 return SdkSpec{SdkInvalid, NoneApiLevel, str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900345 }
346
satayev0ee2f912021-12-01 17:39:48 +0000347 apiLevel, err := ApiLevelFromUserWithConfig(config, versionString)
Jiyong Park92315372021-04-02 08:45:46 +0900348 if err != nil {
Spandan Das15da5882023-03-02 23:36:39 +0000349 return SdkSpec{SdkInvalid, NewInvalidApiLevel(versionString), str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900350 }
Jiyong Park54105c42021-03-31 18:17:53 +0900351 return SdkSpec{kind, apiLevel, str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900352 }
353}
354
Jiyong Park7416d672024-01-04 23:20:42 +0000355// Checks if the use of this SDK `s` is valid for the given module context `ctx`.
Jiyong Parkf1691d22021-03-29 20:11:58 +0900356func (s SdkSpec) ValidateSystemSdk(ctx EarlyModuleContext) bool {
Jiyong Park7416d672024-01-04 23:20:42 +0000357 // Do some early checks. This check is currently only for Java modules. And our only concern
358 // is the use of "system" SDKs.
Jiyong Park3bb99242024-01-04 23:21:26 +0000359 if !isJava(ctx.Module()) || s.Kind != SdkSystem || ctx.DeviceConfig().BuildBrokenDontCheckSystemSdk() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900360 return true
361 }
Jiyong Park7416d672024-01-04 23:20:42 +0000362
363 inVendor := ctx.DeviceSpecific() || ctx.SocSpecific()
364 inProduct := ctx.ProductSpecific()
365 isProductUnbundled := ctx.Config().EnforceProductPartitionInterface()
366 inApex := false
367 if am, ok := ctx.Module().(ApexModule); ok {
368 inApex = am.InAnyApex()
369 }
370 isUnbundled := inVendor || (inProduct && isProductUnbundled) || inApex
371
372 // Bundled modules can use any SDK
373 if !isUnbundled {
374 return true
375 }
376
377 // Unbundled modules are allowed to use BOARD_SYSTEMSDK_VERSIONS
378 supportedVersions := ctx.DeviceConfig().SystemSdkVersions()
379
380 // b/314011075: special case for vendor modules. Java modules in the vendor partition can
381 // not use SDK 35 or later. This is to discourage the use of Java APIs in the vendor
382 // partition which hasn't been officially supported since the Project Treble back in Android
383 // 10. We would like to eventually evacuate all Java modules from the partition, but that
384 // shall be done progressively.
385 if inVendor {
386 // 28 was the API when BOARD_SYSTEMSDK_VERSIONS was introduced, so that's the oldest
387 // we should allow.
388 supportedVersions = []string{}
389 for v := 28; v <= 34; v++ {
390 supportedVersions = append(supportedVersions, strconv.Itoa(v))
Jiyong Parkf1691d22021-03-29 20:11:58 +0900391 }
392 }
Jiyong Park7416d672024-01-04 23:20:42 +0000393
394 // APEXes in the system partition are still considered as part of the platform, thus can use
395 // more SDKs from PLATFORM_SYSTEMSDK_VERSIONS
396 if inApex && !inVendor {
397 supportedVersions = ctx.DeviceConfig().PlatformSystemSdkVersions()
398 }
399
400 thisVer, err := s.EffectiveVersion(ctx)
401 if err != nil {
402 ctx.PropertyErrorf("sdk_version", "invalid sdk version %q", s.Raw)
403 return false
404 }
405
406 thisVerString := strconv.Itoa(thisVer.FinalOrPreviewInt())
407 if thisVer.IsPreview() {
408 thisVerString = *ctx.Config().productVariables.Platform_sdk_version_or_codename
409 }
410
411 if !InList(thisVerString, supportedVersions) {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900412 ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
Jiyong Park7416d672024-01-04 23:20:42 +0000413 s.Raw, supportedVersions)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900414 return false
415 }
416 return true
417}
Spandan Das6b73fcb2023-03-20 20:20:58 +0000418
Jiyong Park7416d672024-01-04 23:20:42 +0000419func isJava(m Module) bool {
420 moduleType := reflect.TypeOf(m).String()
421 return strings.HasPrefix(moduleType, "*java.")
422}
423
424func isSdkVersion34AvailableIn(c Config) bool {
425 return c.PlatformSdkVersion().FinalInt() >= 34
426}
427
Spandan Das6b73fcb2023-03-20 20:20:58 +0000428func init() {
429 RegisterMakeVarsProvider(pctx, javaSdkMakeVars)
430}
431
432// Export the name of the soong modules representing the various Java API surfaces.
433func javaSdkMakeVars(ctx MakeVarsContext) {
Jihoon Kang91c83952023-05-30 19:12:28 +0000434 ctx.Strict("ANDROID_PUBLIC_STUBS", SdkPublic.DefaultJavaLibraryName())
Jihoon Kang7cf2c0c2024-02-05 22:45:24 +0000435 ctx.Strict("ANDROID_PUBLIC_EXPORTABLE_STUBS", SdkPublic.DefaultExportableJavaLibraryName())
Jihoon Kang91c83952023-05-30 19:12:28 +0000436 ctx.Strict("ANDROID_SYSTEM_STUBS", SdkSystem.DefaultJavaLibraryName())
437 ctx.Strict("ANDROID_TEST_STUBS", SdkTest.DefaultJavaLibraryName())
438 ctx.Strict("ANDROID_MODULE_LIB_STUBS", SdkModule.DefaultJavaLibraryName())
439 ctx.Strict("ANDROID_SYSTEM_SERVER_STUBS", SdkSystemServer.DefaultJavaLibraryName())
440 ctx.Strict("ANDROID_CORE_STUBS", SdkCore.DefaultJavaLibraryName())
Spandan Das6b73fcb2023-03-20 20:20:58 +0000441}