diff options
Diffstat (limited to 'java')
| -rw-r--r-- | java/androidmk.go | 4 | ||||
| -rwxr-xr-x | java/app.go | 5 | ||||
| -rw-r--r-- | java/app_builder.go | 12 | ||||
| -rw-r--r-- | java/app_test.go | 2 | ||||
| -rw-r--r-- | java/base.go | 34 | ||||
| -rw-r--r-- | java/bootclasspath_fragment.go | 91 | ||||
| -rw-r--r-- | java/classpath_fragment.go | 118 | ||||
| -rw-r--r-- | java/dex.go | 39 | ||||
| -rw-r--r-- | java/dexpreopt_bootjars.go | 10 | ||||
| -rw-r--r-- | java/dexpreopt_config.go | 36 | ||||
| -rw-r--r-- | java/droidstubs.go | 56 | ||||
| -rw-r--r-- | java/hiddenapi.go | 10 | ||||
| -rw-r--r-- | java/java.go | 3 | ||||
| -rw-r--r-- | java/platform_bootclasspath.go | 88 | ||||
| -rw-r--r-- | java/sdk_library.go | 76 | ||||
| -rw-r--r-- | java/sdk_library_test.go | 123 | ||||
| -rw-r--r-- | java/systemserver_classpath_fragment.go | 52 | ||||
| -rw-r--r-- | java/systemserver_classpath_fragment_test.go | 2 | ||||
| -rw-r--r-- | java/testing.go | 22 |
19 files changed, 585 insertions, 198 deletions
diff --git a/java/androidmk.go b/java/androidmk.go index 04357e066..43214e586 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -423,6 +423,10 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries { fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n", app.installApkName, app.noticeOutputs.HtmlOutput.String(), app.installApkName+"_NOTICE.html") } + if app.javaApiUsedByOutputFile.String() != "" { + fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s/$(notdir %s))\n", + app.installApkName, app.javaApiUsedByOutputFile.String(), "java_apis_used_by_apex", app.javaApiUsedByOutputFile.String()) + } }, }, }} diff --git a/java/app.go b/java/app.go index fc1ace07b..cdbea2e42 100755 --- a/java/app.go +++ b/java/app.go @@ -167,6 +167,8 @@ type AndroidApp struct { overriddenManifestPackageName string android.ApexBundleDepsInfo + + javaApiUsedByOutputFile android.ModuleOutPath } func (a *AndroidApp) IsInstallable() bool { @@ -275,6 +277,7 @@ func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleCon func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.checkAppSdkVersions(ctx) a.generateAndroidBuildActions(ctx) + a.generateJavaUsedByApex(ctx) } func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) { @@ -288,7 +291,7 @@ func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) { if minSdkVersion, err := a.MinSdkVersion(ctx).EffectiveVersion(ctx); err == nil { a.checkJniLibsSdkVersion(ctx, minSdkVersion) - android.CheckMinSdkVersion(a, ctx, minSdkVersion) + android.CheckMinSdkVersion(ctx, minSdkVersion, a.WalkPayloadDeps) } else { ctx.PropertyErrorf("min_sdk_version", "%s", err.Error()) } diff --git a/java/app_builder.go b/java/app_builder.go index 4a18dcada..bafc98054 100644 --- a/java/app_builder.go +++ b/java/app_builder.go @@ -254,6 +254,18 @@ func TransformJniLibsToJar(ctx android.ModuleContext, outputFile android.Writabl }) } +func (a *AndroidApp) generateJavaUsedByApex(ctx android.ModuleContext) { + javaApiUsedByOutputFile := android.PathForModuleOut(ctx, a.installApkName+"_using.xml") + javaUsedByRule := android.NewRuleBuilder(pctx, ctx) + javaUsedByRule.Command(). + Tool(android.PathForSource(ctx, "build/soong/scripts/gen_java_usedby_apex.sh")). + BuiltTool("dexdeps"). + Output(javaApiUsedByOutputFile). + Input(a.Library.Module.outputFile) + javaUsedByRule.Build("java_usedby_list", "Generate Java APIs used by Apex") + a.javaApiUsedByOutputFile = javaApiUsedByOutputFile +} + func targetToJniDir(target android.Target) string { return filepath.Join("lib", target.Arch.Abi[0]) } diff --git a/java/app_test.go b/java/app_test.go index a99ac62da..7997f7ad8 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -2471,7 +2471,7 @@ func TestDexpreoptBcp(t *testing.T) { PrepareForTestWithJavaSdkLibraryFiles, FixtureWithLastReleaseApis("runtime-library", "foo", "bar"), dexpreopt.FixtureSetBootJars("platform:foo"), - dexpreopt.FixtureSetUpdatableBootJars("platform:bar"), + dexpreopt.FixtureSetApexBootJars("platform:bar"), dexpreopt.FixtureSetPreoptWithUpdatableBcp(test.with), ).RunTestWithBp(t, bp) diff --git a/java/base.go b/java/base.go index df70efb44..4780cc909 100644 --- a/java/base.go +++ b/java/base.go @@ -185,6 +185,10 @@ type DeviceProperties struct { // Defaults to sdk_version if not set. Min_sdk_version *string + // if not blank, set the maximum version of the sdk that the compiled artifacts will run against. + // Defaults to empty string "". See sdk_version for possible values. + Max_sdk_version *string + // if not blank, set the targetSdkVersion in the AndroidManifest.xml. // Defaults to sdk_version if not set. Target_sdk_version *string @@ -367,6 +371,7 @@ type Module struct { sdkVersion android.SdkSpec minSdkVersion android.SdkSpec + maxSdkVersion android.SdkSpec } func (j *Module) CheckStableSdkVersion(ctx android.BaseModuleContext) error { @@ -524,6 +529,13 @@ func (j *Module) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { return j.SdkVersion(ctx) } +func (j *Module) MaxSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { + maxSdkVersion := proptools.StringDefault(j.deviceProperties.Max_sdk_version, "") + // SdkSpecFrom returns SdkSpecPrivate for this, which may be confusing. + // TODO(b/208456999): ideally MaxSdkVersion should be an ApiLevel and not SdkSpec. + return android.SdkSpecFrom(ctx, maxSdkVersion) +} + func (j *Module) MinSdkVersionString() string { return j.minSdkVersion.Raw } @@ -1152,10 +1164,25 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { // Check package restrictions if necessary. if len(j.properties.Permitted_packages) > 0 { - // Check packages and copy to package-checked file. + // Time stamp file created by the package check rule. pkgckFile := android.PathForModuleOut(ctx, "package-check.stamp") + + // Create a rule to copy the output jar to another path and add a validate dependency that + // will check that the jar only contains the permitted packages. The new location will become + // the output file of this module. + inputFile := outputFile + outputFile = android.PathForModuleOut(ctx, "package-check", jarName).OutputPath + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cp, + Input: inputFile, + Output: outputFile, + // Make sure that any dependency on the output file will cause ninja to run the package check + // rule. + Validation: pkgckFile, + }) + + // Check packages and create a timestamp file when complete. CheckJarPackages(ctx, pkgckFile, outputFile, j.properties.Permitted_packages) - j.additionalCheckedModules = append(j.additionalCheckedModules, pkgckFile) if ctx.Failed() { return @@ -1473,8 +1500,7 @@ func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu } // Implements android.ApexModule -func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, - sdkVersion android.ApiLevel) error { +func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error { sdkSpec := j.MinSdkVersion(ctx) if !sdkSpec.Specified() { return fmt.Errorf("min_sdk_version is not specified") diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index a0399645f..7b4ddc573 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -139,6 +139,74 @@ type bootclasspathFragmentProperties struct { BootclasspathFragmentsDepsProperties } +type SourceOnlyBootclasspathProperties struct { + Hidden_api struct { + // Contains prefixes of a package hierarchy that is provided solely by this + // bootclasspath_fragment. + // + // This affects the signature patterns file that is used to select the subset of monolithic + // hidden API flags. See split_packages property for more details. + Package_prefixes []string + + // The list of split packages provided by this bootclasspath_fragment. + // + // A split package is one that contains classes which are provided by multiple + // bootclasspath_fragment modules. + // + // This defaults to "*" - which treats all packages as being split. A module that has no split + // packages must specify an empty list. + // + // This affects the signature patterns file that is generated by a bootclasspath_fragment and + // used to select the subset of monolithic hidden API flags against which the flags generated + // by the bootclasspath_fragment are compared. + // + // The signature patterns file selects the subset of monolithic hidden API flags using a number + // of patterns, i.e.: + // * The qualified name (including package) of an outermost class, e.g. java/lang/Character. + // This selects all the flags for all the members of this class and any nested classes. + // * A package wildcard, e.g. java/lang/*. This selects all the flags for all the members of all + // the classes in this package (but not in sub-packages). + // * A recursive package wildcard, e.g. java/**. This selects all the flags for all the members + // of all the classes in this package and sub-packages. + // + // The signature patterns file is constructed as follows: + // * All the signatures are retrieved from the all-flags.csv file. + // * The member and inner class names are removed. + // * If a class is in a split package then that is kept, otherwise the class part is removed + // and replaced with a wildcard, i.e. *. + // * If a package matches a package prefix then the package is removed. + // * All the package prefixes are added with a recursive wildcard appended to each, i.e. **. + // * The resulting patterns are sorted. + // + // So, by default (i.e. without specifying any package_prefixes or split_packages) the signature + // patterns is a list of class names, because there are no package packages and all packages are + // assumed to be split. + // + // If any split packages are specified then only those packages are treated as split and all + // other packages are treated as belonging solely to the bootclasspath_fragment and so they use + // wildcard package patterns. + // + // So, if an empty list of split packages is specified then the signature patterns file just + // includes a wildcard package pattern for every package provided by the bootclasspath_fragment. + // + // If split_packages are specified and a package that is split is not listed then it could lead + // to build failures as it will select monolithic flags that are generated by another + // bootclasspath_fragment to compare against the flags provided by this fragment. The latter + // will obviously not contain those flags and that can cause the comparison and build to fail. + // + // If any package prefixes are specified then any matching packages are removed from the + // signature patterns and replaced with a single recursive package pattern. + // + // It is not strictly necessary to specify either package_prefixes or split_packages as the + // defaults will produce a valid set of signature patterns. However, those patterns may include + // implementation details, e.g. names of implementation classes or packages, which will be + // exported to the sdk snapshot in the signature patterns file. That is something that should be + // avoided where possible. Specifying package_prefixes and split_packages allows those + // implementation details to be excluded from the snapshot. + Split_packages []string + } +} + type BootclasspathFragmentModule struct { android.ModuleBase android.ApexModuleBase @@ -146,6 +214,8 @@ type BootclasspathFragmentModule struct { ClasspathFragmentBase properties bootclasspathFragmentProperties + + sourceOnlyProperties SourceOnlyBootclasspathProperties } // commonBootclasspathFragment defines the methods that are implemented by both source and prebuilt @@ -177,7 +247,7 @@ type bootImageFilesByArch map[android.ArchType]android.Paths func bootclasspathFragmentFactory() android.Module { m := &BootclasspathFragmentModule{} - m.AddProperties(&m.properties) + m.AddProperties(&m.properties, &m.sourceOnlyProperties) android.InitApexModule(m) android.InitSdkAwareModule(m) initClasspathFragment(m, BOOTCLASSPATH) @@ -514,31 +584,28 @@ func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleC // generateClasspathProtoBuildActions generates all required build actions for classpath.proto config func (b *BootclasspathFragmentModule) generateClasspathProtoBuildActions(ctx android.ModuleContext) { var classpathJars []classpathJar + configuredJars := b.configuredJars(ctx) if "art" == proptools.String(b.properties.Image_name) { // ART and platform boot jars must have a corresponding entry in DEX2OATBOOTCLASSPATH - classpathJars = configuredJarListToClasspathJars(ctx, b.ClasspathFragmentToConfiguredJarList(ctx), BOOTCLASSPATH, DEX2OATBOOTCLASSPATH) + classpathJars = configuredJarListToClasspathJars(ctx, configuredJars, BOOTCLASSPATH, DEX2OATBOOTCLASSPATH) } else { - classpathJars = configuredJarListToClasspathJars(ctx, b.ClasspathFragmentToConfiguredJarList(ctx), b.classpathType) + classpathJars = configuredJarListToClasspathJars(ctx, configuredJars, b.classpathType) } - b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, classpathJars) + b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars) } -func (b *BootclasspathFragmentModule) ClasspathFragmentToConfiguredJarList(ctx android.ModuleContext) android.ConfiguredJarList { +func (b *BootclasspathFragmentModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList { if "art" == proptools.String(b.properties.Image_name) { return b.getImageConfig(ctx).modules } global := dexpreopt.GetGlobalConfig(ctx) - possibleUpdatableModules := gatherPossibleUpdatableModuleNamesAndStems(ctx, b.properties.Contents, bootclasspathFragmentContentDepTag) - - // Only create configs for updatable boot jars. Non-updatable boot jars must be part of the - // platform_bootclasspath's classpath proto config to guarantee that they come before any - // updatable jars at runtime. - jars := global.UpdatableBootJars.Filter(possibleUpdatableModules) + possibleUpdatableModules := gatherPossibleApexModuleNamesAndStems(ctx, b.properties.Contents, bootclasspathFragmentContentDepTag) + jars := global.ApexBootJars.Filter(possibleUpdatableModules) // TODO(satayev): for apex_test we want to include all contents unconditionally to classpaths - // config. However, any test specific jars would not be present in UpdatableBootJars. Instead, + // config. However, any test specific jars would not be present in ApexBootJars. Instead, // we should check if we are creating a config for apex_test via ApexInfo and amend the values. // This is an exception to support end-to-end test for SdkExtensions, until such support exists. if android.InList("test_framework-sdkextensions", possibleUpdatableModules) { diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go index ecfdfb7e5..7eadfe6c3 100644 --- a/java/classpath_fragment.go +++ b/java/classpath_fragment.go @@ -19,6 +19,7 @@ package java import ( "fmt" "github.com/google/blueprint" + "github.com/google/blueprint/proptools" "strings" "android/soong/android" @@ -44,6 +45,11 @@ func (c classpathType) String() string { } type classpathFragmentProperties struct { + // Whether to generated classpaths.proto config instance for the fragment. If the config is not + // generated, then relevant boot jars are added to platform classpath, i.e. platform_bootclasspath + // or platform_systemserverclasspath. This is useful for non-updatable APEX boot jars, to keep + // them as part of dexopt on device. Defaults to true. + Generate_classpaths_proto *bool } // classpathFragment interface is implemented by a module that contributes jars to a *CLASSPATH @@ -52,10 +58,6 @@ type classpathFragment interface { android.Module classpathFragmentBase() *ClasspathFragmentBase - - // ClasspathFragmentToConfiguredJarList returns android.ConfiguredJarList representation of all - // the jars in this classpath fragment. - ClasspathFragmentToConfiguredJarList(ctx android.ModuleContext) android.ConfiguredJarList } // ClasspathFragmentBase is meant to be embedded in any module types that implement classpathFragment; @@ -82,15 +84,14 @@ func initClasspathFragment(c classpathFragment, classpathType classpathType) { // Matches definition of Jar in packages/modules/SdkExtensions/proto/classpaths.proto type classpathJar struct { - path string - classpath classpathType - // TODO(satayev): propagate min/max sdk versions for the jars - minSdkVersion int32 - maxSdkVersion int32 + path string + classpath classpathType + minSdkVersion string + maxSdkVersion string } -// gatherPossibleUpdatableModuleNamesAndStems returns a set of module and stem names from the -// supplied contents that may be in the updatable boot jars. +// gatherPossibleApexModuleNamesAndStems returns a set of module and stem names from the +// supplied contents that may be in the apex boot jars. // // The module names are included because sometimes the stem is set to just change the name of // the installed file and it expects the configuration to still use the actual module name. @@ -98,7 +99,7 @@ type classpathJar struct { // The stem names are included because sometimes the stem is set to change the effective name of the // module that is used in the configuration as well,e .g. when a test library is overriding an // actual boot jar -func gatherPossibleUpdatableModuleNamesAndStems(ctx android.ModuleContext, contents []string, tag blueprint.DependencyTag) []string { +func gatherPossibleApexModuleNamesAndStems(ctx android.ModuleContext, contents []string, tag blueprint.DependencyTag) []string { set := map[string]struct{}{} for _, name := range contents { dep := ctx.GetDirectDepWithTag(name, tag) @@ -118,58 +119,79 @@ func configuredJarListToClasspathJars(ctx android.ModuleContext, configuredJars jars := make([]classpathJar, 0, len(paths)*len(classpaths)) for i := 0; i < len(paths); i++ { for _, classpathType := range classpaths { - jars = append(jars, classpathJar{ + jar := classpathJar{ classpath: classpathType, path: paths[i], + } + ctx.VisitDirectDepsIf(func(m android.Module) bool { + return m.Name() == configuredJars.Jar(i) + }, func(m android.Module) { + if s, ok := m.(*SdkLibrary); ok { + // TODO(208456999): instead of mapping "current" to latest, min_sdk_version should never be set to "current" + if s.minSdkVersion.Specified() { + if s.minSdkVersion.ApiLevel.IsCurrent() { + jar.minSdkVersion = ctx.Config().LatestPreviewApiLevel().String() + } else { + jar.minSdkVersion = s.minSdkVersion.ApiLevel.String() + } + } + if s.maxSdkVersion.Specified() { + if s.maxSdkVersion.ApiLevel.IsCurrent() { + jar.maxSdkVersion = ctx.Config().LatestPreviewApiLevel().String() + } else { + jar.maxSdkVersion = s.maxSdkVersion.ApiLevel.String() + } + } + } }) + jars = append(jars, jar) } } return jars } -func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.ModuleContext, jars []classpathJar) { - outputFilename := strings.ToLower(c.classpathType.String()) + ".pb" - c.outputFilepath = android.PathForModuleOut(ctx, outputFilename).OutputPath - c.installDirPath = android.PathForModuleInstall(ctx, "etc", "classpaths") - - generatedJson := android.PathForModuleOut(ctx, outputFilename+".json") - writeClasspathsJson(ctx, generatedJson, jars) - - rule := android.NewRuleBuilder(pctx, ctx) - rule.Command(). - BuiltTool("conv_classpaths_proto"). - Flag("encode"). - Flag("--format=json"). - FlagWithInput("--input=", generatedJson). - FlagWithOutput("--output=", c.outputFilepath) - - rule.Build("classpath_fragment", "Compiling "+c.outputFilepath.String()) +func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.ModuleContext, configuredJars android.ConfiguredJarList, jars []classpathJar) { + generateProto := proptools.BoolDefault(c.properties.Generate_classpaths_proto, true) + if generateProto { + outputFilename := strings.ToLower(c.classpathType.String()) + ".pb" + c.outputFilepath = android.PathForModuleOut(ctx, outputFilename).OutputPath + c.installDirPath = android.PathForModuleInstall(ctx, "etc", "classpaths") + + generatedTextproto := android.PathForModuleOut(ctx, outputFilename+".textproto") + writeClasspathsTextproto(ctx, generatedTextproto, jars) + + rule := android.NewRuleBuilder(pctx, ctx) + rule.Command(). + BuiltTool("conv_classpaths_proto"). + Flag("encode"). + Flag("--format=textproto"). + FlagWithInput("--input=", generatedTextproto). + FlagWithOutput("--output=", c.outputFilepath) + + rule.Build("classpath_fragment", "Compiling "+c.outputFilepath.String()) + } classpathProtoInfo := ClasspathFragmentProtoContentInfo{ + ClasspathFragmentProtoGenerated: generateProto, + ClasspathFragmentProtoContents: configuredJars, ClasspathFragmentProtoInstallDir: c.installDirPath, ClasspathFragmentProtoOutput: c.outputFilepath, } ctx.SetProvider(ClasspathFragmentProtoContentInfoProvider, classpathProtoInfo) } -func writeClasspathsJson(ctx android.ModuleContext, output android.WritablePath, jars []classpathJar) { +func writeClasspathsTextproto(ctx android.ModuleContext, output android.WritablePath, jars []classpathJar) { var content strings.Builder - fmt.Fprintf(&content, "{\n") - fmt.Fprintf(&content, "\"jars\": [\n") - for idx, jar := range jars { - fmt.Fprintf(&content, "{\n") - - fmt.Fprintf(&content, "\"path\": \"%s\",\n", jar.path) - fmt.Fprintf(&content, "\"classpath\": \"%s\"\n", jar.classpath) - if idx < len(jars)-1 { - fmt.Fprintf(&content, "},\n") - } else { - fmt.Fprintf(&content, "}\n") - } + for _, jar := range jars { + fmt.Fprintf(&content, "jars {\n") + fmt.Fprintf(&content, "path: \"%s\"\n", jar.path) + fmt.Fprintf(&content, "classpath: %s\n", jar.classpath) + fmt.Fprintf(&content, "min_sdk_version: \"%s\"\n", jar.minSdkVersion) + fmt.Fprintf(&content, "max_sdk_version: \"%s\"\n", jar.maxSdkVersion) + fmt.Fprintf(&content, "}\n") } - fmt.Fprintf(&content, "]\n") - fmt.Fprintf(&content, "}\n") + android.WriteFileRule(ctx, output, content.String()) } @@ -191,6 +213,12 @@ func (c *ClasspathFragmentBase) androidMkEntries() []android.AndroidMkEntries { var ClasspathFragmentProtoContentInfoProvider = blueprint.NewProvider(ClasspathFragmentProtoContentInfo{}) type ClasspathFragmentProtoContentInfo struct { + // Whether the classpaths.proto config is generated for the fragment. + ClasspathFragmentProtoGenerated bool + + // ClasspathFragmentProtoContents contains a list of jars that are part of this classpath fragment. + ClasspathFragmentProtoContents android.ConfiguredJarList + // ClasspathFragmentProtoOutput is an output path for the generated classpaths.proto config of this module. // // The file should be copied to a relevant place on device, see ClasspathFragmentProtoInstallDir diff --git a/java/dex.go b/java/dex.go index 7898e9dff..1acfebd51 100644 --- a/java/dex.go +++ b/java/dex.go @@ -69,6 +69,9 @@ type DexProperties struct { // This defaults to reasonable value based on module and should not be set. // It exists only to support ART tests. Uncompress_dex *bool + + // Exclude kotlinc generate files: *.kotlin_module, *.kotlin_builtins. Defaults to false. + Exclude_kotlinc_generated_files *bool } type dexer struct { @@ -89,7 +92,7 @@ var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8", Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + `$d8Template${config.D8Cmd} ${config.DexFlags} --output $outDir $d8Flags $in && ` + `$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` + - `${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`, + `${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in`, CommandDeps: []string{ "${config.D8Cmd}", "${config.SoongZipCmd}", @@ -110,7 +113,7 @@ var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8", ExecStrategy: "${config.RED8ExecStrategy}", Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, }, - }, []string{"outDir", "d8Flags", "zipFlags"}, nil) + }, []string{"outDir", "d8Flags", "zipFlags", "mergeZipsFlags"}, nil) var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8", blueprint.RuleParams{ @@ -126,7 +129,7 @@ var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8", `${config.SoongZipCmd} -o ${outUsageZip} -C ${outUsageDir} -f ${outUsage} && ` + `rm -rf ${outUsageDir} && ` + `$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` + - `${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`, + `${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in`, CommandDeps: []string{ "${config.R8Cmd}", "${config.SoongZipCmd}", @@ -156,7 +159,7 @@ var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8", Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, }, }, []string{"outDir", "outDict", "outUsage", "outUsageZip", "outUsageDir", - "r8Flags", "zipFlags"}, []string{"implicits"}) + "r8Flags", "zipFlags", "mergeZipsFlags"}, []string{"implicits"}) func (d *dexer) dexCommonFlags(ctx android.ModuleContext, minSdkVersion android.SdkSpec) []string { flags := d.dexProperties.Dxflags @@ -281,6 +284,12 @@ func (d *dexer) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, mi commonFlags := d.dexCommonFlags(ctx, minSdkVersion) + // Exclude kotlinc generated files when "exclude_kotlinc_generated_files" is set to true. + mergeZipsFlags := "" + if proptools.BoolDefault(d.dexProperties.Exclude_kotlinc_generated_files, false) { + mergeZipsFlags = "-stripFile META-INF/*.kotlin_module -stripFile **/*.kotlin_builtins" + } + useR8 := d.effectiveOptimizeEnabled() if useR8 { proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary") @@ -293,13 +302,14 @@ func (d *dexer) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, mi r8Flags, r8Deps := d.r8Flags(ctx, flags) rule := r8 args := map[string]string{ - "r8Flags": strings.Join(append(commonFlags, r8Flags...), " "), - "zipFlags": zipFlags, - "outDict": proguardDictionary.String(), - "outUsageDir": proguardUsageDir.String(), - "outUsage": proguardUsage.String(), - "outUsageZip": proguardUsageZip.String(), - "outDir": outDir.String(), + "r8Flags": strings.Join(append(commonFlags, r8Flags...), " "), + "zipFlags": zipFlags, + "outDict": proguardDictionary.String(), + "outUsageDir": proguardUsageDir.String(), + "outUsage": proguardUsage.String(), + "outUsageZip": proguardUsageZip.String(), + "outDir": outDir.String(), + "mergeZipsFlags": mergeZipsFlags, } if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_R8") { rule = r8RE @@ -327,9 +337,10 @@ func (d *dexer) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, mi Input: classesJar, Implicits: d8Deps, Args: map[string]string{ - "d8Flags": strings.Join(append(commonFlags, d8Flags...), " "), - "zipFlags": zipFlags, - "outDir": outDir.String(), + "d8Flags": strings.Join(append(commonFlags, d8Flags...), " "), + "zipFlags": zipFlags, + "outDir": outDir.String(), + "mergeZipsFlags": mergeZipsFlags, }, }) } diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index 19c65cac7..a9ace19da 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -158,8 +158,10 @@ import ( // name (if the library is a part of the Platform), or a colon-separated pair <apex, name> (if the // library is a part of a non-updatable APEX). // -// A related variable PRODUCT_UPDATABLE_BOOT_JARS contains bootclasspath libraries that are in -// updatable APEXes. They are not included in the boot image. +// A related variable PRODUCT_APEX_BOOT_JARS contains bootclasspath libraries that are in APEXes. +// They are not included in the boot image. The only exception here are ART jars and core-icu4j.jar +// that have been historically part of the boot image and are now in apexes; they are in boot images +// and core-icu4j.jar is generally treated as being part of PRODUCT_BOOT_JARS. // // One exception to the above rules are "coverage" builds (a special build flavor which requires // setting environment variable EMMA_INSTRUMENT_FRAMEWORK=true). In coverage builds the Java code in @@ -799,10 +801,10 @@ func bootFrameworkProfileRule(ctx android.ModuleContext, image *bootImageConfig) // generateUpdatableBcpPackagesRule generates the rule to create the updatable-bcp-packages.txt file // and returns a path to the generated file. -func generateUpdatableBcpPackagesRule(ctx android.ModuleContext, image *bootImageConfig, updatableModules []android.Module) android.WritablePath { +func generateUpdatableBcpPackagesRule(ctx android.ModuleContext, image *bootImageConfig, apexModules []android.Module) android.WritablePath { // Collect `permitted_packages` for updatable boot jars. var updatablePackages []string - for _, module := range updatableModules { + for _, module := range apexModules { if j, ok := module.(PermittedPackagesForUpdatableBootJars); ok { pp := j.PermittedPackagesForUpdatableBootJars() if len(pp) > 0 { diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go index b13955fba..9d16aa20e 100644 --- a/java/dexpreopt_config.go +++ b/java/dexpreopt_config.go @@ -142,14 +142,14 @@ func defaultBootImageConfig(ctx android.PathContext) *bootImageConfig { return genBootImageConfigs(ctx)[frameworkBootImageName] } -// Updatable boot config allows to access build/install paths of updatable boot jars without going +// Apex boot config allows to access build/install paths of apex boot jars without going // through the usual trouble of registering dependencies on those modules and extracting build paths // from those dependencies. -type updatableBootConfig struct { - // A list of updatable boot jars. +type apexBootConfig struct { + // A list of apex boot jars. modules android.ConfiguredJarList - // A list of predefined build paths to updatable boot jars. They are configured very early, + // A list of predefined build paths to apex boot jars. They are configured very early, // before the modules for these jars are processed and the actual paths are generated, and // later on a singleton adds commands to copy actual jars to the predefined paths. dexPaths android.WritablePaths @@ -161,21 +161,21 @@ type updatableBootConfig struct { dexLocations []string } -var updatableBootConfigKey = android.NewOnceKey("updatableBootConfig") +var updatableBootConfigKey = android.NewOnceKey("apexBootConfig") -// Returns updatable boot config. -func GetUpdatableBootConfig(ctx android.PathContext) updatableBootConfig { +// Returns apex boot config. +func GetApexBootConfig(ctx android.PathContext) apexBootConfig { return ctx.Config().Once(updatableBootConfigKey, func() interface{} { - updatableBootJars := dexpreopt.GetGlobalConfig(ctx).UpdatableBootJars + apexBootJars := dexpreopt.GetGlobalConfig(ctx).ApexBootJars - dir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "updatable_bootjars") - dexPaths := updatableBootJars.BuildPaths(ctx, dir) - dexPathsByModuleName := updatableBootJars.BuildPathsByModule(ctx, dir) + dir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "apex_bootjars") + dexPaths := apexBootJars.BuildPaths(ctx, dir) + dexPathsByModuleName := apexBootJars.BuildPathsByModule(ctx, dir) - dexLocations := updatableBootJars.DevicePaths(ctx.Config(), android.Android) + dexLocations := apexBootJars.DevicePaths(ctx.Config(), android.Android) - return updatableBootConfig{updatableBootJars, dexPaths, dexPathsByModuleName, dexLocations} - }).(updatableBootConfig) + return apexBootConfig{apexBootJars, dexPaths, dexPathsByModuleName, dexLocations} + }).(apexBootConfig) } // Returns a list of paths and a list of locations for the boot jars used in dexpreopt (to be @@ -188,10 +188,10 @@ func bcpForDexpreopt(ctx android.PathContext, withUpdatable bool) (android.Writa dexLocations := bootImage.getAnyAndroidVariant().dexLocationsDeps if withUpdatable { - // Updatable boot jars (they are used only in dexpreopt, but not in the boot image). - updBootConfig := GetUpdatableBootConfig(ctx) - dexPaths = append(dexPaths, updBootConfig.dexPaths...) - dexLocations = append(dexLocations, updBootConfig.dexLocations...) + // Apex boot jars (they are used only in dexpreopt, but not in the boot image). + apexBootConfig := GetApexBootConfig(ctx) + dexPaths = append(dexPaths, apexBootConfig.dexPaths...) + dexLocations = append(dexLocations, apexBootConfig.dexLocations...) } return dexPaths, dexLocations diff --git a/java/droidstubs.go b/java/droidstubs.go index c756815c6..a1a8c2e7d 100644 --- a/java/droidstubs.go +++ b/java/droidstubs.go @@ -16,6 +16,7 @@ package java import ( "fmt" + "path/filepath" "strings" "github.com/google/blueprint/proptools" @@ -153,6 +154,7 @@ type ApiStubsSrcProvider interface { // Provider of information about API stubs, used by java_sdk_library. type ApiStubsProvider interface { + AnnotationsZip() android.Path ApiFilePath RemovedApiFilePath() android.Path @@ -207,6 +209,10 @@ func (d *Droidstubs) OutputFiles(tag string) (android.Paths, error) { } } +func (d *Droidstubs) AnnotationsZip() android.Path { + return d.annotationsZip +} + func (d *Droidstubs) ApiFilePath() android.Path { return d.apiFilePath } @@ -767,7 +773,7 @@ type PrebuiltStubsSources struct { properties PrebuiltStubsSourcesProperties - stubsSrcJar android.ModuleOutPath + stubsSrcJar android.Path } func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) { @@ -784,35 +790,39 @@ func (d *PrebuiltStubsSources) StubsSrcJar() android.Path { } func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) { - p.stubsSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar") - if len(p.properties.Srcs) != 1 { - ctx.PropertyErrorf("srcs", "must only specify one directory path, contains %d paths", len(p.properties.Srcs)) + ctx.PropertyErrorf("srcs", "must only specify one directory path or srcjar, contains %d paths", len(p.properties.Srcs)) return } - localSrcDir := p.properties.Srcs[0] - // Although PathForModuleSrc can return nil if either the path doesn't exist or - // the path components are invalid it won't in this case because no components - // are specified and the module directory must exist in order to get this far. - srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, localSrcDir) + src := p.properties.Srcs[0] + if filepath.Ext(src) == ".srcjar" { + // This is a srcjar. We can use it directly. + p.stubsSrcJar = android.PathForModuleSrc(ctx, src) + } else { + outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar") - // Glob the contents of the directory just in case the directory does not exist. - srcGlob := localSrcDir + "/**/*" - srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob}) + // This is a directory. Glob the contents just in case the directory does not exist. + srcGlob := src + "/**/*" + srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob}) - rule := android.NewRuleBuilder(pctx, ctx) - rule.Command(). - BuiltTool("soong_zip"). - Flag("-write_if_changed"). - Flag("-jar"). - FlagWithOutput("-o ", p.stubsSrcJar). - FlagWithArg("-C ", srcDir.String()). - FlagWithRspFileInputList("-r ", p.stubsSrcJar.ReplaceExtension(ctx, "rsp"), srcPaths) - - rule.Restat() + // Although PathForModuleSrc can return nil if either the path doesn't exist or + // the path components are invalid it won't in this case because no components + // are specified and the module directory must exist in order to get this far. + srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, src) - rule.Build("zip src", "Create srcjar from prebuilt source") + rule := android.NewRuleBuilder(pctx, ctx) + rule.Command(). + BuiltTool("soong_zip"). + Flag("-write_if_changed"). + Flag("-jar"). + FlagWithOutput("-o ", outPath). + FlagWithArg("-C ", srcDir.String()). + FlagWithRspFileInputList("-r ", outPath.ReplaceExtension(ctx, "rsp"), srcPaths) + rule.Restat() + rule.Build("zip src", "Create srcjar from prebuilt source") + p.stubsSrcJar = outPath + } } func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt { diff --git a/java/hiddenapi.go b/java/hiddenapi.go index f901434a0..30683daa0 100644 --- a/java/hiddenapi.go +++ b/java/hiddenapi.go @@ -118,11 +118,11 @@ func (h *hiddenAPI) initHiddenAPI(ctx android.ModuleContext, dexJar, classesJar } func isModuleInBootClassPath(ctx android.BaseModuleContext, module android.Module) bool { - // Get the configured non-updatable and updatable boot jars. - nonUpdatableBootJars := ctx.Config().NonUpdatableBootJars() - updatableBootJars := ctx.Config().UpdatableBootJars() - active := isModuleInConfiguredList(ctx, module, nonUpdatableBootJars) || - isModuleInConfiguredList(ctx, module, updatableBootJars) + // Get the configured platform and apex boot jars. + nonApexBootJars := ctx.Config().NonApexBootJars() + apexBootJars := ctx.Config().ApexBootJars() + active := isModuleInConfiguredList(ctx, module, nonApexBootJars) || + isModuleInConfiguredList(ctx, module, apexBootJars) return active } diff --git a/java/java.go b/java/java.go index bbed42def..a61ddf426 100644 --- a/java/java.go +++ b/java/java.go @@ -450,7 +450,7 @@ type Library struct { var _ android.ApexModule = (*Library)(nil) -// Provides access to the list of permitted packages from updatable boot jars. +// Provides access to the list of permitted packages from apex boot jars. type PermittedPackagesForUpdatableBootJars interface { PermittedPackagesForUpdatableBootJars() []string } @@ -487,6 +487,7 @@ func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bo func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.sdkVersion = j.SdkVersion(ctx) j.minSdkVersion = j.MinSdkVersion(ctx) + j.maxSdkVersion = j.MaxSdkVersion(ctx) apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo) if !apexInfo.IsForPlatform() { diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index 10739b015..ca87f92fd 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -32,9 +32,9 @@ func registerPlatformBootclasspathBuildComponents(ctx android.RegistrationContex // The tags used for the dependencies between the platform bootclasspath and any configured boot // jars. var ( - platformBootclasspathArtBootJarDepTag = bootclasspathDependencyTag{name: "art-boot-jar"} - platformBootclasspathNonUpdatableBootJarDepTag = bootclasspathDependencyTag{name: "non-updatable-boot-jar"} - platformBootclasspathUpdatableBootJarDepTag = bootclasspathDependencyTag{name: "updatable-boot-jar"} + platformBootclasspathArtBootJarDepTag = bootclasspathDependencyTag{name: "art-boot-jar"} + platformBootclasspathBootJarDepTag = bootclasspathDependencyTag{name: "platform-boot-jar"} + platformBootclasspathApexBootJarDepTag = bootclasspathDependencyTag{name: "apex-boot-jar"} ) type platformBootclasspathModule struct { @@ -68,7 +68,6 @@ type platformBootclasspathProperties struct { func platformBootclasspathFactory() android.SingletonModule { m := &platformBootclasspathModule{} m.AddProperties(&m.properties) - // TODO(satayev): split apex jars into separate configs. initClasspathFragment(m, BOOTCLASSPATH) android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) return m @@ -131,11 +130,11 @@ func (b *platformBootclasspathModule) BootclasspathDepsMutator(ctx android.Botto // Add dependencies on all the non-updatable module configured in the "boot" boot image. That does // not include modules configured in the "art" boot image. bootImageConfig := b.getImageConfig(ctx) - addDependenciesOntoBootImageModules(ctx, bootImageConfig.modules, platformBootclasspathNonUpdatableBootJarDepTag) + addDependenciesOntoBootImageModules(ctx, bootImageConfig.modules, platformBootclasspathBootJarDepTag) - // Add dependencies on all the updatable modules. - updatableModules := dexpreopt.GetGlobalConfig(ctx).UpdatableBootJars - addDependenciesOntoBootImageModules(ctx, updatableModules, platformBootclasspathUpdatableBootJarDepTag) + // Add dependencies on all the apex jars. + apexJars := dexpreopt.GetGlobalConfig(ctx).ApexBootJars + addDependenciesOntoBootImageModules(ctx, apexJars, platformBootclasspathApexBootJarDepTag) // Add dependencies on all the fragments. b.properties.BootclasspathFragmentsDepsProperties.addDependenciesOntoFragments(ctx) @@ -163,16 +162,16 @@ func (d *platformBootclasspathModule) MakeVars(ctx android.MakeVarsContext) { } func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { - // Gather all the dependencies from the art, updatable and non-updatable boot jars. + // Gather all the dependencies from the art, platform, and apex boot jars. artModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathArtBootJarDepTag) - nonUpdatableModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathNonUpdatableBootJarDepTag) - updatableModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathUpdatableBootJarDepTag) + platformModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathBootJarDepTag) + apexModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathApexBootJarDepTag) // Concatenate them all, in order as they would appear on the bootclasspath. var allModules []android.Module allModules = append(allModules, artModules...) - allModules = append(allModules, nonUpdatableModules...) - allModules = append(allModules, updatableModules...) + allModules = append(allModules, platformModules...) + allModules = append(allModules, apexModules...) b.configuredModules = allModules // Gather all the fragments dependencies. @@ -180,8 +179,8 @@ func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.Mo // Check the configuration of the boot modules. // ART modules are checked by the art-bootclasspath-fragment. - b.checkNonUpdatableModules(ctx, nonUpdatableModules) - b.checkUpdatableModules(ctx, updatableModules) + b.checkPlatformModules(ctx, platformModules) + b.checkApexModules(ctx, apexModules) b.generateClasspathProtoBuildActions(ctx) @@ -193,23 +192,40 @@ func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.Mo return } - b.generateBootImageBuildActions(ctx, nonUpdatableModules, updatableModules) + b.generateBootImageBuildActions(ctx, platformModules, apexModules) } // Generate classpaths.proto config func (b *platformBootclasspathModule) generateClasspathProtoBuildActions(ctx android.ModuleContext) { + configuredJars := b.configuredJars(ctx) // ART and platform boot jars must have a corresponding entry in DEX2OATBOOTCLASSPATH - classpathJars := configuredJarListToClasspathJars(ctx, b.ClasspathFragmentToConfiguredJarList(ctx), BOOTCLASSPATH, DEX2OATBOOTCLASSPATH) - b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, classpathJars) + classpathJars := configuredJarListToClasspathJars(ctx, configuredJars, BOOTCLASSPATH, DEX2OATBOOTCLASSPATH) + b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars) } -func (b *platformBootclasspathModule) ClasspathFragmentToConfiguredJarList(ctx android.ModuleContext) android.ConfiguredJarList { - return b.getImageConfig(ctx).modules +func (b *platformBootclasspathModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList { + // Include all non APEX jars + jars := b.getImageConfig(ctx).modules + + // Include jars from APEXes that don't populate their classpath proto config. + remainingJars := dexpreopt.GetGlobalConfig(ctx).ApexBootJars + for _, fragment := range b.fragments { + info := ctx.OtherModuleProvider(fragment, ClasspathFragmentProtoContentInfoProvider).(ClasspathFragmentProtoContentInfo) + if info.ClasspathFragmentProtoGenerated { + remainingJars = remainingJars.RemoveList(info.ClasspathFragmentProtoContents) + } + } + for i := 0; i < remainingJars.Len(); i++ { + jars = jars.Append(remainingJars.Apex(i), remainingJars.Jar(i)) + } + + return jars } -// checkNonUpdatableModules ensures that the non-updatable modules supplied are not part of an -// updatable module. -func (b *platformBootclasspathModule) checkNonUpdatableModules(ctx android.ModuleContext, modules []android.Module) { +// checkPlatformModules ensures that the non-updatable modules supplied are not part of an +// apex module. +func (b *platformBootclasspathModule) checkPlatformModules(ctx android.ModuleContext, modules []android.Module) { + // TODO(satayev): change this check to only allow core-icu4j, all apex jars should not be here. for _, m := range modules { apexInfo := ctx.OtherModuleProvider(m, android.ApexInfoProvider).(android.ApexInfo) fromUpdatableApex := apexInfo.Updatable @@ -222,8 +238,8 @@ func (b *platformBootclasspathModule) checkNonUpdatableModules(ctx android.Modul } } -// checkUpdatableModules ensures that the updatable modules supplied are not from the platform. -func (b *platformBootclasspathModule) checkUpdatableModules(ctx android.ModuleContext, modules []android.Module) { +// checkApexModules ensures that the apex modules supplied are not from the platform. +func (b *platformBootclasspathModule) checkApexModules(ctx android.ModuleContext, modules []android.Module) { for _, m := range modules { apexInfo := ctx.OtherModuleProvider(m, android.ApexInfoProvider).(android.ApexInfo) fromUpdatableApex := apexInfo.Updatable @@ -239,12 +255,12 @@ func (b *platformBootclasspathModule) checkUpdatableModules(ctx android.ModuleCo // modules is complete. if !ctx.Config().AlwaysUsePrebuiltSdks() { // error: this jar is part of the platform - ctx.ModuleErrorf("module %q from platform is not allowed in the updatable boot jars list", name) + ctx.ModuleErrorf("module %q from platform is not allowed in the apex boot jars list", name) } } else { // TODO(b/177892522): Treat this as an error. // Cannot do that at the moment because framework-wifi and framework-tethering are in the - // PRODUCT_UPDATABLE_BOOT_JARS but not marked as updatable in AOSP. + // PRODUCT_APEX_BOOT_JARS but not marked as updatable in AOSP. } } } @@ -389,7 +405,7 @@ func (b *platformBootclasspathModule) generateHiddenApiMakeVars(ctx android.Make } // generateBootImageBuildActions generates ninja rules related to the boot image creation. -func (b *platformBootclasspathModule) generateBootImageBuildActions(ctx android.ModuleContext, nonUpdatableModules, updatableModules []android.Module) { +func (b *platformBootclasspathModule) generateBootImageBuildActions(ctx android.ModuleContext, platformModules, apexModules []android.Module) { // Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars // GenerateSingletonBuildActions method as it cannot create it for itself. dexpreopt.GetGlobalSoongConfig(ctx) @@ -408,16 +424,16 @@ func (b *platformBootclasspathModule) generateBootImageBuildActions(ctx android. bootFrameworkProfileRule(ctx, imageConfig) // Generate the updatable bootclasspath packages rule. - generateUpdatableBcpPackagesRule(ctx, imageConfig, updatableModules) + generateUpdatableBcpPackagesRule(ctx, imageConfig, apexModules) - // Copy non-updatable module dex jars to their predefined locations. - nonUpdatableBootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, nonUpdatableModules) - copyBootJarsToPredefinedLocations(ctx, nonUpdatableBootDexJarsByModule, imageConfig.dexPathsByModule) + // Copy platform module dex jars to their predefined locations. + platformBootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, platformModules) + copyBootJarsToPredefinedLocations(ctx, platformBootDexJarsByModule, imageConfig.dexPathsByModule) - // Copy updatable module dex jars to their predefined locations. - config := GetUpdatableBootConfig(ctx) - updatableBootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, updatableModules) - copyBootJarsToPredefinedLocations(ctx, updatableBootDexJarsByModule, config.dexPathsByModule) + // Copy apex module dex jars to their predefined locations. + config := GetApexBootConfig(ctx) + apexBootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, apexModules) + copyBootJarsToPredefinedLocations(ctx, apexBootDexJarsByModule, config.dexPathsByModule) // Build a profile for the image config and then use that to build the boot image. profile := bootImageProfileRule(ctx, imageConfig) diff --git a/java/sdk_library.go b/java/sdk_library.go index 8c664383d..ad6d2ed60 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -376,6 +376,9 @@ type ApiScopeProperties struct { } type sdkLibraryProperties struct { + // List of source files that are needed to compile the API, but are not part of runtime library. + Api_srcs []string `android:"arch_variant"` + // Visibility for impl library module. If not specified then defaults to the // visibility property. Impl_library_visibility []string @@ -547,6 +550,9 @@ type scopePaths struct { // The stubs source jar. stubsSrcJar android.OptionalPath + + // Extracted annotations. + annotationsZip android.OptionalPath } func (paths *scopePaths) extractStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.Module) error { @@ -582,6 +588,7 @@ func (paths *scopePaths) treatDepAsApiStubsSrcProvider(dep android.Module, actio } func (paths *scopePaths) extractApiInfoFromApiStubsProvider(provider ApiStubsProvider) { + paths.annotationsZip = android.OptionalPathForPath(provider.AnnotationsZip()) paths.currentApiFilePath = android.OptionalPathForPath(provider.ApiFilePath()) paths.removedApiFilePath = android.OptionalPathForPath(provider.RemovedApiFilePath()) } @@ -736,6 +743,8 @@ const ( apiTxtComponentName = "api.txt" removedApiTxtComponentName = "removed-api.txt" + + annotationsComponentName = "annotations.zip" ) // A regular expression to match tags that reference a specific stubs component. @@ -754,7 +763,7 @@ var tagSplitter = func() *regexp.Regexp { scopesRegexp := choice(allScopeNames...) // Regular expression to match one of the components. - componentsRegexp := choice(stubsSourceComponentName, apiTxtComponentName, removedApiTxtComponentName) + componentsRegexp := choice(stubsSourceComponentName, apiTxtComponentName, removedApiTxtComponentName, annotationsComponentName) // Regular expression to match any combination of one scope and one component. return regexp.MustCompile(fmt.Sprintf(`^\.(%s)\.(%s)$`, scopesRegexp, componentsRegexp)) @@ -762,9 +771,7 @@ var tagSplitter = func() *regexp.Regexp { // For OutputFileProducer interface // -// .<scope>.stubs.source -// .<scope>.api.txt -// .<scope>.removed-api.txt +// .<scope>.<component name>, for all ComponentNames (for example: .public.removed-api.txt) func (c *commonToSdkLibraryAndImport) commonOutputFiles(tag string) (android.Paths, error) { if groups := tagSplitter.FindStringSubmatch(tag); groups != nil { scopeName := groups[1] @@ -791,6 +798,11 @@ func (c *commonToSdkLibraryAndImport) commonOutputFiles(tag string) (android.Pat if paths.removedApiFilePath.Valid() { return android.Paths{paths.removedApiFilePath.Path()}, nil } + + case annotationsComponentName: + if paths.annotationsZip.Valid() { + return android.Paths{paths.annotationsZip.Path()}, nil + } } return nil, fmt.Errorf("%s not available for api scope %s", component, scopeName) @@ -1110,6 +1122,22 @@ func (module *SdkLibrary) getGeneratedApiScopes(ctx android.EarlyModuleContext) return generatedScopes } +var _ android.ModuleWithMinSdkVersionCheck = (*SdkLibrary)(nil) + +func (module *SdkLibrary) CheckMinSdkVersion(ctx android.ModuleContext) { + android.CheckMinSdkVersion(ctx, module.MinSdkVersion(ctx).ApiLevel, func(c android.ModuleContext, do android.PayloadDepsCallback) { + ctx.WalkDeps(func(child android.Module, parent android.Module) bool { + isExternal := !module.depIsInSameApex(ctx, child) + if am, ok := child.(android.ApexModule); ok { + if !do(ctx, parent, am, isExternal) { + return false + } + } + return !isExternal + }) + }) +} + type sdkLibraryComponentTag struct { blueprint.BaseDependencyTag name string @@ -1195,6 +1223,10 @@ func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) { } func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { + if proptools.String(module.deviceProperties.Min_sdk_version) != "" { + module.CheckMinSdkVersion(ctx) + } + module.generateCommonBuildActions(ctx) // Only build an implementation library if required. @@ -1442,6 +1474,7 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC props.Name = proptools.StringPtr(name) props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_source_visibility) props.Srcs = append(props.Srcs, module.properties.Srcs...) + props.Srcs = append(props.Srcs, module.sdkLibraryProperties.Api_srcs...) props.Sdk_version = module.deviceProperties.Sdk_version props.System_modules = module.deviceProperties.System_modules props.Installable = proptools.BoolPtr(false) @@ -1884,6 +1917,9 @@ type sdkLibraryScopeProperties struct { // The removed.txt Removed_api *string `android:"path"` + + // Annotation zip + Annotations *string `android:"path"` } type sdkLibraryImportProperties struct { @@ -2134,7 +2170,15 @@ func (module *SdkLibraryImport) UniqueApexVariations() bool { } func (module *SdkLibraryImport) OutputFiles(tag string) (android.Paths, error) { - return module.commonOutputFiles(tag) + paths, err := module.commonOutputFiles(tag) + if paths != nil || err != nil { + return paths, err + } + if module.implLibraryModule != nil { + return module.implLibraryModule.OutputFiles(tag) + } else { + return nil, nil + } } func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -2185,6 +2229,7 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo } paths := module.getScopePathsCreateIfNeeded(apiScope) + paths.annotationsZip = android.OptionalPathForModuleSrc(ctx, scopeProperties.Annotations) paths.currentApiFilePath = android.OptionalPathForModuleSrc(ctx, scopeProperties.Current_api) paths.removedApiFilePath = android.OptionalPathForModuleSrc(ctx, scopeProperties.Removed_api) } @@ -2449,12 +2494,12 @@ func (module *sdkLibraryXml) GenerateAndroidBuildActions(ctx android.ModuleConte func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries { if module.hideApexVariantFromMake { - return []android.AndroidMkEntries{android.AndroidMkEntries{ + return []android.AndroidMkEntries{{ Disabled: true, }} } - return []android.AndroidMkEntries{android.AndroidMkEntries{ + return []android.AndroidMkEntries{{ Class: "ETC", OutputFile: android.OptionalPathForPath(module.outputFilePath), ExtraEntries: []android.AndroidMkExtraEntriesFunc{ @@ -2499,7 +2544,7 @@ type sdkLibrarySdkMemberProperties struct { android.SdkMemberPropertiesBase // Scope to per scope properties. - Scopes map[*apiScope]scopeProperties + Scopes map[*apiScope]*scopeProperties // The Java stubs source files. Stub_srcs []string @@ -2525,13 +2570,14 @@ type scopeProperties struct { StubsSrcJar android.Path CurrentApiFile android.Path RemovedApiFile android.Path + AnnotationsZip android.Path `supported_build_releases:"Tiramisu+"` SdkVersion string } func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) { sdk := variant.(*SdkLibrary) - s.Scopes = make(map[*apiScope]scopeProperties) + s.Scopes = make(map[*apiScope]*scopeProperties) for _, apiScope := range allApiScopes { paths := sdk.findScopePaths(apiScope) if paths == nil { @@ -2550,7 +2596,11 @@ func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMembe if paths.removedApiFilePath.Valid() { properties.RemovedApiFile = paths.removedApiFilePath.Path() } - s.Scopes[apiScope] = properties + // The annotations zip is only available for modules that set annotations_enabled: true. + if paths.annotationsZip.Valid() { + properties.AnnotationsZip = paths.annotationsZip.Path() + } + s.Scopes[apiScope] = &properties } } @@ -2614,6 +2664,12 @@ func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberCo scopeSet.AddProperty("removed_api", removedApiSnapshotPath) } + if properties.AnnotationsZip != nil { + annotationsSnapshotPath := filepath.Join(scopeDir, ctx.Name()+"_annotations.zip") + ctx.SnapshotBuilder().CopyToSnapshot(properties.AnnotationsZip, annotationsSnapshotPath) + scopeSet.AddProperty("annotations", annotationsSnapshotPath) + } + if properties.SdkVersion != "" { scopeSet.AddProperty("sdk_version", properties.SdkVersion) } diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go index 65af95314..f8717c066 100644 --- a/java/sdk_library_test.go +++ b/java/sdk_library_test.go @@ -47,6 +47,7 @@ func TestJavaSdkLibrary(t *testing.T) { name: "bar", srcs: ["a.java", "b.java"], api_packages: ["bar"], + exclude_kotlinc_generated_files: true, } java_library { name: "baz", @@ -159,6 +160,14 @@ func TestJavaSdkLibrary(t *testing.T) { sdkLibs := quxLib.ClassLoaderContexts().UsesLibs() android.AssertDeepEquals(t, "qux exports", []string{"foo", "bar", "fred", "quuz"}, sdkLibs) } + + fooDexJar := result.ModuleForTests("foo", "android_common").Rule("d8") + // tests if kotlinc generated files are NOT excluded from output of foo. + android.AssertStringDoesNotContain(t, "foo dex", fooDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module") + + barDexJar := result.ModuleForTests("bar", "android_common").Rule("d8") + // tests if kotlinc generated files are excluded from output of bar. + android.AssertStringDoesContain(t, "bar dex", barDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module") } func TestJavaSdkLibrary_StubOrImplOnlyLibs(t *testing.T) { @@ -247,7 +256,7 @@ func TestJavaSdkLibrary_DoNotAccessImplWhenItIsNotBuilt(t *testing.T) { } } -func TestJavaSdkLibrary_UseSourcesFromAnotherSdkLibrary(t *testing.T) { +func TestJavaSdkLibrary_AccessOutputFiles(t *testing.T) { android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, @@ -257,6 +266,31 @@ func TestJavaSdkLibrary_UseSourcesFromAnotherSdkLibrary(t *testing.T) { name: "foo", srcs: ["a.java"], api_packages: ["foo"], + annotations_enabled: true, + public: { + enabled: true, + }, + } + java_library { + name: "bar", + srcs: ["b.java", ":foo{.public.stubs.source}"], + java_resources: [":foo{.public.annotations.zip}"], + } + `) +} + +func TestJavaSdkLibrary_AccessOutputFiles_NoAnnotations(t *testing.T) { + android.GroupFixturePreparers( + prepareForJavaTest, + PrepareForTestWithJavaSdkLibraryFiles, + FixtureWithLastReleaseApis("foo"), + ). + ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "bar" variant "android_common": path dependency ":foo{.public.annotations.zip}": annotations.zip not available for api scope public`)). + RunTestWithBp(t, ` + java_sdk_library { + name: "foo", + srcs: ["a.java"], + api_packages: ["foo"], public: { enabled: true, }, @@ -265,6 +299,7 @@ func TestJavaSdkLibrary_UseSourcesFromAnotherSdkLibrary(t *testing.T) { java_library { name: "bar", srcs: ["b.java", ":foo{.public.stubs.source}"], + java_resources: [":foo{.public.annotations.zip}"], } `) } @@ -328,6 +363,7 @@ func TestJavaSdkLibraryImport_AccessOutputFiles(t *testing.T) { stub_srcs: ["a.java"], current_api: "api/current.txt", removed_api: "api/removed.txt", + annotations: "x/annotations.zip", }, } @@ -337,6 +373,7 @@ func TestJavaSdkLibraryImport_AccessOutputFiles(t *testing.T) { java_resources: [ ":foo{.public.api.txt}", ":foo{.public.removed-api.txt}", + ":foo{.public.annotations.zip}", ], } `) @@ -930,3 +967,87 @@ func TestJavaSdkLibraryDist(t *testing.T) { }) } } + +func TestSdkLibrary_CheckMinSdkVersion(t *testing.T) { + preparer := android.GroupFixturePreparers( + PrepareForTestWithJavaBuildComponents, + PrepareForTestWithJavaDefaultModules, + PrepareForTestWithJavaSdkLibraryFiles, + ) + + preparer.RunTestWithBp(t, ` + java_sdk_library { + name: "sdklib", + srcs: ["a.java"], + static_libs: ["util"], + min_sdk_version: "30", + unsafe_ignore_missing_latest_api: true, + } + + java_library { + name: "util", + srcs: ["a.java"], + min_sdk_version: "30", + } + `) + + preparer. + RunTestWithBp(t, ` + java_sdk_library { + name: "sdklib", + srcs: ["a.java"], + libs: ["util"], + impl_only_libs: ["util"], + stub_only_libs: ["util"], + stub_only_static_libs: ["util"], + min_sdk_version: "30", + unsafe_ignore_missing_latest_api: true, + } + + java_library { + name: "util", + srcs: ["a.java"], + } + `) + + preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "util".*should support min_sdk_version\(30\)`)). + RunTestWithBp(t, ` + java_sdk_library { + name: "sdklib", + srcs: ["a.java"], + static_libs: ["util"], + min_sdk_version: "30", + unsafe_ignore_missing_latest_api: true, + } + + java_library { + name: "util", + srcs: ["a.java"], + min_sdk_version: "31", + } + `) + + preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "another_util".*should support min_sdk_version\(30\)`)). + RunTestWithBp(t, ` + java_sdk_library { + name: "sdklib", + srcs: ["a.java"], + static_libs: ["util"], + min_sdk_version: "30", + unsafe_ignore_missing_latest_api: true, + } + + java_library { + name: "util", + srcs: ["a.java"], + static_libs: ["another_util"], + min_sdk_version: "30", + } + + java_library { + name: "another_util", + srcs: ["a.java"], + min_sdk_version: "31", + } + `) +} diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go index a2006b778..be28fe9c2 100644 --- a/java/systemserver_classpath_fragment.go +++ b/java/systemserver_classpath_fragment.go @@ -48,13 +48,14 @@ func (p *platformSystemServerClasspathModule) AndroidMkEntries() (entries []andr } func (p *platformSystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { - classpathJars := configuredJarListToClasspathJars(ctx, p.ClasspathFragmentToConfiguredJarList(ctx), p.classpathType) - p.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, classpathJars) + configuredJars := p.configuredJars(ctx) + classpathJars := configuredJarListToClasspathJars(ctx, configuredJars, p.classpathType) + p.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars) } -func (p *platformSystemServerClasspathModule) ClasspathFragmentToConfiguredJarList(ctx android.ModuleContext) android.ConfiguredJarList { - global := dexpreopt.GetGlobalConfig(ctx) - return global.SystemServerJars +func (p *platformSystemServerClasspathModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList { + // TODO(satayev): include any apex jars that don't populate their classpath proto config. + return dexpreopt.GetGlobalConfig(ctx).SystemServerJars } type SystemServerClasspathModule struct { @@ -71,10 +72,15 @@ func (s *SystemServerClasspathModule) ShouldSupportSdkVersion(ctx android.BaseMo } type systemServerClasspathFragmentProperties struct { - // The contents of this systemserverclasspath_fragment, could be either java_library, or java_sdk_library. + // List of system_server classpath jars, could be either java_library, or java_sdk_library. // // The order of this list matters as it is the order that is used in the SYSTEMSERVERCLASSPATH. Contents []string + + // List of jars that system_server loads dynamically using separate classloaders. + // + // The order does not matter. + Standalone_contents []string } func systemServerClasspathFactory() android.Module { @@ -87,23 +93,24 @@ func systemServerClasspathFactory() android.Module { } func (s *SystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { - if len(s.properties.Contents) == 0 { - ctx.PropertyErrorf("contents", "empty contents are not allowed") + if len(s.properties.Contents) == 0 && len(s.properties.Standalone_contents) == 0 { + ctx.PropertyErrorf("contents", "Either contents or standalone_contents needs to be non-empty") + } + + if s.ShouldIgnore() { + return } - classpathJars := configuredJarListToClasspathJars(ctx, s.ClasspathFragmentToConfiguredJarList(ctx), s.classpathType) - s.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, classpathJars) + configuredJars := s.configuredJars(ctx) + classpathJars := configuredJarListToClasspathJars(ctx, configuredJars, s.classpathType) + s.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars) } -func (s *SystemServerClasspathModule) ClasspathFragmentToConfiguredJarList(ctx android.ModuleContext) android.ConfiguredJarList { +func (s *SystemServerClasspathModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList { global := dexpreopt.GetGlobalConfig(ctx) - possibleUpdatableModules := gatherPossibleUpdatableModuleNamesAndStems(ctx, s.properties.Contents, systemServerClasspathFragmentContentDepTag) - - // Only create configs for updatable boot jars. Non-updatable system server jars must be part of the - // platform_systemserverclasspath's classpath proto config to guarantee that they come before any - // updatable jars at runtime. - return global.UpdatableSystemServerJars.Filter(possibleUpdatableModules) + possibleUpdatableModules := gatherPossibleApexModuleNamesAndStems(ctx, s.properties.Contents, systemServerClasspathFragmentContentDepTag) + return global.ApexSystemServerJars.Filter(possibleUpdatableModules) } type systemServerClasspathFragmentContentDependencyTag struct { @@ -130,8 +137,17 @@ func IsSystemServerClasspathFragmentContentDepTag(tag blueprint.DependencyTag) b func (s *SystemServerClasspathModule) ComponentDepsMutator(ctx android.BottomUpMutatorContext) { module := ctx.Module() + var deps []string + deps = append(deps, s.properties.Contents...) + deps = append(deps, s.properties.Standalone_contents...) - for _, name := range s.properties.Contents { + for _, name := range deps { ctx.AddDependency(module, systemServerClasspathFragmentContentDepTag, name) } } + +func (s *SystemServerClasspathModule) ShouldIgnore() bool { + // Ignore this `systemserverclasspath_fragment` if it only contains `standalone_contents` because + // it is for T and above. + return len(s.properties.Contents) == 0 +} diff --git a/java/systemserver_classpath_fragment_test.go b/java/systemserver_classpath_fragment_test.go index 9ad50dd4a..ba328e7b1 100644 --- a/java/systemserver_classpath_fragment_test.go +++ b/java/systemserver_classpath_fragment_test.go @@ -99,7 +99,7 @@ func TestPlatformSystemServerClasspathModule_AndroidMkEntries(t *testing.T) { func TestSystemServerClasspathFragmentWithoutContents(t *testing.T) { prepareForTestWithSystemServerClasspath. ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern( - `\Qempty contents are not allowed\E`)). + `\QEither contents or standalone_contents needs to be non-empty\E`)). RunTestWithBp(t, ` systemserverclasspath_fragment { name: "systemserverclasspath-fragment", diff --git a/java/testing.go b/java/testing.go index 3ef51bd4d..243e5e849 100644 --- a/java/testing.go +++ b/java/testing.go @@ -54,6 +54,8 @@ var PrepareForTestWithJavaBuildComponents = android.GroupFixturePreparers( "build/soong/java/lint_defaults.txt": nil, // Needed for apps that do not provide their own. "build/make/target/product/security": nil, + // Required to generate Java used-by API coverage + "build/soong/scripts/gen_java_usedby_apex.sh": nil, }.AddToFixture(), ) @@ -214,15 +216,15 @@ func FixtureConfigureBootJars(bootJars ...string) android.FixturePreparer { ) } -// FixtureConfigureUpdatableBootJars configures the updatable boot jars in both the +// FixtureConfigureApexBootJars configures the apex boot jars in both the // dexpreopt.GlobalConfig and Config.productVariables structs. As a side effect that enables // dexpreopt. -func FixtureConfigureUpdatableBootJars(bootJars ...string) android.FixturePreparer { +func FixtureConfigureApexBootJars(bootJars ...string) android.FixturePreparer { return android.GroupFixturePreparers( android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { - variables.UpdatableBootJars = android.CreateTestConfiguredJarList(bootJars) + variables.ApexBootJars = android.CreateTestConfiguredJarList(bootJars) }), - dexpreopt.FixtureSetUpdatableBootJars(bootJars...), + dexpreopt.FixtureSetApexBootJars(bootJars...), // Add a fake dex2oatd module. dexpreopt.PrepareForTestWithFakeDex2oatd, @@ -280,6 +282,7 @@ func gatherRequiredDepsForTest() string { "kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8", "kotlin-annotations", + "stub-annotations", } for _, extra := range extraModules { @@ -364,6 +367,17 @@ func CheckPlatformBootclasspathModules(t *testing.T, result *android.TestResult, android.AssertDeepEquals(t, fmt.Sprintf("%s modules", "platform-bootclasspath"), expected, pairs) } +func CheckClasspathFragmentProtoContentInfoProvider(t *testing.T, result *android.TestResult, generated bool, contents, outputFilename, installDir string) { + t.Helper() + p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule) + info := result.ModuleProvider(p, ClasspathFragmentProtoContentInfoProvider).(ClasspathFragmentProtoContentInfo) + + android.AssertBoolEquals(t, "classpath proto generated", generated, info.ClasspathFragmentProtoGenerated) + android.AssertStringEquals(t, "classpath proto contents", contents, info.ClasspathFragmentProtoContents.String()) + android.AssertStringEquals(t, "output filepath", outputFilename, info.ClasspathFragmentProtoOutput.Base()) + android.AssertPathRelativeToTopEquals(t, "install filepath", installDir, info.ClasspathFragmentProtoInstallDir) +} + // ApexNamePairsFromModules returns the apex:module pair for the supplied modules. func ApexNamePairsFromModules(ctx *android.TestContext, modules []android.Module) []string { pairs := []string{} |