blob: c188c4808e1a1e17a60ede00cc4347ae955ac084 [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
28 // MinSdkVersion returns SdkSpec that corresponds to the min_sdk_version property of the current module,
29 // or from sdk_version if it is not set.
Jiyong Park92315372021-04-02 08:45:46 +090030 MinSdkVersion(ctx EarlyModuleContext) SdkSpec
William Loh5a082f92022-05-17 20:21:50 +000031 // ReplaceMaxSdkVersionPlaceholder returns SdkSpec to replace the maxSdkVersion property of permission and
32 // uses-permission tags if it is set.
33 ReplaceMaxSdkVersionPlaceholder(ctx EarlyModuleContext) SdkSpec
Jiyong Parkf1691d22021-03-29 20:11:58 +090034 // TargetSdkVersion returns the SdkSpec that corresponds to the target_sdk_version property of the current module,
35 // or from sdk_version if it is not set.
Jiyong Park92315372021-04-02 08:45:46 +090036 TargetSdkVersion(ctx EarlyModuleContext) SdkSpec
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
47 SdkPublic
48 SdkSystem
49 SdkTest
50 SdkModule
51 SdkSystemServer
52 SdkPrivate
53)
54
55// String returns the string representation of this SdkKind
56func (k SdkKind) String() string {
57 switch k {
58 case SdkPrivate:
59 return "private"
60 case SdkNone:
61 return "none"
62 case SdkPublic:
63 return "public"
64 case SdkSystem:
65 return "system"
66 case SdkTest:
67 return "test"
68 case SdkCore:
69 return "core"
70 case SdkCorePlatform:
71 return "core_platform"
72 case SdkModule:
73 return "module-lib"
74 case SdkSystemServer:
75 return "system-server"
76 default:
77 return "invalid"
78 }
79}
80
Jiyong Parkf1691d22021-03-29 20:11:58 +090081// SdkSpec represents the kind and the version of an SDK for a module to build against
82type SdkSpec struct {
Jiyong Park54105c42021-03-31 18:17:53 +090083 Kind SdkKind
84 ApiLevel ApiLevel
85 Raw string
Jiyong Parkf1691d22021-03-29 20:11:58 +090086}
87
88func (s SdkSpec) String() string {
Jiyong Park54105c42021-03-31 18:17:53 +090089 return fmt.Sprintf("%s_%s", s.Kind, s.ApiLevel)
Jiyong Parkf1691d22021-03-29 20:11:58 +090090}
91
92// Valid checks if this SdkSpec is well-formed. Note however that true doesn't mean that the
93// specified SDK actually exists.
94func (s SdkSpec) Valid() bool {
95 return s.Kind != SdkInvalid
96}
97
98// Specified checks if this SdkSpec is well-formed and is not "".
99func (s SdkSpec) Specified() bool {
100 return s.Valid() && s.Kind != SdkPrivate
101}
102
103// whether the API surface is managed and versioned, i.e. has .txt file that
104// get frozen on SDK freeze and changes get reviewed by API council.
105func (s SdkSpec) Stable() bool {
106 if !s.Specified() {
107 return false
108 }
109 switch s.Kind {
110 case SdkNone:
111 // there is nothing to manage and version in this case; de facto stable API.
112 return true
113 case SdkCore, SdkPublic, SdkSystem, SdkModule, SdkSystemServer:
114 return true
115 case SdkCorePlatform, SdkTest, SdkPrivate:
116 return false
117 default:
118 panic(fmt.Errorf("unknown SdkKind=%v", s.Kind))
119 }
120 return false
121}
122
satayev0ee2f912021-12-01 17:39:48 +0000123// PrebuiltSdkAvailableForUnbundledBuild tells whether this SdkSpec can have a prebuilt SDK
Jiyong Parkf1691d22021-03-29 20:11:58 +0900124// that can be used for unbundled builds.
125func (s SdkSpec) PrebuiltSdkAvailableForUnbundledBuild() bool {
126 // "", "none", and "core_platform" are not available for unbundled build
127 // as we don't/can't have prebuilt stub for the versions
128 return s.Kind != SdkPrivate && s.Kind != SdkNone && s.Kind != SdkCorePlatform
129}
130
131func (s SdkSpec) ForVendorPartition(ctx EarlyModuleContext) SdkSpec {
132 // If BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES has a numeric value,
133 // use it instead of "current" for the vendor partition.
134 currentSdkVersion := ctx.DeviceConfig().CurrentApiLevelForVendorModules()
135 if currentSdkVersion == "current" {
136 return s
137 }
138
139 if s.Kind == SdkPublic || s.Kind == SdkSystem {
Jiyong Park54105c42021-03-31 18:17:53 +0900140 if s.ApiLevel.IsCurrent() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900141 if i, err := strconv.Atoi(currentSdkVersion); err == nil {
Jiyong Park54105c42021-03-31 18:17:53 +0900142 apiLevel := uncheckedFinalApiLevel(i)
143 return SdkSpec{s.Kind, apiLevel, s.Raw}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900144 }
145 panic(fmt.Errorf("BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES must be either \"current\" or a number, but was %q", currentSdkVersion))
146 }
147 }
148 return s
149}
150
151// UsePrebuilt determines whether prebuilt SDK should be used for this SdkSpec with the given context.
152func (s SdkSpec) UsePrebuilt(ctx EarlyModuleContext) bool {
Jiyong Parkc7022042021-04-15 16:53:05 +0900153 switch s {
154 case SdkSpecNone, SdkSpecCorePlatform, SdkSpecPrivate:
155 return false
156 }
157
Jiyong Park54105c42021-03-31 18:17:53 +0900158 if s.ApiLevel.IsCurrent() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900159 // "current" can be built from source and be from prebuilt SDK
160 return ctx.Config().AlwaysUsePrebuiltSdks()
Jiyong Park54105c42021-03-31 18:17:53 +0900161 } else if !s.ApiLevel.IsPreview() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900162 // validation check
Paul Duffin12e311d2021-10-28 17:42:16 +0100163 if s.Kind != SdkPublic && s.Kind != SdkSystem && s.Kind != SdkTest && s.Kind != SdkModule && s.Kind != SdkSystemServer {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900164 panic(fmt.Errorf("prebuilt SDK is not not available for SdkKind=%q", s.Kind))
165 return false
166 }
167 // numbered SDKs are always from prebuilt
168 return true
169 }
Jiyong Parkf1691d22021-03-29 20:11:58 +0900170 return false
171}
172
Jiyong Park54105c42021-03-31 18:17:53 +0900173// EffectiveVersion converts an SdkSpec into the concrete ApiLevel that the module should use. For
174// modules targeting an unreleased SDK (meaning it does not yet have a number) it returns
175// FutureApiLevel(10000).
176func (s SdkSpec) EffectiveVersion(ctx EarlyModuleContext) (ApiLevel, error) {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900177 if !s.Valid() {
Jiyong Park54105c42021-03-31 18:17:53 +0900178 return s.ApiLevel, fmt.Errorf("invalid sdk version %q", s.Raw)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900179 }
180
181 if ctx.DeviceSpecific() || ctx.SocSpecific() {
182 s = s.ForVendorPartition(ctx)
183 }
Jiyong Park54105c42021-03-31 18:17:53 +0900184 if !s.ApiLevel.IsPreview() {
185 return s.ApiLevel, nil
Jiyong Parkf1691d22021-03-29 20:11:58 +0900186 }
Jiyong Park54105c42021-03-31 18:17:53 +0900187 ret := ctx.Config().DefaultAppTargetSdk(ctx)
188 if ret.IsPreview() {
189 return FutureApiLevel, nil
190 }
191 return ret, nil
Jiyong Parkf1691d22021-03-29 20:11:58 +0900192}
193
194// EffectiveVersionString converts an SdkSpec into the concrete version string that the module
195// should use. For modules targeting an unreleased SDK (meaning it does not yet have a number)
196// it returns the codename (P, Q, R, etc.)
197func (s SdkSpec) EffectiveVersionString(ctx EarlyModuleContext) (string, error) {
Jiyong Park54105c42021-03-31 18:17:53 +0900198 if !s.Valid() {
199 return s.ApiLevel.String(), fmt.Errorf("invalid sdk version %q", s.Raw)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900200 }
Jiyong Park54105c42021-03-31 18:17:53 +0900201
202 if ctx.DeviceSpecific() || ctx.SocSpecific() {
203 s = s.ForVendorPartition(ctx)
204 }
205 if !s.ApiLevel.IsPreview() {
206 return s.ApiLevel.String(), nil
207 }
208 return ctx.Config().DefaultAppTargetSdk(ctx).String(), nil
Jiyong Parkf1691d22021-03-29 20:11:58 +0900209}
210
Jiyong Park92315372021-04-02 08:45:46 +0900211var (
Jiyong Parkc7022042021-04-15 16:53:05 +0900212 SdkSpecNone = SdkSpec{SdkNone, NoneApiLevel, "(no version)"}
213 SdkSpecPrivate = SdkSpec{SdkPrivate, FutureApiLevel, ""}
214 SdkSpecCorePlatform = SdkSpec{SdkCorePlatform, FutureApiLevel, "core_platform"}
Jiyong Park92315372021-04-02 08:45:46 +0900215)
216
217func SdkSpecFrom(ctx EarlyModuleContext, str string) SdkSpec {
satayev0ee2f912021-12-01 17:39:48 +0000218 return SdkSpecFromWithConfig(ctx.Config(), str)
219}
220
221func SdkSpecFromWithConfig(config Config, str string) SdkSpec {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900222 switch str {
223 // special cases first
224 case "":
Jiyong Park92315372021-04-02 08:45:46 +0900225 return SdkSpecPrivate
Jiyong Parkf1691d22021-03-29 20:11:58 +0900226 case "none":
Jiyong Park92315372021-04-02 08:45:46 +0900227 return SdkSpecNone
Jiyong Parkf1691d22021-03-29 20:11:58 +0900228 case "core_platform":
Jiyong Park92315372021-04-02 08:45:46 +0900229 return SdkSpecCorePlatform
Jiyong Parkf1691d22021-03-29 20:11:58 +0900230 default:
231 // the syntax is [kind_]version
232 sep := strings.LastIndex(str, "_")
233
234 var kindString string
235 if sep == 0 {
Jiyong Park54105c42021-03-31 18:17:53 +0900236 return SdkSpec{SdkInvalid, NoneApiLevel, str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900237 } else if sep == -1 {
238 kindString = ""
239 } else {
240 kindString = str[0:sep]
241 }
242 versionString := str[sep+1 : len(str)]
243
244 var kind SdkKind
245 switch kindString {
246 case "":
247 kind = SdkPublic
248 case "core":
249 kind = SdkCore
250 case "system":
251 kind = SdkSystem
252 case "test":
253 kind = SdkTest
254 case "module":
255 kind = SdkModule
256 case "system_server":
257 kind = SdkSystemServer
258 default:
Jiyong Park54105c42021-03-31 18:17:53 +0900259 return SdkSpec{SdkInvalid, NoneApiLevel, str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900260 }
261
satayev0ee2f912021-12-01 17:39:48 +0000262 apiLevel, err := ApiLevelFromUserWithConfig(config, versionString)
Jiyong Park92315372021-04-02 08:45:46 +0900263 if err != nil {
Jiyong Park54105c42021-03-31 18:17:53 +0900264 return SdkSpec{SdkInvalid, apiLevel, str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900265 }
Jiyong Park54105c42021-03-31 18:17:53 +0900266 return SdkSpec{kind, apiLevel, str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900267 }
268}
269
270func (s SdkSpec) ValidateSystemSdk(ctx EarlyModuleContext) bool {
271 // Ensures that the specified system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor/product Java module)
272 // Assuming that BOARD_SYSTEMSDK_VERSIONS := 28 29,
273 // 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 +0900274 if s.Kind != SdkSystem || s.ApiLevel.IsPreview() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900275 return true
276 }
277 allowedVersions := ctx.DeviceConfig().PlatformSystemSdkVersions()
278 if ctx.DeviceSpecific() || ctx.SocSpecific() || (ctx.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
279 systemSdkVersions := ctx.DeviceConfig().SystemSdkVersions()
280 if len(systemSdkVersions) > 0 {
281 allowedVersions = systemSdkVersions
282 }
283 }
Jiyong Park54105c42021-03-31 18:17:53 +0900284 if len(allowedVersions) > 0 && !InList(s.ApiLevel.String(), allowedVersions) {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900285 ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
286 s.Raw, allowedVersions)
287 return false
288 }
289 return true
290}