Merge "Revert "Remove armv7-a without neon support""
diff --git a/android/config.go b/android/config.go
index 9217aab..7d2e829 100644
--- a/android/config.go
+++ b/android/config.go
@@ -948,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 {
@@ -956,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/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/coverage.go b/cc/coverage.go
index 0549705..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
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/dexpreopt.go b/dexpreopt/dexpreopt.go
index eacb86a..7fdfb49 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -578,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/java/aar.go b/java/aar.go
index b8a5e35..e5ab036 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -190,9 +190,6 @@
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/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/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.