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