Merge "DO NOT MERGE - Merge PPRL.190205.001 into master"
diff --git a/Android.bp b/Android.bp
index b407314..36a428a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -250,6 +250,7 @@
"java/builder.go",
"java/dex.go",
"java/dexpreopt.go",
+ "java/dexpreopt_bootjars.go",
"java/droiddoc.go",
"java/gen.go",
"java/genrule.go",
@@ -267,6 +268,7 @@
"java/sdk_library.go",
"java/support_libraries.go",
"java/system_modules.go",
+ "java/testing.go",
],
testSrcs: [
"java/app_test.go",
diff --git a/android/arch.go b/android/arch.go
index b88b275..151cabd 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -107,6 +107,7 @@
var archVariants = map[ArchType][]string{
Arm: {
+ "armv7-a",
"armv7-a-neon",
"armv8-a",
"armv8-2a",
@@ -1314,6 +1315,7 @@
func getMegaDeviceConfig() []archConfig {
return []archConfig{
+ {"arm", "armv7-a", "generic", []string{"armeabi-v7a"}},
{"arm", "armv7-a-neon", "generic", []string{"armeabi-v7a"}},
{"arm", "armv7-a-neon", "cortex-a7", []string{"armeabi-v7a"}},
{"arm", "armv7-a-neon", "cortex-a8", []string{"armeabi-v7a"}},
@@ -1365,7 +1367,7 @@
func getNdkAbisConfig() []archConfig {
return []archConfig{
- {"arm", "armv7-a-neon", "", []string{"armeabi"}},
+ {"arm", "armv7-a", "", []string{"armeabi"}},
{"arm64", "armv8-a", "", []string{"arm64-v8a"}},
{"x86", "", "", []string{"x86"}},
{"x86_64", "", "", []string{"x86_64"}},
diff --git a/android/config.go b/android/config.go
index 63788b7..7d2e829 100644
--- a/android/config.go
+++ b/android/config.go
@@ -779,7 +779,11 @@
return c.productVariables.PreoptBootJars
}
-func (c *config) DisableDexPreopt(name string) bool {
+func (c *config) DisableDexPreopt() bool {
+ return Bool(c.productVariables.DisableDexPreopt)
+}
+
+func (c *config) DisableDexPreoptForModule(name string) bool {
return Bool(c.productVariables.DisableDexPreopt) || InList(name, c.productVariables.DisableDexPreoptModules)
}
@@ -944,6 +948,8 @@
return "", false
}
+// SecondArchIsTranslated returns true if the primary device arch is X86 or X86_64 and the device also has an arch
+// that is Arm or Arm64.
func (c *config) SecondArchIsTranslated() bool {
deviceTargets := c.Targets[Android]
if len(deviceTargets) < 2 {
@@ -952,8 +958,7 @@
arch := deviceTargets[0].Arch
- return (arch.ArchType == X86 || arch.ArchType == X86_64) &&
- (hasArmAbi(arch) || hasArmAndroidArch(deviceTargets))
+ return (arch.ArchType == X86 || arch.ArchType == X86_64) && hasArmAndroidArch(deviceTargets)
}
func (c *config) IntegerOverflowDisabledForPath(path string) bool {
diff --git a/android/makevars.go b/android/makevars.go
index 2c2fb6f..c011ea6 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -90,6 +90,25 @@
makeVarsProviders = append(makeVarsProviders, makeVarsProvider{pctx, provider})
}
+// SingletonMakeVarsProvider is a Singleton with an extra method to provide extra values to be exported to Make.
+type SingletonMakeVarsProvider interface {
+ Singleton
+
+ // MakeVars uses a MakeVarsContext to provide extra values to be exported to Make.
+ MakeVars(ctx MakeVarsContext)
+}
+
+// registerSingletonMakeVarsProvider adds a singleton that implements SingletonMakeVarsProvider to the list of
+// MakeVarsProviders to run.
+func registerSingletonMakeVarsProvider(singleton SingletonMakeVarsProvider) {
+ makeVarsProviders = append(makeVarsProviders, makeVarsProvider{pctx, SingletonmakeVarsProviderAdapter(singleton)})
+}
+
+// SingletonmakeVarsProviderAdapter converts a SingletonMakeVarsProvider to a MakeVarsProvider.
+func SingletonmakeVarsProviderAdapter(singleton SingletonMakeVarsProvider) MakeVarsProvider {
+ return func(ctx MakeVarsContext) { singleton.MakeVars(ctx) }
+}
+
///////////////////////////////////////////////////////////////////////////////
func makeVarsSingletonFunc() Singleton {
diff --git a/android/onceper.go b/android/onceper.go
index f06f428..5ad17fa 100644
--- a/android/onceper.go
+++ b/android/onceper.go
@@ -70,7 +70,7 @@
panic(fmt.Errorf("Get() called before Once()"))
}
- return v
+ return once.maybeWaitFor(key, v)
}
// OnceStringSlice is the same as Once, but returns the value cast to a []string
diff --git a/android/onceper_test.go b/android/onceper_test.go
index f27799b..95303ba 100644
--- a/android/onceper_test.go
+++ b/android/onceper_test.go
@@ -16,6 +16,7 @@
import (
"testing"
+ "time"
)
func TestOncePer_Once(t *testing.T) {
@@ -34,6 +35,21 @@
}
}
+func TestOncePer_Once_wait(t *testing.T) {
+ once := OncePer{}
+ key := NewOnceKey("key")
+
+ ch := make(chan bool)
+
+ go once.Once(key, func() interface{} { close(ch); time.Sleep(100 * time.Millisecond); return "foo" })
+ <-ch
+ a := once.Once(key, func() interface{} { return "bar" }).(string)
+
+ if a != "foo" {
+ t.Errorf("expect %q, got %q", "foo", a)
+ }
+}
+
func TestOncePer_Get(t *testing.T) {
once := OncePer{}
key := NewOnceKey("key")
@@ -65,6 +81,21 @@
once.Get(key)
}
+func TestOncePer_Get_wait(t *testing.T) {
+ once := OncePer{}
+ key := NewOnceKey("key")
+
+ ch := make(chan bool)
+
+ go once.Once(key, func() interface{} { close(ch); time.Sleep(100 * time.Millisecond); return "foo" })
+ <-ch
+ a := once.Get(key).(string)
+
+ if a != "foo" {
+ t.Errorf("expect %q, got %q", "foo", a)
+ }
+}
+
func TestOncePer_OnceStringSlice(t *testing.T) {
once := OncePer{}
key := NewOnceKey("key")
diff --git a/android/paths.go b/android/paths.go
index 31500ab..3366db1 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -677,6 +677,15 @@
return OutputPath{basePath{path, ctx.Config(), ""}}
}
+// PathsForOutput returns Paths rooted from buildDir
+func PathsForOutput(ctx PathContext, paths []string) WritablePaths {
+ ret := make(WritablePaths, len(paths))
+ for i, path := range paths {
+ ret[i] = PathForOutput(ctx, path)
+ }
+ return ret
+}
+
func (p OutputPath) writablePath() {}
func (p OutputPath) String() string {
@@ -707,6 +716,18 @@
return ret
}
+// InSameDir creates a new OutputPath from the directory of the current OutputPath joined with the elements in paths.
+func (p OutputPath) InSameDir(ctx PathContext, paths ...string) OutputPath {
+ path, err := validatePath(paths...)
+ if err != nil {
+ reportPathError(ctx, err)
+ }
+
+ ret := PathForOutput(ctx, filepath.Dir(p.path), path)
+ ret.rel = p.rel
+ return ret
+}
+
// PathForIntermediates returns an OutputPath representing the top-level
// intermediates directory.
func PathForIntermediates(ctx PathContext, paths ...string) OutputPath {
@@ -1019,6 +1040,14 @@
return p.path
}
+type testWritablePath struct {
+ testPath
+}
+
+func (p testPath) writablePath() {}
+
+// PathForTesting returns a Path constructed from joining the elements of paths with '/'. It should only be used from
+// within tests.
func PathForTesting(paths ...string) Path {
p, err := validateSafePath(paths...)
if err != nil {
@@ -1027,7 +1056,8 @@
return testPath{basePath{path: p, rel: p}}
}
-func PathsForTesting(strs []string) Paths {
+// PathsForTesting returns a Path constructed from each element in strs. It should only be used from within tests.
+func PathsForTesting(strs ...string) Paths {
p := make(Paths, len(strs))
for i, s := range strs {
p[i] = PathForTesting(s)
@@ -1036,6 +1066,45 @@
return p
}
+// WritablePathForTesting returns a Path constructed from joining the elements of paths with '/'. It should only be
+// used from within tests.
+func WritablePathForTesting(paths ...string) WritablePath {
+ p, err := validateSafePath(paths...)
+ if err != nil {
+ panic(err)
+ }
+ return testWritablePath{testPath{basePath{path: p, rel: p}}}
+}
+
+// WritablePathsForTesting returns a Path constructed from each element in strs. It should only be used from within
+// tests.
+func WritablePathsForTesting(strs ...string) WritablePaths {
+ p := make(WritablePaths, len(strs))
+ for i, s := range strs {
+ p[i] = WritablePathForTesting(s)
+ }
+
+ return p
+}
+
+type testPathContext struct {
+ config Config
+ fs pathtools.FileSystem
+}
+
+func (x *testPathContext) Fs() pathtools.FileSystem { return x.fs }
+func (x *testPathContext) Config() Config { return x.config }
+func (x *testPathContext) AddNinjaFileDeps(...string) {}
+
+// PathContextForTesting returns a PathContext that can be used in tests, for example to create an OutputPath with
+// PathForOutput.
+func PathContextForTesting(config Config, fs map[string][]byte) PathContext {
+ return &testPathContext{
+ config: config,
+ fs: pathtools.MockFs(fs),
+ }
+}
+
// Rel performs the same function as filepath.Rel, but reports errors to a PathContext, and reports an error if
// targetPath is not inside basePath.
func Rel(ctx PathContext, basePath string, targetPath string) string {
diff --git a/android/paths_test.go b/android/paths_test.go
index 1972591..3b6d2ec 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -703,3 +703,15 @@
// Output:
// out/system/framework/boot.art out/system/framework/boot.oat
}
+
+func ExampleOutputPath_FileInSameDir() {
+ ctx := &configErrorWrapper{
+ config: TestConfig("out", nil),
+ }
+ p := PathForOutput(ctx, "system/framework/boot.art")
+ p2 := p.InSameDir(ctx, "oat", "arm", "boot.vdex")
+ fmt.Println(p, p2)
+
+ // Output:
+ // out/system/framework/boot.art out/system/framework/oat/arm/boot.vdex
+}
diff --git a/android/register.go b/android/register.go
index 19745fe..93c2870 100644
--- a/android/register.go
+++ b/android/register.go
@@ -58,6 +58,9 @@
func SingletonFactoryAdaptor(factory SingletonFactory) blueprint.SingletonFactory {
return func() blueprint.Singleton {
singleton := factory()
+ if makevars, ok := singleton.(SingletonMakeVarsProvider); ok {
+ registerSingletonMakeVarsProvider(makevars)
+ }
return singletonAdaptor{singleton}
}
}
diff --git a/android/util.go b/android/util.go
index 92ab845..8fc159d 100644
--- a/android/util.go
+++ b/android/util.go
@@ -20,6 +20,11 @@
"strings"
)
+// CopyOf returns a new slice that has the same contents as s.
+func CopyOf(s []string) []string {
+ return append([]string(nil), s...)
+}
+
func JoinWithPrefix(strs []string, prefix string) string {
if len(strs) == 0 {
return ""
diff --git a/android/util_test.go b/android/util_test.go
index 1c791b2..2e5eb07 100644
--- a/android/util_test.go
+++ b/android/util_test.go
@@ -15,6 +15,7 @@
package android
import (
+ "fmt"
"reflect"
"testing"
)
@@ -359,3 +360,47 @@
})
}
}
+
+func ExampleCopyOf() {
+ a := []string{"1", "2", "3"}
+ b := CopyOf(a)
+ a[0] = "-1"
+ fmt.Printf("a = %q\n", a)
+ fmt.Printf("b = %q\n", b)
+
+ // Output:
+ // a = ["-1" "2" "3"]
+ // b = ["1" "2" "3"]
+}
+
+func ExampleCopyOf_append() {
+ a := make([]string, 1, 2)
+ a[0] = "foo"
+
+ fmt.Println("Without CopyOf:")
+ b := append(a, "bar")
+ c := append(a, "baz")
+ fmt.Printf("a = %q\n", a)
+ fmt.Printf("b = %q\n", b)
+ fmt.Printf("c = %q\n", c)
+
+ a = make([]string, 1, 2)
+ a[0] = "foo"
+
+ fmt.Println("With CopyOf:")
+ b = append(CopyOf(a), "bar")
+ c = append(CopyOf(a), "baz")
+ fmt.Printf("a = %q\n", a)
+ fmt.Printf("b = %q\n", b)
+ fmt.Printf("c = %q\n", c)
+
+ // Output:
+ // Without CopyOf:
+ // a = ["foo"]
+ // b = ["foo" "baz"]
+ // c = ["foo" "baz"]
+ // With CopyOf:
+ // a = ["foo"]
+ // b = ["foo" "bar"]
+ // c = ["foo" "baz"]
+}
diff --git a/apex/apex.go b/apex/apex.go
index 3b06a99..408415e 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -379,6 +379,13 @@
outputFiles map[apexPackaging]android.WritablePath
installDir android.OutputPath
+ public_key_file android.Path
+ private_key_file android.Path
+ bundle_public_key bool
+
+ container_certificate_file android.Path
+ container_private_key_file android.Path
+
// list of files to be included in this apex
filesInfo []apexFile
@@ -635,10 +642,6 @@
func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
filesInfo := []apexFile{}
- var keyFile android.Path
- var pubKeyFile android.Path
- var certificate java.Certificate
-
if a.properties.Payload_type == nil || *a.properties.Payload_type == "image" {
a.apexTypes = imageApex
} else if *a.properties.Payload_type == "zip" {
@@ -704,20 +707,20 @@
}
case keyTag:
if key, ok := child.(*apexKey); ok {
- keyFile = key.private_key_file
- if !key.installable() && ctx.Config().Debuggable() {
- // If the key is not installed, bundled it with the APEX.
- // Note: this bundled key is valid only for non-production builds
- // (eng/userdebug).
- pubKeyFile = key.public_key_file
- }
+ a.private_key_file = key.private_key_file
+ a.public_key_file = key.public_key_file
+ // If the key is not installed, bundled it with the APEX.
+ // Note: this bundled key is valid only for non-production builds
+ // (eng/userdebug).
+ a.bundle_public_key = !key.installable() && ctx.Config().Debuggable()
return false
} else {
ctx.PropertyErrorf("key", "%q is not an apex_key module", depName)
}
case certificateTag:
if dep, ok := child.(*java.AndroidAppCertificate); ok {
- certificate = dep.Certificate
+ a.container_certificate_file = dep.Certificate.Pem
+ a.container_private_key_file = dep.Certificate.Key
return false
} else {
ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", depName)
@@ -741,7 +744,7 @@
})
a.flattened = ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild()
- if keyFile == nil {
+ if a.private_key_file == nil {
ctx.PropertyErrorf("key", "private_key for %q could not be found", String(a.properties.Key))
return
}
@@ -775,30 +778,28 @@
a.filesInfo = filesInfo
if a.apexTypes.zip() {
- a.buildUnflattenedApex(ctx, keyFile, pubKeyFile, certificate, zipApex)
+ a.buildUnflattenedApex(ctx, zipApex)
}
if a.apexTypes.image() {
// Build rule for unflattened APEX is created even when ctx.Config().FlattenApex()
// is true. This is to support referencing APEX via ":<module_name" syntax
// in other modules. It is in AndroidMk where the selection of flattened
// or unflattened APEX is made.
- a.buildUnflattenedApex(ctx, keyFile, pubKeyFile, certificate, imageApex)
+ a.buildUnflattenedApex(ctx, imageApex)
a.buildFlattenedApex(ctx)
}
}
-func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, keyFile android.Path,
- pubKeyFile android.Path, certificate java.Certificate, apexType apexPackaging) {
+func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext, apexType apexPackaging) {
cert := String(a.properties.Certificate)
if cert != "" && android.SrcIsModule(cert) == "" {
defaultDir := ctx.Config().DefaultAppCertificateDir(ctx)
- certificate = java.Certificate{
- defaultDir.Join(ctx, cert+".x509.pem"),
- defaultDir.Join(ctx, cert+".pk8"),
- }
+ a.container_certificate_file = defaultDir.Join(ctx, cert+".x509.pem")
+ a.container_private_key_file = defaultDir.Join(ctx, cert+".pk8")
} else if cert == "" {
pem, key := ctx.Config().DefaultAppCertificate(ctx)
- certificate = java.Certificate{pem, key}
+ a.container_certificate_file = pem
+ a.container_private_key_file = key
}
manifest := ctx.ExpandSource(proptools.StringDefault(a.properties.Manifest, "apex_manifest.json"), "manifest")
@@ -886,10 +887,10 @@
optFlags := []string{}
// Additional implicit inputs.
- implicitInputs = append(implicitInputs, cannedFsConfig, fileContexts, keyFile)
- if pubKeyFile != nil {
- implicitInputs = append(implicitInputs, pubKeyFile)
- optFlags = append(optFlags, "--pubkey "+pubKeyFile.String())
+ implicitInputs = append(implicitInputs, cannedFsConfig, fileContexts, a.private_key_file)
+ if a.bundle_public_key {
+ implicitInputs = append(implicitInputs, a.public_key_file)
+ optFlags = append(optFlags, "--pubkey "+a.public_key_file.String())
}
manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(ctx.ModuleName())
@@ -915,7 +916,7 @@
"manifest": manifest.String(),
"file_contexts": fileContexts.String(),
"canned_fs_config": cannedFsConfig.String(),
- "key": keyFile.String(),
+ "key": a.private_key_file.String(),
"opt_flags": strings.Join(optFlags, " "),
},
})
@@ -962,14 +963,14 @@
Output: a.outputFiles[apexType],
Input: unsignedOutputFile,
Args: map[string]string{
- "certificates": strings.Join([]string{certificate.Pem.String(), certificate.Key.String()}, " "),
+ "certificates": a.container_certificate_file.String() + " " + a.container_private_key_file.String(),
"flags": "-a 4096", //alignment
},
})
// Install to $OUT/soong/{target,host}/.../apex
if a.installable() && (!ctx.Config().FlattenApex() || apexType.zip()) {
- ctx.InstallFile(android.PathForModuleInstall(ctx, "apex"), ctx.ModuleName()+suffix, a.outputFiles[apexType])
+ ctx.InstallFile(a.installDir, ctx.ModuleName()+suffix, a.outputFiles[apexType])
}
}
diff --git a/apex/key.go b/apex/key.go
index 5282416..4c83861 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -17,6 +17,7 @@
import (
"fmt"
"io"
+ "strings"
"android/soong/android"
@@ -27,6 +28,8 @@
func init() {
android.RegisterModuleType("apex_key", apexKeyFactory)
+ android.RegisterSingletonType("apex_keys_text", apexKeysTextFactory)
+ android.RegisterMakeVarsProvider(pctx, apexKeysFileProvider)
}
type apexKey struct {
@@ -102,3 +105,53 @@
},
}
}
+
+////////////////////////////////////////////////////////////////////////
+// apex_keys_text
+type apexKeysText struct{}
+
+func (s *apexKeysText) GenerateBuildActions(ctx android.SingletonContext) {
+ output := android.PathForOutput(ctx, "apexkeys.txt")
+ *apexKeysFile(ctx.Config()) = output.String()
+ var filecontent strings.Builder
+ ctx.VisitAllModules(func(module android.Module) {
+ if m, ok := module.(android.Module); ok && !m.Enabled() {
+ return
+ }
+
+ if m, ok := module.(*apexBundle); ok {
+ fmt.Fprintf(&filecontent,
+ "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q\\n",
+ m.Name()+".apex",
+ m.public_key_file.String(),
+ m.private_key_file.String(),
+ m.container_certificate_file.String(),
+ m.container_private_key_file.String())
+ }
+ })
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.WriteFile,
+ Description: "apex_keys.txt",
+ Output: output,
+ Args: map[string]string{
+ "content": filecontent.String(),
+ },
+ })
+}
+
+var apexKeysFileKey = android.NewOnceKey("apexKeysFile")
+
+func apexKeysFile(config android.Config) *string {
+ return config.Once(apexKeysFileKey, func() interface{} {
+ str := ""
+ return &str
+ }).(*string)
+}
+
+func apexKeysTextFactory() android.Singleton {
+ return &apexKeysText{}
+}
+
+func apexKeysFileProvider(ctx android.MakeVarsContext) {
+ ctx.Strict("SOONG_APEX_KEYS_FILE", *apexKeysFile(ctx.Config()))
+}
diff --git a/cc/builder.go b/cc/builder.go
index 6e24d56..97ae806 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -197,8 +197,8 @@
sAbiDiff = pctx.AndroidRuleFunc("sAbiDiff",
func(ctx android.PackageRuleContext) blueprint.RuleParams {
// TODO(b/78139997): Add -check-all-apis back
- commandStr := "($sAbiDiffer $allowFlags -lib $libName -arch $arch -o ${out} -new $in -old $referenceDump)"
- commandStr += "|| (echo ' ---- Please update abi references by running $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l ${libName} ----'"
+ commandStr := "($sAbiDiffer ${allowFlags} -lib ${libName} -arch ${arch} -o ${out} -new ${in} -old ${referenceDump})"
+ commandStr += "|| (echo 'error: Please update ABI references with: $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py ${createReferenceDumpFlags} -l ${libName}'"
commandStr += " && (mkdir -p $$DIST_DIR/abidiffs && cp ${out} $$DIST_DIR/abidiffs/)"
commandStr += " && exit 1)"
return blueprint.RuleParams{
@@ -206,7 +206,7 @@
CommandDeps: []string{"$sAbiDiffer"},
}
},
- "allowFlags", "referenceDump", "libName", "arch")
+ "allowFlags", "referenceDump", "libName", "arch", "createReferenceDumpFlags")
unzipRefSAbiDump = pctx.AndroidStaticRule("unzipRefSAbiDump",
blueprint.RuleParams{
@@ -711,16 +711,19 @@
}
func SourceAbiDiff(ctx android.ModuleContext, inputDump android.Path, referenceDump android.Path,
- baseName, exportedHeaderFlags string, isVndkExt bool) android.OptionalPath {
+ baseName, exportedHeaderFlags string, isLlndk, isVndkExt bool) android.OptionalPath {
outputFile := android.PathForModuleOut(ctx, baseName+".abidiff")
libName := strings.TrimSuffix(baseName, filepath.Ext(baseName))
+ createReferenceDumpFlags := ""
+
localAbiCheckAllowFlags := append([]string(nil), abiCheckAllowFlags...)
if exportedHeaderFlags == "" {
localAbiCheckAllowFlags = append(localAbiCheckAllowFlags, "-advice-only")
}
- if inList(libName, llndkLibraries) {
+ if isLlndk {
localAbiCheckAllowFlags = append(localAbiCheckAllowFlags, "-consider-opaque-types-different")
+ createReferenceDumpFlags = "--llndk"
}
if isVndkExt {
localAbiCheckAllowFlags = append(localAbiCheckAllowFlags, "-allow-extensions")
@@ -733,10 +736,11 @@
Input: inputDump,
Implicit: referenceDump,
Args: map[string]string{
- "referenceDump": referenceDump.String(),
- "libName": libName,
- "arch": ctx.Arch().ArchType.Name,
- "allowFlags": strings.Join(localAbiCheckAllowFlags, " "),
+ "referenceDump": referenceDump.String(),
+ "libName": libName,
+ "arch": ctx.Arch().ArchType.Name,
+ "allowFlags": strings.Join(localAbiCheckAllowFlags, " "),
+ "createReferenceDumpFlags": createReferenceDumpFlags,
},
})
return android.OptionalPathForPath(outputFile)
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 22ac0d9..a0914c8 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -1039,7 +1039,7 @@
func TestSplitListForSize(t *testing.T) {
for _, testCase := range splitListForSizeTestCases {
- out, _ := splitListForSize(android.PathsForTesting(testCase.in), testCase.size)
+ out, _ := splitListForSize(android.PathsForTesting(testCase.in...), testCase.size)
var outStrings [][]string
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index aee16eb..cd7c410 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -51,6 +51,11 @@
}
armClangArchVariantCflags = map[string][]string{
+ "armv7-a": []string{
+ "-march=armv7-a",
+ "-mfloat-abi=softfp",
+ "-mfpu=vfpv3-d16",
+ },
"armv7-a-neon": []string{
"-march=armv7-a",
"-mfloat-abi=softfp",
@@ -184,6 +189,8 @@
pctx.StaticVariable("ArmClangThumbCflags", strings.Join(ClangFilterUnknownCflags(armThumbCflags), " "))
// Clang arch variant cflags
+ pctx.StaticVariable("ArmClangArmv7ACflags",
+ strings.Join(armClangArchVariantCflags["armv7-a"], " "))
pctx.StaticVariable("ArmClangArmv7ANeonCflags",
strings.Join(armClangArchVariantCflags["armv7-a-neon"], " "))
pctx.StaticVariable("ArmClangArmv8ACflags",
@@ -212,6 +219,7 @@
var (
armClangArchVariantCflagsVar = map[string]string{
+ "armv7-a": "${config.ArmClangArmv7ACflags}",
"armv7-a-neon": "${config.ArmClangArmv7ANeonCflags}",
"armv8-a": "${config.ArmClangArmv8ACflags}",
"armv8-2a": "${config.ArmClangArmv82ACflags}",
@@ -327,6 +335,8 @@
default:
fixCortexA8 = "-Wl,--no-fix-cortex-a8"
}
+ case "armv7-a":
+ fixCortexA8 = "-Wl,--fix-cortex-a8"
case "armv8-a", "armv8-2a":
// Nothing extra for armv8-a/armv8-2a
default:
diff --git a/cc/coverage.go b/cc/coverage.go
index cf67c9f..ad2f1e4 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -53,6 +53,10 @@
flags.Coverage = true
flags.GlobalFlags = append(flags.GlobalFlags, "--coverage", "-O0")
cov.linkCoverage = true
+
+ // Override -Wframe-larger-than and non-default optimization
+ // flags that the module may use.
+ flags.CFlags = append(flags.CFlags, "-Wno-frame-larger-than=", "-O0")
}
// Even if we don't have coverage enabled, if any of our object files were compiled
@@ -109,8 +113,6 @@
if mctx.Host() {
// TODO(dwillemsen): because of -nodefaultlibs, we must depend on libclang_rt.profile-*.a
// Just turn off for now.
- } else if c.useVndk() || c.hasVendorVariant() {
- // Do not enable coverage for VNDK libraries
} else if c.IsStubs() {
// Do not enable coverage for platform stub libraries
} else if c.isNDKStubLibrary() {
diff --git a/cc/library.go b/cc/library.go
index a48b45d..c23f26b 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -794,7 +794,7 @@
refAbiDumpFile := getRefAbiDumpFile(ctx, vndkVersion, fileName)
if refAbiDumpFile != nil {
library.sAbiDiff = SourceAbiDiff(ctx, library.sAbiOutputFile.Path(),
- refAbiDumpFile, fileName, exportedHeaderFlags, ctx.isVndkExt())
+ refAbiDumpFile, fileName, exportedHeaderFlags, ctx.isLlndk(), ctx.isVndkExt())
}
}
}
diff --git a/cc/test.go b/cc/test.go
index f7180b5..e9f0944 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -244,7 +244,7 @@
func (test *testBinary) install(ctx ModuleContext, file android.Path) {
test.data = ctx.ExpandSources(test.Properties.Data, nil)
test.testConfig = tradefed.AutoGenNativeTestConfig(ctx, test.Properties.Test_config,
- test.Properties.Test_config_template)
+ test.Properties.Test_config_template, test.Properties.Test_suites)
test.binaryDecorator.baseInstaller.dir = "nativetest"
test.binaryDecorator.baseInstaller.dir64 = "nativetest64"
@@ -368,7 +368,7 @@
func (benchmark *benchmarkDecorator) install(ctx ModuleContext, file android.Path) {
benchmark.data = ctx.ExpandSources(benchmark.Properties.Data, nil)
benchmark.testConfig = tradefed.AutoGenNativeBenchmarkTestConfig(ctx, benchmark.Properties.Test_config,
- benchmark.Properties.Test_config_template)
+ benchmark.Properties.Test_config_template, benchmark.Properties.Test_suites)
benchmark.binaryDecorator.baseInstaller.dir = filepath.Join("benchmarktest", ctx.ModuleName())
benchmark.binaryDecorator.baseInstaller.dir64 = filepath.Join("benchmarktest64", ctx.ModuleName())
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 1f6002e..41c7d46 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -75,8 +75,7 @@
bootstrap.Main(ctx.Context, configuration, configuration.ConfigFileName, configuration.ProductVariablesFileName)
if docFile != "" {
- err := writeDocs(ctx, docFile)
- if err != nil {
+ if err := writeDocs(ctx, docFile); err != nil {
fmt.Fprintf(os.Stderr, "%s", err)
os.Exit(1)
}
diff --git a/cmd/soong_build/writedocs.go b/cmd/soong_build/writedocs.go
index 8f86b33..74c854a 100644
--- a/cmd/soong_build/writedocs.go
+++ b/cmd/soong_build/writedocs.go
@@ -26,7 +26,25 @@
"github.com/google/blueprint/bootstrap/bpdoc"
)
-func writeDocs(ctx *android.Context, filename string) error {
+type moduleTypeTemplateData struct {
+ Name string
+ Synopsis string
+ Properties []bpdoc.Property
+}
+
+// The properties in this map are displayed first, according to their rank.
+// TODO(jungjw): consider providing module type-dependent ranking
+var propertyRank = map[string]int{
+ "name": 0,
+ "src": 1,
+ "srcs": 2,
+ "defautls": 3,
+ "host_supported": 4,
+ "device_supported": 5,
+}
+
+// For each module type, extract its documentation and convert it to the template data.
+func moduleTypeDocsToTemplates(ctx *android.Context) ([]moduleTypeTemplateData, error) {
moduleTypeFactories := android.ModuleTypeFactories()
bpModuleTypeFactories := make(map[string]reflect.Value)
for moduleType, factory := range moduleTypeFactories {
@@ -35,39 +53,83 @@
packages, err := bootstrap.ModuleTypeDocs(ctx.Context, bpModuleTypeFactories)
if err != nil {
- return err
+ return []moduleTypeTemplateData{}, err
}
-
- buf := &bytes.Buffer{}
-
var moduleTypeList []*bpdoc.ModuleType
for _, pkg := range packages {
moduleTypeList = append(moduleTypeList, pkg.ModuleTypes...)
}
- sort.Slice(moduleTypeList, func(i, j int) bool { return moduleTypeList[i].Name < moduleTypeList[j].Name })
- unique := 0
+ result := make([]moduleTypeTemplateData, 0)
+ // Combine properties from all PropertyStruct's and reorder them -- first the ones
+ // with rank, then the rest of the properties in alphabetic order.
+ for _, m := range moduleTypeList {
+ item := moduleTypeTemplateData{
+ Name: m.Name,
+ Synopsis: m.Text,
+ Properties: make([]bpdoc.Property, 0),
+ }
+ props := make([]bpdoc.Property, 0)
+ for _, propStruct := range m.PropertyStructs {
+ props = append(props, propStruct.Properties...)
+ }
+ sort.Slice(props, func(i, j int) bool {
+ if rankI, ok := propertyRank[props[i].Name]; ok {
+ if rankJ, ok := propertyRank[props[j].Name]; ok {
+ return rankI < rankJ
+ } else {
+ return true
+ }
+ }
+ if _, ok := propertyRank[props[j].Name]; ok {
+ return false
+ }
+ return props[i].Name < props[j].Name
+ })
+ // Eliminate top-level duplicates. TODO(jungjw): improve bpdoc to handle this.
+ previousPropertyName := ""
+ for _, prop := range props {
+ if prop.Name == previousPropertyName {
+ oldProp := &item.Properties[len(item.Properties)-1].Properties
+ bpdoc.CollapseDuplicateProperties(oldProp, &prop.Properties)
+ } else {
+ item.Properties = append(item.Properties, prop)
+ }
+ previousPropertyName = prop.Name
+ }
+ result = append(result, item)
+ }
+ sort.Slice(result, func(i, j int) bool { return result[i].Name < result[j].Name })
+ return result, err
+}
+
+func writeDocs(ctx *android.Context, filename string) error {
+ buf := &bytes.Buffer{}
+
+ // We need a module name getter/setter function because I couldn't
+ // find a way to keep it in a variable defined within the template.
+ currentModuleName := ""
+ data, err := moduleTypeDocsToTemplates(ctx)
+ if err != nil {
+ return err
+ }
tmpl, err := template.New("file").Funcs(map[string]interface{}{
- "unique": func() int {
- unique++
- return unique
- }}).Parse(fileTemplate)
- if err != nil {
- return err
+ "setModule": func(moduleName string) string {
+ currentModuleName = moduleName
+ return ""
+ },
+ "getModule": func() string {
+ return currentModuleName
+ },
+ }).Parse(fileTemplate)
+ if err == nil {
+ err = tmpl.Execute(buf, data)
}
-
- err = tmpl.Execute(buf, moduleTypeList)
- if err != nil {
- return err
+ if err == nil {
+ err = ioutil.WriteFile(filename, buf.Bytes(), 0666)
}
-
- err = ioutil.WriteFile(filename, buf.Bytes(), 0666)
- if err != nil {
- return err
- }
-
- return nil
+ return err
}
const (
@@ -75,70 +137,112 @@
<html>
<head>
<title>Build Docs</title>
-<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
-<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
-<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
+<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css">
+<style>
+.accordion,.simple{margin-left:1.5em;text-indent:-1.5em;margin-top:.25em}
+.collapsible{border-width:0 0 0 1;margin-left:.25em;padding-left:.25em;border-style:solid;
+ border-color:grey;display:none;}
+span.fixed{display: block; float: left; clear: left; width: 1em;}
+ul {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+ width: 30ch;
+ background-color: #f1f1f1;
+ position: fixed;
+ height: 100%;
+ overflow: auto;
+}
+li a {
+ display: block;
+ color: #000;
+ padding: 8px 16px;
+ text-decoration: none;
+}
+
+li a.active {
+ background-color: #4CAF50;
+ color: white;
+}
+
+li a:hover:not(.active) {
+ background-color: #555;
+ color: white;
+}
+</style>
</head>
<body>
-<h1>Build Docs</h1>
-<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
- {{range .}}
- {{ $collapseIndex := unique }}
- <div class="panel panel-default">
- <div class="panel-heading" role="tab" id="heading{{$collapseIndex}}">
- <h2 class="panel-title">
- <a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse{{$collapseIndex}}" aria-expanded="false" aria-controls="collapse{{$collapseIndex}}">
- {{.Name}}
- </a>
- </h2>
- </div>
- </div>
- <div id="collapse{{$collapseIndex}}" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading{{$collapseIndex}}">
- <div class="panel-body">
- <p>{{.Text}}</p>
- {{range .PropertyStructs}}
- <p>{{.Text}}</p>
- {{template "properties" .Properties}}
- {{end}}
- </div>
- </div>
- {{end}}
-</div>
-</body>
-</html>
+{{- /* Fixed sidebar with module types */ -}}
+<ul>
+<li><h3>Module Types:</h3></li>
+{{range $moduleType := .}}<li><a href="#{{$moduleType.Name}}">{{$moduleType.Name}}</a></li>
+{{end -}}
+</ul>
+{{/* Main panel with H1 section per module type */}}
+<div style="margin-left:30ch;padding:1px 16px;">
+<H1>Soong Modules Reference</H1>
+The latest versions of Android use the Soong build system, which greatly simplifies build
+configuration over the previous Make-based system. This site contains the generated reference
+files for the Soong build system.
+<p>
+See the <a href=https://source.android.com/setup/build/build-system>Android Build System</a>
+description for an overview of Soong and examples for its use.
-{{define "properties"}}
- <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
- {{range .}}
- {{$collapseIndex := unique}}
- {{if .Properties}}
- <div class="panel panel-default">
- <div class="panel-heading" role="tab" id="heading{{$collapseIndex}}">
- <h4 class="panel-title">
- <a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse{{$collapseIndex}}" aria-expanded="false" aria-controls="collapse{{$collapseIndex}}">
- {{.Name}}{{range .OtherNames}}, {{.}}{{end}}
- </a>
- </h4>
- </div>
- </div>
- <div id="collapse{{$collapseIndex}}" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading{{$collapseIndex}}">
- <div class="panel-body">
- <p>{{.Text}}</p>
- {{range .OtherTexts}}<p>{{.}}</p>{{end}}
- {{template "properties" .Properties}}
- </div>
- </div>
- {{else}}
- <div>
- <h4>{{.Name}}{{range .OtherNames}}, {{.}}{{end}}</h4>
- <p>{{.Text}}</p>
- {{range .OtherTexts}}<p>{{.}}</p>{{end}}
- <p><i>Type: {{.Type}}</i></p>
- {{if .Default}}<p><i>Default: {{.Default}}</i></p>{{end}}
- </div>
- {{end}}
- {{end}}
+{{range $imodule, $moduleType := .}}
+ {{setModule $moduleType.Name}}
+ <p>
+ <h2 id="{{$moduleType.Name}}">{{$moduleType.Name}}</h2>
+ {{if $moduleType.Synopsis }}{{$moduleType.Synopsis}}{{else}}<i>Missing synopsis</i>{{end}}
+ {{- /* Comma-separated list of module attributes' links module attributes */ -}}
+ <div class="breadcrumb">
+ {{range $i,$prop := $moduleType.Properties }}
+ {{ if gt $i 0 }}, {{end -}}
+ <a href=#{{getModule}}.{{$prop.Name}}>{{$prop.Name}}</a>
+ {{- end -}}
</div>
-{{end}}
+ {{- /* Property description */ -}}
+ {{- template "properties" $moduleType.Properties -}}
+{{- end -}}
+
+{{define "properties" -}}
+ {{range .}}
+ {{if .Properties -}}
+ <div class="accordion" id="{{getModule}}.{{.Name}}">
+ <span class="fixed">⊕</span><b>{{.Name}}</b>
+ {{- range .OtherNames -}}, {{.}}{{- end -}}
+ </div>
+ <div class="collapsible">
+ {{- .Text}} {{range .OtherTexts}}{{.}}{{end}}
+ {{template "properties" .Properties -}}
+ </div>
+ {{- else -}}
+ <div class="simple" id="{{getModule}}.{{.Name}}">
+ <span class="fixed"> </span><b>{{.Name}} {{range .OtherNames}}, {{.}}{{end -}}</b>
+ {{- if .Text -}}{{.Text}}{{- end -}}
+ {{- with .OtherTexts -}}{{.}}{{- end -}}<i>{{.Type}}</i>
+ {{- if .Default -}}<i>Default: {{.Default}}</i>{{- end -}}
+ </div>
+ {{- end}}
+ {{- end -}}
+{{- end -}}
+
+</div>
+<script>
+ accordions = document.getElementsByClassName('accordion');
+ for (i=0; i < accordions.length; ++i) {
+ accordions[i].addEventListener("click", function() {
+ var panel = this.nextElementSibling;
+ var child = this.firstElementChild;
+ if (panel.style.display === "block") {
+ panel.style.display = "none";
+ child.textContent = '\u2295';
+ } else {
+ panel.style.display = "block";
+ child.textContent = '\u2296';
+ }
+ });
+ }
+</script>
+</body>
`
)
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index c7f0638..0eb162d 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -34,11 +34,12 @@
DisableGenerateProfile bool // don't generate profiles
- PreoptBootClassPathDexFiles []string // file paths of boot class path files
- PreoptBootClassPathDexLocations []string // virtual locations of boot class path files
+ BootJars []string // modules for jars that form the boot class path
- BootJars []string // modules for jars that form the boot class path
- PreoptBootJars []string // modules for jars that form the boot image
+ TargetCoreJars []string // modules for jars that are in the runtime apex
+ ProductUpdatableBootModules []string
+ ProductUpdatableBootLocations []string
+
SystemServerJars []string // jars that form the system server
SystemServerApps []string // apps that are loaded into system server
SpeedApps []string // apps that should be speed optimized
@@ -64,15 +65,22 @@
DefaultAppImages bool // build app images (TODO: .art files?) by default
- Dex2oatXmx string // max heap size
- Dex2oatXms string // initial heap size
+ Dex2oatXmx string // max heap size for dex2oat
+ Dex2oatXms string // initial heap size for dex2oat
EmptyDirectory string // path to an empty directory
- DefaultDexPreoptImage map[android.ArchType]string // default boot image location for each architecture
CpuVariant map[android.ArchType]string // cpu variant for each architecture
InstructionSetFeatures map[android.ArchType]string // instruction set for each architecture
+ // Only used for boot image
+ DirtyImageObjects string // path to a dirty-image-objects file
+ PreloadedClasses string // path to a preloaded-classes file
+ BootImageProfiles []string // path to a boot-image-profile.txt file
+ BootFlags string // extra flags to pass to dex2oat for the boot image
+ Dex2oatImageXmx string // max heap size for dex2oat for the boot image
+ Dex2oatImageXms string // initial heap size for dex2oat for the boot image
+
Tools Tools // paths to tools possibly used by the generated commands
}
@@ -109,6 +117,9 @@
Archs []android.ArchType
DexPreoptImages []string
+ PreoptBootClassPathDexFiles []string // file paths of boot class path files
+ PreoptBootClassPathDexLocations []string // virtual locations of boot class path files
+
PreoptExtractedApk bool // Overrides OnlyPreoptModules
NoCreateAppImage bool
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 68bd3ea..7fdfb49 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -199,9 +199,6 @@
pathtools.ReplaceExtension(filepath.Base(path), "odex"))
}
- bcp := strings.Join(global.PreoptBootClassPathDexFiles, ":")
- bcp_locations := strings.Join(global.PreoptBootClassPathDexLocations, ":")
-
odexPath := toOdexPath(filepath.Join(filepath.Dir(module.BuildPath), base))
odexInstallPath := toOdexPath(module.DexLocation)
if odexOnSystemOther(module, global) {
@@ -320,9 +317,8 @@
FlagWithOutput("--write-invocation-to=", invocationPath).ImplicitOutput(invocationPath).
Flag("--runtime-arg").FlagWithArg("-Xms", global.Dex2oatXms).
Flag("--runtime-arg").FlagWithArg("-Xmx", global.Dex2oatXmx).
- Flag("--runtime-arg").FlagWithArg("-Xbootclasspath:", bcp).
- Implicits(global.PreoptBootClassPathDexFiles).
- Flag("--runtime-arg").FlagWithArg("-Xbootclasspath-locations:", bcp_locations).
+ Flag("--runtime-arg").FlagWithInputList("-Xbootclasspath:", module.PreoptBootClassPathDexFiles, ":").
+ Flag("--runtime-arg").FlagWithList("-Xbootclasspath-locations:", module.PreoptBootClassPathDexLocations, ":").
Flag("${class_loader_context_arg}").
Flag("${stored_class_loader_context_arg}").
FlagWithArg("--boot-image=", bootImageLocation).Implicit(bootImage).
@@ -582,9 +578,7 @@
}
}
-func copyOf(l []string) []string {
- return append([]string(nil), l...)
-}
+var copyOf = android.CopyOf
func anyHavePrefix(l []string, prefix string) bool {
for _, x := range l {
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index 40c694f..a2c6f77 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -29,6 +29,9 @@
PatternsOnSystemOther: nil,
DisableGenerateProfile: false,
BootJars: nil,
+ TargetCoreJars: nil,
+ ProductUpdatableBootModules: nil,
+ ProductUpdatableBootLocations: nil,
SystemServerJars: nil,
SystemServerApps: nil,
SpeedApps: nil,
@@ -49,9 +52,14 @@
Dex2oatXmx: "",
Dex2oatXms: "",
EmptyDirectory: "",
- DefaultDexPreoptImage: nil,
CpuVariant: nil,
InstructionSetFeatures: nil,
+ DirtyImageObjects: "",
+ PreloadedClasses: "",
+ BootImageProfiles: nil,
+ BootFlags: "",
+ Dex2oatImageXmx: "",
+ Dex2oatImageXms: "",
Tools: Tools{
Profman: "profman",
Dex2oat: "dex2oat",
@@ -64,28 +72,30 @@
}
var testModuleConfig = ModuleConfig{
- Name: "",
- DexLocation: "",
- BuildPath: "",
- DexPath: "",
- UncompressedDex: false,
- HasApkLibraries: false,
- PreoptFlags: nil,
- ProfileClassListing: "",
- ProfileIsTextListing: false,
- EnforceUsesLibraries: false,
- OptionalUsesLibraries: nil,
- UsesLibraries: nil,
- LibraryPaths: nil,
- Archs: []android.ArchType{android.Arm},
- DexPreoptImages: []string{"system/framework/arm/boot.art"},
- PreoptExtractedApk: false,
- NoCreateAppImage: false,
- ForceCreateAppImage: false,
- PresignedPrebuilt: false,
- NoStripping: false,
- StripInputPath: "",
- StripOutputPath: "",
+ Name: "",
+ DexLocation: "",
+ BuildPath: "",
+ DexPath: "",
+ UncompressedDex: false,
+ HasApkLibraries: false,
+ PreoptFlags: nil,
+ ProfileClassListing: "",
+ ProfileIsTextListing: false,
+ EnforceUsesLibraries: false,
+ OptionalUsesLibraries: nil,
+ UsesLibraries: nil,
+ LibraryPaths: nil,
+ Archs: []android.ArchType{android.Arm},
+ DexPreoptImages: []string{"system/framework/arm/boot.art"},
+ PreoptBootClassPathDexFiles: nil,
+ PreoptBootClassPathDexLocations: nil,
+ PreoptExtractedApk: false,
+ NoCreateAppImage: false,
+ ForceCreateAppImage: false,
+ PresignedPrebuilt: false,
+ NoStripping: false,
+ StripInputPath: "",
+ StripOutputPath: "",
}
func TestDexPreopt(t *testing.T) {
diff --git a/java/aar.go b/java/aar.go
index 583a6fc..e5ab036 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -77,6 +77,7 @@
isLibrary bool
uncompressedJNI bool
useEmbeddedDex bool
+ usesNonSdkApis bool
aaptProperties aaptProperties
}
@@ -184,14 +185,11 @@
manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile)
manifestPath := manifestMerger(ctx, manifestSrcPath, sdkContext, staticLibManifests, a.isLibrary,
- a.uncompressedJNI, a.useEmbeddedDex)
+ a.uncompressedJNI, a.useEmbeddedDex, a.usesNonSdkApis)
linkFlags, linkDeps, resDirs, overlayDirs, rroDirs := a.aapt2Flags(ctx, sdkContext, manifestPath)
rroDirs = append(rroDirs, staticRRODirs...)
- // TODO(b/124035856): stop de-duping when there are no more dupe resource dirs.
- rroDirs = android.FirstUniquePaths(rroDirs)
-
linkFlags = append(linkFlags, libFlags...)
linkDeps = append(linkDeps, libDeps...)
linkFlags = append(linkFlags, extraLinkFlags...)
diff --git a/java/android_manifest.go b/java/android_manifest.go
index e63fb80..3cca4f7 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -44,7 +44,7 @@
"libs")
func manifestMerger(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext,
- staticLibManifests android.Paths, isLibrary bool, uncompressedJNI, useEmbeddedDex bool) android.Path {
+ staticLibManifests android.Paths, isLibrary, uncompressedJNI, useEmbeddedDex, usesNonSdkApis bool) android.Path {
var args []string
if isLibrary {
@@ -62,6 +62,10 @@
}
}
+ if usesNonSdkApis {
+ args = append(args, "--uses-non-sdk-api")
+ }
+
if useEmbeddedDex {
args = append(args, "--use-embedded-dex=true")
}
diff --git a/java/app.go b/java/app.go
index 3cb7e8e..c08aefd 100644
--- a/java/app.go
+++ b/java/app.go
@@ -186,6 +186,8 @@
}
func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) {
+ a.aapt.usesNonSdkApis = Bool(a.Module.deviceProperties.Platform_apis)
+
aaptLinkFlags := []string{}
// Add TARGET_AAPT_CHARACTERISTICS values to AAPT link flags if they exist and --product flags were not provided.
@@ -441,7 +443,7 @@
func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.generateAndroidBuildActions(ctx)
- a.testConfig = tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config, a.testProperties.Test_config_template, a.manifestPath)
+ a.testConfig = tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config, a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites)
a.data = ctx.ExpandSources(a.testProperties.Data, nil)
}
diff --git a/java/dex.go b/java/dex.go
index 913eee6..54b7bfc 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -177,9 +177,9 @@
javalibJar := android.PathForModuleOut(ctx, "dex", jarName)
outDir := android.PathForModuleOut(ctx, "dex")
- zipFlags := ""
+ zipFlags := "--ignore_missing_files"
if j.deviceProperties.UncompressDex {
- zipFlags = "-L 0"
+ zipFlags += " -L 0"
}
if useR8 {
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 127deab..0a56529 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -56,7 +56,11 @@
}
func (d *dexpreopter) dexpreoptDisabled(ctx android.ModuleContext) bool {
- if ctx.Config().DisableDexPreopt(ctx.ModuleName()) {
+ if ctx.Config().DisableDexPreopt() {
+ return true
+ }
+
+ if ctx.Config().DisableDexPreoptForModule(ctx.ModuleName()) {
return true
}
@@ -83,8 +87,8 @@
var dexpreoptGlobalConfigKey = android.NewOnceKey("DexpreoptGlobalConfig")
-func getGlobalConfig(ctx android.ModuleContext) dexpreopt.GlobalConfig {
- globalConfig := ctx.Config().Once(dexpreoptGlobalConfigKey, func() interface{} {
+func dexpreoptGlobalConfig(ctx android.PathContext) dexpreopt.GlobalConfig {
+ return ctx.Config().Once(dexpreoptGlobalConfigKey, func() interface{} {
if f := ctx.Config().DexpreoptGlobalConfig(); f != "" {
ctx.AddNinjaFileDeps(f)
globalConfig, err := dexpreopt.LoadGlobalConfig(f)
@@ -95,11 +99,10 @@
}
return dexpreopt.GlobalConfig{}
}).(dexpreopt.GlobalConfig)
- return globalConfig
}
func odexOnSystemOther(ctx android.ModuleContext, installPath android.OutputPath) bool {
- return dexpreopt.OdexOnSystemOtherByName(ctx.ModuleName(), android.InstallPathToOnDevicePath(ctx, installPath), getGlobalConfig(ctx))
+ return dexpreopt.OdexOnSystemOtherByName(ctx.ModuleName(), android.InstallPathToOnDevicePath(ctx, installPath), dexpreoptGlobalConfig(ctx))
}
func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.ModuleOutPath) android.ModuleOutPath {
@@ -107,7 +110,7 @@
return dexJarFile
}
- globalConfig := getGlobalConfig(ctx)
+ info := dexpreoptBootJarsInfo(ctx)
var archs []android.ArchType
for _, a := range ctx.MultiTargets() {
@@ -118,7 +121,7 @@
for _, target := range ctx.Config().Targets[android.Android] {
archs = append(archs, target.Arch.ArchType)
}
- if inList(ctx.ModuleName(), globalConfig.SystemServerJars) && !d.isSDKLibrary {
+ if inList(ctx.ModuleName(), info.global.SystemServerJars) && !d.isSDKLibrary {
// If the module is not an SDK library and it's a system server jar, only preopt the primary arch.
archs = archs[:1]
}
@@ -130,7 +133,7 @@
var images []string
for _, arch := range archs {
- images = append(images, globalConfig.DefaultDexPreoptImage[arch])
+ images = append(images, info.images[arch].String())
}
dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
@@ -178,6 +181,9 @@
Archs: archs,
DexPreoptImages: images,
+ PreoptBootClassPathDexFiles: info.preoptBootDex.Strings(),
+ PreoptBootClassPathDexLocations: info.preoptBootLocations,
+
PreoptExtractedApk: false,
NoCreateAppImage: !BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, true),
@@ -188,7 +194,7 @@
StripOutputPath: strippedDexJarFile.String(),
}
- dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(globalConfig, dexpreoptConfig)
+ dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(info.global, dexpreoptConfig)
if err != nil {
ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error())
return dexJarFile
@@ -198,7 +204,7 @@
d.builtInstalled = dexpreoptRule.Installs().String()
- stripRule, err := dexpreopt.GenerateStripRule(globalConfig, dexpreoptConfig)
+ stripRule, err := dexpreopt.GenerateStripRule(info.global, dexpreoptConfig)
if err != nil {
ctx.ModuleErrorf("error generating dexpreopt strip rule: %s", err.Error())
return dexJarFile
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
new file mode 100644
index 0000000..0656ff4
--- /dev/null
+++ b/java/dexpreopt_bootjars.go
@@ -0,0 +1,463 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java
+
+import (
+ "path/filepath"
+ "strings"
+
+ "android/soong/android"
+ "android/soong/dexpreopt"
+
+ "github.com/google/blueprint/pathtools"
+ "github.com/google/blueprint/proptools"
+)
+
+func init() {
+ android.RegisterSingletonType("dex_bootjars", dexpreoptBootJarsFactory)
+}
+
+// The image "location" is a symbolic path that with multiarchitecture
+// support doesn't really exist on the device. Typically it is
+// /system/framework/boot.art and should be the same for all supported
+// architectures on the device. The concrete architecture specific
+// content actually ends up in a "filename" that contains an
+// architecture specific directory name such as arm, arm64, mips,
+// mips64, x86, x86_64.
+//
+// Here are some example values for an x86_64 / x86 configuration:
+//
+// bootImages["x86_64"] = "out/soong/generic_x86_64/dex_bootjars/system/framework/x86_64/boot.art"
+// dexpreopt.PathToLocation(bootImages["x86_64"], "x86_64") = "out/soong/generic_x86_64/dex_bootjars/system/framework/boot.art"
+//
+// bootImages["x86"] = "out/soong/generic_x86_64/dex_bootjars/system/framework/x86/boot.art"
+// dexpreopt.PathToLocation(bootImages["x86"])= "out/soong/generic_x86_64/dex_bootjars/system/framework/boot.art"
+//
+// The location is passed as an argument to the ART tools like dex2oat instead of the real path. The ART tools
+// will then reconstruct the real path, so the rules must have a dependency on the real path.
+
+type bootJarsInfo struct {
+ dir android.OutputPath
+ symbolsDir android.OutputPath
+ images map[android.ArchType]android.OutputPath
+ installs map[android.ArchType]android.RuleBuilderInstalls
+
+ vdexInstalls map[android.ArchType]android.RuleBuilderInstalls
+ unstrippedInstalls map[android.ArchType]android.RuleBuilderInstalls
+ profileInstalls android.RuleBuilderInstalls
+
+ global dexpreopt.GlobalConfig
+
+ preoptBootModules []string
+ preoptBootLocations []string
+ preoptBootDex android.WritablePaths
+ allBootModules []string
+ allBootLocations []string
+ bootclasspath string
+ systemServerClasspath string
+}
+
+var dexpreoptBootJarsInfoKey = android.NewOnceKey("dexpreoptBootJarsInfoKey")
+
+// dexpreoptBootJarsInfo creates all the paths for singleton files the first time it is called, which may be
+// from a ModuleContext that needs to reference a file that will be created by a singleton rule that hasn't
+// yet been created.
+func dexpreoptBootJarsInfo(ctx android.PathContext) *bootJarsInfo {
+ return ctx.Config().Once(dexpreoptBootJarsInfoKey, func() interface{} {
+
+ info := &bootJarsInfo{
+ dir: android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_bootjars"),
+ symbolsDir: android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_bootjars_unstripped"),
+ images: make(map[android.ArchType]android.OutputPath),
+ installs: make(map[android.ArchType]android.RuleBuilderInstalls),
+
+ vdexInstalls: make(map[android.ArchType]android.RuleBuilderInstalls),
+ unstrippedInstalls: make(map[android.ArchType]android.RuleBuilderInstalls),
+ }
+
+ for _, target := range ctx.Config().Targets[android.Android] {
+ info.images[target.Arch.ArchType] = info.dir.Join(ctx,
+ "system/framework", target.Arch.ArchType.String(), "boot.art")
+ }
+
+ info.global = dexpreoptGlobalConfig(ctx)
+ computeBootClasspath(ctx, info)
+ computeSystemServerClasspath(ctx, info)
+
+ return info
+ }).(*bootJarsInfo)
+}
+
+func concat(lists ...[]string) []string {
+ var size int
+ for _, l := range lists {
+ size += len(l)
+ }
+ ret := make([]string, 0, size)
+ for _, l := range lists {
+ ret = append(ret, l...)
+ }
+ return ret
+}
+
+func computeBootClasspath(ctx android.PathContext, info *bootJarsInfo) {
+ runtimeModules := android.RemoveListFromList(info.global.TargetCoreJars, info.global.ProductUpdatableBootModules)
+ nonFrameworkModules := concat(runtimeModules, info.global.ProductUpdatableBootModules)
+ frameworkModules := android.RemoveListFromList(info.global.BootJars, nonFrameworkModules)
+
+ var nonUpdatableBootModules []string
+ var nonUpdatableBootLocations []string
+
+ for _, m := range runtimeModules {
+ nonUpdatableBootModules = append(nonUpdatableBootModules, m)
+ nonUpdatableBootLocations = append(nonUpdatableBootLocations,
+ filepath.Join("/apex/com.android.runtime/javalib", m+".jar"))
+ }
+
+ for _, m := range frameworkModules {
+ nonUpdatableBootModules = append(nonUpdatableBootModules, m)
+ nonUpdatableBootLocations = append(nonUpdatableBootLocations,
+ filepath.Join("/system/framework", m+".jar"))
+ }
+
+ // The path to bootclasspath dex files needs to be known at module GenerateAndroidBuildAction time, before
+ // the bootclasspath modules have been compiled. Set up known paths for them, the singleton rules will copy
+ // them there.
+ // TODO: use module dependencies instead
+ var nonUpdatableBootDex android.WritablePaths
+ for _, m := range nonUpdatableBootModules {
+ nonUpdatableBootDex = append(nonUpdatableBootDex,
+ android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_bootjars_input", m+".jar"))
+ }
+
+ allBootModules := concat(nonUpdatableBootModules, info.global.ProductUpdatableBootModules)
+ allBootLocations := concat(nonUpdatableBootLocations, info.global.ProductUpdatableBootLocations)
+
+ bootclasspath := strings.Join(allBootLocations, ":")
+
+ info.preoptBootModules = nonUpdatableBootModules
+ info.preoptBootLocations = nonUpdatableBootLocations
+ info.preoptBootDex = nonUpdatableBootDex
+ info.allBootModules = allBootModules
+ info.allBootLocations = allBootLocations
+ info.bootclasspath = bootclasspath
+}
+
+func computeSystemServerClasspath(ctx android.PathContext, info *bootJarsInfo) {
+ var systemServerClasspathLocations []string
+ for _, m := range info.global.SystemServerJars {
+ systemServerClasspathLocations = append(systemServerClasspathLocations,
+ filepath.Join("/system/framework", m+".jar"))
+ }
+
+ info.systemServerClasspath = strings.Join(systemServerClasspathLocations, ":")
+}
+func dexpreoptBootJarsFactory() android.Singleton {
+ return dexpreoptBootJars{}
+}
+
+func skipDexpreoptBootJars(ctx android.PathContext) bool {
+ if ctx.Config().UnbundledBuild() {
+ return true
+ }
+
+ if len(ctx.Config().Targets[android.Android]) == 0 {
+ // Host-only build
+ return true
+ }
+
+ return false
+}
+
+type dexpreoptBootJars struct{}
+
+// dexpreoptBoot singleton rules
+func (dexpreoptBootJars) GenerateBuildActions(ctx android.SingletonContext) {
+ if skipDexpreoptBootJars(ctx) {
+ return
+ }
+
+ info := dexpreoptBootJarsInfo(ctx)
+
+ // Skip recompiling the boot image for the second sanitization phase. We'll get separate paths
+ // and invalidate first-stage artifacts which are crucial to SANITIZE_LITE builds.
+ // Note: this is technically incorrect. Compiled code contains stack checks which may depend
+ // on ASAN settings.
+ if len(ctx.Config().SanitizeDevice()) == 1 &&
+ ctx.Config().SanitizeDevice()[0] == "address" &&
+ info.global.SanitizeLite {
+ return
+ }
+
+ bootDexJars := make(android.Paths, len(info.preoptBootModules))
+
+ ctx.VisitAllModules(func(module android.Module) {
+ // Collect dex jar paths for the modules listed above.
+ if j, ok := module.(Dependency); ok {
+ name := ctx.ModuleName(module)
+ if i := android.IndexList(name, info.preoptBootModules); i != -1 {
+ bootDexJars[i] = j.DexJar()
+ }
+ }
+ })
+
+ var missingDeps []string
+ // Ensure all modules were converted to paths
+ for i := range bootDexJars {
+ if bootDexJars[i] == nil {
+ if ctx.Config().AllowMissingDependencies() {
+ missingDeps = append(missingDeps, info.preoptBootModules[i])
+ bootDexJars[i] = android.PathForOutput(ctx, "missing")
+ } else {
+ ctx.Errorf("failed to find dex jar path for module %q",
+ info.preoptBootModules[i])
+ }
+ }
+ }
+
+ // The path to bootclasspath dex files needs to be known at module GenerateAndroidBuildAction time, before
+ // the bootclasspath modules have been compiled. Copy the dex jars there so the module rules that have
+ // already been set up can find them.
+ for i := range bootDexJars {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: bootDexJars[i],
+ Output: info.preoptBootDex[i],
+ })
+ }
+
+ profile := bootImageProfileRule(ctx, info, missingDeps)
+
+ if !ctx.Config().DisableDexPreopt() {
+ targets := ctx.Config().Targets[android.Android]
+ if ctx.Config().SecondArchIsTranslated() {
+ targets = targets[:1]
+ }
+
+ for _, target := range targets {
+ dexPreoptBootImageRule(ctx, info, target.Arch.ArchType, profile, missingDeps)
+ }
+ }
+}
+
+func dexPreoptBootImageRule(ctx android.SingletonContext, info *bootJarsInfo,
+ arch android.ArchType, profile android.Path, missingDeps []string) {
+
+ symbolsDir := info.symbolsDir.Join(ctx, "system/framework", arch.String())
+ symbolsFile := symbolsDir.Join(ctx, "boot.oat")
+ outputDir := info.dir.Join(ctx, "system/framework", arch.String())
+ outputPath := info.images[arch]
+ oatLocation := pathtools.ReplaceExtension(dexpreopt.PathToLocation(outputPath.String(), arch), "oat")
+
+ rule := android.NewRuleBuilder()
+ rule.MissingDeps(missingDeps)
+
+ rule.Command().Text("mkdir").Flag("-p").Flag(symbolsDir.String())
+ rule.Command().Text("rm").Flag("-f").
+ Flag(symbolsDir.Join(ctx, "*.art").String()).
+ Flag(symbolsDir.Join(ctx, "*.oat").String()).
+ Flag(symbolsDir.Join(ctx, "*.invocation").String())
+ rule.Command().Text("rm").Flag("-f").
+ Flag(outputDir.Join(ctx, "*.art").String()).
+ Flag(outputDir.Join(ctx, "*.oat").String()).
+ Flag(outputDir.Join(ctx, "*.invocation").String())
+
+ cmd := rule.Command()
+
+ extraFlags := ctx.Config().Getenv("ART_BOOT_IMAGE_EXTRA_ARGS")
+ if extraFlags == "" {
+ // Use ANDROID_LOG_TAGS to suppress most logging by default...
+ cmd.Text(`ANDROID_LOG_TAGS="*:e"`)
+ } else {
+ // ...unless the boot image is generated specifically for testing, then allow all logging.
+ cmd.Text(`ANDROID_LOG_TAGS="*:v"`)
+ }
+
+ invocationPath := outputPath.ReplaceExtension(ctx, "invocation")
+
+ cmd.Tool(info.global.Tools.Dex2oat).
+ Flag("--avoid-storing-invocation").
+ FlagWithOutput("--write-invocation-to=", invocationPath.String()).ImplicitOutput(invocationPath.String()).
+ Flag("--runtime-arg").FlagWithArg("-Xms", info.global.Dex2oatImageXms).
+ Flag("--runtime-arg").FlagWithArg("-Xmx", info.global.Dex2oatImageXmx)
+
+ if profile == nil {
+ cmd.FlagWithArg("--image-classes=", info.global.PreloadedClasses)
+ } else {
+ cmd.FlagWithArg("--compiler-filter=", "speed-profile")
+ cmd.FlagWithInput("--profile-file=", profile.String())
+ }
+
+ if info.global.DirtyImageObjects != "" {
+ cmd.FlagWithArg("--dirty-image-objects=", info.global.DirtyImageObjects)
+ }
+
+ cmd.
+ FlagForEachInput("--dex-file=", info.preoptBootDex.Strings()).
+ FlagForEachArg("--dex-location=", info.preoptBootLocations).
+ Flag("--generate-debug-info").
+ Flag("--generate-build-id").
+ FlagWithArg("--oat-symbols=", symbolsFile.String()).
+ Flag("--strip").
+ FlagWithOutput("--oat-file=", outputPath.ReplaceExtension(ctx, "oat").String()).
+ FlagWithArg("--oat-location=", oatLocation).
+ FlagWithOutput("--image=", outputPath.String()).
+ FlagWithArg("--base=", ctx.Config().LibartImgDeviceBaseAddress()).
+ FlagWithArg("--instruction-set=", arch.String()).
+ FlagWithArg("--instruction-set-variant=", info.global.CpuVariant[arch]).
+ FlagWithArg("--instruction-set-features=", info.global.InstructionSetFeatures[arch]).
+ FlagWithArg("--android-root=", info.global.EmptyDirectory).
+ FlagWithArg("--no-inline-from=", "core-oj.jar").
+ Flag("--abort-on-hard-verifier-error")
+
+ if info.global.BootFlags != "" {
+ cmd.Flag(info.global.BootFlags)
+ }
+
+ if extraFlags != "" {
+ cmd.Flag(extraFlags)
+ }
+
+ cmd.Textf(`|| ( echo %s ; false )`, proptools.ShellEscape([]string{failureMessage})[0])
+
+ installDir := filepath.Join("/system/framework", arch.String())
+ vdexInstallDir := filepath.Join("/system/framework")
+
+ var extraFiles android.WritablePaths
+ var vdexInstalls android.RuleBuilderInstalls
+ var unstrippedInstalls android.RuleBuilderInstalls
+
+ // dex preopt on the bootclasspath produces multiple files. The first dex file
+ // is converted into to boot.art (to match the legacy assumption that boot.art
+ // exists), and the rest are converted to boot-<name>.art.
+ // In addition, each .art file has an associated .oat and .vdex file, and an
+ // unstripped .oat file
+ for i, m := range info.preoptBootModules {
+ name := "boot"
+ if i != 0 {
+ name += "-" + m
+ }
+
+ art := outputDir.Join(ctx, name+".art")
+ oat := outputDir.Join(ctx, name+".oat")
+ vdex := outputDir.Join(ctx, name+".vdex")
+ unstrippedOat := symbolsDir.Join(ctx, name+".oat")
+
+ extraFiles = append(extraFiles, art, oat, vdex, unstrippedOat)
+
+ // Install the .oat and .art files.
+ rule.Install(art.String(), filepath.Join(installDir, art.Base()))
+ rule.Install(oat.String(), filepath.Join(installDir, oat.Base()))
+
+ // The vdex files are identical between architectures, install them to a shared location. The Make rules will
+ // only use the install rules for one architecture, and will create symlinks into the architecture-specific
+ // directories.
+ vdexInstalls = append(vdexInstalls,
+ android.RuleBuilderInstall{vdex.String(), filepath.Join(vdexInstallDir, vdex.Base())})
+
+ // Install the unstripped oat files. The Make rules will put these in $(TARGET_OUT_UNSTRIPPED)
+ unstrippedInstalls = append(unstrippedInstalls,
+ android.RuleBuilderInstall{unstrippedOat.String(), filepath.Join(installDir, unstrippedOat.Base())})
+ }
+
+ cmd.ImplicitOutputs(extraFiles.Strings())
+
+ rule.Build(pctx, ctx, "bootJarsDexpreopt_"+arch.String(), "dexpreopt boot jars "+arch.String())
+
+ // save output and installed files for makevars
+ info.installs[arch] = rule.Installs()
+ info.vdexInstalls[arch] = vdexInstalls
+ info.unstrippedInstalls[arch] = unstrippedInstalls
+}
+
+const failureMessage = `ERROR: Dex2oat failed to compile a boot image.
+It is likely that the boot classpath is inconsistent.
+Rebuild with ART_BOOT_IMAGE_EXTRA_ARGS="--runtime-arg -verbose:verifier" to see verification errors.`
+
+func bootImageProfileRule(ctx android.SingletonContext, info *bootJarsInfo, missingDeps []string) android.WritablePath {
+ if len(info.global.BootImageProfiles) == 0 {
+ return nil
+ }
+
+ tools := info.global.Tools
+
+ rule := android.NewRuleBuilder()
+ rule.MissingDeps(missingDeps)
+
+ var bootImageProfile string
+ if len(info.global.BootImageProfiles) > 1 {
+ combinedBootImageProfile := info.dir.Join(ctx, "boot-image-profile.txt")
+ rule.Command().Text("cat").Inputs(info.global.BootImageProfiles).Output(combinedBootImageProfile.String())
+ bootImageProfile = combinedBootImageProfile.String()
+ } else {
+ bootImageProfile = info.global.BootImageProfiles[0]
+ }
+
+ profile := info.dir.Join(ctx, "boot.prof")
+
+ rule.Command().
+ Text(`ANDROID_LOG_TAGS="*:e"`).
+ Tool(tools.Profman).
+ FlagWithArg("--create-profile-from=", bootImageProfile).
+ FlagForEachInput("--apk=", info.preoptBootDex.Strings()).
+ FlagForEachArg("--dex-location=", info.preoptBootLocations).
+ FlagWithOutput("--reference-profile-file=", profile.String())
+
+ rule.Install(profile.String(), "/system/etc/boot-image.prof")
+
+ rule.Build(pctx, ctx, "bootJarsProfile", "profile boot jars")
+
+ info.profileInstalls = rule.Installs()
+
+ return profile
+}
+
+func init() {
+ android.RegisterMakeVarsProvider(pctx, bootImageMakeVars)
+}
+
+// Export paths to Make. INTERNAL_PLATFORM_HIDDENAPI_FLAGS is used by Make rules in art/ and cts/.
+// Both paths are used to call dist-for-goals.
+func bootImageMakeVars(ctx android.MakeVarsContext) {
+ if skipDexpreoptBootJars(ctx) {
+ return
+ }
+
+ info := dexpreoptBootJarsInfo(ctx)
+ for arch, _ := range info.images {
+ ctx.Strict("DEXPREOPT_IMAGE_"+arch.String(), info.images[arch].String())
+
+ var builtInstalled []string
+ for _, install := range info.installs[arch] {
+ builtInstalled = append(builtInstalled, install.From+":"+install.To)
+ }
+
+ var unstrippedBuiltInstalled []string
+ for _, install := range info.unstrippedInstalls[arch] {
+ unstrippedBuiltInstalled = append(unstrippedBuiltInstalled, install.From+":"+install.To)
+ }
+
+ ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+arch.String(), info.installs[arch].String())
+ ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+arch.String(), info.unstrippedInstalls[arch].String())
+ ctx.Strict("DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_"+arch.String(), info.vdexInstalls[arch].String())
+ }
+
+ ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", info.profileInstalls.String())
+
+ ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(info.preoptBootDex.Strings(), " "))
+ ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(info.preoptBootLocations, " "))
+ ctx.Strict("PRODUCT_BOOTCLASSPATH", info.bootclasspath)
+ ctx.Strict("PRODUCT_SYSTEM_SERVER_CLASSPATH", info.systemServerClasspath)
+}
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index de1bcf5..adbd356 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -44,13 +44,15 @@
}
func hiddenAPISingletonFactory() android.Singleton {
- return hiddenAPISingleton{}
+ return &hiddenAPISingleton{}
}
-type hiddenAPISingleton struct{}
+type hiddenAPISingleton struct {
+ flags, metadata android.Path
+}
// hiddenAPI singleton rules
-func (hiddenAPISingleton) GenerateBuildActions(ctx android.SingletonContext) {
+func (h *hiddenAPISingleton) GenerateBuildActions(ctx android.SingletonContext) {
// Don't run any hiddenapi rules if UNSAFE_DISABLE_HIDDENAPI_FLAGS=true
if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
return
@@ -60,10 +62,24 @@
// These rules depend on files located in frameworks/base, skip them if running in a tree that doesn't have them.
if ctx.Config().FrameworksBaseDirExists(ctx) {
- flagsRule(ctx)
- metadataRule(ctx)
+ h.flags = flagsRule(ctx)
+ h.metadata = metadataRule(ctx)
} else {
- emptyFlagsRule(ctx)
+ h.flags = emptyFlagsRule(ctx)
+ }
+}
+
+// Export paths to Make. INTERNAL_PLATFORM_HIDDENAPI_FLAGS is used by Make rules in art/ and cts/.
+// Both paths are used to call dist-for-goals.
+func (h *hiddenAPISingleton) MakeVars(ctx android.MakeVarsContext) {
+ if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
+ return
+ }
+
+ ctx.Strict("INTERNAL_PLATFORM_HIDDENAPI_FLAGS", h.flags.String())
+
+ if h.metadata != nil {
+ ctx.Strict("INTERNAL_PLATFORM_HIDDENAPI_GREYLIST_METADATA", h.metadata.String())
}
}
@@ -170,7 +186,7 @@
// flagsRule creates a rule to build hiddenapi-flags.csv out of flags.csv files generated for boot image modules and
// the greylists.
-func flagsRule(ctx android.SingletonContext) {
+func flagsRule(ctx android.SingletonContext) android.Path {
var flagsCSV android.Paths
var greylistIgnoreConflicts android.Path
@@ -187,7 +203,7 @@
if greylistIgnoreConflicts == nil {
ctx.Errorf("failed to find removed_dex_api_filename from hiddenapi-lists-docs module")
- return
+ return nil
}
rule := android.NewRuleBuilder()
@@ -216,11 +232,13 @@
commitChangeForRestat(rule, tempPath, outputPath)
rule.Build(pctx, ctx, "hiddenAPIFlagsFile", "hiddenapi flags")
+
+ return outputPath
}
// emptyFlagsRule creates a rule to build an empty hiddenapi-flags.csv, which is needed by master-art-host builds that
// have a partial manifest without frameworks/base but still need to build a boot image.
-func emptyFlagsRule(ctx android.SingletonContext) {
+func emptyFlagsRule(ctx android.SingletonContext) android.Path {
rule := android.NewRuleBuilder()
outputPath := hiddenAPISingletonPaths(ctx).flags
@@ -229,11 +247,13 @@
rule.Command().Text("touch").Output(outputPath.String())
rule.Build(pctx, ctx, "emptyHiddenAPIFlagsFile", "empty hiddenapi flags")
+
+ return outputPath
}
// metadataRule creates a rule to build hiddenapi-greylist.csv out of the metadata.csv files generated for boot image
// modules.
-func metadataRule(ctx android.SingletonContext) {
+func metadataRule(ctx android.SingletonContext) android.Path {
var metadataCSV android.Paths
ctx.VisitAllModules(func(module android.Module) {
@@ -255,6 +275,8 @@
Output(outputPath.String())
rule.Build(pctx, ctx, "hiddenAPIGreylistMetadataFile", "hiddenapi greylist metadata")
+
+ return outputPath
}
// commitChangeForRestat adds a command to a rule that updates outputPath from tempPath if they are different. It
@@ -274,17 +296,3 @@
Text("fi").
Text(")")
}
-
-func init() {
- android.RegisterMakeVarsProvider(pctx, hiddenAPIMakeVars)
-}
-
-// Export paths to Make. INTERNAL_PLATFORM_HIDDENAPI_FLAGS is used by Make rules in art/ and cts/.
-// Both paths are used to call dist-for-goals.
-func hiddenAPIMakeVars(ctx android.MakeVarsContext) {
- if !ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
- singletonPaths := hiddenAPISingletonPaths(ctx)
- ctx.Strict("INTERNAL_PLATFORM_HIDDENAPI_FLAGS", singletonPaths.flags.String())
- ctx.Strict("INTERNAL_PLATFORM_HIDDENAPI_GREYLIST_METADATA", singletonPaths.metadata.String())
- }
-}
diff --git a/java/java.go b/java/java.go
index 880f920..3501174 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1527,7 +1527,7 @@
}
func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template)
+ j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template, j.testProperties.Test_suites)
j.data = ctx.ExpandSources(j.testProperties.Data, nil)
j.Library.GenerateAndroidBuildActions(ctx)
diff --git a/java/java_test.go b/java/java_test.go
index 034e905..8d3efcb 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -15,7 +15,6 @@
package java
import (
- "fmt"
"io/ioutil"
"os"
"path/filepath"
@@ -54,16 +53,7 @@
}
func testConfig(env map[string]string) android.Config {
- if env == nil {
- env = make(map[string]string)
- }
- if env["ANDROID_JAVA8_HOME"] == "" {
- env["ANDROID_JAVA8_HOME"] = "jdk8"
- }
- config := android.TestArchConfig(buildDir, env)
- config.TestProductVariables.DeviceSystemSdkVersions = []string{"14", "15"}
- return config
-
+ return TestConfig(buildDir, env)
}
func testContext(config android.Config, bp string,
@@ -113,53 +103,7 @@
ctx.Register()
- extraModules := []string{
- "core-lambda-stubs",
- "framework",
- "ext",
- "android_stubs_current",
- "android_system_stubs_current",
- "android_test_stubs_current",
- "core.current.stubs",
- "core.platform.api.stubs",
- "kotlin-stdlib",
- "kotlin-annotations",
- }
-
- for _, extra := range extraModules {
- bp += fmt.Sprintf(`
- java_library {
- name: "%s",
- srcs: ["a.java"],
- no_standard_libs: true,
- sdk_version: "core_current",
- system_modules: "core-platform-api-stubs-system-modules",
- }
- `, extra)
- }
-
- bp += `
- android_app {
- name: "framework-res",
- no_framework_libs: true,
- }
- `
-
- systemModules := []string{
- "core-system-modules",
- "core-platform-api-stubs-system-modules",
- "android_stubs_current_system_modules",
- "android_system_stubs_current_system_modules",
- "android_test_stubs_current_system_modules",
- }
-
- for _, extra := range systemModules {
- bp += fmt.Sprintf(`
- java_system_modules {
- name: "%s",
- }
- `, extra)
- }
+ bp += GatherRequiredDepsForTest()
mockFS := map[string][]byte{
"Android.bp": []byte(bp),
diff --git a/java/testing.go b/java/testing.go
new file mode 100644
index 0000000..6febfa1
--- /dev/null
+++ b/java/testing.go
@@ -0,0 +1,88 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java
+
+import (
+ "fmt"
+
+ "android/soong/android"
+)
+
+func TestConfig(buildDir string, env map[string]string) android.Config {
+ if env == nil {
+ env = make(map[string]string)
+ }
+ if env["ANDROID_JAVA8_HOME"] == "" {
+ env["ANDROID_JAVA8_HOME"] = "jdk8"
+ }
+ config := android.TestArchConfig(buildDir, env)
+ config.TestProductVariables.DeviceSystemSdkVersions = []string{"14", "15"}
+
+ return config
+}
+
+func GatherRequiredDepsForTest() string {
+ var bp string
+
+ extraModules := []string{
+ "core-lambda-stubs",
+ "framework",
+ "ext",
+ "android_stubs_current",
+ "android_system_stubs_current",
+ "android_test_stubs_current",
+ "core.current.stubs",
+ "core.platform.api.stubs",
+ "kotlin-stdlib",
+ "kotlin-annotations",
+ }
+
+ for _, extra := range extraModules {
+ bp += fmt.Sprintf(`
+ java_library {
+ name: "%s",
+ srcs: ["a.java"],
+ no_standard_libs: true,
+ sdk_version: "core_current",
+ system_modules: "core-platform-api-stubs-system-modules",
+ }
+ `, extra)
+ }
+
+ bp += `
+ android_app {
+ name: "framework-res",
+ no_framework_libs: true,
+ }
+ `
+
+ systemModules := []string{
+ "core-system-modules",
+ "core-platform-api-stubs-system-modules",
+ "android_stubs_current_system_modules",
+ "android_system_stubs_current_system_modules",
+ "android_test_stubs_current_system_modules",
+ }
+
+ for _, extra := range systemModules {
+ bp += fmt.Sprintf(`
+ java_system_modules {
+ name: "%s",
+ }
+ `, extra)
+ }
+
+ return bp
+}
diff --git a/python/test.go b/python/test.go
index 43ee54c..55b0ab5 100644
--- a/python/test.go
+++ b/python/test.go
@@ -50,7 +50,7 @@
func (test *testDecorator) install(ctx android.ModuleContext, file android.Path) {
test.testConfig = tradefed.AutoGenPythonBinaryHostTestConfig(ctx, test.testProperties.Test_config,
- test.testProperties.Test_config_template)
+ test.testProperties.Test_config_template, test.binaryDecorator.binaryProperties.Test_suites)
test.binaryDecorator.pythonInstaller.dir = "nativetest"
test.binaryDecorator.pythonInstaller.dir64 = "nativetest64"
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index 92e0af4..745e424 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -19,7 +19,6 @@
"android/soong/cc"
"android/soong/java"
- "fmt"
"io/ioutil"
"os"
"strings"
@@ -90,54 +89,7 @@
ctx.Register()
- extraModules := []string{
- "core-lambda-stubs",
- "framework",
- "ext",
- "updatable_media_stubs",
-
- "android_stubs_current",
- "android_system_stubs_current",
- "android_test_stubs_current",
- "core.current.stubs",
- "core.platform.api.stubs",
- }
-
- for _, extra := range extraModules {
- bp += fmt.Sprintf(`
- java_library {
- name: "%s",
- srcs: ["a.java"],
- no_standard_libs: true,
- sdk_version: "core_current",
- system_modules: "core-platform-api-stubs-system-modules",
- }
- `, extra)
- }
-
- bp += `
- android_app {
- name: "framework-res",
- no_framework_libs: true,
- }
- `
-
- systemModules := []string{
- "core-system-modules",
- "core-platform-api-stubs-system-modules",
- "android_stubs_current_system_modules",
- "android_system_stubs_current_system_modules",
- "android_test_stubs_current_system_modules",
- }
-
- for _, extra := range systemModules {
- bp += fmt.Sprintf(`
- java_system_modules {
- name: "%s",
- }
- `, extra)
- }
-
+ bp += java.GatherRequiredDepsForTest()
bp += cc.GatherRequiredDepsForTest(android.Android)
mockFS := map[string][]byte{
@@ -224,16 +176,12 @@
}
func testConfig(env map[string]string) android.Config {
- if env == nil {
- env = make(map[string]string)
- }
- if env["ANDROID_JAVA8_HOME"] == "" {
- env["ANDROID_JAVA8_HOME"] = "jdk8"
- }
- config := android.TestArchConfig(buildDir, env)
+ config := java.TestConfig(buildDir, env)
+
config.TestProductVariables.DeviceSystemSdkVersions = []string{"28"}
config.TestProductVariables.DeviceVndkVersion = proptools.StringPtr("current")
config.TestProductVariables.Platform_vndk_version = proptools.StringPtr("VER")
+
return config
}
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index e6a1b48..cfa7164 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -15,8 +15,6 @@
package tradefed
import (
- "strings"
-
"github.com/google/blueprint"
"android/soong/android"
@@ -40,10 +38,10 @@
CommandDeps: []string{"$template"},
}, "name", "template")
-func testConfigPath(ctx android.ModuleContext, prop *string) (path android.Path, autogenPath android.WritablePath) {
+func testConfigPath(ctx android.ModuleContext, prop *string, testSuites []string) (path android.Path, autogenPath android.WritablePath) {
if p := getTestConfig(ctx, prop); p != nil {
return p, nil
- } else if !strings.HasPrefix(ctx.ModuleDir(), "cts/") {
+ } else if !android.InList("cts", testSuites) {
outputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".config")
return nil, outputFile
} else {
@@ -67,8 +65,8 @@
}
func AutoGenNativeTestConfig(ctx android.ModuleContext, testConfigProp *string,
- testConfigTemplateProp *string) android.Path {
- path, autogenPath := testConfigPath(ctx, testConfigProp)
+ testConfigTemplateProp *string, testSuites []string) android.Path {
+ path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites)
if autogenPath != nil {
templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
if templatePath.Valid() {
@@ -86,8 +84,8 @@
}
func AutoGenNativeBenchmarkTestConfig(ctx android.ModuleContext, testConfigProp *string,
- testConfigTemplateProp *string) android.Path {
- path, autogenPath := testConfigPath(ctx, testConfigProp)
+ testConfigTemplateProp *string, testSuites []string) android.Path {
+ path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites)
if autogenPath != nil {
templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
if templatePath.Valid() {
@@ -100,8 +98,8 @@
return path
}
-func AutoGenJavaTestConfig(ctx android.ModuleContext, testConfigProp *string, testConfigTemplateProp *string) android.Path {
- path, autogenPath := testConfigPath(ctx, testConfigProp)
+func AutoGenJavaTestConfig(ctx android.ModuleContext, testConfigProp *string, testConfigTemplateProp *string, testSuites []string) android.Path {
+ path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites)
if autogenPath != nil {
templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
if templatePath.Valid() {
@@ -119,9 +117,9 @@
}
func AutoGenPythonBinaryHostTestConfig(ctx android.ModuleContext, testConfigProp *string,
- testConfigTemplateProp *string) android.Path {
+ testConfigTemplateProp *string, testSuites []string) android.Path {
- path, autogenPath := testConfigPath(ctx, testConfigProp)
+ path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites)
if autogenPath != nil {
templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
if templatePath.Valid() {
@@ -143,8 +141,8 @@
},
}, "name", "template")
-func AutoGenInstrumentationTestConfig(ctx android.ModuleContext, testConfigProp *string, testConfigTemplateProp *string, manifest android.Path) android.Path {
- path, autogenPath := testConfigPath(ctx, testConfigProp)
+func AutoGenInstrumentationTestConfig(ctx android.ModuleContext, testConfigProp *string, testConfigTemplateProp *string, manifest android.Path, testSuites []string) android.Path {
+ path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites)
if autogenPath != nil {
template := "${InstrumentationTestConfigTemplate}"
moduleTemplate := getTestConfigTemplate(ctx, testConfigTemplateProp)
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index d4922f3..fb30f85 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -74,41 +74,39 @@
}
var Configuration = map[string]PathConfig{
- "bash": Allowed,
- "bc": Allowed,
- "bzip2": Allowed,
- "date": Allowed,
- "dd": Allowed,
- "diff": Allowed,
- "egrep": Allowed,
- "find": Allowed,
- "fuser": Allowed,
- "getopt": Allowed,
- "git": Allowed,
- "grep": Allowed,
- "gzip": Allowed,
- "hexdump": Allowed,
- "jar": Allowed,
- "java": Allowed,
- "javap": Allowed,
- "lsof": Allowed,
- "m4": Allowed,
- "openssl": Allowed,
- "patch": Allowed,
- "pstree": Allowed,
- "python": Allowed,
- "python2.7": Allowed,
- "python3": Allowed,
- "realpath": Allowed,
- "rsync": Allowed,
- "sh": Allowed,
- "tar": Allowed,
- "timeout": Allowed,
- "tr": Allowed,
- "unzip": Allowed,
- "xz": Allowed,
- "zip": Allowed,
- "zipinfo": Allowed,
+ "bash": Allowed,
+ "bc": Allowed,
+ "bzip2": Allowed,
+ "date": Allowed,
+ "dd": Allowed,
+ "diff": Allowed,
+ "egrep": Allowed,
+ "find": Allowed,
+ "fuser": Allowed,
+ "getopt": Allowed,
+ "git": Allowed,
+ "grep": Allowed,
+ "gzip": Allowed,
+ "hexdump": Allowed,
+ "jar": Allowed,
+ "java": Allowed,
+ "javap": Allowed,
+ "lsof": Allowed,
+ "m4": Allowed,
+ "openssl": Allowed,
+ "patch": Allowed,
+ "pstree": Allowed,
+ "python3": Allowed,
+ "realpath": Allowed,
+ "rsync": Allowed,
+ "sh": Allowed,
+ "tar": Allowed,
+ "timeout": Allowed,
+ "tr": Allowed,
+ "unzip": Allowed,
+ "xz": Allowed,
+ "zip": Allowed,
+ "zipinfo": Allowed,
// Host toolchain is removed. In-tree toolchain should be used instead.
// GCC also can't find cc1 with this implementation.