blob: 73568af8a40fa99b5fd507c0a33f7ead96ed222b [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
43const (
44 SdkInvalid SdkKind = iota
45 SdkNone
46 SdkCore
47 SdkCorePlatform
Spandan Das0b555e32022-11-28 18:48:51 +000048 SdkIntraCore // API surface provided by one core module to another
Jiyong Parkf1691d22021-03-29 20:11:58 +090049 SdkPublic
50 SdkSystem
51 SdkTest
Mark White9421c4c2023-08-10 00:07:03 +000052 SdkTestFrameworksCore
Jiyong Parkf1691d22021-03-29 20:11:58 +090053 SdkModule
54 SdkSystemServer
55 SdkPrivate
Spandan Das4ac2aed2022-12-28 01:54:29 +000056 SdkToolchain // API surface provided by ART to compile other API domains
Jiyong Parkf1691d22021-03-29 20:11:58 +090057)
58
59// String returns the string representation of this SdkKind
60func (k SdkKind) String() string {
61 switch k {
62 case SdkPrivate:
63 return "private"
64 case SdkNone:
65 return "none"
66 case SdkPublic:
67 return "public"
68 case SdkSystem:
69 return "system"
70 case SdkTest:
71 return "test"
Mark White9421c4c2023-08-10 00:07:03 +000072 case SdkTestFrameworksCore:
73 return "test_frameworks_core"
Jiyong Parkf1691d22021-03-29 20:11:58 +090074 case SdkCore:
75 return "core"
76 case SdkCorePlatform:
77 return "core_platform"
Spandan Das0b555e32022-11-28 18:48:51 +000078 case SdkIntraCore:
79 return "intracore"
Jiyong Parkf1691d22021-03-29 20:11:58 +090080 case SdkModule:
81 return "module-lib"
82 case SdkSystemServer:
83 return "system-server"
Spandan Das4ac2aed2022-12-28 01:54:29 +000084 case SdkToolchain:
85 return "toolchain"
Jiyong Parkf1691d22021-03-29 20:11:58 +090086 default:
87 return "invalid"
88 }
89}
90
Jihoon Kang5b065bb2023-04-05 21:08:08 +000091func (k SdkKind) DefaultJavaLibraryName() string {
Spandan Das626a8ad2023-03-20 18:52:50 +000092 switch k {
93 case SdkPublic:
94 return "android_stubs_current"
95 case SdkSystem:
96 return "android_system_stubs_current"
97 case SdkTest:
98 return "android_test_stubs_current"
Mark White9421c4c2023-08-10 00:07:03 +000099 case SdkTestFrameworksCore:
100 return "android_test_frameworks_core_stubs_current"
Spandan Das626a8ad2023-03-20 18:52:50 +0000101 case SdkCore:
102 return "core.current.stubs"
103 case SdkModule:
104 return "android_module_lib_stubs_current"
105 case SdkSystemServer:
106 return "android_system_server_stubs_current"
107 default:
108 panic(fmt.Errorf("APIs of API surface %v cannot be provided by a single Soong module\n", k))
109 }
110}
111
Jiyong Parkf1691d22021-03-29 20:11:58 +0900112// SdkSpec represents the kind and the version of an SDK for a module to build against
113type SdkSpec struct {
Jiyong Park54105c42021-03-31 18:17:53 +0900114 Kind SdkKind
115 ApiLevel ApiLevel
116 Raw string
Jiyong Parkf1691d22021-03-29 20:11:58 +0900117}
118
119func (s SdkSpec) String() string {
Jiyong Park54105c42021-03-31 18:17:53 +0900120 return fmt.Sprintf("%s_%s", s.Kind, s.ApiLevel)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900121}
122
123// Valid checks if this SdkSpec is well-formed. Note however that true doesn't mean that the
124// specified SDK actually exists.
125func (s SdkSpec) Valid() bool {
126 return s.Kind != SdkInvalid
127}
128
129// Specified checks if this SdkSpec is well-formed and is not "".
130func (s SdkSpec) Specified() bool {
131 return s.Valid() && s.Kind != SdkPrivate
132}
133
134// whether the API surface is managed and versioned, i.e. has .txt file that
135// get frozen on SDK freeze and changes get reviewed by API council.
136func (s SdkSpec) Stable() bool {
137 if !s.Specified() {
138 return false
139 }
140 switch s.Kind {
141 case SdkNone:
142 // there is nothing to manage and version in this case; de facto stable API.
143 return true
144 case SdkCore, SdkPublic, SdkSystem, SdkModule, SdkSystemServer:
145 return true
Mark White9421c4c2023-08-10 00:07:03 +0000146 case SdkCorePlatform, SdkTest, SdkTestFrameworksCore, SdkPrivate:
Jiyong Parkf1691d22021-03-29 20:11:58 +0900147 return false
148 default:
149 panic(fmt.Errorf("unknown SdkKind=%v", s.Kind))
150 }
151 return false
152}
153
satayev0ee2f912021-12-01 17:39:48 +0000154// PrebuiltSdkAvailableForUnbundledBuild tells whether this SdkSpec can have a prebuilt SDK
Jiyong Parkf1691d22021-03-29 20:11:58 +0900155// that can be used for unbundled builds.
156func (s SdkSpec) PrebuiltSdkAvailableForUnbundledBuild() bool {
157 // "", "none", and "core_platform" are not available for unbundled build
158 // as we don't/can't have prebuilt stub for the versions
159 return s.Kind != SdkPrivate && s.Kind != SdkNone && s.Kind != SdkCorePlatform
160}
161
162func (s SdkSpec) ForVendorPartition(ctx EarlyModuleContext) SdkSpec {
163 // If BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES has a numeric value,
164 // use it instead of "current" for the vendor partition.
165 currentSdkVersion := ctx.DeviceConfig().CurrentApiLevelForVendorModules()
Jiyong Park7416d672024-01-04 23:20:42 +0000166 // b/314011075: special case for Java modules in vendor partition. They can no longer use
167 // SDK 35 or later. Their maximum API level is limited to 34 (Android U). This is to
168 // discourage the use of Java APIs in the vendor partition which hasn't been officially
169 // supported since the Project Treble back in Android 10. We would like to eventually
170 // evacuate all Java modules from the partition, but that shall be done progressively.
171 // Note that the check for the availability of SDK 34 is to not break existing tests where
172 // any of the frozen SDK version is unavailable.
173 if isJava(ctx.Module()) && isSdkVersion34AvailableIn(ctx.Config()) {
174 currentSdkVersion = "34"
175 }
176
Jiyong Parkf1691d22021-03-29 20:11:58 +0900177 if currentSdkVersion == "current" {
178 return s
179 }
180
181 if s.Kind == SdkPublic || s.Kind == SdkSystem {
Jiyong Park54105c42021-03-31 18:17:53 +0900182 if s.ApiLevel.IsCurrent() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900183 if i, err := strconv.Atoi(currentSdkVersion); err == nil {
Jiyong Park54105c42021-03-31 18:17:53 +0900184 apiLevel := uncheckedFinalApiLevel(i)
185 return SdkSpec{s.Kind, apiLevel, s.Raw}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900186 }
187 panic(fmt.Errorf("BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES must be either \"current\" or a number, but was %q", currentSdkVersion))
188 }
189 }
190 return s
191}
192
193// UsePrebuilt determines whether prebuilt SDK should be used for this SdkSpec with the given context.
194func (s SdkSpec) UsePrebuilt(ctx EarlyModuleContext) bool {
Jiyong Parkc7022042021-04-15 16:53:05 +0900195 switch s {
196 case SdkSpecNone, SdkSpecCorePlatform, SdkSpecPrivate:
197 return false
198 }
199
Jiyong Park54105c42021-03-31 18:17:53 +0900200 if s.ApiLevel.IsCurrent() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900201 // "current" can be built from source and be from prebuilt SDK
202 return ctx.Config().AlwaysUsePrebuiltSdks()
Jiyong Park54105c42021-03-31 18:17:53 +0900203 } else if !s.ApiLevel.IsPreview() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900204 // validation check
Mark White9421c4c2023-08-10 00:07:03 +0000205 if s.Kind != SdkPublic && s.Kind != SdkSystem && s.Kind != SdkTest &&
206 s.Kind != SdkTestFrameworksCore && s.Kind != SdkModule && s.Kind != SdkSystemServer {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900207 panic(fmt.Errorf("prebuilt SDK is not not available for SdkKind=%q", s.Kind))
208 return false
209 }
210 // numbered SDKs are always from prebuilt
211 return true
212 }
Jiyong Parkf1691d22021-03-29 20:11:58 +0900213 return false
214}
215
Jiyong Park54105c42021-03-31 18:17:53 +0900216// EffectiveVersion converts an SdkSpec into the concrete ApiLevel that the module should use. For
217// modules targeting an unreleased SDK (meaning it does not yet have a number) it returns
218// FutureApiLevel(10000).
219func (s SdkSpec) EffectiveVersion(ctx EarlyModuleContext) (ApiLevel, error) {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900220 if !s.Valid() {
Jiyong Park54105c42021-03-31 18:17:53 +0900221 return s.ApiLevel, fmt.Errorf("invalid sdk version %q", s.Raw)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900222 }
223
224 if ctx.DeviceSpecific() || ctx.SocSpecific() {
225 s = s.ForVendorPartition(ctx)
226 }
Spandan Dasdd7057c2023-01-05 01:03:47 +0000227 return s.ApiLevel.EffectiveVersion(ctx)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900228}
229
230// EffectiveVersionString converts an SdkSpec into the concrete version string that the module
231// should use. For modules targeting an unreleased SDK (meaning it does not yet have a number)
232// it returns the codename (P, Q, R, etc.)
233func (s SdkSpec) EffectiveVersionString(ctx EarlyModuleContext) (string, error) {
Jiyong Park54105c42021-03-31 18:17:53 +0900234 if !s.Valid() {
235 return s.ApiLevel.String(), fmt.Errorf("invalid sdk version %q", s.Raw)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900236 }
Jiyong Park54105c42021-03-31 18:17:53 +0900237
238 if ctx.DeviceSpecific() || ctx.SocSpecific() {
239 s = s.ForVendorPartition(ctx)
240 }
Spandan Dasdd7057c2023-01-05 01:03:47 +0000241 return s.ApiLevel.EffectiveVersionString(ctx)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900242}
243
Jiyong Park92315372021-04-02 08:45:46 +0900244var (
Jiyong Parkc7022042021-04-15 16:53:05 +0900245 SdkSpecNone = SdkSpec{SdkNone, NoneApiLevel, "(no version)"}
Spandan Das15da5882023-03-02 23:36:39 +0000246 SdkSpecPrivate = SdkSpec{SdkPrivate, PrivateApiLevel, ""}
Jiyong Parkc7022042021-04-15 16:53:05 +0900247 SdkSpecCorePlatform = SdkSpec{SdkCorePlatform, FutureApiLevel, "core_platform"}
Jiyong Park92315372021-04-02 08:45:46 +0900248)
249
250func SdkSpecFrom(ctx EarlyModuleContext, str string) SdkSpec {
satayev0ee2f912021-12-01 17:39:48 +0000251 return SdkSpecFromWithConfig(ctx.Config(), str)
252}
253
254func SdkSpecFromWithConfig(config Config, str string) SdkSpec {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900255 switch str {
256 // special cases first
257 case "":
Jiyong Park92315372021-04-02 08:45:46 +0900258 return SdkSpecPrivate
Jiyong Parkf1691d22021-03-29 20:11:58 +0900259 case "none":
Jiyong Park92315372021-04-02 08:45:46 +0900260 return SdkSpecNone
Jiyong Parkf1691d22021-03-29 20:11:58 +0900261 case "core_platform":
Jiyong Park92315372021-04-02 08:45:46 +0900262 return SdkSpecCorePlatform
Jiyong Parkf1691d22021-03-29 20:11:58 +0900263 default:
264 // the syntax is [kind_]version
265 sep := strings.LastIndex(str, "_")
266
267 var kindString string
268 if sep == 0 {
Spandan Das15da5882023-03-02 23:36:39 +0000269 return SdkSpec{SdkInvalid, NewInvalidApiLevel(str), str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900270 } else if sep == -1 {
271 kindString = ""
272 } else {
273 kindString = str[0:sep]
274 }
275 versionString := str[sep+1 : len(str)]
276
277 var kind SdkKind
278 switch kindString {
279 case "":
280 kind = SdkPublic
281 case "core":
282 kind = SdkCore
283 case "system":
284 kind = SdkSystem
285 case "test":
286 kind = SdkTest
Mark White9421c4c2023-08-10 00:07:03 +0000287 case "test_frameworks_core":
288 kind = SdkTestFrameworksCore
Jiyong Parkf1691d22021-03-29 20:11:58 +0900289 case "module":
290 kind = SdkModule
291 case "system_server":
292 kind = SdkSystemServer
293 default:
Jiyong Park54105c42021-03-31 18:17:53 +0900294 return SdkSpec{SdkInvalid, NoneApiLevel, str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900295 }
296
satayev0ee2f912021-12-01 17:39:48 +0000297 apiLevel, err := ApiLevelFromUserWithConfig(config, versionString)
Jiyong Park92315372021-04-02 08:45:46 +0900298 if err != nil {
Spandan Das15da5882023-03-02 23:36:39 +0000299 return SdkSpec{SdkInvalid, NewInvalidApiLevel(versionString), str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900300 }
Jiyong Park54105c42021-03-31 18:17:53 +0900301 return SdkSpec{kind, apiLevel, str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900302 }
303}
304
Jiyong Park7416d672024-01-04 23:20:42 +0000305// Checks if the use of this SDK `s` is valid for the given module context `ctx`.
Jiyong Parkf1691d22021-03-29 20:11:58 +0900306func (s SdkSpec) ValidateSystemSdk(ctx EarlyModuleContext) bool {
Jiyong Park7416d672024-01-04 23:20:42 +0000307 // Do some early checks. This check is currently only for Java modules. And our only concern
308 // is the use of "system" SDKs.
Jiyong Park3bb99242024-01-04 23:21:26 +0000309 if !isJava(ctx.Module()) || s.Kind != SdkSystem || ctx.DeviceConfig().BuildBrokenDontCheckSystemSdk() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900310 return true
311 }
Jiyong Park7416d672024-01-04 23:20:42 +0000312
313 inVendor := ctx.DeviceSpecific() || ctx.SocSpecific()
314 inProduct := ctx.ProductSpecific()
315 isProductUnbundled := ctx.Config().EnforceProductPartitionInterface()
316 inApex := false
317 if am, ok := ctx.Module().(ApexModule); ok {
318 inApex = am.InAnyApex()
319 }
320 isUnbundled := inVendor || (inProduct && isProductUnbundled) || inApex
321
322 // Bundled modules can use any SDK
323 if !isUnbundled {
324 return true
325 }
326
327 // Unbundled modules are allowed to use BOARD_SYSTEMSDK_VERSIONS
328 supportedVersions := ctx.DeviceConfig().SystemSdkVersions()
329
330 // b/314011075: special case for vendor modules. Java modules in the vendor partition can
331 // not use SDK 35 or later. This is to discourage the use of Java APIs in the vendor
332 // partition which hasn't been officially supported since the Project Treble back in Android
333 // 10. We would like to eventually evacuate all Java modules from the partition, but that
334 // shall be done progressively.
335 if inVendor {
336 // 28 was the API when BOARD_SYSTEMSDK_VERSIONS was introduced, so that's the oldest
337 // we should allow.
338 supportedVersions = []string{}
339 for v := 28; v <= 34; v++ {
340 supportedVersions = append(supportedVersions, strconv.Itoa(v))
Jiyong Parkf1691d22021-03-29 20:11:58 +0900341 }
342 }
Jiyong Park7416d672024-01-04 23:20:42 +0000343
344 // APEXes in the system partition are still considered as part of the platform, thus can use
345 // more SDKs from PLATFORM_SYSTEMSDK_VERSIONS
346 if inApex && !inVendor {
347 supportedVersions = ctx.DeviceConfig().PlatformSystemSdkVersions()
348 }
349
350 thisVer, err := s.EffectiveVersion(ctx)
351 if err != nil {
352 ctx.PropertyErrorf("sdk_version", "invalid sdk version %q", s.Raw)
353 return false
354 }
355
356 thisVerString := strconv.Itoa(thisVer.FinalOrPreviewInt())
357 if thisVer.IsPreview() {
358 thisVerString = *ctx.Config().productVariables.Platform_sdk_version_or_codename
359 }
360
361 if !InList(thisVerString, supportedVersions) {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900362 ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
Jiyong Park7416d672024-01-04 23:20:42 +0000363 s.Raw, supportedVersions)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900364 return false
365 }
366 return true
367}
Spandan Das6b73fcb2023-03-20 20:20:58 +0000368
Jiyong Park7416d672024-01-04 23:20:42 +0000369func isJava(m Module) bool {
370 moduleType := reflect.TypeOf(m).String()
371 return strings.HasPrefix(moduleType, "*java.")
372}
373
374func isSdkVersion34AvailableIn(c Config) bool {
375 return c.PlatformSdkVersion().FinalInt() >= 34
376}
377
Spandan Das6b73fcb2023-03-20 20:20:58 +0000378func init() {
379 RegisterMakeVarsProvider(pctx, javaSdkMakeVars)
380}
381
382// Export the name of the soong modules representing the various Java API surfaces.
383func javaSdkMakeVars(ctx MakeVarsContext) {
Jihoon Kang91c83952023-05-30 19:12:28 +0000384 ctx.Strict("ANDROID_PUBLIC_STUBS", SdkPublic.DefaultJavaLibraryName())
385 ctx.Strict("ANDROID_SYSTEM_STUBS", SdkSystem.DefaultJavaLibraryName())
386 ctx.Strict("ANDROID_TEST_STUBS", SdkTest.DefaultJavaLibraryName())
387 ctx.Strict("ANDROID_MODULE_LIB_STUBS", SdkModule.DefaultJavaLibraryName())
388 ctx.Strict("ANDROID_SYSTEM_SERVER_STUBS", SdkSystemServer.DefaultJavaLibraryName())
389 ctx.Strict("ANDROID_CORE_STUBS", SdkCore.DefaultJavaLibraryName())
Spandan Das6b73fcb2023-03-20 20:20:58 +0000390}