blob: 08762eff2ad4348807812a3f6c30f725558bd61c [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
51 SdkModule
52 SdkSystemServer
53 SdkPrivate
Spandan Das4ac2aed2022-12-28 01:54:29 +000054 SdkToolchain // API surface provided by ART to compile other API domains
Jiyong Parkf1691d22021-03-29 20:11:58 +090055)
56
57// String returns the string representation of this SdkKind
58func (k SdkKind) String() string {
59 switch k {
60 case SdkPrivate:
61 return "private"
62 case SdkNone:
63 return "none"
64 case SdkPublic:
65 return "public"
66 case SdkSystem:
67 return "system"
68 case SdkTest:
69 return "test"
70 case SdkCore:
71 return "core"
72 case SdkCorePlatform:
73 return "core_platform"
Spandan Das0b555e32022-11-28 18:48:51 +000074 case SdkIntraCore:
75 return "intracore"
Jiyong Parkf1691d22021-03-29 20:11:58 +090076 case SdkModule:
77 return "module-lib"
78 case SdkSystemServer:
79 return "system-server"
Spandan Das4ac2aed2022-12-28 01:54:29 +000080 case SdkToolchain:
81 return "toolchain"
Jiyong Parkf1691d22021-03-29 20:11:58 +090082 default:
83 return "invalid"
84 }
85}
86
Spandan Das626a8ad2023-03-20 18:52:50 +000087// JavaLibraryName returns the soong module containing the Java APIs of that API surface.
88func (k SdkKind) JavaLibraryName(c Config) string {
Jihoon Kang5b065bb2023-04-05 21:08:08 +000089 name := k.DefaultJavaLibraryName()
Spandan Das69f42182023-03-29 16:25:16 +000090 return JavaApiLibraryName(c, name)
Spandan Das626a8ad2023-03-20 18:52:50 +000091}
92
Spandan Das69f42182023-03-29 16:25:16 +000093// JavaApiLibraryName returns the name of .txt equivalent of a java_library, but does
Spandan Das626a8ad2023-03-20 18:52:50 +000094// not check if either module exists.
95// TODO: Return .txt (single-tree or multi-tree equivalents) based on config
Spandan Das69f42182023-03-29 16:25:16 +000096func JavaApiLibraryName(c Config, name string) string {
Jihoon Kang1bff0342023-01-17 20:40:22 +000097 if c.BuildFromTextStub() {
98 return name + ".from-text"
99 }
Spandan Das626a8ad2023-03-20 18:52:50 +0000100 return name
101}
102
Jihoon Kangb5078312023-03-29 23:25:49 +0000103// JavaApiLibraryNames applies JavaApiLibraryName to the list of java_library names.
104func JavaApiLibraryNames(c Config, names []string) []string {
105 apiLibs := make([]string, len(names))
106 for i, name := range names {
107 apiLibs[i] = JavaApiLibraryName(c, name)
108 }
109 return apiLibs
110}
111
Jihoon Kang5b065bb2023-04-05 21:08:08 +0000112func (k SdkKind) DefaultJavaLibraryName() string {
Spandan Das626a8ad2023-03-20 18:52:50 +0000113 switch k {
114 case SdkPublic:
115 return "android_stubs_current"
116 case SdkSystem:
117 return "android_system_stubs_current"
118 case SdkTest:
119 return "android_test_stubs_current"
120 case SdkCore:
121 return "core.current.stubs"
122 case SdkModule:
123 return "android_module_lib_stubs_current"
124 case SdkSystemServer:
125 return "android_system_server_stubs_current"
126 default:
127 panic(fmt.Errorf("APIs of API surface %v cannot be provided by a single Soong module\n", k))
128 }
129}
130
Jiyong Parkf1691d22021-03-29 20:11:58 +0900131// SdkSpec represents the kind and the version of an SDK for a module to build against
132type SdkSpec struct {
Jiyong Park54105c42021-03-31 18:17:53 +0900133 Kind SdkKind
134 ApiLevel ApiLevel
135 Raw string
Jiyong Parkf1691d22021-03-29 20:11:58 +0900136}
137
138func (s SdkSpec) String() string {
Jiyong Park54105c42021-03-31 18:17:53 +0900139 return fmt.Sprintf("%s_%s", s.Kind, s.ApiLevel)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900140}
141
142// Valid checks if this SdkSpec is well-formed. Note however that true doesn't mean that the
143// specified SDK actually exists.
144func (s SdkSpec) Valid() bool {
145 return s.Kind != SdkInvalid
146}
147
148// Specified checks if this SdkSpec is well-formed and is not "".
149func (s SdkSpec) Specified() bool {
150 return s.Valid() && s.Kind != SdkPrivate
151}
152
153// whether the API surface is managed and versioned, i.e. has .txt file that
154// get frozen on SDK freeze and changes get reviewed by API council.
155func (s SdkSpec) Stable() bool {
156 if !s.Specified() {
157 return false
158 }
159 switch s.Kind {
160 case SdkNone:
161 // there is nothing to manage and version in this case; de facto stable API.
162 return true
163 case SdkCore, SdkPublic, SdkSystem, SdkModule, SdkSystemServer:
164 return true
165 case SdkCorePlatform, SdkTest, SdkPrivate:
166 return false
167 default:
168 panic(fmt.Errorf("unknown SdkKind=%v", s.Kind))
169 }
170 return false
171}
172
satayev0ee2f912021-12-01 17:39:48 +0000173// PrebuiltSdkAvailableForUnbundledBuild tells whether this SdkSpec can have a prebuilt SDK
Jiyong Parkf1691d22021-03-29 20:11:58 +0900174// that can be used for unbundled builds.
175func (s SdkSpec) PrebuiltSdkAvailableForUnbundledBuild() bool {
176 // "", "none", and "core_platform" are not available for unbundled build
177 // as we don't/can't have prebuilt stub for the versions
178 return s.Kind != SdkPrivate && s.Kind != SdkNone && s.Kind != SdkCorePlatform
179}
180
181func (s SdkSpec) ForVendorPartition(ctx EarlyModuleContext) SdkSpec {
182 // If BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES has a numeric value,
183 // use it instead of "current" for the vendor partition.
184 currentSdkVersion := ctx.DeviceConfig().CurrentApiLevelForVendorModules()
185 if currentSdkVersion == "current" {
186 return s
187 }
188
189 if s.Kind == SdkPublic || s.Kind == SdkSystem {
Jiyong Park54105c42021-03-31 18:17:53 +0900190 if s.ApiLevel.IsCurrent() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900191 if i, err := strconv.Atoi(currentSdkVersion); err == nil {
Jiyong Park54105c42021-03-31 18:17:53 +0900192 apiLevel := uncheckedFinalApiLevel(i)
193 return SdkSpec{s.Kind, apiLevel, s.Raw}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900194 }
195 panic(fmt.Errorf("BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES must be either \"current\" or a number, but was %q", currentSdkVersion))
196 }
197 }
198 return s
199}
200
201// UsePrebuilt determines whether prebuilt SDK should be used for this SdkSpec with the given context.
202func (s SdkSpec) UsePrebuilt(ctx EarlyModuleContext) bool {
Jiyong Parkc7022042021-04-15 16:53:05 +0900203 switch s {
204 case SdkSpecNone, SdkSpecCorePlatform, SdkSpecPrivate:
205 return false
206 }
207
Jiyong Park54105c42021-03-31 18:17:53 +0900208 if s.ApiLevel.IsCurrent() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900209 // "current" can be built from source and be from prebuilt SDK
210 return ctx.Config().AlwaysUsePrebuiltSdks()
Jiyong Park54105c42021-03-31 18:17:53 +0900211 } else if !s.ApiLevel.IsPreview() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900212 // validation check
Paul Duffin12e311d2021-10-28 17:42:16 +0100213 if s.Kind != SdkPublic && s.Kind != SdkSystem && s.Kind != SdkTest && s.Kind != SdkModule && s.Kind != SdkSystemServer {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900214 panic(fmt.Errorf("prebuilt SDK is not not available for SdkKind=%q", s.Kind))
215 return false
216 }
217 // numbered SDKs are always from prebuilt
218 return true
219 }
Jiyong Parkf1691d22021-03-29 20:11:58 +0900220 return false
221}
222
Jiyong Park54105c42021-03-31 18:17:53 +0900223// EffectiveVersion converts an SdkSpec into the concrete ApiLevel that the module should use. For
224// modules targeting an unreleased SDK (meaning it does not yet have a number) it returns
225// FutureApiLevel(10000).
226func (s SdkSpec) EffectiveVersion(ctx EarlyModuleContext) (ApiLevel, error) {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900227 if !s.Valid() {
Jiyong Park54105c42021-03-31 18:17:53 +0900228 return s.ApiLevel, fmt.Errorf("invalid sdk version %q", s.Raw)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900229 }
230
231 if ctx.DeviceSpecific() || ctx.SocSpecific() {
232 s = s.ForVendorPartition(ctx)
233 }
Spandan Dasdd7057c2023-01-05 01:03:47 +0000234 return s.ApiLevel.EffectiveVersion(ctx)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900235}
236
237// EffectiveVersionString converts an SdkSpec into the concrete version string that the module
238// should use. For modules targeting an unreleased SDK (meaning it does not yet have a number)
239// it returns the codename (P, Q, R, etc.)
240func (s SdkSpec) EffectiveVersionString(ctx EarlyModuleContext) (string, error) {
Jiyong Park54105c42021-03-31 18:17:53 +0900241 if !s.Valid() {
242 return s.ApiLevel.String(), fmt.Errorf("invalid sdk version %q", s.Raw)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900243 }
Jiyong Park54105c42021-03-31 18:17:53 +0900244
245 if ctx.DeviceSpecific() || ctx.SocSpecific() {
246 s = s.ForVendorPartition(ctx)
247 }
Spandan Dasdd7057c2023-01-05 01:03:47 +0000248 return s.ApiLevel.EffectiveVersionString(ctx)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900249}
250
Jiyong Park92315372021-04-02 08:45:46 +0900251var (
Jiyong Parkc7022042021-04-15 16:53:05 +0900252 SdkSpecNone = SdkSpec{SdkNone, NoneApiLevel, "(no version)"}
Spandan Das15da5882023-03-02 23:36:39 +0000253 SdkSpecPrivate = SdkSpec{SdkPrivate, PrivateApiLevel, ""}
Jiyong Parkc7022042021-04-15 16:53:05 +0900254 SdkSpecCorePlatform = SdkSpec{SdkCorePlatform, FutureApiLevel, "core_platform"}
Jiyong Park92315372021-04-02 08:45:46 +0900255)
256
257func SdkSpecFrom(ctx EarlyModuleContext, str string) SdkSpec {
satayev0ee2f912021-12-01 17:39:48 +0000258 return SdkSpecFromWithConfig(ctx.Config(), str)
259}
260
261func SdkSpecFromWithConfig(config Config, str string) SdkSpec {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900262 switch str {
263 // special cases first
264 case "":
Jiyong Park92315372021-04-02 08:45:46 +0900265 return SdkSpecPrivate
Jiyong Parkf1691d22021-03-29 20:11:58 +0900266 case "none":
Jiyong Park92315372021-04-02 08:45:46 +0900267 return SdkSpecNone
Jiyong Parkf1691d22021-03-29 20:11:58 +0900268 case "core_platform":
Jiyong Park92315372021-04-02 08:45:46 +0900269 return SdkSpecCorePlatform
Jiyong Parkf1691d22021-03-29 20:11:58 +0900270 default:
271 // the syntax is [kind_]version
272 sep := strings.LastIndex(str, "_")
273
274 var kindString string
275 if sep == 0 {
Spandan Das15da5882023-03-02 23:36:39 +0000276 return SdkSpec{SdkInvalid, NewInvalidApiLevel(str), str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900277 } else if sep == -1 {
278 kindString = ""
279 } else {
280 kindString = str[0:sep]
281 }
282 versionString := str[sep+1 : len(str)]
283
284 var kind SdkKind
285 switch kindString {
286 case "":
287 kind = SdkPublic
288 case "core":
289 kind = SdkCore
290 case "system":
291 kind = SdkSystem
292 case "test":
293 kind = SdkTest
294 case "module":
295 kind = SdkModule
296 case "system_server":
297 kind = SdkSystemServer
298 default:
Jiyong Park54105c42021-03-31 18:17:53 +0900299 return SdkSpec{SdkInvalid, NoneApiLevel, str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900300 }
301
satayev0ee2f912021-12-01 17:39:48 +0000302 apiLevel, err := ApiLevelFromUserWithConfig(config, versionString)
Jiyong Park92315372021-04-02 08:45:46 +0900303 if err != nil {
Spandan Das15da5882023-03-02 23:36:39 +0000304 return SdkSpec{SdkInvalid, NewInvalidApiLevel(versionString), str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900305 }
Jiyong Park54105c42021-03-31 18:17:53 +0900306 return SdkSpec{kind, apiLevel, str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900307 }
308}
309
310func (s SdkSpec) ValidateSystemSdk(ctx EarlyModuleContext) bool {
311 // Ensures that the specified system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor/product Java module)
312 // Assuming that BOARD_SYSTEMSDK_VERSIONS := 28 29,
313 // sdk_version of the modules in vendor/product that use system sdk must be either system_28, system_29 or system_current
Jiyong Park54105c42021-03-31 18:17:53 +0900314 if s.Kind != SdkSystem || s.ApiLevel.IsPreview() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900315 return true
316 }
317 allowedVersions := ctx.DeviceConfig().PlatformSystemSdkVersions()
318 if ctx.DeviceSpecific() || ctx.SocSpecific() || (ctx.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
319 systemSdkVersions := ctx.DeviceConfig().SystemSdkVersions()
320 if len(systemSdkVersions) > 0 {
321 allowedVersions = systemSdkVersions
322 }
323 }
Jiyong Park54105c42021-03-31 18:17:53 +0900324 if len(allowedVersions) > 0 && !InList(s.ApiLevel.String(), allowedVersions) {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900325 ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
326 s.Raw, allowedVersions)
327 return false
328 }
329 return true
330}
Spandan Das6b73fcb2023-03-20 20:20:58 +0000331
332func init() {
333 RegisterMakeVarsProvider(pctx, javaSdkMakeVars)
334}
335
336// Export the name of the soong modules representing the various Java API surfaces.
337func javaSdkMakeVars(ctx MakeVarsContext) {
338 ctx.Strict("ANDROID_PUBLIC_STUBS", SdkPublic.JavaLibraryName(ctx.Config()))
339 ctx.Strict("ANDROID_SYSTEM_STUBS", SdkSystem.JavaLibraryName(ctx.Config()))
340 ctx.Strict("ANDROID_TEST_STUBS", SdkTest.JavaLibraryName(ctx.Config()))
341 ctx.Strict("ANDROID_MODULE_LIB_STUBS", SdkModule.JavaLibraryName(ctx.Config()))
342 ctx.Strict("ANDROID_SYSTEM_SERVER_STUBS", SdkSystemServer.JavaLibraryName(ctx.Config()))
343 // TODO (jihoonkang): Create a .txt equivalent for core.current.stubs
344 ctx.Strict("ANDROID_CORE_STUBS", SdkCore.JavaLibraryName(ctx.Config()))
345}