Merge "Disable ubsan diagnostics under HWASan."
diff --git a/android/sdk.go b/android/sdk.go
index 36c576d..93beb6e 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -300,6 +300,22 @@
Name() string
}
+// BpPrintable is a marker interface that must be implemented by any struct that is added as a
+// property value.
+type BpPrintable interface {
+ bpPrintable()
+}
+
+// BpPrintableBase must be embedded within any struct that is added as a
+// property value.
+type BpPrintableBase struct {
+}
+
+func (b BpPrintableBase) bpPrintable() {
+}
+
+var _ BpPrintable = BpPrintableBase{}
+
// An individual member of the SDK, includes all of the variants that the SDK
// requires.
type SdkMember interface {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 88da21b..792f7f3 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -1695,6 +1695,36 @@
expectNoLink("libx", "shared_apex10000", "libz", "shared")
}
+func TestApexMinSdkVersion_SupportsCodeNames_JavaLibs(t *testing.T) {
+ testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ java_libs: ["libx"],
+ min_sdk_version: "S",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_library {
+ name: "libx",
+ srcs: ["a.java"],
+ apex_available: [ "myapex" ],
+ sdk_version: "current",
+ min_sdk_version: "S", // should be okay
+ }
+ `,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_version_active_codenames = []string{"S"}
+ variables.Platform_sdk_codename = proptools.StringPtr("S")
+ }),
+ )
+}
+
func TestApexMinSdkVersion_DefaultsToLatest(t *testing.T) {
ctx := testApex(t, `
apex {
@@ -3338,60 +3368,109 @@
}
func TestVndkApexCurrent(t *testing.T) {
- ctx := testApex(t, `
- apex_vndk {
- name: "com.android.vndk.current",
- key: "com.android.vndk.current.key",
- updatable: false,
- }
-
- apex_key {
- name: "com.android.vndk.current.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
- cc_library {
- name: "libvndk",
- srcs: ["mylib.cpp"],
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- system_shared_libs: [],
- stl: "none",
- apex_available: [ "com.android.vndk.current" ],
- }
-
- cc_library {
- name: "libvndksp",
- srcs: ["mylib.cpp"],
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- system_shared_libs: [],
- stl: "none",
- apex_available: [ "com.android.vndk.current" ],
- }
- `+vndkLibrariesTxtFiles("current"))
-
- ensureExactContents(t, ctx, "com.android.vndk.current", "android_common_image", []string{
- "lib/libvndk.so",
- "lib/libvndksp.so",
+ commonFiles := []string{
"lib/libc++.so",
- "lib64/libvndk.so",
- "lib64/libvndksp.so",
"lib64/libc++.so",
"etc/llndk.libraries.29.txt",
"etc/vndkcore.libraries.29.txt",
"etc/vndksp.libraries.29.txt",
"etc/vndkprivate.libraries.29.txt",
"etc/vndkproduct.libraries.29.txt",
- })
+ }
+ testCases := []struct {
+ vndkVersion string
+ expectedFiles []string
+ }{
+ {
+ vndkVersion: "current",
+ expectedFiles: append(commonFiles,
+ "lib/libvndk.so",
+ "lib/libvndksp.so",
+ "lib64/libvndk.so",
+ "lib64/libvndksp.so"),
+ },
+ {
+ vndkVersion: "",
+ expectedFiles: append(commonFiles,
+ // Legacy VNDK APEX contains only VNDK-SP files (of core variant)
+ "lib/libvndksp.so",
+ "lib64/libvndksp.so"),
+ },
+ }
+ for _, tc := range testCases {
+ t.Run("VNDK.current with DeviceVndkVersion="+tc.vndkVersion, func(t *testing.T) {
+ ctx := testApex(t, `
+ apex_vndk {
+ name: "com.android.vndk.current",
+ key: "com.android.vndk.current.key",
+ updatable: false,
+ }
+
+ apex_key {
+ name: "com.android.vndk.current.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libvndk",
+ srcs: ["mylib.cpp"],
+ vendor_available: true,
+ product_available: true,
+ vndk: {
+ enabled: true,
+ },
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "com.android.vndk.current" ],
+ }
+
+ cc_library {
+ name: "libvndksp",
+ srcs: ["mylib.cpp"],
+ vendor_available: true,
+ product_available: true,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "com.android.vndk.current" ],
+ }
+
+ // VNDK-Ext should not cause any problems
+
+ cc_library {
+ name: "libvndk.ext",
+ srcs: ["mylib2.cpp"],
+ vendor: true,
+ vndk: {
+ enabled: true,
+ extends: "libvndk",
+ },
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ cc_library {
+ name: "libvndksp.ext",
+ srcs: ["mylib2.cpp"],
+ vendor: true,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ extends: "libvndksp",
+ },
+ system_shared_libs: [],
+ stl: "none",
+ }
+ `+vndkLibrariesTxtFiles("current"), android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.DeviceVndkVersion = proptools.StringPtr(tc.vndkVersion)
+ }))
+ ensureExactContents(t, ctx, "com.android.vndk.current", "android_common_image", tc.expectedFiles)
+ })
+ }
}
func TestVndkApexWithPrebuilt(t *testing.T) {
diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go
index bd4a9d5..279cf54 100644
--- a/apex/platform_bootclasspath_test.go
+++ b/apex/platform_bootclasspath_test.go
@@ -481,3 +481,62 @@
pairs := java.ApexNamePairsFromModules(ctx, modules)
android.AssertDeepEquals(t, "module dependencies", expected, pairs)
}
+
+// TestPlatformBootclasspath_IncludesRemainingApexJars verifies that any apex boot jar is present in
+// platform_bootclasspath's classpaths.proto config, if the apex does not generate its own config
+// by setting generate_classpaths_proto property to false.
+func TestPlatformBootclasspath_IncludesRemainingApexJars(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForTestWithPlatformBootclasspath,
+ prepareForTestWithMyapex,
+ java.FixtureConfigureUpdatableBootJars("myapex:foo"),
+ android.FixtureWithRootAndroidBp(`
+ platform_bootclasspath {
+ name: "platform-bootclasspath",
+ fragments: [
+ {
+ apex: "myapex",
+ module:"foo-fragment",
+ },
+ ],
+ }
+
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ bootclasspath_fragments: ["foo-fragment"],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ bootclasspath_fragment {
+ name: "foo-fragment",
+ generate_classpaths_proto: false,
+ contents: ["foo"],
+ apex_available: ["myapex"],
+ }
+
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ system_modules: "none",
+ sdk_version: "none",
+ compile_dex: true,
+ apex_available: ["myapex"],
+ permitted_packages: ["foo"],
+ }
+ `),
+ ).RunTest(t)
+
+ java.CheckClasspathFragmentProtoContentInfoProvider(t, result,
+ true, // proto should be generated
+ "myapex:foo", // apex doesn't generate its own config, so must be in platform_bootclasspath
+ "bootclasspath.pb",
+ "out/soong/target/product/test_device/system/etc/classpaths",
+ )
+}
diff --git a/cc/vndk.go b/cc/vndk.go
index dd1c3e1..0b40076 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -371,7 +371,7 @@
if mctx.ModuleName() == "libz" {
return false
}
- return m.ImageVariation().Variation == android.CoreVariation && lib.shared() && m.IsVndkSp()
+ return m.ImageVariation().Variation == android.CoreVariation && lib.shared() && m.IsVndkSp() && !m.IsVndkExt()
}
useCoreVariant := m.VndkVersion() == mctx.DeviceConfig().PlatformVndkVersion() &&
diff --git a/java/base.go b/java/base.go
index a7cc58e..a251c3f 100644
--- a/java/base.go
+++ b/java/base.go
@@ -260,8 +260,8 @@
EmbeddableSdkLibraryComponent
}
-func (e *embeddableInModuleAndImport) initModuleAndImport(moduleBase *android.ModuleBase) {
- e.initSdkLibraryComponent(moduleBase)
+func (e *embeddableInModuleAndImport) initModuleAndImport(module android.Module) {
+ e.initSdkLibraryComponent(module)
}
// Module/Import's DepIsInSameApex(...) delegates to this method.
@@ -1513,12 +1513,8 @@
if sdkSpec.Kind == android.SdkCore {
return nil
}
- ver, err := sdkSpec.EffectiveVersion(ctx)
- if err != nil {
- return err
- }
- if ver.GreaterThan(sdkVersion) {
- return fmt.Errorf("newer SDK(%v)", ver)
+ if sdkSpec.ApiLevel.GreaterThan(sdkVersion) {
+ return fmt.Errorf("newer SDK(%v)", sdkSpec.ApiLevel)
}
return nil
}
diff --git a/java/bootclasspath.go b/java/bootclasspath.go
index eddcc83..ccb69a0 100644
--- a/java/bootclasspath.go
+++ b/java/bootclasspath.go
@@ -144,6 +144,8 @@
// ApexVariantReference specifies a particular apex variant of a module.
type ApexVariantReference struct {
+ android.BpPrintableBase
+
// The name of the module apex variant, i.e. the apex containing the module variant.
//
// If this is not specified then it defaults to "platform" which will cause a dependency to be
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 4d23820..c7249b0 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -496,13 +496,14 @@
// 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.configuredJars(ctx), BOOTCLASSPATH, DEX2OATBOOTCLASSPATH)
+ classpathJars = configuredJarListToClasspathJars(ctx, configuredJars, BOOTCLASSPATH, DEX2OATBOOTCLASSPATH)
} else {
- classpathJars = configuredJarListToClasspathJars(ctx, b.configuredJars(ctx), b.classpathType)
+ classpathJars = configuredJarListToClasspathJars(ctx, configuredJars, b.classpathType)
}
- b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, classpathJars)
+ b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars)
}
func (b *BootclasspathFragmentModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList {
@@ -748,6 +749,9 @@
Stub_libs []string
Core_platform_stub_libs []string
+ // Fragment properties
+ Fragments []ApexVariantReference
+
// Flag files by *hiddenAPIFlagFileCategory
Flag_files_by_category FlagFilesByCategory
@@ -788,6 +792,9 @@
// Copy stub_libs properties.
b.Stub_libs = module.properties.Api.Stub_libs
b.Core_platform_stub_libs = module.properties.Core_platform_api.Stub_libs
+
+ // Copy fragment properties.
+ b.Fragments = module.properties.Fragments
}
func (b *bootclasspathFragmentSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
@@ -810,6 +817,9 @@
corePlatformApiPropertySet := propertySet.AddPropertySet("core_platform_api")
corePlatformApiPropertySet.AddPropertyWithTag("stub_libs", b.Core_platform_stub_libs, requiredMemberDependency)
}
+ if len(b.Fragments) > 0 {
+ propertySet.AddProperty("fragments", b.Fragments)
+ }
hiddenAPISet := propertySet.AddPropertySet("hidden_api")
hiddenAPIDir := "hiddenapi"
diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go
index 3d72580..f7a200a 100644
--- a/java/classpath_fragment.go
+++ b/java/classpath_fragment.go
@@ -106,7 +106,7 @@
return jars
}
-func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.ModuleContext, jars []classpathJar) {
+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"
@@ -129,6 +129,7 @@
classpathProtoInfo := ClasspathFragmentProtoContentInfo{
ClasspathFragmentProtoGenerated: generateProto,
+ ClasspathFragmentProtoContents: configuredJars,
ClasspathFragmentProtoInstallDir: c.installDirPath,
ClasspathFragmentProtoOutput: c.outputFilepath,
}
@@ -177,6 +178,9 @@
// 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/java.go b/java/java.go
index ae8adf2..be1ad87 100644
--- a/java/java.go
+++ b/java/java.go
@@ -643,7 +643,7 @@
module.addHostAndDeviceProperties()
- module.initModuleAndImport(&module.ModuleBase)
+ module.initModuleAndImport(module)
android.InitApexModule(module)
android.InitSdkAwareModule(module)
@@ -1416,12 +1416,8 @@
if sdkSpec.Kind == android.SdkCore {
return nil
}
- ver, err := sdkSpec.EffectiveVersion(ctx)
- if err != nil {
- return err
- }
- if ver.GreaterThan(sdkVersion) {
- return fmt.Errorf("newer SDK(%v)", ver)
+ if sdkSpec.ApiLevel.GreaterThan(sdkVersion) {
+ return fmt.Errorf("newer SDK(%v)", sdkSpec.ApiLevel)
}
return nil
}
@@ -1496,7 +1492,7 @@
&module.dexer.dexProperties,
)
- module.initModuleAndImport(&module.ModuleBase)
+ module.initModuleAndImport(module)
module.dexProperties.Optimize.EnabledByDefault = false
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 2a6a83e..a444de0 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -198,13 +198,29 @@
// 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.configuredJars(ctx), BOOTCLASSPATH, DEX2OATBOOTCLASSPATH)
- b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, classpathJars)
+ classpathJars := configuredJarListToClasspathJars(ctx, configuredJars, BOOTCLASSPATH, DEX2OATBOOTCLASSPATH)
+ b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars)
}
func (b *platformBootclasspathModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList {
- return b.getImageConfig(ctx).modules
+ // 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).UpdatableBootJars
+ 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
diff --git a/java/sdk_library.go b/java/sdk_library.go
index dae31b9..101a658 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -631,9 +631,17 @@
Doctag_files []string `android:"path"`
}
+// commonSdkLibraryAndImportModule defines the interface that must be provided by a module that
+// embeds the commonToSdkLibraryAndImport struct.
+type commonSdkLibraryAndImportModule interface {
+ android.Module
+
+ BaseModuleName() string
+}
+
// Common code between sdk library and sdk library import
type commonToSdkLibraryAndImport struct {
- moduleBase *android.ModuleBase
+ module commonSdkLibraryAndImportModule
scopePaths map[*apiScope]*scopePaths
@@ -648,13 +656,13 @@
EmbeddableSdkLibraryComponent
}
-func (c *commonToSdkLibraryAndImport) initCommon(moduleBase *android.ModuleBase) {
- c.moduleBase = moduleBase
+func (c *commonToSdkLibraryAndImport) initCommon(module commonSdkLibraryAndImportModule) {
+ c.module = module
- moduleBase.AddProperties(&c.commonSdkLibraryProperties)
+ module.AddProperties(&c.commonSdkLibraryProperties)
// Initialize this as an sdk library component.
- c.initSdkLibraryComponent(moduleBase)
+ c.initSdkLibraryComponent(module)
}
func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android.DefaultableHookContext) bool {
@@ -670,7 +678,7 @@
// Only track this sdk library if this can be used as a shared library.
if c.sharedLibrary() {
// Use the name specified in the module definition as the owner.
- c.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack = proptools.StringPtr(c.moduleBase.BaseModuleName())
+ c.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack = proptools.StringPtr(c.module.BaseModuleName())
}
return true
@@ -682,23 +690,23 @@
// Module name of the runtime implementation library
func (c *commonToSdkLibraryAndImport) implLibraryModuleName() string {
- return c.moduleBase.BaseModuleName() + ".impl"
+ return c.module.BaseModuleName() + ".impl"
}
// Module name of the XML file for the lib
func (c *commonToSdkLibraryAndImport) xmlPermissionsModuleName() string {
- return c.moduleBase.BaseModuleName() + sdkXmlFileSuffix
+ return c.module.BaseModuleName() + sdkXmlFileSuffix
}
// Name of the java_library module that compiles the stubs source.
func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope) string {
- return c.namingScheme.stubsLibraryModuleName(apiScope, c.moduleBase.BaseModuleName())
+ return c.namingScheme.stubsLibraryModuleName(apiScope, c.module.BaseModuleName())
}
// Name of the droidstubs module that generates the stubs source and may also
// generate/check the API.
func (c *commonToSdkLibraryAndImport) stubsSourceModuleName(apiScope *apiScope) string {
- return c.namingScheme.stubsSourceModuleName(apiScope, c.moduleBase.BaseModuleName())
+ return c.namingScheme.stubsSourceModuleName(apiScope, c.module.BaseModuleName())
}
// The component names for different outputs of the java_sdk_library.
@@ -747,7 +755,7 @@
if scope, ok := scopeByName[scopeName]; ok {
paths := c.findScopePaths(scope)
if paths == nil {
- return nil, fmt.Errorf("%q does not provide api scope %s", c.moduleBase.BaseModuleName(), scopeName)
+ return nil, fmt.Errorf("%q does not provide api scope %s", c.module.BaseModuleName(), scopeName)
}
switch component {
@@ -778,7 +786,7 @@
if c.doctagPaths != nil {
return c.doctagPaths, nil
} else {
- return nil, fmt.Errorf("no doctag_files specified on %s", c.moduleBase.BaseModuleName())
+ return nil, fmt.Errorf("no doctag_files specified on %s", c.module.BaseModuleName())
}
}
return nil, nil
@@ -824,7 +832,7 @@
// If a specific numeric version has been requested then use prebuilt versions of the sdk.
if !sdkVersion.ApiLevel.IsPreview() {
- return PrebuiltJars(ctx, c.moduleBase.BaseModuleName(), sdkVersion)
+ return PrebuiltJars(ctx, c.module.BaseModuleName(), sdkVersion)
}
paths := c.selectScopePaths(ctx, sdkVersion.Kind)
@@ -851,7 +859,7 @@
scopes = append(scopes, s.name)
}
}
- ctx.ModuleErrorf("requires api scope %s from %s but it only has %q available", apiScope.name, c.moduleBase.BaseModuleName(), scopes)
+ ctx.ModuleErrorf("requires api scope %s from %s but it only has %q available", apiScope.name, c.module.BaseModuleName(), scopes)
return nil
}
@@ -907,7 +915,7 @@
// any app that includes code which depends (directly or indirectly) on the stubs
// library will have the appropriate <uses-library> invocation inserted into its
// manifest if necessary.
- componentProps.SdkLibraryToImplicitlyTrack = proptools.StringPtr(c.moduleBase.BaseModuleName())
+ componentProps.SdkLibraryToImplicitlyTrack = proptools.StringPtr(c.module.BaseModuleName())
}
return componentProps
@@ -939,8 +947,8 @@
sdkLibraryComponentProperties SdkLibraryComponentProperties
}
-func (e *EmbeddableSdkLibraryComponent) initSdkLibraryComponent(moduleBase *android.ModuleBase) {
- moduleBase.AddProperties(&e.sdkLibraryComponentProperties)
+func (e *EmbeddableSdkLibraryComponent) initSdkLibraryComponent(module android.Module) {
+ module.AddProperties(&e.sdkLibraryComponentProperties)
}
// to satisfy SdkLibraryComponentDependency
@@ -1707,7 +1715,7 @@
module.addHostAndDeviceProperties()
module.AddProperties(&module.sdkLibraryProperties)
- module.initSdkLibraryComponent(&module.ModuleBase)
+ module.initSdkLibraryComponent(module)
module.properties.Installable = proptools.BoolPtr(true)
module.deviceProperties.IsSDKLibrary = true
@@ -1772,7 +1780,7 @@
module := &SdkLibrary{}
// Initialize information common between source and prebuilt.
- module.initCommon(&module.ModuleBase)
+ module.initCommon(module)
module.InitSdkLibraryProperties()
android.InitApexModule(module)
@@ -1920,7 +1928,7 @@
module.AddProperties(&module.properties, allScopeProperties)
// Initialize information common between source and prebuilt.
- module.initCommon(&module.ModuleBase)
+ module.initCommon(module)
android.InitPrebuiltModule(module, &[]string{""})
android.InitApexModule(module)
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index a0decb7..252c615 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -48,13 +48,14 @@
}
func (p *platformSystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- classpathJars := configuredJarListToClasspathJars(ctx, p.configuredJars(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) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList {
- global := dexpreopt.GetGlobalConfig(ctx)
- return global.SystemServerJars
+ // TODO(satayev): include any apex jars that don't populate their classpath proto config.
+ return dexpreopt.GetGlobalConfig(ctx).SystemServerJars
}
type SystemServerClasspathModule struct {
@@ -94,8 +95,9 @@
ctx.PropertyErrorf("contents", "empty contents are not allowed")
}
- classpathJars := configuredJarListToClasspathJars(ctx, s.configuredJars(ctx), s.classpathType)
- s.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, classpathJars)
+ configuredJars := s.configuredJars(ctx)
+ classpathJars := configuredJarListToClasspathJars(ctx, configuredJars, s.classpathType)
+ s.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars)
// Collect the module directory for IDE info in java/jdeps.go.
s.modulePaths = append(s.modulePaths, ctx.ModuleDir())
diff --git a/java/testing.go b/java/testing.go
index 7b452f7..c3803c8 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -363,6 +363,17 @@
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{}
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 378f7cf..d47eb1f 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -511,6 +511,127 @@
)
}
+// TestSnapshotWithBootClasspathFragment_Fragments makes sure that the fragments property of a
+// bootclasspath_fragment is correctly output to the sdk snapshot.
+func TestSnapshotWithBootClasspathFragment_Fragments(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForSdkTestWithJava,
+ java.PrepareForTestWithJavaDefaultModules,
+ java.PrepareForTestWithJavaSdkLibraryFiles,
+ java.FixtureWithLastReleaseApis("mysdklibrary", "myothersdklibrary"),
+ prepareForSdkTestWithApex,
+
+ // Some additional files needed for the myotherapex.
+ android.FixtureMergeMockFs(android.MockFS{
+ "system/sepolicy/apex/myotherapex-file_contexts": nil,
+ "myotherapex/apex_manifest.json": nil,
+ "myotherapex/Test.java": nil,
+ }),
+
+ android.FixtureAddTextFile("myotherapex/Android.bp", `
+ apex {
+ name: "myotherapex",
+ key: "myapex.key",
+ min_sdk_version: "2",
+ bootclasspath_fragments: ["myotherbootclasspathfragment"],
+ }
+
+ bootclasspath_fragment {
+ name: "myotherbootclasspathfragment",
+ apex_available: ["myotherapex"],
+ contents: [
+ "myotherlib",
+ ],
+ }
+
+ java_library {
+ name: "myotherlib",
+ apex_available: ["myotherapex"],
+ srcs: ["Test.java"],
+ min_sdk_version: "2",
+ permitted_packages: ["myothersdklibrary"],
+ compile_dex: true,
+ }
+ `),
+
+ android.FixtureWithRootAndroidBp(`
+ sdk {
+ name: "mysdk",
+ bootclasspath_fragments: ["mybootclasspathfragment"],
+ }
+
+ bootclasspath_fragment {
+ name: "mybootclasspathfragment",
+ contents: [
+ "mysdklibrary",
+ ],
+ fragments: [
+ {
+ apex: "myotherapex",
+ module: "myotherbootclasspathfragment"
+ },
+ ],
+ }
+
+ java_sdk_library {
+ name: "mysdklibrary",
+ srcs: ["Test.java"],
+ shared_library: false,
+ public: {enabled: true},
+ min_sdk_version: "2",
+ }
+ `),
+ ).RunTest(t)
+
+ // A preparer to update the test fixture used when processing an unpackage snapshot.
+ preparerForSnapshot := fixtureAddPrebuiltApexForBootclasspathFragment("myapex", "mybootclasspathfragment")
+
+ CheckSnapshot(t, result, "mysdk", "",
+ checkUnversionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+prebuilt_bootclasspath_fragment {
+ name: "mybootclasspathfragment",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
+ contents: ["mysdklibrary"],
+ fragments: [
+ {
+ apex: "myotherapex",
+ module: "myotherbootclasspathfragment",
+ },
+ ],
+ hidden_api: {
+ stub_flags: "hiddenapi/stub-flags.csv",
+ annotation_flags: "hiddenapi/annotation-flags.csv",
+ metadata: "hiddenapi/metadata.csv",
+ index: "hiddenapi/index.csv",
+ all_flags: "hiddenapi/all-flags.csv",
+ },
+}
+
+java_sdk_library_import {
+ name: "mysdklibrary",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
+ shared_library: false,
+ public: {
+ jars: ["sdk_library/public/mysdklibrary-stubs.jar"],
+ stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"],
+ current_api: "sdk_library/public/mysdklibrary.txt",
+ removed_api: "sdk_library/public/mysdklibrary-removed.txt",
+ sdk_version: "current",
+ },
+}
+ `),
+ snapshotTestPreparer(checkSnapshotWithoutSource, preparerForSnapshot),
+ snapshotTestPreparer(checkSnapshotWithSourcePreferred, preparerForSnapshot),
+ snapshotTestPreparer(checkSnapshotPreferredWithSource, preparerForSnapshot),
+ )
+}
+
// Test that bootclasspath_fragment works with sdk.
func TestBasicSdkWithBootclasspathFragment(t *testing.T) {
android.GroupFixturePreparers(
diff --git a/sdk/update.go b/sdk/update.go
index 36b564f..e2e5997 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -114,8 +114,16 @@
gc.indentLevel--
}
-func (gc *generatedContents) Printfln(format string, args ...interface{}) {
- fmt.Fprintf(&(gc.content), strings.Repeat(" ", gc.indentLevel)+format+"\n", args...)
+// IndentedPrintf will add spaces to indent the line to the appropriate level before printing the
+// arguments.
+func (gc *generatedContents) IndentedPrintf(format string, args ...interface{}) {
+ fmt.Fprintf(&(gc.content), strings.Repeat(" ", gc.indentLevel)+format, args...)
+}
+
+// UnindentedPrintf does not add spaces to indent the line to the appropriate level before printing
+// the arguments.
+func (gc *generatedContents) UnindentedPrintf(format string, args ...interface{}) {
+ fmt.Fprintf(&(gc.content), format, args...)
}
func (gf *generatedFile) build(pctx android.PackageContext, ctx android.BuilderContext, implicits android.Paths) {
@@ -742,13 +750,13 @@
}
func generateFilteredBpContents(contents *generatedContents, bpFile *bpFile, moduleFilter func(module *bpModule) bool) {
- contents.Printfln("// This is auto-generated. DO NOT EDIT.")
+ contents.IndentedPrintf("// This is auto-generated. DO NOT EDIT.\n")
for _, bpModule := range bpFile.order {
if moduleFilter(bpModule) {
- contents.Printfln("")
- contents.Printfln("%s {", bpModule.moduleType)
+ contents.IndentedPrintf("\n")
+ contents.IndentedPrintf("%s {\n", bpModule.moduleType)
outputPropertySet(contents, bpModule.bpPropertySet)
- contents.Printfln("}")
+ contents.IndentedPrintf("}\n")
}
}
}
@@ -759,7 +767,7 @@
addComment := func(name string) {
if text, ok := set.comments[name]; ok {
for _, line := range strings.Split(text, "\n") {
- contents.Printfln("// %s", line)
+ contents.IndentedPrintf("// %s\n", line)
}
}
}
@@ -776,29 +784,8 @@
}
addComment(name)
- switch v := value.(type) {
- case []string:
- length := len(v)
- if length > 1 {
- contents.Printfln("%s: [", name)
- contents.Indent()
- for i := 0; i < length; i = i + 1 {
- contents.Printfln("%q,", v[i])
- }
- contents.Dedent()
- contents.Printfln("],")
- } else if length == 0 {
- contents.Printfln("%s: [],", name)
- } else {
- contents.Printfln("%s: [%q],", name, v[0])
- }
-
- case bool:
- contents.Printfln("%s: %t,", name, v)
-
- default:
- contents.Printfln("%s: %q,", name, value)
- }
+ reflectValue := reflect.ValueOf(value)
+ outputNamedValue(contents, name, reflectValue)
}
for _, name := range set.order {
@@ -808,15 +795,94 @@
switch v := value.(type) {
case *bpPropertySet:
addComment(name)
- contents.Printfln("%s: {", name)
+ contents.IndentedPrintf("%s: {\n", name)
outputPropertySet(contents, v)
- contents.Printfln("},")
+ contents.IndentedPrintf("},\n")
}
}
contents.Dedent()
}
+// outputNamedValue outputs a value that has an associated name. The name will be indented, followed
+// by the value and then followed by a , and a newline.
+func outputNamedValue(contents *generatedContents, name string, value reflect.Value) {
+ contents.IndentedPrintf("%s: ", name)
+ outputUnnamedValue(contents, value)
+ contents.UnindentedPrintf(",\n")
+}
+
+// outputUnnamedValue outputs a single value. The value is not indented and is not followed by
+// either a , or a newline. With multi-line values, e.g. slices, all but the first line will be
+// indented and all but the last line will end with a newline.
+func outputUnnamedValue(contents *generatedContents, value reflect.Value) {
+ valueType := value.Type()
+ switch valueType.Kind() {
+ case reflect.Bool:
+ contents.UnindentedPrintf("%t", value.Bool())
+
+ case reflect.String:
+ contents.UnindentedPrintf("%q", value)
+
+ case reflect.Ptr:
+ outputUnnamedValue(contents, value.Elem())
+
+ case reflect.Slice:
+ length := value.Len()
+ if length == 0 {
+ contents.UnindentedPrintf("[]")
+ } else {
+ firstValue := value.Index(0)
+ if length == 1 && !multiLineValue(firstValue) {
+ contents.UnindentedPrintf("[")
+ outputUnnamedValue(contents, firstValue)
+ contents.UnindentedPrintf("]")
+ } else {
+ contents.UnindentedPrintf("[\n")
+ contents.Indent()
+ for i := 0; i < length; i++ {
+ itemValue := value.Index(i)
+ contents.IndentedPrintf("")
+ outputUnnamedValue(contents, itemValue)
+ contents.UnindentedPrintf(",\n")
+ }
+ contents.Dedent()
+ contents.IndentedPrintf("]")
+ }
+ }
+
+ case reflect.Struct:
+ // Avoid unlimited recursion by requiring every structure to implement android.BpPrintable.
+ v := value.Interface()
+ if _, ok := v.(android.BpPrintable); !ok {
+ panic(fmt.Errorf("property value %#v of type %T does not implement android.BpPrintable", v, v))
+ }
+ contents.UnindentedPrintf("{\n")
+ contents.Indent()
+ for f := 0; f < valueType.NumField(); f++ {
+ fieldType := valueType.Field(f)
+ if fieldType.Anonymous {
+ continue
+ }
+ fieldValue := value.Field(f)
+ fieldName := fieldType.Name
+ propertyName := proptools.PropertyNameForField(fieldName)
+ outputNamedValue(contents, propertyName, fieldValue)
+ }
+ contents.Dedent()
+ contents.IndentedPrintf("}")
+
+ default:
+ panic(fmt.Errorf("Unknown type: %T of value %#v", value, value))
+ }
+}
+
+// multiLineValue returns true if the supplied value may require multiple lines in the output.
+func multiLineValue(value reflect.Value) bool {
+ kind := value.Kind()
+ return kind == reflect.Slice || kind == reflect.Struct
+}
+
func (s *sdk) GetAndroidBpContentsForTests() string {
contents := &generatedContents{}
generateBpContents(contents, s.builderForTests.bpFile)