blob: 2004c9290a95553b71d0fb5ead2ea5ba2facf179 [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
Jiyong Parkf1691d22021-03-29 20:11:58 +090031 // TargetSdkVersion returns the SdkSpec that corresponds to the target_sdk_version property of the current module,
32 // or from sdk_version if it is not set.
Jiyong Park92315372021-04-02 08:45:46 +090033 TargetSdkVersion(ctx EarlyModuleContext) SdkSpec
Jiyong Parkf1691d22021-03-29 20:11:58 +090034}
35
36// SdkKind represents a particular category of an SDK spec like public, system, test, etc.
37type SdkKind int
38
39const (
40 SdkInvalid SdkKind = iota
41 SdkNone
42 SdkCore
43 SdkCorePlatform
44 SdkPublic
45 SdkSystem
46 SdkTest
47 SdkModule
48 SdkSystemServer
49 SdkPrivate
50)
51
52// String returns the string representation of this SdkKind
53func (k SdkKind) String() string {
54 switch k {
55 case SdkPrivate:
56 return "private"
57 case SdkNone:
58 return "none"
59 case SdkPublic:
60 return "public"
61 case SdkSystem:
62 return "system"
63 case SdkTest:
64 return "test"
65 case SdkCore:
66 return "core"
67 case SdkCorePlatform:
68 return "core_platform"
69 case SdkModule:
70 return "module-lib"
71 case SdkSystemServer:
72 return "system-server"
73 default:
74 return "invalid"
75 }
76}
77
Jiyong Parkf1691d22021-03-29 20:11:58 +090078// SdkSpec represents the kind and the version of an SDK for a module to build against
79type SdkSpec struct {
Jiyong Park54105c42021-03-31 18:17:53 +090080 Kind SdkKind
81 ApiLevel ApiLevel
82 Raw string
Jiyong Parkf1691d22021-03-29 20:11:58 +090083}
84
85func (s SdkSpec) String() string {
Jiyong Park54105c42021-03-31 18:17:53 +090086 return fmt.Sprintf("%s_%s", s.Kind, s.ApiLevel)
Jiyong Parkf1691d22021-03-29 20:11:58 +090087}
88
89// Valid checks if this SdkSpec is well-formed. Note however that true doesn't mean that the
90// specified SDK actually exists.
91func (s SdkSpec) Valid() bool {
92 return s.Kind != SdkInvalid
93}
94
95// Specified checks if this SdkSpec is well-formed and is not "".
96func (s SdkSpec) Specified() bool {
97 return s.Valid() && s.Kind != SdkPrivate
98}
99
100// whether the API surface is managed and versioned, i.e. has .txt file that
101// get frozen on SDK freeze and changes get reviewed by API council.
102func (s SdkSpec) Stable() bool {
103 if !s.Specified() {
104 return false
105 }
106 switch s.Kind {
107 case SdkNone:
108 // there is nothing to manage and version in this case; de facto stable API.
109 return true
110 case SdkCore, SdkPublic, SdkSystem, SdkModule, SdkSystemServer:
111 return true
112 case SdkCorePlatform, SdkTest, SdkPrivate:
113 return false
114 default:
115 panic(fmt.Errorf("unknown SdkKind=%v", s.Kind))
116 }
117 return false
118}
119
satayev0ee2f912021-12-01 17:39:48 +0000120// PrebuiltSdkAvailableForUnbundledBuild tells whether this SdkSpec can have a prebuilt SDK
Jiyong Parkf1691d22021-03-29 20:11:58 +0900121// that can be used for unbundled builds.
122func (s SdkSpec) PrebuiltSdkAvailableForUnbundledBuild() bool {
123 // "", "none", and "core_platform" are not available for unbundled build
124 // as we don't/can't have prebuilt stub for the versions
125 return s.Kind != SdkPrivate && s.Kind != SdkNone && s.Kind != SdkCorePlatform
126}
127
128func (s SdkSpec) ForVendorPartition(ctx EarlyModuleContext) SdkSpec {
129 // If BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES has a numeric value,
130 // use it instead of "current" for the vendor partition.
131 currentSdkVersion := ctx.DeviceConfig().CurrentApiLevelForVendorModules()
132 if currentSdkVersion == "current" {
133 return s
134 }
135
136 if s.Kind == SdkPublic || s.Kind == SdkSystem {
Jiyong Park54105c42021-03-31 18:17:53 +0900137 if s.ApiLevel.IsCurrent() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900138 if i, err := strconv.Atoi(currentSdkVersion); err == nil {
Jiyong Park54105c42021-03-31 18:17:53 +0900139 apiLevel := uncheckedFinalApiLevel(i)
140 return SdkSpec{s.Kind, apiLevel, s.Raw}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900141 }
142 panic(fmt.Errorf("BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES must be either \"current\" or a number, but was %q", currentSdkVersion))
143 }
144 }
145 return s
146}
147
148// UsePrebuilt determines whether prebuilt SDK should be used for this SdkSpec with the given context.
149func (s SdkSpec) UsePrebuilt(ctx EarlyModuleContext) bool {
Jiyong Parkc7022042021-04-15 16:53:05 +0900150 switch s {
151 case SdkSpecNone, SdkSpecCorePlatform, SdkSpecPrivate:
152 return false
153 }
154
Jiyong Park54105c42021-03-31 18:17:53 +0900155 if s.ApiLevel.IsCurrent() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900156 // "current" can be built from source and be from prebuilt SDK
157 return ctx.Config().AlwaysUsePrebuiltSdks()
Jiyong Park54105c42021-03-31 18:17:53 +0900158 } else if !s.ApiLevel.IsPreview() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900159 // validation check
Paul Duffin12e311d2021-10-28 17:42:16 +0100160 if s.Kind != SdkPublic && s.Kind != SdkSystem && s.Kind != SdkTest && s.Kind != SdkModule && s.Kind != SdkSystemServer {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900161 panic(fmt.Errorf("prebuilt SDK is not not available for SdkKind=%q", s.Kind))
162 return false
163 }
164 // numbered SDKs are always from prebuilt
165 return true
166 }
Jiyong Parkf1691d22021-03-29 20:11:58 +0900167 return false
168}
169
Jiyong Park54105c42021-03-31 18:17:53 +0900170// EffectiveVersion converts an SdkSpec into the concrete ApiLevel that the module should use. For
171// modules targeting an unreleased SDK (meaning it does not yet have a number) it returns
172// FutureApiLevel(10000).
173func (s SdkSpec) EffectiveVersion(ctx EarlyModuleContext) (ApiLevel, error) {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900174 if !s.Valid() {
Jiyong Park54105c42021-03-31 18:17:53 +0900175 return s.ApiLevel, fmt.Errorf("invalid sdk version %q", s.Raw)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900176 }
177
178 if ctx.DeviceSpecific() || ctx.SocSpecific() {
179 s = s.ForVendorPartition(ctx)
180 }
Jiyong Park54105c42021-03-31 18:17:53 +0900181 if !s.ApiLevel.IsPreview() {
182 return s.ApiLevel, nil
Jiyong Parkf1691d22021-03-29 20:11:58 +0900183 }
Jiyong Park54105c42021-03-31 18:17:53 +0900184 ret := ctx.Config().DefaultAppTargetSdk(ctx)
185 if ret.IsPreview() {
186 return FutureApiLevel, nil
187 }
188 return ret, nil
Jiyong Parkf1691d22021-03-29 20:11:58 +0900189}
190
191// EffectiveVersionString converts an SdkSpec into the concrete version string that the module
192// should use. For modules targeting an unreleased SDK (meaning it does not yet have a number)
193// it returns the codename (P, Q, R, etc.)
194func (s SdkSpec) EffectiveVersionString(ctx EarlyModuleContext) (string, error) {
Jiyong Park54105c42021-03-31 18:17:53 +0900195 if !s.Valid() {
196 return s.ApiLevel.String(), fmt.Errorf("invalid sdk version %q", s.Raw)
Jiyong Parkf1691d22021-03-29 20:11:58 +0900197 }
Jiyong Park54105c42021-03-31 18:17:53 +0900198
199 if ctx.DeviceSpecific() || ctx.SocSpecific() {
200 s = s.ForVendorPartition(ctx)
201 }
202 if !s.ApiLevel.IsPreview() {
203 return s.ApiLevel.String(), nil
204 }
205 return ctx.Config().DefaultAppTargetSdk(ctx).String(), nil
Jiyong Parkf1691d22021-03-29 20:11:58 +0900206}
207
Jiyong Park92315372021-04-02 08:45:46 +0900208var (
Jiyong Parkc7022042021-04-15 16:53:05 +0900209 SdkSpecNone = SdkSpec{SdkNone, NoneApiLevel, "(no version)"}
210 SdkSpecPrivate = SdkSpec{SdkPrivate, FutureApiLevel, ""}
211 SdkSpecCorePlatform = SdkSpec{SdkCorePlatform, FutureApiLevel, "core_platform"}
Jiyong Park92315372021-04-02 08:45:46 +0900212)
213
214func SdkSpecFrom(ctx EarlyModuleContext, str string) SdkSpec {
satayev0ee2f912021-12-01 17:39:48 +0000215 return SdkSpecFromWithConfig(ctx.Config(), str)
216}
217
218func SdkSpecFromWithConfig(config Config, str string) SdkSpec {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900219 switch str {
220 // special cases first
221 case "":
Jiyong Park92315372021-04-02 08:45:46 +0900222 return SdkSpecPrivate
Jiyong Parkf1691d22021-03-29 20:11:58 +0900223 case "none":
Jiyong Park92315372021-04-02 08:45:46 +0900224 return SdkSpecNone
Jiyong Parkf1691d22021-03-29 20:11:58 +0900225 case "core_platform":
Jiyong Park92315372021-04-02 08:45:46 +0900226 return SdkSpecCorePlatform
Jiyong Parkf1691d22021-03-29 20:11:58 +0900227 default:
228 // the syntax is [kind_]version
229 sep := strings.LastIndex(str, "_")
230
231 var kindString string
232 if sep == 0 {
Jiyong Park54105c42021-03-31 18:17:53 +0900233 return SdkSpec{SdkInvalid, NoneApiLevel, str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900234 } else if sep == -1 {
235 kindString = ""
236 } else {
237 kindString = str[0:sep]
238 }
239 versionString := str[sep+1 : len(str)]
240
241 var kind SdkKind
242 switch kindString {
243 case "":
244 kind = SdkPublic
245 case "core":
246 kind = SdkCore
247 case "system":
248 kind = SdkSystem
249 case "test":
250 kind = SdkTest
251 case "module":
252 kind = SdkModule
253 case "system_server":
254 kind = SdkSystemServer
255 default:
Jiyong Park54105c42021-03-31 18:17:53 +0900256 return SdkSpec{SdkInvalid, NoneApiLevel, str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900257 }
258
satayev0ee2f912021-12-01 17:39:48 +0000259 apiLevel, err := ApiLevelFromUserWithConfig(config, versionString)
Jiyong Park92315372021-04-02 08:45:46 +0900260 if err != nil {
Jiyong Park54105c42021-03-31 18:17:53 +0900261 return SdkSpec{SdkInvalid, apiLevel, str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900262 }
Jiyong Park54105c42021-03-31 18:17:53 +0900263 return SdkSpec{kind, apiLevel, str}
Jiyong Parkf1691d22021-03-29 20:11:58 +0900264 }
265}
266
267func (s SdkSpec) ValidateSystemSdk(ctx EarlyModuleContext) bool {
268 // Ensures that the specified system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor/product Java module)
269 // Assuming that BOARD_SYSTEMSDK_VERSIONS := 28 29,
270 // 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 +0900271 if s.Kind != SdkSystem || s.ApiLevel.IsPreview() {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900272 return true
273 }
274 allowedVersions := ctx.DeviceConfig().PlatformSystemSdkVersions()
275 if ctx.DeviceSpecific() || ctx.SocSpecific() || (ctx.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
276 systemSdkVersions := ctx.DeviceConfig().SystemSdkVersions()
277 if len(systemSdkVersions) > 0 {
278 allowedVersions = systemSdkVersions
279 }
280 }
Jiyong Park54105c42021-03-31 18:17:53 +0900281 if len(allowedVersions) > 0 && !InList(s.ApiLevel.String(), allowedVersions) {
Jiyong Parkf1691d22021-03-29 20:11:58 +0900282 ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
283 s.Raw, allowedVersions)
284 return false
285 }
286 return true
287}