1// Copyright 2019 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 java 16 17import ( 18 "fmt" 19 "path/filepath" 20 "sort" 21 "strconv" 22 23 "android/soong/android" 24 "android/soong/java/config" 25 26 "github.com/google/blueprint/pathtools" 27) 28 29func init() { 30 android.RegisterPreSingletonType("sdk_versions", sdkPreSingletonFactory) 31 android.RegisterSingletonType("sdk", sdkSingletonFactory) 32 android.RegisterMakeVarsProvider(pctx, sdkMakeVars) 33} 34 35var sdkVersionsKey = android.NewOnceKey("sdkVersionsKey") 36var sdkFrameworkAidlPathKey = android.NewOnceKey("sdkFrameworkAidlPathKey") 37var nonUpdatableFrameworkAidlPathKey = android.NewOnceKey("nonUpdatableFrameworkAidlPathKey") 38var apiFingerprintPathKey = android.NewOnceKey("apiFingerprintPathKey") 39 40func UseApiFingerprint(ctx android.BaseModuleContext) bool { 41 if ctx.Config().UnbundledBuild() && 42 !ctx.Config().AlwaysUsePrebuiltSdks() && 43 ctx.Config().IsEnvTrue("UNBUNDLED_BUILD_TARGET_SDK_WITH_API_FINGERPRINT") { 44 return true 45 } 46 return false 47} 48 49func defaultJavaLanguageVersion(ctx android.EarlyModuleContext, s android.SdkSpec) javaVersion { 50 sdk, err := s.EffectiveVersion(ctx) 51 if err != nil { 52 ctx.PropertyErrorf("sdk_version", "%s", err) 53 } 54 if sdk.FinalOrFutureInt() <= 23 { 55 return JAVA_VERSION_7 56 } else if sdk.FinalOrFutureInt() <= 29 { 57 return JAVA_VERSION_8 58 } else if sdk.FinalOrFutureInt() <= 31 { 59 return JAVA_VERSION_9 60 } else if sdk.FinalOrFutureInt() <= 33 { 61 return JAVA_VERSION_11 62 } else { 63 return JAVA_VERSION_17 64 } 65} 66 67// systemModuleKind returns the kind of system modules to use for the supplied combination of sdk 68// kind and API level. 69func systemModuleKind(sdkKind android.SdkKind, apiLevel android.ApiLevel) android.SdkKind { 70 systemModuleKind := sdkKind 71 if apiLevel.LessThanOrEqualTo(android.LastWithoutModuleLibCoreSystemModules) { 72 // API levels less than or equal to 31 did not provide a core-for-system-modules.jar 73 // specifically for the module-lib API. So, always use the public system modules for them. 74 systemModuleKind = android.SdkPublic 75 } else if systemModuleKind == android.SdkCore { 76 // Core is by definition what is included in the system module for the public API so should 77 // just use its system modules. 78 systemModuleKind = android.SdkPublic 79 } else if systemModuleKind == android.SdkSystem || systemModuleKind == android.SdkTest { 80 // The core system and test APIs are currently the same as the public API so they should use 81 // its system modules. 82 systemModuleKind = android.SdkPublic 83 } else if systemModuleKind == android.SdkSystemServer { 84 // The core system server API is the same as the core module-lib API. 85 systemModuleKind = android.SdkModule 86 } 87 88 return systemModuleKind 89} 90 91func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext android.SdkContext) sdkDep { 92 sdkVersion := sdkContext.SdkVersion(ctx) 93 if !sdkVersion.Valid() { 94 ctx.PropertyErrorf("sdk_version", "invalid version %q", sdkVersion.Raw) 95 return sdkDep{} 96 } 97 98 if ctx.DeviceSpecific() || ctx.SocSpecific() { 99 sdkVersion = sdkVersion.ForVendorPartition(ctx) 100 } 101 102 if !sdkVersion.ValidateSystemSdk(ctx) { 103 return sdkDep{} 104 } 105 106 if sdkVersion.UsePrebuilt(ctx) { 107 dir := filepath.Join("prebuilts", "sdk", sdkVersion.ApiLevel.String(), sdkVersion.Kind.String()) 108 jar := filepath.Join(dir, "android.jar") 109 // There's no aidl for other SDKs yet. 110 // TODO(77525052): Add aidl files for other SDKs too. 111 publicDir := filepath.Join("prebuilts", "sdk", sdkVersion.ApiLevel.String(), "public") 112 aidl := filepath.Join(publicDir, "framework.aidl") 113 jarPath := android.ExistentPathForSource(ctx, jar) 114 aidlPath := android.ExistentPathForSource(ctx, aidl) 115 lambdaStubsPath := android.PathForSource(ctx, config.SdkLambdaStubsPath) 116 117 if (!jarPath.Valid() || !aidlPath.Valid()) && ctx.Config().AllowMissingDependencies() { 118 return sdkDep{ 119 invalidVersion: true, 120 bootclasspath: []string{fmt.Sprintf("sdk_%s_%s_android", sdkVersion.Kind, sdkVersion.ApiLevel.String())}, 121 } 122 } 123 124 if !jarPath.Valid() { 125 ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", sdkVersion.Raw, jar) 126 return sdkDep{} 127 } 128 129 if !aidlPath.Valid() { 130 ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", sdkVersion.Raw, aidl) 131 return sdkDep{} 132 } 133 134 var systemModules string 135 if defaultJavaLanguageVersion(ctx, sdkVersion).usesJavaModules() { 136 systemModuleKind := systemModuleKind(sdkVersion.Kind, sdkVersion.ApiLevel) 137 systemModules = fmt.Sprintf("sdk_%s_%s_system_modules", systemModuleKind, sdkVersion.ApiLevel) 138 } 139 140 return sdkDep{ 141 useFiles: true, 142 jars: android.Paths{jarPath.Path(), lambdaStubsPath}, 143 aidl: android.OptionalPathForPath(aidlPath.Path()), 144 systemModules: systemModules, 145 } 146 } 147 148 toModule := func(module string, aidl android.Path) sdkDep { 149 // Select the kind of system modules needed for the sdk version. 150 systemModulesKind := systemModuleKind(sdkVersion.Kind, android.FutureApiLevel) 151 systemModules := android.JavaApiLibraryName(ctx.Config(), fmt.Sprintf("core-%s-stubs-system-modules", systemModulesKind)) 152 return sdkDep{ 153 useModule: true, 154 bootclasspath: []string{module, android.JavaApiLibraryName(ctx.Config(), config.DefaultLambdaStubsLibrary)}, 155 systemModules: systemModules, 156 java9Classpath: []string{module}, 157 frameworkResModule: "framework-res", 158 aidl: android.OptionalPathForPath(aidl), 159 } 160 } 161 162 switch sdkVersion.Kind { 163 case android.SdkPrivate: 164 return sdkDep{ 165 useModule: true, 166 systemModules: corePlatformSystemModules(ctx), 167 bootclasspath: corePlatformBootclasspathLibraries(ctx), 168 classpath: config.FrameworkLibraries, 169 frameworkResModule: "framework-res", 170 } 171 case android.SdkNone: 172 systemModules := sdkContext.SystemModules() 173 if systemModules == "" { 174 ctx.PropertyErrorf("sdk_version", 175 `system_modules is required to be set to a non-empty value when sdk_version is "none", did you mean sdk_version: "core_platform"?`) 176 } else if systemModules == "none" { 177 return sdkDep{ 178 noStandardLibs: true, 179 } 180 } 181 182 return sdkDep{ 183 useModule: true, 184 noStandardLibs: true, 185 systemModules: systemModules, 186 bootclasspath: []string{systemModules}, 187 } 188 case android.SdkCorePlatform: 189 return sdkDep{ 190 useModule: true, 191 systemModules: corePlatformSystemModules(ctx), 192 bootclasspath: corePlatformBootclasspathLibraries(ctx), 193 noFrameworksLibs: true, 194 } 195 case android.SdkPublic, android.SdkSystem, android.SdkTest: 196 return toModule(sdkVersion.Kind.JavaLibraryName(ctx.Config()), sdkFrameworkAidlPath(ctx)) 197 case android.SdkCore: 198 return sdkDep{ 199 useModule: true, 200 bootclasspath: []string{android.SdkCore.JavaLibraryName(ctx.Config()), android.JavaApiLibraryName(ctx.Config(), config.DefaultLambdaStubsLibrary)}, 201 systemModules: android.JavaApiLibraryName(ctx.Config(), "core-public-stubs-system-modules"), 202 noFrameworksLibs: true, 203 } 204 case android.SdkModule: 205 // TODO(146757305): provide .apk and .aidl that have more APIs for modules 206 return toModule(sdkVersion.Kind.JavaLibraryName(ctx.Config()), nonUpdatableFrameworkAidlPath(ctx)) 207 case android.SdkSystemServer: 208 // TODO(146757305): provide .apk and .aidl that have more APIs for modules 209 return toModule(sdkVersion.Kind.JavaLibraryName(ctx.Config()), sdkFrameworkAidlPath(ctx)) 210 default: 211 panic(fmt.Errorf("invalid sdk %q", sdkVersion.Raw)) 212 } 213} 214 215func sdkPreSingletonFactory() android.Singleton { 216 return sdkPreSingleton{} 217} 218 219type sdkPreSingleton struct{} 220 221func (sdkPreSingleton) GenerateBuildActions(ctx android.SingletonContext) { 222 sdkJars, err := ctx.GlobWithDeps("prebuilts/sdk/*/public/android.jar", nil) 223 if err != nil { 224 ctx.Errorf("failed to glob prebuilts/sdk/*/public/android.jar: %s", err.Error()) 225 } 226 227 var sdkVersions []int 228 for _, sdkJar := range sdkJars { 229 dir := filepath.Base(filepath.Dir(filepath.Dir(sdkJar))) 230 v, err := strconv.Atoi(dir) 231 if scerr, ok := err.(*strconv.NumError); ok && scerr.Err == strconv.ErrSyntax { 232 continue 233 } else if err != nil { 234 ctx.Errorf("invalid sdk jar %q, %s, %v", sdkJar, err.Error()) 235 } 236 sdkVersions = append(sdkVersions, v) 237 } 238 239 sort.Ints(sdkVersions) 240 241 ctx.Config().Once(sdkVersionsKey, func() interface{} { return sdkVersions }) 242} 243 244func LatestSdkVersionInt(ctx android.EarlyModuleContext) int { 245 sdkVersions := ctx.Config().Get(sdkVersionsKey).([]int) 246 latestSdkVersion := 0 247 if len(sdkVersions) > 0 { 248 latestSdkVersion = sdkVersions[len(sdkVersions)-1] 249 } 250 return latestSdkVersion 251} 252 253func sdkSingletonFactory() android.Singleton { 254 return sdkSingleton{} 255} 256 257type sdkSingleton struct{} 258 259func (sdkSingleton) GenerateBuildActions(ctx android.SingletonContext) { 260 if ctx.Config().AlwaysUsePrebuiltSdks() { 261 return 262 } 263 264 createSdkFrameworkAidl(ctx) 265 createNonUpdatableFrameworkAidl(ctx) 266 createAPIFingerprint(ctx) 267} 268 269// Create framework.aidl by extracting anything that implements android.os.Parcelable from the SDK stubs modules. 270func createSdkFrameworkAidl(ctx android.SingletonContext) { 271 stubsModules := []string{ 272 android.SdkPublic.JavaLibraryName(ctx.Config()), 273 android.SdkTest.JavaLibraryName(ctx.Config()), 274 android.SdkSystem.JavaLibraryName(ctx.Config()), 275 } 276 277 combinedAidl := sdkFrameworkAidlPath(ctx) 278 tempPath := tempPathForRestat(ctx, combinedAidl) 279 280 rule := createFrameworkAidl(stubsModules, tempPath, ctx) 281 282 commitChangeForRestat(rule, tempPath, combinedAidl) 283 284 rule.Build("framework_aidl", "generate framework.aidl") 285} 286 287// Creates a version of framework.aidl for the non-updatable part of the platform. 288func createNonUpdatableFrameworkAidl(ctx android.SingletonContext) { 289 stubsModules := []string{android.SdkModule.JavaLibraryName(ctx.Config())} 290 291 combinedAidl := nonUpdatableFrameworkAidlPath(ctx) 292 tempPath := tempPathForRestat(ctx, combinedAidl) 293 294 rule := createFrameworkAidl(stubsModules, tempPath, ctx) 295 296 commitChangeForRestat(rule, tempPath, combinedAidl) 297 298 rule.Build("framework_non_updatable_aidl", "generate framework_non_updatable.aidl") 299} 300 301func createFrameworkAidl(stubsModules []string, path android.WritablePath, ctx android.SingletonContext) *android.RuleBuilder { 302 stubsJars := make([]android.Paths, len(stubsModules)) 303 304 ctx.VisitAllModules(func(module android.Module) { 305 // Collect dex jar paths for the modules listed above. 306 if ctx.ModuleHasProvider(module, JavaInfoProvider) { 307 j := ctx.ModuleProvider(module, JavaInfoProvider).(JavaInfo) 308 name := ctx.ModuleName(module) 309 if i := android.IndexList(name, stubsModules); i != -1 { 310 stubsJars[i] = j.HeaderJars 311 } 312 } 313 }) 314 315 var missingDeps []string 316 317 for i := range stubsJars { 318 if stubsJars[i] == nil { 319 if ctx.Config().AllowMissingDependencies() { 320 missingDeps = append(missingDeps, stubsModules[i]) 321 } else { 322 ctx.Errorf("failed to find dex jar path for module %q", stubsModules[i]) 323 } 324 } 325 } 326 327 rule := android.NewRuleBuilder(pctx, ctx) 328 rule.MissingDeps(missingDeps) 329 330 var aidls android.Paths 331 for _, jars := range stubsJars { 332 for _, jar := range jars { 333 aidl := android.PathForOutput(ctx, "aidl", pathtools.ReplaceExtension(jar.Base(), "aidl")) 334 335 rule.Command(). 336 Text("rm -f").Output(aidl) 337 rule.Command(). 338 BuiltTool("sdkparcelables"). 339 Input(jar). 340 Output(aidl) 341 342 aidls = append(aidls, aidl) 343 } 344 } 345 346 rule.Command(). 347 Text("rm -f").Output(path) 348 rule.Command(). 349 Text("cat"). 350 Inputs(aidls). 351 Text("| sort -u >"). 352 Output(path) 353 354 return rule 355} 356 357func sdkFrameworkAidlPath(ctx android.PathContext) android.OutputPath { 358 return ctx.Config().Once(sdkFrameworkAidlPathKey, func() interface{} { 359 return android.PathForOutput(ctx, "framework.aidl") 360 }).(android.OutputPath) 361} 362 363func nonUpdatableFrameworkAidlPath(ctx android.PathContext) android.OutputPath { 364 return ctx.Config().Once(nonUpdatableFrameworkAidlPathKey, func() interface{} { 365 return android.PathForOutput(ctx, "framework_non_updatable.aidl") 366 }).(android.OutputPath) 367} 368 369// Create api_fingerprint.txt 370func createAPIFingerprint(ctx android.SingletonContext) { 371 out := ApiFingerprintPath(ctx) 372 373 rule := android.NewRuleBuilder(pctx, ctx) 374 375 rule.Command(). 376 Text("rm -f").Output(out) 377 cmd := rule.Command() 378 379 if ctx.Config().PlatformSdkCodename() == "REL" { 380 cmd.Text("echo REL >").Output(out) 381 } else if ctx.Config().FrameworksBaseDirExists(ctx) && !ctx.Config().AlwaysUsePrebuiltSdks() { 382 cmd.Text("cat") 383 apiTxtFileModules := []string{ 384 "api_fingerprint", 385 } 386 count := 0 387 ctx.VisitAllModules(func(module android.Module) { 388 name := ctx.ModuleName(module) 389 if android.InList(name, apiTxtFileModules) { 390 cmd.Inputs(android.OutputFilesForModule(ctx, module, "")) 391 count++ 392 } 393 }) 394 if count != len(apiTxtFileModules) { 395 ctx.Errorf("Could not find expected API module %v, found %d\n", apiTxtFileModules, count) 396 return 397 } 398 cmd.Text(">"). 399 Output(out) 400 } else { 401 // Unbundled build 402 // TODO: use a prebuilt api_fingerprint.txt from prebuilts/sdk/current.txt once we have one 403 cmd.Text("echo"). 404 Flag(ctx.Config().PlatformPreviewSdkVersion()). 405 Text(">"). 406 Output(out) 407 } 408 409 rule.Build("api_fingerprint", "generate api_fingerprint.txt") 410} 411 412func ApiFingerprintPath(ctx android.PathContext) android.OutputPath { 413 return ctx.Config().Once(apiFingerprintPathKey, func() interface{} { 414 return android.PathForOutput(ctx, "api_fingerprint.txt") 415 }).(android.OutputPath) 416} 417 418func sdkMakeVars(ctx android.MakeVarsContext) { 419 if ctx.Config().AlwaysUsePrebuiltSdks() { 420 return 421 } 422 423 ctx.Strict("FRAMEWORK_AIDL", sdkFrameworkAidlPath(ctx).String()) 424 ctx.Strict("API_FINGERPRINT", ApiFingerprintPath(ctx).String()) 425} 426