1// 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 "reflect" 20 "strconv" 21 "strings" 22) 23 24type SdkContext interface { 25 // SdkVersion returns SdkSpec that corresponds to the sdk_version property of the current module 26 SdkVersion(ctx EarlyModuleContext) SdkSpec 27 // SystemModules returns the system_modules property of the current module, or an empty string if it is not set. 28 SystemModules() string 29 // MinSdkVersion returns ApiLevel that corresponds to the min_sdk_version property of the current module, 30 // or from sdk_version if it is not set. 31 MinSdkVersion(ctx EarlyModuleContext) ApiLevel 32 // ReplaceMaxSdkVersionPlaceholder returns Apilevel to replace the maxSdkVersion property of permission and 33 // uses-permission tags if it is set. 34 ReplaceMaxSdkVersionPlaceholder(ctx EarlyModuleContext) ApiLevel 35 // TargetSdkVersion returns the ApiLevel that corresponds to the target_sdk_version property of the current module, 36 // or from sdk_version if it is not set. 37 TargetSdkVersion(ctx EarlyModuleContext) ApiLevel 38} 39 40// SdkKind represents a particular category of an SDK spec like public, system, test, etc. 41type SdkKind int 42 43// 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. 48const ( 49 SdkInvalid SdkKind = iota 50 SdkNone 51 SdkToolchain // API surface provided by ART to compile other API domains 52 SdkCore 53 SdkCorePlatform 54 SdkIntraCore // API surface provided by one core module to another 55 SdkPublic 56 SdkSystem 57 SdkTest 58 SdkTestFrameworksCore 59 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" 77 case SdkTestFrameworksCore: 78 return "test_frameworks_core" 79 case SdkCore: 80 return "core" 81 case SdkCorePlatform: 82 return "core_platform" 83 case SdkIntraCore: 84 return "intracore" 85 case SdkModule: 86 return "module-lib" 87 case SdkSystemServer: 88 return "system-server" 89 case SdkToolchain: 90 return "toolchain" 91 default: 92 return "invalid" 93 } 94} 95 96func 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 105func (k SdkKind) DefaultJavaLibraryName() string { 106 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" 113 case SdkTestFrameworksCore: 114 return "android_test_frameworks_core_stubs_current" 115 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 126func 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 151func (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 162// SdkSpec represents the kind and the version of an SDK for a module to build against 163type SdkSpec struct { 164 Kind SdkKind 165 ApiLevel ApiLevel 166 Raw string 167} 168 169func (s SdkSpec) String() string { 170 return fmt.Sprintf("%s_%s", s.Kind, s.ApiLevel) 171} 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 196 case SdkCorePlatform, SdkTest, SdkTestFrameworksCore, SdkPrivate: 197 return false 198 default: 199 panic(fmt.Errorf("unknown SdkKind=%v", s.Kind)) 200 } 201 return false 202} 203 204// PrebuiltSdkAvailableForUnbundledBuild tells whether this SdkSpec can have a prebuilt SDK 205// 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() 216 // 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 227 if currentSdkVersion == "current" { 228 return s 229 } 230 231 if s.Kind == SdkPublic || s.Kind == SdkSystem { 232 if s.ApiLevel.IsCurrent() { 233 if i, err := strconv.Atoi(currentSdkVersion); err == nil { 234 apiLevel := uncheckedFinalApiLevel(i) 235 return SdkSpec{s.Kind, apiLevel, s.Raw} 236 } 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 { 245 switch s { 246 case SdkSpecNone, SdkSpecCorePlatform, SdkSpecPrivate: 247 return false 248 } 249 250 if s.ApiLevel.IsCurrent() { 251 // "current" can be built from source and be from prebuilt SDK 252 return ctx.Config().AlwaysUsePrebuiltSdks() 253 } else if !s.ApiLevel.IsPreview() { 254 // validation check 255 if s.Kind != SdkPublic && s.Kind != SdkSystem && s.Kind != SdkTest && 256 s.Kind != SdkTestFrameworksCore && s.Kind != SdkModule && s.Kind != SdkSystemServer { 257 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 } 263 return false 264} 265 266// 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) { 270 if !s.Valid() { 271 return s.ApiLevel, fmt.Errorf("invalid sdk version %q", s.Raw) 272 } 273 274 if ctx.DeviceSpecific() || ctx.SocSpecific() { 275 s = s.ForVendorPartition(ctx) 276 } 277 return s.ApiLevel.EffectiveVersion(ctx) 278} 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) { 284 if !s.Valid() { 285 return s.ApiLevel.String(), fmt.Errorf("invalid sdk version %q", s.Raw) 286 } 287 288 if ctx.DeviceSpecific() || ctx.SocSpecific() { 289 s = s.ForVendorPartition(ctx) 290 } 291 return s.ApiLevel.EffectiveVersionString(ctx) 292} 293 294var ( 295 SdkSpecNone = SdkSpec{SdkNone, NoneApiLevel, "(no version)"} 296 SdkSpecPrivate = SdkSpec{SdkPrivate, PrivateApiLevel, ""} 297 SdkSpecCorePlatform = SdkSpec{SdkCorePlatform, FutureApiLevel, "core_platform"} 298) 299 300func SdkSpecFrom(ctx EarlyModuleContext, str string) SdkSpec { 301 return SdkSpecFromWithConfig(ctx.Config(), str) 302} 303 304func SdkSpecFromWithConfig(config Config, str string) SdkSpec { 305 switch str { 306 // special cases first 307 case "": 308 return SdkSpecPrivate 309 case "none": 310 return SdkSpecNone 311 case "core_platform": 312 return SdkSpecCorePlatform 313 default: 314 // the syntax is [kind_]version 315 sep := strings.LastIndex(str, "_") 316 317 var kindString string 318 if sep == 0 { 319 return SdkSpec{SdkInvalid, NewInvalidApiLevel(str), str} 320 } 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 337 case "test_frameworks_core": 338 kind = SdkTestFrameworksCore 339 case "module": 340 kind = SdkModule 341 case "system_server": 342 kind = SdkSystemServer 343 default: 344 return SdkSpec{SdkInvalid, NoneApiLevel, str} 345 } 346 347 apiLevel, err := ApiLevelFromUserWithConfig(config, versionString) 348 if err != nil { 349 return SdkSpec{SdkInvalid, NewInvalidApiLevel(versionString), str} 350 } 351 return SdkSpec{kind, apiLevel, str} 352 } 353} 354 355// Checks if the use of this SDK `s` is valid for the given module context `ctx`. 356func (s SdkSpec) ValidateSystemSdk(ctx EarlyModuleContext) bool { 357 // Do some early checks. This check is currently only for Java modules. And our only concern 358 // is the use of "system" SDKs. 359 if !isJava(ctx.Module()) || s.Kind != SdkSystem || ctx.DeviceConfig().BuildBrokenDontCheckSystemSdk() { 360 return true 361 } 362 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)) 391 } 392 } 393 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) { 412 ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q", 413 s.Raw, supportedVersions) 414 return false 415 } 416 return true 417} 418 419func 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 428func 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) { 434 ctx.Strict("ANDROID_PUBLIC_STUBS", SdkPublic.DefaultJavaLibraryName()) 435 ctx.Strict("ANDROID_PUBLIC_EXPORTABLE_STUBS", SdkPublic.DefaultExportableJavaLibraryName()) 436 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()) 441} 442