Merge "Check whether value_variables are set"
diff --git a/android/androidmk.go b/android/androidmk.go
index b32048a..73f60d0 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -627,7 +627,7 @@
fmt.Fprintln(buf, "LOCAL_MODULE_MAKEFILE := $(lastword $(MAKEFILE_LIST))")
- type_stats := make(map[string]int)
+ typeStats := make(map[string]int)
for _, mod := range mods {
err := translateAndroidMkModule(ctx, buf, mod)
if err != nil {
@@ -636,19 +636,19 @@
}
if amod, ok := mod.(Module); ok && ctx.PrimaryModule(amod) == amod {
- type_stats[ctx.ModuleType(amod)] += 1
+ typeStats[ctx.ModuleType(amod)] += 1
}
}
keys := []string{}
fmt.Fprintln(buf, "\nSTATS.SOONG_MODULE_TYPE :=")
- for k := range type_stats {
+ for k := range typeStats {
keys = append(keys, k)
}
sort.Strings(keys)
for _, mod_type := range keys {
fmt.Fprintln(buf, "STATS.SOONG_MODULE_TYPE +=", mod_type)
- fmt.Fprintf(buf, "STATS.SOONG_MODULE_TYPE.%s := %d\n", mod_type, type_stats[mod_type])
+ fmt.Fprintf(buf, "STATS.SOONG_MODULE_TYPE.%s := %d\n", mod_type, typeStats[mod_type])
}
// Don't write to the file if it hasn't changed
@@ -820,7 +820,7 @@
}
return !module.Enabled() ||
- module.commonProperties.SkipInstall ||
+ module.commonProperties.HideFromMake ||
// Make does not understand LinuxBionic
module.Os() == LinuxBionic
}
diff --git a/android/apex.go b/android/apex.go
index f6eca86..47d14cc 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -253,6 +253,12 @@
CopyDirectlyInAnyApex()
}
+// Interface that identifies dependencies to skip Apex dependency check
+type SkipApexAllowedDependenciesCheck interface {
+ // Returns true to skip the Apex dependency check, which limits the allowed dependency in build.
+ SkipApexAllowedDependenciesCheck() bool
+}
+
// ApexModuleBase provides the default implementation for the ApexModule interface. APEX-aware
// modules are expected to include this struct and call InitApexModule().
type ApexModuleBase struct {
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 81ca475..357b99f 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -387,25 +387,25 @@
if err != nil {
return err
}
- cquery_file_relpath := filepath.Join(context.intermediatesDir(), "buildroot.cquery")
+ cqueryFileRelpath := filepath.Join(context.intermediatesDir(), "buildroot.cquery")
err = ioutil.WriteFile(
- absolutePath(cquery_file_relpath),
+ absolutePath(cqueryFileRelpath),
context.cqueryStarlarkFileContents(), 0666)
if err != nil {
return err
}
- workspace_file_relpath := filepath.Join(context.intermediatesDir(), "WORKSPACE.bazel")
+ workspaceFileRelpath := filepath.Join(context.intermediatesDir(), "WORKSPACE.bazel")
err = ioutil.WriteFile(
- absolutePath(workspace_file_relpath),
+ absolutePath(workspaceFileRelpath),
context.workspaceFileContents(), 0666)
if err != nil {
return err
}
- buildroot_label := "//:buildroot"
+ buildrootLabel := "//:buildroot"
cqueryOutput, err = context.issueBazelCommand(bazel.CqueryBuildRootRunName, "cquery",
- []string{fmt.Sprintf("deps(%s)", buildroot_label)},
+ []string{fmt.Sprintf("deps(%s)", buildrootLabel)},
"--output=starlark",
- "--starlark:file="+cquery_file_relpath)
+ "--starlark:file="+cqueryFileRelpath)
if err != nil {
return err
@@ -432,7 +432,7 @@
// TODO(cparsons): Use --target_pattern_file to avoid command line limits.
var aqueryOutput string
aqueryOutput, err = context.issueBazelCommand(bazel.AqueryBuildRootRunName, "aquery",
- []string{fmt.Sprintf("deps(%s)", buildroot_label),
+ []string{fmt.Sprintf("deps(%s)", buildrootLabel),
// Use jsonproto instead of proto; actual proto parsing would require a dependency on Bazel's
// proto sources, which would add a number of unnecessary dependencies.
"--output=jsonproto"})
diff --git a/android/makevars.go b/android/makevars.go
index 5101436..546abcf 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -90,6 +90,7 @@
ModuleDir(module blueprint.Module) string
ModuleSubDir(module blueprint.Module) string
ModuleType(module blueprint.Module) string
+ ModuleProvider(module blueprint.Module, key blueprint.ProviderKey) interface{}
BlueprintFile(module blueprint.Module) string
ModuleErrorf(module blueprint.Module, format string, args ...interface{})
diff --git a/android/module.go b/android/module.go
index 429f311..cfb32c1 100644
--- a/android/module.go
+++ b/android/module.go
@@ -452,8 +452,8 @@
InstallInRoot() bool
InstallBypassMake() bool
InstallForceOS() (*OsType, *ArchType)
- SkipInstall()
- IsSkipInstall() bool
+ HideFromMake()
+ IsHideFromMake() bool
MakeUninstallable()
ReplacedByPrebuilt()
IsReplacedByPrebuilt() bool
@@ -751,6 +751,13 @@
// Set by osMutator.
CommonOSVariant bool `blueprint:"mutated"`
+ // When HideFromMake is set to true, no entry for this variant will be emitted in the
+ // generated Android.mk file.
+ HideFromMake bool `blueprint:"mutated"`
+
+ // When SkipInstall is set to true, calls to ctx.InstallFile, ctx.InstallExecutable,
+ // ctx.InstallSymlink and ctx.InstallAbsoluteSymlink act like calls to ctx.PackageFile
+ // and don't create a rule to install the file.
SkipInstall bool `blueprint:"mutated"`
// Whether the module has been replaced by a prebuilt
@@ -1355,26 +1362,33 @@
m.commonProperties.ForcedDisabled = true
}
+// HideFromMake marks this variant so that it is not emitted in the generated Android.mk file.
+func (m *ModuleBase) HideFromMake() {
+ m.commonProperties.HideFromMake = true
+}
+
+// IsHideFromMake returns true if HideFromMake was previously called.
+func (m *ModuleBase) IsHideFromMake() bool {
+ return m.commonProperties.HideFromMake == true
+}
+
+// SkipInstall marks this variant to not create install rules when ctx.Install* are called.
func (m *ModuleBase) SkipInstall() {
m.commonProperties.SkipInstall = true
}
-func (m *ModuleBase) IsSkipInstall() bool {
- return m.commonProperties.SkipInstall == true
-}
-
-// Similar to SkipInstall, but if the AndroidMk entry would set
+// Similar to HideFromMake, but if the AndroidMk entry would set
// LOCAL_UNINSTALLABLE_MODULE then this variant may still output that entry
// rather than leaving it out altogether. That happens in cases where it would
// have other side effects, in particular when it adds a NOTICE file target,
// which other install targets might depend on.
func (m *ModuleBase) MakeUninstallable() {
- m.SkipInstall()
+ m.HideFromMake()
}
func (m *ModuleBase) ReplacedByPrebuilt() {
m.commonProperties.ReplacedByPrebuilt = true
- m.SkipInstall()
+ m.HideFromMake()
}
func (m *ModuleBase) IsReplacedByPrebuilt() bool {
@@ -2440,11 +2454,15 @@
return m.module.InstallForceOS()
}
-func (m *moduleContext) skipInstall(fullInstallPath InstallPath) bool {
+func (m *moduleContext) skipInstall() bool {
if m.module.base().commonProperties.SkipInstall {
return true
}
+ if m.module.base().commonProperties.HideFromMake {
+ return true
+ }
+
// We'll need a solution for choosing which of modules with the same name in different
// namespaces to install. For now, reuse the list of namespaces exported to Make as the
// list of namespaces to install in a Soong-only build.
@@ -2492,7 +2510,7 @@
fullInstallPath := installPath.Join(m, name)
m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, false)
- if !m.skipInstall(fullInstallPath) {
+ if !m.skipInstall() {
deps = append(deps, m.module.base().installFilesDepSet.ToList().Paths()...)
var implicitDeps, orderOnlyDeps Paths
@@ -2526,6 +2544,7 @@
m.packageFile(fullInstallPath, srcPath, executable)
m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
+
return fullInstallPath
}
@@ -2537,7 +2556,7 @@
if err != nil {
panic(fmt.Sprintf("Unable to generate symlink between %q and %q: %s", fullInstallPath.Base(), srcPath.Base(), err))
}
- if !m.skipInstall(fullInstallPath) {
+ if !m.skipInstall() {
m.Build(pctx, BuildParams{
Rule: Symlink,
@@ -2570,7 +2589,7 @@
fullInstallPath := installPath.Join(m, name)
m.module.base().hooks.runInstallHooks(m, nil, fullInstallPath, true)
- if !m.skipInstall(fullInstallPath) {
+ if !m.skipInstall() {
m.Build(pctx, BuildParams{
Rule: Symlink,
Description: "install symlink " + fullInstallPath.Base() + " -> " + absPath,
@@ -2738,6 +2757,7 @@
// Modules can implement HostToolProvider and return a valid OptionalPath from HostToolPath() to
// specify that they can be used as a tool by a genrule module.
type HostToolProvider interface {
+ Module
// HostToolPath returns the path to the host tool for the module if it is one, or an invalid
// OptionalPath.
HostToolPath() OptionalPath
diff --git a/android/namespace.go b/android/namespace.go
index 9d7e8ac..d137636 100644
--- a/android/namespace.go
+++ b/android/namespace.go
@@ -232,13 +232,14 @@
}
-func (r *NameResolver) getNamespacesToSearchForModule(sourceNamespace *Namespace) (searchOrder []*Namespace) {
- if sourceNamespace.visibleNamespaces == nil {
+func (r *NameResolver) getNamespacesToSearchForModule(sourceNamespace blueprint.Namespace) (searchOrder []*Namespace) {
+ ns, ok := sourceNamespace.(*Namespace)
+ if !ok || ns.visibleNamespaces == nil {
// When handling dependencies before namespaceMutator, assume they are non-Soong Blueprint modules and give
// access to all namespaces.
return r.sortedNamespaces.sortedItems()
}
- return sourceNamespace.visibleNamespaces
+ return ns.visibleNamespaces
}
func (r *NameResolver) ModuleFromName(name string, namespace blueprint.Namespace) (group blueprint.ModuleGroup, found bool) {
@@ -252,7 +253,7 @@
container := namespace.moduleContainer
return container.ModuleFromName(moduleName, nil)
}
- for _, candidate := range r.getNamespacesToSearchForModule(namespace.(*Namespace)) {
+ for _, candidate := range r.getNamespacesToSearchForModule(namespace) {
group, found = candidate.moduleContainer.ModuleFromName(name, nil)
if found {
return group, true
diff --git a/android/neverallow.go b/android/neverallow.go
index 8b8e1ac..031b3f4 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -51,7 +51,6 @@
func init() {
AddNeverAllowRules(createIncludeDirsRules()...)
AddNeverAllowRules(createTrebleRules()...)
- AddNeverAllowRules(createLibcoreRules()...)
AddNeverAllowRules(createMediaRules()...)
AddNeverAllowRules(createJavaDeviceForHostRules()...)
AddNeverAllowRules(createCcSdkVariantRules()...)
@@ -133,38 +132,6 @@
}
}
-func createLibcoreRules() []Rule {
- var coreLibraryProjects = []string{
- "libcore",
- "external/apache-harmony",
- "external/apache-xml",
- "external/bouncycastle",
- "external/conscrypt",
- "external/icu",
- "external/okhttp",
- "external/wycheproof",
- "prebuilts",
- }
-
- // Additional whitelisted path only used for ART testing, which needs access to core library
- // targets. This does not affect the contents of a device image (system, vendor, etc.).
- var artTests = []string{
- "art/test",
- }
-
- // Core library constraints. The sdk_version: "none" can only be used in core library projects and ART tests.
- // Access to core library targets is restricted using visibility rules.
- rules := []Rule{
- NeverAllow().
- NotIn(coreLibraryProjects...).
- NotIn(artTests...).
- With("sdk_version", "none").
- WithoutMatcher("name", Regexp("^android_.*stubs_current$")),
- }
-
- return rules
-}
-
func createMediaRules() []Rule {
return []Rule{
NeverAllow().
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 1d454e5..8c7a538 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -215,50 +215,6 @@
"java_device_for_host can only be used in allowed projects",
},
},
- // Libcore rule tests
- {
- name: "sdk_version: \"none\" inside core libraries",
- fs: map[string][]byte{
- "libcore/Android.bp": []byte(`
- java_library {
- name: "inside_core_libraries",
- sdk_version: "none",
- }`),
- },
- },
- {
- name: "sdk_version: \"none\" on android_*stubs_current stub",
- fs: map[string][]byte{
- "frameworks/base/Android.bp": []byte(`
- java_library {
- name: "android_stubs_current",
- sdk_version: "none",
- }`),
- },
- },
- {
- name: "sdk_version: \"none\" outside core libraries",
- fs: map[string][]byte{
- "Android.bp": []byte(`
- java_library {
- name: "outside_core_libraries",
- sdk_version: "none",
- }`),
- },
- expectedErrors: []string{
- "module \"outside_core_libraries\": violates neverallow",
- },
- },
- {
- name: "sdk_version: \"current\"",
- fs: map[string][]byte{
- "Android.bp": []byte(`
- java_library {
- name: "outside_core_libraries",
- sdk_version: "current",
- }`),
- },
- },
// CC sdk rule tests
{
name: `"sdk_variant_only" outside allowed list`,
diff --git a/android/override_module.go b/android/override_module.go
index f8342d5..fa08566 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -235,7 +235,7 @@
return
}
// See if there's a prebuilt module that overrides this override module with prefer flag,
- // in which case we call SkipInstall on the corresponding variant later.
+ // in which case we call HideFromMake on the corresponding variant later.
ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(dep Module) {
prebuilt, ok := dep.(PrebuiltInterface)
if !ok {
@@ -284,7 +284,7 @@
mods[i+1].(OverridableModule).override(ctx, o)
if o.getOverriddenByPrebuilt() {
// The overriding module itself, too, is overridden by a prebuilt. Skip its installation.
- mods[i+1].SkipInstall()
+ mods[i+1].HideFromMake()
}
}
} else if o, ok := ctx.Module().(OverrideModule); ok {
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 8114a65..39d30c5 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -289,7 +289,7 @@
})
}
} else {
- m.SkipInstall()
+ m.HideFromMake()
}
}
}
diff --git a/android/prebuilt_build_tool.go b/android/prebuilt_build_tool.go
index b00dc2f..516d042 100644
--- a/android/prebuilt_build_tool.go
+++ b/android/prebuilt_build_tool.go
@@ -86,6 +86,9 @@
func (t *prebuiltBuildTool) MakeVars(ctx MakeVarsModuleContext) {
if makeVar := String(t.properties.Export_to_make_var); makeVar != "" {
+ if t.Target().Os != BuildOs {
+ return
+ }
ctx.StrictRaw(makeVar, t.toolPath.String())
}
}
diff --git a/android/rule_builder.go b/android/rule_builder.go
index e2d8187..84501fe 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -32,6 +32,7 @@
const sboxSandboxBaseDir = "__SBOX_SANDBOX_DIR__"
const sboxOutSubDir = "out"
+const sboxToolsSubDir = "tools"
const sboxOutDir = sboxSandboxBaseDir + "/" + sboxOutSubDir
// RuleBuilder provides an alternative to ModuleContext.Rule and ModuleContext.Build to add a command line to the build
@@ -48,6 +49,7 @@
highmem bool
remoteable RemoteRuleSupports
outDir WritablePath
+ sboxTools bool
sboxManifestPath WritablePath
missingDeps []string
}
@@ -140,6 +142,19 @@
return r
}
+// SandboxTools enables tool sandboxing for the rule by copying any referenced tools into the
+// sandbox.
+func (r *RuleBuilder) SandboxTools() *RuleBuilder {
+ if !r.sbox {
+ panic("SandboxTools() must be called after Sbox()")
+ }
+ if len(r.commands) > 0 {
+ panic("SandboxTools() may not be called after Command()")
+ }
+ r.sboxTools = true
+ return r
+}
+
// Install associates an output of the rule with an install location, which can be retrieved later using
// RuleBuilder.Installs.
func (r *RuleBuilder) Install(from Path, to string) {
@@ -468,8 +483,29 @@
manifest.OutputDepfile = proto.String(depFile.String())
}
+ // If sandboxing tools is enabled, add copy rules to the manifest to copy each tool
+ // into the sbox directory.
+ if r.sboxTools {
+ for _, tool := range tools {
+ command.CopyBefore = append(command.CopyBefore, &sbox_proto.Copy{
+ From: proto.String(tool.String()),
+ To: proto.String(sboxPathForToolRel(r.ctx, tool)),
+ })
+ }
+ for _, c := range r.commands {
+ for _, tool := range c.packagedTools {
+ command.CopyBefore = append(command.CopyBefore, &sbox_proto.Copy{
+ From: proto.String(tool.srcPath.String()),
+ To: proto.String(sboxPathForPackagedToolRel(tool)),
+ Executable: proto.Bool(tool.executable),
+ })
+ tools = append(tools, tool.srcPath)
+ }
+ }
+ }
+
// Add copy rules to the manifest to copy each output file from the sbox directory.
- // to the output directory.
+ // to the output directory after running the commands.
sboxOutputs := make([]string, len(outputs))
for i, output := range outputs {
rel := Rel(r.ctx, r.outDir.String(), output.String())
@@ -582,6 +618,7 @@
symlinkOutputs WritablePaths
depFiles WritablePaths
tools Paths
+ packagedTools []PackagingSpec
rspFileInputs Paths
// spans [start,end) of the command that should not be ninja escaped
@@ -625,6 +662,79 @@
return path.String()
}
+// SboxPathForTool takes a path to a tool, which may be an output file or a source file, and returns
+// the corresponding path for the tool in the sbox sandbox. It assumes that sandboxing and tool
+// sandboxing are enabled.
+func SboxPathForTool(ctx BuilderContext, path Path) string {
+ return filepath.Join(sboxSandboxBaseDir, sboxPathForToolRel(ctx, path))
+}
+
+func sboxPathForToolRel(ctx BuilderContext, path Path) string {
+ // Errors will be handled in RuleBuilder.Build where we have a context to report them
+ relOut, isRelOut, _ := maybeRelErr(PathForOutput(ctx, "host", ctx.Config().PrebuiltOS()).String(), path.String())
+ if isRelOut {
+ // The tool is in the output directory, it will be copied to __SBOX_OUT_DIR__/tools/out
+ return filepath.Join(sboxToolsSubDir, "out", relOut)
+ }
+ // The tool is in the source directory, it will be copied to __SBOX_OUT_DIR__/tools/src
+ return filepath.Join(sboxToolsSubDir, "src", path.String())
+}
+
+// SboxPathForPackagedTool takes a PackageSpec for a tool and returns the corresponding path for the
+// tool after copying it into the sandbox. This can be used on the RuleBuilder command line to
+// reference the tool.
+func SboxPathForPackagedTool(spec PackagingSpec) string {
+ return filepath.Join(sboxSandboxBaseDir, sboxPathForPackagedToolRel(spec))
+}
+
+func sboxPathForPackagedToolRel(spec PackagingSpec) string {
+ return filepath.Join(sboxToolsSubDir, "out", spec.relPathInPackage)
+}
+
+// PathForTool takes a path to a tool, which may be an output file or a source file, and returns
+// the corresponding path for the tool in the sbox sandbox if sbox is enabled, or the original path
+// if it is not. This can be used on the RuleBuilder command line to reference the tool.
+func (c *RuleBuilderCommand) PathForTool(path Path) string {
+ if c.rule.sbox && c.rule.sboxTools {
+ return filepath.Join(sboxSandboxBaseDir, sboxPathForToolRel(c.rule.ctx, path))
+ }
+ return path.String()
+}
+
+// PackagedTool adds the specified tool path to the command line. It can only be used with tool
+// sandboxing enabled by SandboxTools(), and will copy the tool into the sandbox.
+func (c *RuleBuilderCommand) PackagedTool(spec PackagingSpec) *RuleBuilderCommand {
+ if !c.rule.sboxTools {
+ panic("PackagedTool() requires SandboxTools()")
+ }
+
+ c.packagedTools = append(c.packagedTools, spec)
+ c.Text(sboxPathForPackagedToolRel(spec))
+ return c
+}
+
+// ImplicitPackagedTool copies the specified tool into the sandbox without modifying the command
+// line. It can only be used with tool sandboxing enabled by SandboxTools().
+func (c *RuleBuilderCommand) ImplicitPackagedTool(spec PackagingSpec) *RuleBuilderCommand {
+ if !c.rule.sboxTools {
+ panic("ImplicitPackagedTool() requires SandboxTools()")
+ }
+
+ c.packagedTools = append(c.packagedTools, spec)
+ return c
+}
+
+// ImplicitPackagedTools copies the specified tools into the sandbox without modifying the command
+// line. It can only be used with tool sandboxing enabled by SandboxTools().
+func (c *RuleBuilderCommand) ImplicitPackagedTools(specs []PackagingSpec) *RuleBuilderCommand {
+ if !c.rule.sboxTools {
+ panic("ImplicitPackagedTools() requires SandboxTools()")
+ }
+
+ c.packagedTools = append(c.packagedTools, specs...)
+ return c
+}
+
// Text adds the specified raw text to the command line. The text should not contain input or output paths or the
// rule will not have them listed in its dependencies or outputs.
func (c *RuleBuilderCommand) Text(text string) *RuleBuilderCommand {
@@ -693,7 +803,19 @@
// RuleBuilder.Tools.
func (c *RuleBuilderCommand) Tool(path Path) *RuleBuilderCommand {
c.tools = append(c.tools, path)
- return c.Text(path.String())
+ return c.Text(c.PathForTool(path))
+}
+
+// Tool adds the specified tool path to the dependencies returned by RuleBuilder.Tools.
+func (c *RuleBuilderCommand) ImplicitTool(path Path) *RuleBuilderCommand {
+ c.tools = append(c.tools, path)
+ return c
+}
+
+// Tool adds the specified tool path to the dependencies returned by RuleBuilder.Tools.
+func (c *RuleBuilderCommand) ImplicitTools(paths Paths) *RuleBuilderCommand {
+ c.tools = append(c.tools, paths...)
+ return c
}
// BuiltTool adds the specified tool path that was built using a host Soong module to the command line. The path will
diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go
index e676e4a..06ea124 100644
--- a/android/rule_builder_test.go
+++ b/android/rule_builder_test.go
@@ -436,6 +436,44 @@
t.Errorf("\nwant rule.depFileMergerCmd() = %#v\n got %#v", w, g)
}
})
+
+ t.Run("sbox tools", func(t *testing.T) {
+ rule := NewRuleBuilder(pctx, ctx).Sbox(PathForOutput(ctx, ""),
+ PathForOutput(ctx, "sbox.textproto")).SandboxTools()
+ addCommands(rule)
+
+ wantCommands := []string{
+ "__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output Input __SBOX_SANDBOX_DIR__/out/Output __SBOX_SANDBOX_DIR__/out/SymlinkOutput Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd",
+ "command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/tools/src/tool2",
+ "command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3",
+ }
+
+ wantDepMergerCommand := "__SBOX_SANDBOX_DIR__/tools/out/bin/dep_fixer __SBOX_SANDBOX_DIR__/out/DepFile __SBOX_SANDBOX_DIR__/out/depfile __SBOX_SANDBOX_DIR__/out/ImplicitDepFile __SBOX_SANDBOX_DIR__/out/depfile2"
+
+ if g, w := rule.Commands(), wantCommands; !reflect.DeepEqual(g, w) {
+ t.Errorf("\nwant rule.Commands() = %#v\n got %#v", w, g)
+ }
+
+ if g, w := rule.Inputs(), wantInputs; !reflect.DeepEqual(w, g) {
+ t.Errorf("\nwant rule.Inputs() = %#v\n got %#v", w, g)
+ }
+ if g, w := rule.Outputs(), wantOutputs; !reflect.DeepEqual(w, g) {
+ t.Errorf("\nwant rule.Outputs() = %#v\n got %#v", w, g)
+ }
+ if g, w := rule.DepFiles(), wantDepFiles; !reflect.DeepEqual(w, g) {
+ t.Errorf("\nwant rule.DepFiles() = %#v\n got %#v", w, g)
+ }
+ if g, w := rule.Tools(), wantTools; !reflect.DeepEqual(w, g) {
+ t.Errorf("\nwant rule.Tools() = %#v\n got %#v", w, g)
+ }
+ if g, w := rule.OrderOnlys(), wantOrderOnlys; !reflect.DeepEqual(w, g) {
+ t.Errorf("\nwant rule.OrderOnlys() = %#v\n got %#v", w, g)
+ }
+
+ if g, w := rule.depFileMergerCmd(rule.DepFiles()).String(), wantDepMergerCommand; g != w {
+ t.Errorf("\nwant rule.depFileMergerCmd() = %#v\n got %#v", w, g)
+ }
+ })
}
func testRuleBuilderFactory() Module {
diff --git a/android/variable.go b/android/variable.go
index 93dac3d..753ddd7 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -126,13 +126,14 @@
}
Arc struct {
- Cflags []string
- Exclude_srcs []string
- Include_dirs []string
- Shared_libs []string
- Static_libs []string
- Srcs []string
- }
+ Cflags []string `android:"arch_variant"`
+ Exclude_srcs []string `android:"arch_variant"`
+ Include_dirs []string `android:"arch_variant"`
+ Shared_libs []string `android:"arch_variant"`
+ Static_libs []string `android:"arch_variant"`
+ Srcs []string `android:"arch_variant"`
+ Whole_static_libs []string `android:"arch_variant"`
+ } `android:"arch_variant"`
Flatten_apex struct {
Enabled *bool
diff --git a/androidmk/androidmk/android.go b/androidmk/androidmk/android.go
index 4540a1f..f0f51bf 100644
--- a/androidmk/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -24,8 +24,8 @@
)
const (
- clear_vars = "__android_mk_clear_vars"
- include_ignored = "__android_mk_include_ignored"
+ clearVarsPath = "__android_mk_clear_vars"
+ includeIgnoredPath = "__android_mk_include_ignored"
)
type bpVariable struct {
@@ -913,7 +913,7 @@
}
func includeIgnored(args []string) []string {
- return []string{include_ignored}
+ return []string{includeIgnoredPath}
}
var moduleTypes = map[string]string{
@@ -959,7 +959,7 @@
}
func mapIncludePath(path string) (string, bool) {
- if path == clear_vars || path == include_ignored {
+ if path == clearVarsPath || path == includeIgnoredPath {
return path, true
}
module, ok := includePathToModule[path]
@@ -968,7 +968,7 @@
func androidScope() mkparser.Scope {
globalScope := mkparser.NewScope(nil)
- globalScope.Set("CLEAR_VARS", clear_vars)
+ globalScope.Set("CLEAR_VARS", clearVarsPath)
globalScope.SetFunc("my-dir", mydir)
globalScope.SetFunc("all-java-files-under", allFilesUnder("*.java"))
globalScope.SetFunc("all-proto-files-under", allFilesUnder("*.proto"))
diff --git a/androidmk/androidmk/androidmk.go b/androidmk/androidmk/androidmk.go
index f4e5fa0..2d1bbb4 100644
--- a/androidmk/androidmk/androidmk.go
+++ b/androidmk/androidmk/androidmk.go
@@ -156,9 +156,9 @@
continue
}
switch module {
- case clear_vars:
+ case clearVarsPath:
resetModule(file)
- case include_ignored:
+ case includeIgnoredPath:
// subdirs are already automatically included in Soong
continue
default:
diff --git a/apex/apex.go b/apex/apex.go
index 88d93af..9fb616d 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -298,12 +298,12 @@
// Inputs
// Keys for apex_paylaod.img
- public_key_file android.Path
- private_key_file android.Path
+ publicKeyFile android.Path
+ privateKeyFile android.Path
// Cert/priv-key for the zip container
- container_certificate_file android.Path
- container_private_key_file android.Path
+ containerCertificateFile android.Path
+ containerPrivateKeyFile android.Path
// Flags for special variants of APEX
testApex bool
@@ -1183,6 +1183,9 @@
// Implements cc.Coverage
func (a *apexBundle) HideFromMake() {
a.properties.HideFromMake = true
+ // This HideFromMake is shadowing the ModuleBase one, call through to it for now.
+ // TODO(ccross): untangle these
+ a.ModuleBase.HideFromMake()
}
// Implements cc.Coverage
@@ -1681,16 +1684,16 @@
}
case keyTag:
if key, ok := child.(*apexKey); ok {
- a.private_key_file = key.private_key_file
- a.public_key_file = key.public_key_file
+ a.privateKeyFile = key.privateKeyFile
+ a.publicKeyFile = key.publicKeyFile
} else {
ctx.PropertyErrorf("key", "%q is not an apex_key module", depName)
}
return false
case certificateTag:
if dep, ok := child.(*java.AndroidAppCertificate); ok {
- a.container_certificate_file = dep.Certificate.Pem
- a.container_private_key_file = dep.Certificate.Key
+ a.containerCertificateFile = dep.Certificate.Pem
+ a.containerPrivateKeyFile = dep.Certificate.Key
} else {
ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", depName)
}
@@ -1807,7 +1810,7 @@
}
return false
})
- if a.private_key_file == nil {
+ if a.privateKeyFile == nil {
ctx.PropertyErrorf("key", "private_key for %q could not be found", String(a.properties.Key))
return
}
@@ -1947,7 +1950,7 @@
copiedPubkey := android.PathForModuleOut(ctx, "apex_pubkey")
ctx.Build(pctx, android.BuildParams{
Rule: android.Cp,
- Input: a.public_key_file,
+ Input: a.publicKeyFile,
Output: copiedPubkey,
})
a.filesInfo = append(a.filesInfo, newApexFile(ctx, copiedPubkey, "apex_pubkey", ".", etc, nil))
@@ -2836,14 +2839,14 @@
func createApexPermittedPackagesRules(modules_packages map[string][]string) []android.Rule {
rules := make([]android.Rule, 0, len(modules_packages))
for module_name, module_packages := range modules_packages {
- permitted_packages_rule := android.NeverAllow().
+ permittedPackagesRule := android.NeverAllow().
BootclasspathJar().
With("apex_available", module_name).
WithMatcher("permitted_packages", android.NotInList(module_packages)).
Because("jars that are part of the " + module_name +
" module may only allow these packages: " + strings.Join(module_packages, ",") +
". Please jarjar or move code around.")
- rules = append(rules, permitted_packages_rule)
+ rules = append(rules, permittedPackagesRule)
}
return rules
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 69b1dbb..84a8356 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -258,7 +258,11 @@
java.RegisterJavaBuildComponents(ctx)
java.RegisterSystemModulesBuildComponents(ctx)
java.RegisterAppBuildComponents(ctx)
+ java.RegisterAppImportBuildComponents(ctx)
+ java.RegisterAppSetBuildComponents(ctx)
+ java.RegisterRuntimeResourceOverlayBuildComponents(ctx)
java.RegisterSdkLibraryBuildComponents(ctx)
+ java.RegisterPrebuiltApisBuildComponents(ctx)
ctx.RegisterSingletonType("apex_keys_text", apexKeysTextFactory)
ctx.RegisterModuleType("bpf", bpf.BpfFactory)
@@ -1355,9 +1359,9 @@
ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libbar.so")
mylibLdFlags := ctx.ModuleForTests("mylib", "android_vendor.VER_arm64_armv8-a_shared_"+tc.apexVariant).Rule("ld").Args["libFlags"]
- ensureContains(t, mylibLdFlags, "libbar.llndk/android_vendor.VER_arm64_armv8-a_shared_"+tc.shouldLink+"/libbar.so")
+ ensureContains(t, mylibLdFlags, "libbar/android_vendor.VER_arm64_armv8-a_shared_"+tc.shouldLink+"/libbar.so")
for _, ver := range tc.shouldNotLink {
- ensureNotContains(t, mylibLdFlags, "libbar.llndk/android_vendor.VER_arm64_armv8-a_shared_"+ver+"/libbar.so")
+ ensureNotContains(t, mylibLdFlags, "libbar/android_vendor.VER_arm64_armv8-a_shared_"+ver+"/libbar.so")
}
mylibCFlags := ctx.ModuleForTests("mylib", "android_vendor.VER_arm64_armv8-a_static_"+tc.apexVariant).Rule("cc").Args["cFlags"]
@@ -2679,12 +2683,12 @@
// check the APEX keys
keys := ctx.ModuleForTests("myapex.key", "android_common").Module().(*apexKey)
- if keys.public_key_file.String() != "vendor/foo/devkeys/testkey.avbpubkey" {
- t.Errorf("public key %q is not %q", keys.public_key_file.String(),
+ if keys.publicKeyFile.String() != "vendor/foo/devkeys/testkey.avbpubkey" {
+ t.Errorf("public key %q is not %q", keys.publicKeyFile.String(),
"vendor/foo/devkeys/testkey.avbpubkey")
}
- if keys.private_key_file.String() != "vendor/foo/devkeys/testkey.pem" {
- t.Errorf("private key %q is not %q", keys.private_key_file.String(),
+ if keys.privateKeyFile.String() != "vendor/foo/devkeys/testkey.pem" {
+ t.Errorf("private key %q is not %q", keys.privateKeyFile.String(),
"vendor/foo/devkeys/testkey.pem")
}
@@ -4143,12 +4147,12 @@
apex_key := ctx.ModuleForTests("myapex.key", "android_common").Module().(*apexKey)
expected_pubkey := "testkey2.avbpubkey"
- actual_pubkey := apex_key.public_key_file.String()
+ actual_pubkey := apex_key.publicKeyFile.String()
if actual_pubkey != expected_pubkey {
t.Errorf("wrong public key path. expected %q. actual %q", expected_pubkey, actual_pubkey)
}
expected_privkey := "testkey2.pem"
- actual_privkey := apex_key.private_key_file.String()
+ actual_privkey := apex_key.privateKeyFile.String()
if actual_privkey != expected_privkey {
t.Errorf("wrong private key path. expected %q. actual %q", expected_privkey, actual_privkey)
}
@@ -4994,6 +4998,11 @@
"api/test-current.txt": nil,
"api/test-removed.txt": nil,
+ "100/public/api/foo.txt": nil,
+ "100/public/api/foo-removed.txt": nil,
+ "100/system/api/foo.txt": nil,
+ "100/system/api/foo-removed.txt": nil,
+
// For java_sdk_library_import
"a.jar": nil,
}
@@ -5018,6 +5027,11 @@
api_packages: ["foo"],
apex_available: [ "myapex" ],
}
+
+ prebuilt_apis {
+ name: "sdk",
+ api_dirs: ["100"],
+ }
`, withFiles(filesForSdkLibrary))
// java_sdk_library installs both impl jar and permission XML
@@ -5061,6 +5075,11 @@
sdk_version: "none",
system_modules: "none",
}
+
+ prebuilt_apis {
+ name: "sdk",
+ api_dirs: ["100"],
+ }
`, withFiles(filesForSdkLibrary))
// java_sdk_library installs both impl jar and permission XML
@@ -5107,6 +5126,11 @@
sdk_version: "none",
system_modules: "none",
}
+
+ prebuilt_apis {
+ name: "sdk",
+ api_dirs: ["100"],
+ }
`, withFiles(filesForSdkLibrary))
// java_sdk_library installs both impl jar and permission XML
@@ -5123,7 +5147,11 @@
}
func TestJavaSDKLibrary_ImportPreferred(t *testing.T) {
- ctx, _ := testApex(t, ``,
+ ctx, _ := testApex(t, `
+ prebuilt_apis {
+ name: "sdk",
+ api_dirs: ["100"],
+ }`,
withFiles(map[string][]byte{
"apex/a.java": nil,
"apex/apex_manifest.json": nil,
@@ -5190,7 +5218,7 @@
},
}
`),
- }),
+ }), withFiles(filesForSdkLibrary),
)
// java_sdk_library installs both impl jar and permission XML
@@ -6578,7 +6606,7 @@
continue
}
mod := ctx.ModuleForTests(modName, variant).Module().(*cc.Module)
- if !mod.Enabled() || mod.IsSkipInstall() {
+ if !mod.Enabled() || mod.IsHideFromMake() {
continue
}
for _, ent := range android.AndroidMkEntriesForTest(t, config, "", mod) {
diff --git a/apex/builder.go b/apex/builder.go
index 9db8e59..106302b 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -577,8 +577,8 @@
fileContexts := a.buildFileContexts(ctx)
implicitInputs = append(implicitInputs, fileContexts)
- implicitInputs = append(implicitInputs, a.private_key_file, a.public_key_file)
- optFlags = append(optFlags, "--pubkey "+a.public_key_file.String())
+ implicitInputs = append(implicitInputs, a.privateKeyFile, a.publicKeyFile)
+ optFlags = append(optFlags, "--pubkey "+a.publicKeyFile.String())
manifestPackageName := a.getOverrideManifestPackageName(ctx)
if manifestPackageName != "" {
@@ -667,7 +667,7 @@
"manifest": a.manifestPbOut.String(),
"file_contexts": fileContexts.String(),
"canned_fs_config": cannedFsConfig.String(),
- "key": a.private_key_file.String(),
+ "key": a.privateKeyFile.String(),
"opt_flags": strings.Join(optFlags, " "),
},
})
@@ -842,8 +842,8 @@
// the zip container of this APEX. See the description of the 'certificate' property for how
// the cert and the private key are found.
func (a *apexBundle) getCertificateAndPrivateKey(ctx android.PathContext) (pem, key android.Path) {
- if a.container_certificate_file != nil {
- return a.container_certificate_file, a.container_private_key_file
+ if a.containerCertificateFile != nil {
+ return a.containerCertificateFile, a.containerPrivateKeyFile
}
cert := String(a.properties.Certificate)
@@ -902,6 +902,12 @@
return !externalDep
}
+ depTag := ctx.OtherModuleDependencyTag(to)
+ if skipDepCheck, ok := depTag.(android.SkipApexAllowedDependenciesCheck); ok && skipDepCheck.SkipApexAllowedDependenciesCheck() {
+ // Check to see if dependency been marked to skip the dependency check
+ return !externalDep
+ }
+
if info, exists := depInfos[to.Name()]; exists {
if !android.InList(from.Name(), info.From) {
info.From = append(info.From, from.Name())
diff --git a/apex/key.go b/apex/key.go
index d9e3c10..752888d 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -36,8 +36,8 @@
properties apexKeyProperties
- public_key_file android.Path
- private_key_file android.Path
+ publicKeyFile android.Path
+ privateKeyFile android.Path
keyName string
}
@@ -69,30 +69,30 @@
// Otherwise, try to locate the key files in the default cert dir or
// in the local module dir
if android.SrcIsModule(String(m.properties.Public_key)) != "" {
- m.public_key_file = android.PathForModuleSrc(ctx, String(m.properties.Public_key))
+ m.publicKeyFile = android.PathForModuleSrc(ctx, String(m.properties.Public_key))
} else {
- m.public_key_file = ctx.Config().ApexKeyDir(ctx).Join(ctx, String(m.properties.Public_key))
+ m.publicKeyFile = ctx.Config().ApexKeyDir(ctx).Join(ctx, String(m.properties.Public_key))
// If not found, fall back to the local key pairs
- if !android.ExistentPathForSource(ctx, m.public_key_file.String()).Valid() {
- m.public_key_file = android.PathForModuleSrc(ctx, String(m.properties.Public_key))
+ if !android.ExistentPathForSource(ctx, m.publicKeyFile.String()).Valid() {
+ m.publicKeyFile = android.PathForModuleSrc(ctx, String(m.properties.Public_key))
}
}
if android.SrcIsModule(String(m.properties.Private_key)) != "" {
- m.private_key_file = android.PathForModuleSrc(ctx, String(m.properties.Private_key))
+ m.privateKeyFile = android.PathForModuleSrc(ctx, String(m.properties.Private_key))
} else {
- m.private_key_file = ctx.Config().ApexKeyDir(ctx).Join(ctx, String(m.properties.Private_key))
- if !android.ExistentPathForSource(ctx, m.private_key_file.String()).Valid() {
- m.private_key_file = android.PathForModuleSrc(ctx, String(m.properties.Private_key))
+ m.privateKeyFile = ctx.Config().ApexKeyDir(ctx).Join(ctx, String(m.properties.Private_key))
+ if !android.ExistentPathForSource(ctx, m.privateKeyFile.String()).Valid() {
+ m.privateKeyFile = android.PathForModuleSrc(ctx, String(m.properties.Private_key))
}
}
- pubKeyName := m.public_key_file.Base()[0 : len(m.public_key_file.Base())-len(m.public_key_file.Ext())]
- privKeyName := m.private_key_file.Base()[0 : len(m.private_key_file.Base())-len(m.private_key_file.Ext())]
+ pubKeyName := m.publicKeyFile.Base()[0 : len(m.publicKeyFile.Base())-len(m.publicKeyFile.Ext())]
+ privKeyName := m.privateKeyFile.Base()[0 : len(m.privateKeyFile.Base())-len(m.privateKeyFile.Ext())]
if m.properties.Public_key != nil && m.properties.Private_key != nil && pubKeyName != privKeyName {
ctx.ModuleErrorf("public_key %q (keyname:%q) and private_key %q (keyname:%q) do not have same keyname",
- m.public_key_file.String(), pubKeyName, m.private_key_file, privKeyName)
+ m.publicKeyFile.String(), pubKeyName, m.privateKeyFile, privKeyName)
return
}
m.keyName = pubKeyName
@@ -107,20 +107,20 @@
func (s *apexKeysText) GenerateBuildActions(ctx android.SingletonContext) {
s.output = android.PathForOutput(ctx, "apexkeys.txt")
type apexKeyEntry struct {
- name string
- presigned bool
- public_key string
- private_key string
- container_certificate string
- container_private_key string
- partition string
+ name string
+ presigned bool
+ publicKey string
+ privateKey string
+ containerCertificate string
+ containerPrivateKey string
+ partition string
}
toString := func(e apexKeyEntry) string {
format := "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q partition=%q\n"
if e.presigned {
return fmt.Sprintf(format, e.name, "PRESIGNED", "PRESIGNED", "PRESIGNED", "PRESIGNED", e.partition)
} else {
- return fmt.Sprintf(format, e.name, e.public_key, e.private_key, e.container_certificate, e.container_private_key, e.partition)
+ return fmt.Sprintf(format, e.name, e.publicKey, e.privateKey, e.containerCertificate, e.containerPrivateKey, e.partition)
}
}
@@ -129,13 +129,13 @@
if m, ok := module.(*apexBundle); ok && m.Enabled() && m.installable() {
pem, key := m.getCertificateAndPrivateKey(ctx)
apexKeyMap[m.Name()] = apexKeyEntry{
- name: m.Name() + ".apex",
- presigned: false,
- public_key: m.public_key_file.String(),
- private_key: m.private_key_file.String(),
- container_certificate: pem.String(),
- container_private_key: key.String(),
- partition: m.PartitionTag(ctx.DeviceConfig()),
+ name: m.Name() + ".apex",
+ presigned: false,
+ publicKey: m.publicKeyFile.String(),
+ privateKey: m.privateKeyFile.String(),
+ containerCertificate: pem.String(),
+ containerPrivateKey: key.String(),
+ partition: m.PartitionTag(ctx.DeviceConfig()),
}
}
})
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index ce16d73..7931e9e 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -218,7 +218,7 @@
})
if p.prebuiltCommon.checkForceDisable(ctx) {
- p.SkipInstall()
+ p.HideFromMake()
return
}
@@ -392,7 +392,7 @@
})
if a.prebuiltCommon.checkForceDisable(ctx) {
- a.SkipInstall()
+ a.HideFromMake()
return
}
diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go
index faec473..94b8252 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -784,9 +784,9 @@
return nil
}
- bool_variables, ok := getLiteralListProperty(mod, "bool_variables")
+ boolVariables, ok := getLiteralListProperty(mod, "bool_variables")
if ok {
- patchList.Add(bool_variables.RBracePos.Offset, bool_variables.RBracePos.Offset, ","+boolValues.String())
+ patchList.Add(boolVariables.RBracePos.Offset, boolVariables.RBracePos.Offset, ","+boolValues.String())
} else {
patchList.Add(variables.RBracePos.Offset+2, variables.RBracePos.Offset+2,
fmt.Sprintf(`bool_variables: [%s],`, boolValues.String()))
diff --git a/build_test.bash b/build_test.bash
index accca0f..3230f2d 100755
--- a/build_test.bash
+++ b/build_test.bash
@@ -23,6 +23,11 @@
# evolve as we find interesting things to test or track performance for.
#
+# Products that are broken or otherwise don't work with multiproduct_kati
+SKIPPED_PRODUCTS=(
+ mainline_sdk
+)
+
# To track how long we took to startup. %N isn't supported on Darwin, but
# that's detected in the Go code, which skips calculating the startup time.
export TRACE_BEGIN_SOONG=$(date +%s%N)
@@ -50,4 +55,4 @@
echo
echo "Running Soong test..."
soong_build_go multiproduct_kati android/soong/cmd/multiproduct_kati
-exec "$(getoutdir)/multiproduct_kati" "$@"
+exec "$(getoutdir)/multiproduct_kati" --skip-products "$(echo "${SKIPPED_PRODUCTS[@]-}" | tr ' ' ',')" "$@"
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 187a2ff..4ada55d 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -232,8 +232,8 @@
if len(library.Properties.Overrides) > 0 {
entries.SetString("LOCAL_OVERRIDES_MODULES", strings.Join(makeOverrideModuleNames(ctx, library.Properties.Overrides), " "))
}
- if len(library.post_install_cmds) > 0 {
- entries.SetString("LOCAL_POST_INSTALL_CMD", strings.Join(library.post_install_cmds, "&& "))
+ if len(library.postInstallCmds) > 0 {
+ entries.SetString("LOCAL_POST_INSTALL_CMD", strings.Join(library.postInstallCmds, "&& "))
}
})
} else if library.header() {
@@ -269,11 +269,11 @@
if library.shared() && !library.buildStubs() {
ctx.subAndroidMk(entries, library.baseInstaller)
} else {
- if library.buildStubs() {
+ if library.buildStubs() && library.stubsVersion() != "" {
entries.SubName = "." + library.stubsVersion()
}
entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
- // library.makeUninstallable() depends on this to bypass SkipInstall() for
+ // library.makeUninstallable() depends on this to bypass HideFromMake() for
// static libraries.
entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
if library.buildStubs() {
@@ -328,8 +328,8 @@
if len(binary.Properties.Overrides) > 0 {
entries.SetString("LOCAL_OVERRIDES_MODULES", strings.Join(makeOverrideModuleNames(ctx, binary.Properties.Overrides), " "))
}
- if len(binary.post_install_cmds) > 0 {
- entries.SetString("LOCAL_POST_INSTALL_CMD", strings.Join(binary.post_install_cmds, "&& "))
+ if len(binary.postInstallCmds) > 0 {
+ entries.SetString("LOCAL_POST_INSTALL_CMD", strings.Join(binary.postInstallCmds, "&& "))
}
})
}
@@ -471,18 +471,9 @@
}
func (c *llndkStubDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
- entries.Class = "SHARED_LIBRARIES"
- entries.OverrideName = c.implementationModuleName(ctx.BaseModuleName())
-
- entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
- c.libraryDecorator.androidMkWriteExportedFlags(entries)
- _, _, ext := android.SplitFileExt(entries.OutputFile.Path().Base())
-
- entries.SetString("LOCAL_BUILT_MODULE_STEM", "$(LOCAL_MODULE)"+ext)
- entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
- entries.SetBool("LOCAL_NO_NOTICE_FILE", true)
- entries.SetString("LOCAL_SOONG_TOC", c.toc().String())
- })
+ // Don't write anything for an llndk_library module, the vendor variant of the cc_library
+ // module will write the Android.mk entries.
+ entries.Disabled = true
}
func (c *vndkPrebuiltLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
diff --git a/cc/binary.go b/cc/binary.go
index fa3966f..71c865b 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -109,7 +109,7 @@
// Action command lines to run directly after the binary is installed. For example,
// may be used to symlink runtime dependencies (such as bionic) alongside installation.
- post_install_cmds []string
+ postInstallCmds []string
}
var _ linker = (*binaryDecorator)(nil)
@@ -481,11 +481,11 @@
target := "/" + filepath.Join("apex", "com.android.runtime", dir.Base(), file.Base())
ctx.InstallAbsoluteSymlink(dir, file.Base(), target)
- binary.post_install_cmds = append(binary.post_install_cmds, makeSymlinkCmd(dirOnDevice, file.Base(), target))
+ binary.postInstallCmds = append(binary.postInstallCmds, makeSymlinkCmd(dirOnDevice, file.Base(), target))
for _, symlink := range binary.symlinks {
ctx.InstallAbsoluteSymlink(dir, symlink, target)
- binary.post_install_cmds = append(binary.post_install_cmds, makeSymlinkCmd(dirOnDevice, symlink, target))
+ binary.postInstallCmds = append(binary.postInstallCmds, makeSymlinkCmd(dirOnDevice, symlink, target))
}
}
diff --git a/cc/cc.go b/cc/cc.go
index 240080f..b815268 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -360,7 +360,11 @@
//
// If set to false, this module becomes inaccessible from /vendor modules.
//
- // Default value is true when vndk: {enabled: true} or vendor: true.
+ // The modules with vndk: {enabled: true} must define 'vendor_available'
+ // to either 'true' or 'false'. In this case, 'vendor_available: false' has
+ // a different meaning than that of non-VNDK modules.
+ // 'vendor_available: false' for a VNDK module means 'VNDK-private' that
+ // can only be depended on by VNDK libraries, not by non-VNDK vendor modules.
//
// Nothing happens if BOARD_VNDK_VERSION isn't set in the BoardConfig.mk
Vendor_available *bool
@@ -376,7 +380,19 @@
// make assumptions about the system that may not be true in the
// future.
//
- // It must be set to true by default for vndk: {enabled: true} modules.
+ // If set to false, this module becomes inaccessible from /product modules.
+ //
+ // Different from the 'vendor_available' property, the modules with
+ // vndk: {enabled: true} don't have to define 'product_available'. The VNDK
+ // library without 'product_available' may not be depended on by any other
+ // modules that has product variants including the product available VNDKs.
+ // However, for the modules with vndk: {enabled: true},
+ // 'product_available: false' creates the product variant that is available
+ // only for the other product available VNDK modules but not by non-VNDK
+ // product modules.
+ // In the case of the modules with vndk: {enabled: true}, if
+ // 'product_available' is defined, it must have the same value with the
+ // 'vendor_available'.
//
// Nothing happens if BOARD_VNDK_VERSION isn't set in the BoardConfig.mk
// and PRODUCT_PRODUCT_VNDK_VERSION isn't set.
@@ -390,6 +406,13 @@
// explicitly marked as `double_loadable: true` by the owner, or the dependency
// from the LLNDK lib should be cut if the lib is not designed to be double loaded.
Double_loadable *bool
+
+ // IsLLNDK is set to true for the vendor variant of a cc_library module that has LLNDK stubs.
+ IsLLNDK bool `blueprint:"mutated"`
+
+ // IsLLNDKPrivate is set to true for the vendor variant of a cc_library module that has LLNDK
+ // stubs and also sets llndk.vendor_available: false.
+ IsLLNDKPrivate bool `blueprint:"mutated"`
}
// ModuleContextIntf is an interface (on a module context helper) consisting of functions related
@@ -408,9 +431,10 @@
sdkVersion() string
useVndk() bool
isNdk(config android.Config) bool
- isLlndk(config android.Config) bool
- isLlndkPublic(config android.Config) bool
- isVndkPrivate(config android.Config) bool
+ IsLlndk() bool
+ IsLlndkPublic() bool
+ isImplementationForLLNDKPublic() bool
+ IsVndkPrivate() bool
isVndk() bool
isVndkSp() bool
IsVndkExt() bool
@@ -432,6 +456,7 @@
mustUseVendorVariant() bool
nativeCoverage() bool
directlyInAnyApex() bool
+ isPreventInstall() bool
}
type ModuleContext interface {
@@ -584,6 +609,9 @@
makeSuffix string
+ // Whether or not this dependency should skip the apex dependency check
+ skipApexAllowedDependenciesCheck bool
+
// Whether or not this dependency has to be followed for the apex variants
excludeInApex bool
}
@@ -644,6 +672,7 @@
runtimeDepTag = installDependencyTag{name: "runtime lib"}
testPerSrcDepTag = dependencyTag{name: "test_per_src"}
stubImplDepTag = dependencyTag{name: "stub_impl"}
+ llndkStubDepTag = dependencyTag{name: "llndk stub"}
)
type copyDirectlyInAnyApexDependencyTag dependencyTag
@@ -1027,20 +1056,50 @@
return inList(c.BaseModuleName(), *getNDKKnownLibs(config))
}
-func (c *Module) isLlndk(config android.Config) bool {
- // Returns true for both LLNDK (public) and LLNDK-private libs.
- return isLlndkLibrary(c.BaseModuleName(), config)
+// isLLndk returns true for both LLNDK (public) and LLNDK-private libs.
+func (c *Module) IsLlndk() bool {
+ return c.VendorProperties.IsLLNDK
}
-func (c *Module) isLlndkPublic(config android.Config) bool {
- // Returns true only for LLNDK (public) libs.
- name := c.BaseModuleName()
- return isLlndkLibrary(name, config) && !isVndkPrivateLibrary(name, config)
+// IsLlndkPublic returns true only for LLNDK (public) libs.
+func (c *Module) IsLlndkPublic() bool {
+ return c.VendorProperties.IsLLNDK && !c.VendorProperties.IsLLNDKPrivate
}
-func (c *Module) IsVndkPrivate(config android.Config) bool {
- // Returns true for LLNDK-private, VNDK-SP-private, and VNDK-core-private.
- return isVndkPrivateLibrary(c.BaseModuleName(), config)
+// isImplementationForLLNDKPublic returns true for any variant of a cc_library that has LLNDK stubs
+// and does not set llndk.vendor_available: false.
+func (c *Module) isImplementationForLLNDKPublic() bool {
+ library, _ := c.library.(*libraryDecorator)
+ return library != nil && library.hasLLNDKStubs() &&
+ (Bool(library.Properties.Llndk.Vendor_available) ||
+ // TODO(b/170784825): until the LLNDK properties are moved into the cc_library,
+ // the non-Vendor variants of the cc_library don't know if the corresponding
+ // llndk_library set vendor_available: false. Since libft2 is the only
+ // private LLNDK library, hardcode it during the transition.
+ c.BaseModuleName() != "libft2")
+}
+
+// Returns true for LLNDK-private, VNDK-SP-private, and VNDK-core-private.
+func (c *Module) IsVndkPrivate() bool {
+ // Check if VNDK-core-private or VNDK-SP-private
+ if c.IsVndk() {
+ if Bool(c.vndkdep.Properties.Vndk.Private) {
+ return true
+ }
+ // TODO(b/175768895) remove this when we clean up "vendor_available: false" use cases.
+ if c.VendorProperties.Vendor_available != nil && !Bool(c.VendorProperties.Vendor_available) {
+ return true
+ }
+ return false
+ }
+
+ // Check if LLNDK-private
+ if library, ok := c.library.(*libraryDecorator); ok && c.IsLlndk() {
+ // TODO(b/175768895) replace this with 'private' property.
+ return !Bool(library.Properties.Llndk.Vendor_available)
+ }
+
+ return false
}
func (c *Module) IsVndk() bool {
@@ -1246,16 +1305,20 @@
return ctx.mod.IsNdk(config)
}
-func (ctx *moduleContextImpl) isLlndk(config android.Config) bool {
- return ctx.mod.isLlndk(config)
+func (ctx *moduleContextImpl) IsLlndk() bool {
+ return ctx.mod.IsLlndk()
}
-func (ctx *moduleContextImpl) isLlndkPublic(config android.Config) bool {
- return ctx.mod.isLlndkPublic(config)
+func (ctx *moduleContextImpl) IsLlndkPublic() bool {
+ return ctx.mod.IsLlndkPublic()
}
-func (ctx *moduleContextImpl) isVndkPrivate(config android.Config) bool {
- return ctx.mod.IsVndkPrivate(config)
+func (ctx *moduleContextImpl) isImplementationForLLNDKPublic() bool {
+ return ctx.mod.isImplementationForLLNDKPublic()
+}
+
+func (ctx *moduleContextImpl) IsVndkPrivate() bool {
+ return ctx.mod.IsVndkPrivate()
}
func (ctx *moduleContextImpl) isVndk() bool {
@@ -1325,6 +1388,10 @@
return ctx.mod.DirectlyInAnyApex()
}
+func (ctx *moduleContextImpl) isPreventInstall() bool {
+ return ctx.mod.Properties.PreventInstall
+}
+
func newBaseModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
return &Module{
hod: hod,
@@ -1402,7 +1469,7 @@
if vndkVersion == "current" {
vndkVersion = ctx.DeviceConfig().PlatformVndkVersion()
}
- if c.Properties.VndkVersion != vndkVersion {
+ if c.Properties.VndkVersion != vndkVersion && c.Properties.VndkVersion != "" {
// add version suffix only if the module is using different vndk version than the
// version in product or vendor partition.
nameSuffix += "." + c.Properties.VndkVersion
@@ -1434,7 +1501,7 @@
c.Properties.SubName += nativeBridgeSuffix
}
- _, llndk := c.linker.(*llndkStubDecorator)
+ llndk := c.IsLlndk()
_, llndkHeader := c.linker.(*llndkHeadersDecorator)
if llndk || llndkHeader || (c.UseVndk() && c.HasNonSystemVariants()) {
// .vendor.{version} suffix is added for vendor variant or .product.{version} suffix is
@@ -1575,18 +1642,24 @@
}
}
- if c.installable(apexInfo) {
+ if !proptools.BoolDefault(c.Properties.Installable, true) {
+ // If the module has been specifically configure to not be installed then
+ // hide from make as otherwise it will break when running inside make
+ // as the output path to install will not be specified. Not all uninstallable
+ // modules can be hidden from make as some are needed for resolving make side
+ // dependencies.
+ c.HideFromMake()
+ } else if !c.installable(apexInfo) {
+ c.SkipInstall()
+ }
+
+ // Still call c.installer.install though, the installs will be stored as PackageSpecs
+ // to allow using the outputs in a genrule.
+ if c.installer != nil && c.outputFile.Valid() {
c.installer.install(ctx, c.outputFile.Path())
if ctx.Failed() {
return
}
- } else if !proptools.BoolDefault(c.Properties.Installable, true) {
- // If the module has been specifically configure to not be installed then
- // skip the installation as otherwise it will break when running inside make
- // as the output path to install will not be specified. Not all uninstallable
- // modules can skip installation as some are needed for resolving make side
- // dependencies.
- c.SkipInstall()
}
}
@@ -1806,10 +1879,6 @@
vendorSnapshotSharedLibs := vendorSnapshotSharedLibs(actx.Config())
rewriteVendorLibs := func(lib string) string {
- if isLlndkLibrary(lib, ctx.Config()) {
- return lib + llndkLibrarySuffix
- }
-
// only modules with BOARD_VNDK_VERSION uses snapshot.
if c.VndkVersion() != actx.DeviceConfig().VndkVersion() {
return lib
@@ -2226,7 +2295,7 @@
return true
}
- if to.isVndkSp() || to.isLlndk(ctx.Config()) || Bool(to.VendorProperties.Double_loadable) {
+ if to.isVndkSp() || to.IsLlndk() || Bool(to.VendorProperties.Double_loadable) {
return false
}
@@ -2241,7 +2310,7 @@
}
if module, ok := ctx.Module().(*Module); ok {
if lib, ok := module.linker.(*libraryDecorator); ok && lib.shared() {
- if module.isLlndk(ctx.Config()) || Bool(module.VendorProperties.Double_loadable) {
+ if lib.hasLLNDKStubs() || Bool(module.VendorProperties.Double_loadable) {
ctx.WalkDeps(check)
}
}
@@ -2361,9 +2430,6 @@
if depTag == android.ProtoPluginDepTag {
return
}
- if depTag == llndkImplDep {
- return
- }
if dep.Target().Os != ctx.Os() {
ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName)
@@ -2733,7 +2799,8 @@
vendorPublicLibraries := vendorPublicLibraries(ctx.Config())
libName := baseLibName(depName)
- isLLndk := isLlndkLibrary(libName, ctx.Config())
+ ccDepModule, _ := ccDep.(*Module)
+ isLLndk := ccDepModule != nil && ccDepModule.IsLlndk()
isVendorPublicLib := inList(libName, *vendorPublicLibraries)
bothVendorAndCoreVariantsExist := ccDep.HasVendorVariant() || isLLndk
@@ -2885,17 +2952,14 @@
func GetMakeLinkType(actx android.ModuleContext, c LinkableInterface) string {
if c.UseVndk() {
- if ccModule, ok := c.Module().(*Module); ok {
- // Only CC modules provide stubs at the moment.
- if lib, ok := ccModule.linker.(*llndkStubDecorator); ok {
- if Bool(lib.Properties.Vendor_available) {
- return "native:vndk"
- }
+ if c.IsLlndk() {
+ if !c.IsLlndkPublic() {
return "native:vndk_private"
}
+ return "native:vndk"
}
if c.IsVndk() && !c.IsVndkExt() {
- if c.IsVndkPrivate(actx.Config()) {
+ if c.IsVndkPrivate() {
return "native:vndk_private"
}
return "native:vndk"
@@ -3028,7 +3092,7 @@
return false
}
}
- if depTag == stubImplDepTag || depTag == llndkImplDep {
+ if depTag == stubImplDepTag || depTag == llndkStubDepTag {
// We don't track beyond LLNDK or from an implementation library to its stubs.
return false
}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index c16cce8..fb85336 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -326,7 +326,6 @@
cc_library {
name: "libvndk",
vendor_available: true,
- product_available: true,
vndk: {
enabled: true,
},
@@ -335,21 +334,38 @@
cc_library {
name: "libvndk_private",
- vendor_available: false,
- product_available: false,
+ vendor_available: true,
vndk: {
enabled: true,
+ private: true,
},
nocrt: true,
stem: "libvndk-private",
}
cc_library {
- name: "libvndk_sp",
+ name: "libvndk_product",
vendor_available: true,
product_available: true,
vndk: {
enabled: true,
+ },
+ nocrt: true,
+ target: {
+ vendor: {
+ cflags: ["-DTEST"],
+ },
+ product: {
+ cflags: ["-DTEST"],
+ },
+ },
+ }
+
+ cc_library {
+ name: "libvndk_sp",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
support_system_process: true,
},
nocrt: true,
@@ -358,11 +374,11 @@
cc_library {
name: "libvndk_sp_private",
- vendor_available: false,
- product_available: false,
+ vendor_available: true,
vndk: {
enabled: true,
support_system_process: true,
+ private: true,
},
nocrt: true,
target: {
@@ -371,6 +387,27 @@
},
},
}
+
+ cc_library {
+ name: "libvndk_sp_product_private",
+ vendor_available: true,
+ product_available: true,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ private: true,
+ },
+ nocrt: true,
+ target: {
+ vendor: {
+ suffix: "-x",
+ },
+ product: {
+ suffix: "-x",
+ },
+ },
+ }
+
vndk_libraries_txt {
name: "llndk.libraries.txt",
}
@@ -399,13 +436,13 @@
// They are installed as part of VNDK APEX instead.
checkVndkModule(t, ctx, "libvndk", "", false, "", vendorVariant)
checkVndkModule(t, ctx, "libvndk_private", "", false, "", vendorVariant)
+ checkVndkModule(t, ctx, "libvndk_product", "", false, "", vendorVariant)
checkVndkModule(t, ctx, "libvndk_sp", "", true, "", vendorVariant)
checkVndkModule(t, ctx, "libvndk_sp_private", "", true, "", vendorVariant)
+ checkVndkModule(t, ctx, "libvndk_sp_product_private", "", true, "", vendorVariant)
- checkVndkModule(t, ctx, "libvndk", "", false, "", productVariant)
- checkVndkModule(t, ctx, "libvndk_private", "", false, "", productVariant)
- checkVndkModule(t, ctx, "libvndk_sp", "", true, "", productVariant)
- checkVndkModule(t, ctx, "libvndk_sp_private", "", true, "", productVariant)
+ checkVndkModule(t, ctx, "libvndk_product", "", false, "", productVariant)
+ checkVndkModule(t, ctx, "libvndk_sp_product_private", "", true, "", productVariant)
// Check VNDK snapshot output.
@@ -429,6 +466,8 @@
checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", vndkCoreLibPath, variant)
checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", vndkCoreLib2ndPath, variant2nd)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvndk_product", "libvndk_product.so", vndkCoreLibPath, variant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvndk_product", "libvndk_product.so", vndkCoreLib2ndPath, variant2nd)
checkSnapshot(t, ctx, snapshotSingleton, "libvndk_sp", "libvndk_sp-x.so", vndkSpLibPath, variant)
checkSnapshot(t, ctx, snapshotSingleton, "libvndk_sp", "libvndk_sp-x.so", vndkSpLib2ndPath, variant2nd)
@@ -446,16 +485,19 @@
"VNDK-SP: libc++.so",
"VNDK-SP: libvndk_sp-x.so",
"VNDK-SP: libvndk_sp_private-x.so",
+ "VNDK-SP: libvndk_sp_product_private-x.so",
"VNDK-core: libvndk-private.so",
"VNDK-core: libvndk.so",
+ "VNDK-core: libvndk_product.so",
"VNDK-private: libft2.so",
"VNDK-private: libvndk-private.so",
"VNDK-private: libvndk_sp_private-x.so",
+ "VNDK-private: libvndk_sp_product_private-x.so",
})
checkVndkLibrariesOutput(t, ctx, "llndk.libraries.txt", []string{"libc.so", "libdl.so", "libft2.so", "libm.so"})
- checkVndkLibrariesOutput(t, ctx, "vndkcore.libraries.txt", []string{"libvndk-private.so", "libvndk.so"})
- checkVndkLibrariesOutput(t, ctx, "vndkprivate.libraries.txt", []string{"libft2.so", "libvndk-private.so", "libvndk_sp_private-x.so"})
- checkVndkLibrariesOutput(t, ctx, "vndksp.libraries.txt", []string{"libc++.so", "libvndk_sp-x.so", "libvndk_sp_private-x.so"})
+ checkVndkLibrariesOutput(t, ctx, "vndkcore.libraries.txt", []string{"libvndk-private.so", "libvndk.so", "libvndk_product.so"})
+ checkVndkLibrariesOutput(t, ctx, "vndksp.libraries.txt", []string{"libc++.so", "libvndk_sp-x.so", "libvndk_sp_private-x.so", "libvndk_sp_product_private-x.so"})
+ checkVndkLibrariesOutput(t, ctx, "vndkprivate.libraries.txt", []string{"libft2.so", "libvndk-private.so", "libvndk_sp_private-x.so", "libvndk_sp_product_private-x.so"})
checkVndkLibrariesOutput(t, ctx, "vndkcorevariant.libraries.txt", nil)
}
@@ -535,10 +577,11 @@
cc_library {
name: "libvndk2",
- vendor_available: false,
- product_available: false,
+ vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
+ private: true,
},
nocrt: true,
}
@@ -683,17 +726,43 @@
func TestVndkModuleError(t *testing.T) {
// Check the error message for vendor_available and product_available properties.
- testCcError(t, "product_available: may not have different value than `vendor_available`", `
+ testCcErrorProductVndk(t, "vndk: vendor_available must be set to either true or false when `vndk: {enabled: true}`", `
cc_library {
name: "libvndk",
- vendor_available: true,
- product_available: false,
vndk: {
enabled: true,
},
nocrt: true,
}
`)
+
+ testCcErrorProductVndk(t, "vndk: vendor_available must be set to either true or false when `vndk: {enabled: true}`", `
+ cc_library {
+ name: "libvndk",
+ product_available: true,
+ vndk: {
+ enabled: true,
+ },
+ nocrt: true,
+ }
+ `)
+
+ testCcErrorProductVndk(t, "product properties must have the same values with the vendor properties for VNDK modules", `
+ cc_library {
+ name: "libvndkprop",
+ vendor_available: true,
+ product_available: true,
+ vndk: {
+ enabled: true,
+ },
+ nocrt: true,
+ target: {
+ vendor: {
+ cflags: ["-DTEST",],
+ },
+ },
+ }
+ `)
}
func TestVndkDepError(t *testing.T) {
@@ -826,10 +895,11 @@
testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
cc_library {
name: "libvndkprivate",
- vendor_available: false,
- product_available: false,
+ vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
+ private: true,
},
shared_libs: ["libnonvndk"],
nocrt: true,
@@ -867,11 +937,12 @@
testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
cc_library {
name: "libvndkspprivate",
- vendor_available: false,
- product_available: false,
+ vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
support_system_process: true,
+ private: true,
},
shared_libs: ["libnonvndk"],
nocrt: true,
@@ -962,10 +1033,11 @@
cc_library {
name: "libnondoubleloadable",
- vendor_available: false,
- product_available: false,
+ vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
+ private: true,
},
double_loadable: true,
}
@@ -1049,6 +1121,16 @@
name: "obj",
vendor_available: true,
}
+
+ cc_library {
+ name: "libllndk",
+ llndk_stubs: "libllndk.llndk",
+ }
+
+ llndk_library {
+ name: "libllndk.llndk",
+ symbol_file: "",
+ }
`
config := TestConfig(buildDir, android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
@@ -1080,6 +1162,9 @@
filepath.Join(sharedDir, "libvendor.so.json"),
filepath.Join(sharedDir, "libvendor_available.so.json"))
+ // LLNDK modules are not captured
+ checkSnapshotExclude(t, ctx, snapshotSingleton, "libllndk", "libllndk.so", sharedDir, sharedVariant)
+
// For static libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
// Also cfi variants are captured, except for prebuilts like toolchain_library
staticVariant := fmt.Sprintf("android_vendor.VER_%s_%s_static", archType, archVariant)
@@ -1818,10 +1903,11 @@
cc_library {
name: "libnondoubleloadable",
- vendor_available: false,
- product_available: false,
+ vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
+ private: true,
},
}
`)
@@ -2172,14 +2258,15 @@
func TestVndkExtVendorAvailableFalseError(t *testing.T) {
// This test ensures an error is emitted when a VNDK-Ext library extends a VNDK library
- // with `vendor_available: false`.
- testCcError(t, "`extends` refers module \".*\" which does not have `vendor_available: true`", `
+ // with `private: true`.
+ testCcError(t, "`extends` refers module \".*\" which has `private: true`", `
cc_library {
name: "libvndk",
- vendor_available: false,
- product_available: false,
+ vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
+ private: true,
},
nocrt: true,
}
@@ -2195,13 +2282,14 @@
}
`)
- testCcErrorProductVndk(t, "`extends` refers module \".*\" which does not have `vendor_available: true`", `
+ testCcErrorProductVndk(t, "`extends` refers module \".*\" which has `private: true`", `
cc_library {
name: "libvndk",
- vendor_available: false,
- product_available: false,
+ vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
+ private: true,
},
nocrt: true,
}
@@ -2549,7 +2637,6 @@
cc_library {
name: "libvndk2",
vendor_available: true,
- product_available: true,
vndk: {
enabled: true,
},
@@ -2622,7 +2709,6 @@
cc_library {
name: "libvndk_sp2",
vendor_available: true,
- product_available: true,
vndk: {
enabled: true,
},
@@ -2676,6 +2762,20 @@
nocrt: true,
}
cc_library {
+ name: "libboth_available",
+ vendor_available: true,
+ product_available: true,
+ nocrt: true,
+ target: {
+ vendor: {
+ suffix: "-vendor",
+ },
+ product: {
+ suffix: "-product",
+ },
+ }
+ }
+ cc_library {
name: "libproduct_va",
product_specific: true,
vendor_available: true,
@@ -2689,6 +2789,7 @@
"libvndk",
"libvndk_sp",
"libpa",
+ "libboth_available",
"libproduct_va",
],
nocrt: true,
@@ -2701,6 +2802,7 @@
"libvndk",
"libvndk_sp",
"libva",
+ "libboth_available",
"libproduct_va",
],
nocrt: true,
@@ -2716,6 +2818,12 @@
checkVndkModule(t, ctx, "libvndk", "", false, "", productVariant)
checkVndkModule(t, ctx, "libvndk_sp", "", true, "", productVariant)
+
+ mod_vendor := ctx.ModuleForTests("libboth_available", vendorVariant).Module().(*Module)
+ assertString(t, mod_vendor.outputFile.Path().Base(), "libboth_available-vendor.so")
+
+ mod_product := ctx.ModuleForTests("libboth_available", productVariant).Module().(*Module)
+ assertString(t, mod_product.outputFile.Path().Base(), "libboth_available-product.so")
}
func TestEnforceProductVndkVersionErrors(t *testing.T) {
@@ -2748,7 +2856,22 @@
nocrt: true,
}
`)
- testCcErrorProductVndk(t, "Vendor module that is not VNDK should not link to \".*\" which is marked as `vendor_available: false`", `
+ testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:product.VER", `
+ cc_library {
+ name: "libprod",
+ product_specific: true,
+ shared_libs: [
+ "libva",
+ ],
+ nocrt: true,
+ }
+ cc_library {
+ name: "libva",
+ vendor_available: true,
+ nocrt: true,
+ }
+ `)
+ testCcErrorProductVndk(t, "non-VNDK module should not link to \".*\" which has `private: true`", `
cc_library {
name: "libprod",
product_specific: true,
@@ -2759,10 +2882,11 @@
}
cc_library {
name: "libvndk_private",
- vendor_available: false,
- product_available: false,
+ vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
+ private: true,
},
nocrt: true,
}
@@ -2820,10 +2944,11 @@
}
cc_library {
name: "libvndkprivate",
- vendor_available: false,
- product_available: false,
+ vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
+ private: true,
},
}
cc_library {
@@ -2899,7 +3024,7 @@
{vendorVariant, "libvndkprivate", "native:vndk_private"},
{vendorVariant, "libvendor", "native:vendor"},
{vendorVariant, "libvndkext", "native:vendor"},
- {vendorVariant, "libllndk.llndk", "native:vndk"},
+ {vendorVariant, "libllndk", "native:vndk"},
{vendorVariant27, "prevndk.vndk.27.arm.binder32", "native:vndk"},
{coreVariant, "libvndk", "native:platform"},
{coreVariant, "libvndkprivate", "native:platform"},
@@ -3178,8 +3303,39 @@
llndk_library {
name: "libllndk.llndk",
}
+
+ cc_prebuilt_library_shared {
+ name: "libllndkprebuilt",
+ stubs: { versions: ["1", "2"] },
+ llndk_stubs: "libllndkprebuilt.llndk",
+ }
+ llndk_library {
+ name: "libllndkprebuilt.llndk",
+ }
+
+ cc_library {
+ name: "libllndk_with_external_headers",
+ stubs: { versions: ["1", "2"] },
+ llndk_stubs: "libllndk_with_external_headers.llndk",
+ header_libs: ["libexternal_headers"],
+ export_header_lib_headers: ["libexternal_headers"],
+ }
+ llndk_library {
+ name: "libllndk_with_external_headers.llndk",
+ }
+ cc_library_headers {
+ name: "libexternal_headers",
+ export_include_dirs: ["include"],
+ vendor_available: true,
+ }
`)
- actual := ctx.ModuleVariantsForTests("libllndk.llndk")
+ actual := ctx.ModuleVariantsForTests("libllndk")
+ for i := 0; i < len(actual); i++ {
+ if !strings.HasPrefix(actual[i], "android_vendor.VER_") {
+ actual = append(actual[:i], actual[i+1:]...)
+ i--
+ }
+ }
expected := []string{
"android_vendor.VER_arm64_armv8-a_shared_1",
"android_vendor.VER_arm64_armv8-a_shared_2",
@@ -3190,10 +3346,10 @@
}
checkEquals(t, "variants for llndk stubs", expected, actual)
- params := ctx.ModuleForTests("libllndk.llndk", "android_vendor.VER_arm_armv7-a-neon_shared").Description("generate stub")
+ params := ctx.ModuleForTests("libllndk", "android_vendor.VER_arm_armv7-a-neon_shared").Description("generate stub")
checkEquals(t, "use VNDK version for default stubs", "current", params.Args["apiLevel"])
- params = ctx.ModuleForTests("libllndk.llndk", "android_vendor.VER_arm_armv7-a-neon_shared_1").Description("generate stub")
+ params = ctx.ModuleForTests("libllndk", "android_vendor.VER_arm_armv7-a-neon_shared_1").Description("generate stub")
checkEquals(t, "override apiLevel for versioned stubs", "1", params.Args["apiLevel"])
}
diff --git a/cc/check.go b/cc/check.go
index 0058b8c..a357a97 100644
--- a/cc/check.go
+++ b/cc/check.go
@@ -104,7 +104,7 @@
// Check for bad host_ldlibs
func CheckBadHostLdlibs(ctx ModuleContext, prop string, flags []string) {
- allowed_ldlibs := ctx.toolchain().AvailableLibraries()
+ allowedLdlibs := ctx.toolchain().AvailableLibraries()
if !ctx.Host() {
panic("Invalid call to CheckBadHostLdlibs")
@@ -116,7 +116,7 @@
// TODO: Probably should just redo this property to prefix -l in Soong
if !strings.HasPrefix(flag, "-l") && !strings.HasPrefix(flag, "-framework") {
ctx.PropertyErrorf(prop, "Invalid flag: `%s`, must start with `-l` or `-framework`", flag)
- } else if !inList(flag, allowed_ldlibs) {
+ } else if !inList(flag, allowedLdlibs) {
ctx.PropertyErrorf(prop, "Host library `%s` not available", flag)
}
}
diff --git a/cc/cmakelists.go b/cc/cmakelists.go
index f7d9081..d441c57 100644
--- a/cc/cmakelists.go
+++ b/cc/cmakelists.go
@@ -125,15 +125,15 @@
}
// Only write CMakeLists.txt for the first variant of each architecture of each module
- clionproject_location := getCMakeListsForModule(ccModule, ctx)
- if seenProjects[clionproject_location] {
+ clionprojectLocation := getCMakeListsForModule(ccModule, ctx)
+ if seenProjects[clionprojectLocation] {
return
}
- seenProjects[clionproject_location] = true
+ seenProjects[clionprojectLocation] = true
// Ensure the directory hosting the cmakelists.txt exists
- projectDir := path.Dir(clionproject_location)
+ projectDir := path.Dir(clionprojectLocation)
os.MkdirAll(projectDir, os.ModePerm)
// Create cmakelists.txt
diff --git a/cc/compiler.go b/cc/compiler.go
index b78bb6c..2c05899 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -479,8 +479,7 @@
}
if ctx.inProduct() {
- // TODO(b/150902910): must use 'compiler.Properties.Target.Product.Cflags'
- flags.Local.CFlags = append(flags.Local.CFlags, esc(compiler.Properties.Target.Vendor.Cflags)...)
+ flags.Local.CFlags = append(flags.Local.CFlags, esc(compiler.Properties.Target.Product.Cflags)...)
}
if ctx.inRecovery() {
diff --git a/cc/config/vndk.go b/cc/config/vndk.go
index 8a0d7bd..4bcad4b 100644
--- a/cc/config/vndk.go
+++ b/cc/config/vndk.go
@@ -22,6 +22,7 @@
"android.hardware.light-ndk_platform",
"android.hardware.identity-ndk_platform",
"android.hardware.nfc@1.2",
+ "android.hardware.memtrack-unstable-ndk_platform",
"android.hardware.power-ndk_platform",
"android.hardware.rebootescrow-ndk_platform",
"android.hardware.security.keymint-unstable-ndk_platform",
diff --git a/cc/genrule.go b/cc/genrule.go
index 3668e2b..9648869 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -101,8 +101,7 @@
return variants
}
- // TODO(b/150902910): vendor_available will not create product variant. Remove Bool(g.Vendor_available)
- if Bool(g.Vendor_available) || Bool(g.Product_available) || ctx.ProductSpecific() {
+ if Bool(g.Product_available) || ctx.ProductSpecific() {
variants = append(variants, ProductVariationPrefix+ctx.DeviceConfig().PlatformVndkVersion())
if vndkVersion := ctx.DeviceConfig().ProductVndkVersion(); vndkVersion != "current" {
variants = append(variants, ProductVariationPrefix+vndkVersion)
diff --git a/cc/image.go b/cc/image.go
index 32325b9..13d77cc 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -17,6 +17,8 @@
// functions to determine where a module is installed, etc.
import (
+ "fmt"
+ "reflect"
"strings"
"android/soong/android"
@@ -97,17 +99,23 @@
// Returns true when this module is configured to have core and vendor variants.
func (c *Module) HasVendorVariant() bool {
+ // In case of a VNDK, 'vendor_available: false' still creates a vendor variant.
return c.IsVndk() || Bool(c.VendorProperties.Vendor_available)
}
// Returns true when this module is configured to have core and product variants.
func (c *Module) HasProductVariant() bool {
+ if c.VendorProperties.Product_available == nil {
+ // Without 'product_available', product variant will not be created even for VNDKs.
+ return false
+ }
+ // However, 'product_available: false' in a VNDK still creates a product variant.
return c.IsVndk() || Bool(c.VendorProperties.Product_available)
}
// Returns true when this module is configured to have core and either product or vendor variants.
func (c *Module) HasNonSystemVariants() bool {
- return c.IsVndk() || Bool(c.VendorProperties.Vendor_available) || Bool(c.VendorProperties.Product_available)
+ return c.HasVendorVariant() || c.HasProductVariant()
}
// Returns true if the module is "product" variant. Usually these modules are installed in /product
@@ -144,6 +152,52 @@
return c.ModuleBase.InstallInRecovery()
}
+func visitPropsAndCompareVendorAndProductProps(v reflect.Value) bool {
+ if v.Kind() != reflect.Struct {
+ return true
+ }
+ for i := 0; i < v.NumField(); i++ {
+ prop := v.Field(i)
+ if prop.Kind() == reflect.Struct && v.Type().Field(i).Name == "Target" {
+ vendor_prop := prop.FieldByName("Vendor")
+ product_prop := prop.FieldByName("Product")
+ if vendor_prop.Kind() != reflect.Struct && product_prop.Kind() != reflect.Struct {
+ // Neither Target.Vendor nor Target.Product is defined
+ continue
+ }
+ if vendor_prop.Kind() != reflect.Struct || product_prop.Kind() != reflect.Struct ||
+ !reflect.DeepEqual(vendor_prop.Interface(), product_prop.Interface()) {
+ // If only one of either Target.Vendor or Target.Product is
+ // defined or they have different values, it fails the build
+ // since VNDK must have the same properties for both vendor
+ // and product variants.
+ return false
+ }
+ } else if !visitPropsAndCompareVendorAndProductProps(prop) {
+ // Visit the substructures to find Target.Vendor and Target.Product
+ return false
+ }
+ }
+ return true
+}
+
+// In the case of VNDK, vendor and product variants must have the same properties.
+// VNDK installs only one file and shares it for both vendor and product modules on
+// runtime. We may not define different versions of a VNDK lib for each partition.
+// This function is used only for the VNDK modules that is available to both vendor
+// and product partitions.
+func (c *Module) compareVendorAndProductProps() bool {
+ if !c.IsVndk() && c.VendorProperties.Product_available != nil {
+ panic(fmt.Errorf("This is only for product available VNDK libs. %q is not a VNDK library or not product available", c.Name()))
+ }
+ for _, properties := range c.GetProperties() {
+ if !visitPropsAndCompareVendorAndProductProps(reflect.ValueOf(properties).Elem()) {
+ return false
+ }
+ }
+ return true
+}
+
func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) {
// Validation check
vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
@@ -154,14 +208,6 @@
mctx.PropertyErrorf("vendor_available",
"doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific:true`")
}
- // If defined, make sure vendor_available and product_available has the
- // same value since `false` for these properties means the module is
- // for system only but provides the variant.
- if m.VendorProperties.Product_available != nil {
- if Bool(m.VendorProperties.Vendor_available) != Bool(m.VendorProperties.Product_available) {
- mctx.PropertyErrorf("product_available", "may not have different value than `vendor_available`")
- }
- }
}
if m.VendorProperties.Product_available != nil {
@@ -198,6 +244,14 @@
mctx.PropertyErrorf("vndk",
"vendor_available must be set to either true or false when `vndk: {enabled: true}`")
}
+ if m.VendorProperties.Product_available != nil {
+ // If a VNDK module creates both product and vendor variants, they
+ // must have the same properties since they share a single VNDK
+ // library on runtime.
+ if !m.compareVendorAndProductProps() {
+ mctx.ModuleErrorf("product properties must have the same values with the vendor properties for VNDK modules")
+ }
+ }
}
} else {
if vndkdep.isVndkSp() {
@@ -281,13 +335,13 @@
}
}
- // vendor_available modules are also available to /product.
- // TODO(b/150902910): product variant will be created only if
- // m.HasProductVariant() is true.
- productVariants = append(productVariants, platformVndkVersion)
- // VNDK is always PLATFORM_VNDK_VERSION
- if !m.IsVndk() {
- productVariants = append(productVariants, productVndkVersion)
+ // product_available modules are available to /product.
+ if m.HasProductVariant() {
+ productVariants = append(productVariants, platformVndkVersion)
+ // VNDK is always PLATFORM_VNDK_VERSION
+ if !m.IsVndk() {
+ productVariants = append(productVariants, productVndkVersion)
+ }
}
} else if vendorSpecific && String(m.Properties.Sdk_version) == "" {
// This will be available in /vendor (or /odm) only
@@ -308,6 +362,18 @@
} else {
vendorVariants = append(vendorVariants, platformVndkVersion)
}
+ } else if lib := moduleLibraryInterface(m); lib != nil && lib.hasLLNDKStubs() {
+ // This is an LLNDK library. The implementation of the library will be on /system,
+ // and vendor and product variants will be created with LLNDK stubs.
+ coreVariantNeeded = true
+ vendorVariants = append(vendorVariants,
+ platformVndkVersion,
+ boardVndkVersion,
+ )
+ productVariants = append(productVariants,
+ platformVndkVersion,
+ productVndkVersion,
+ )
} else {
// This is either in /system (or similar: /data), or is a
// modules built with the NDK. Modules built with the NDK
@@ -454,12 +520,11 @@
vndkVersion := ctx.DeviceConfig().VndkVersion()
if vndkVersion != "current" && vndkVersion != "" && vndkVersion != m.Properties.VndkVersion {
m.Properties.HideFromMake = true
- m.SkipInstall()
+ m.HideFromMake()
}
} else if strings.HasPrefix(variant, ProductVariationPrefix) {
m.Properties.ImageVariationPrefix = ProductVariationPrefix
m.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix)
- // TODO (b/150902910): This will be replaced with squashProductSrcs(m).
- squashVendorSrcs(m)
+ squashProductSrcs(m)
}
}
diff --git a/cc/library.go b/cc/library.go
index 959d670..23556b0 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -22,6 +22,7 @@
"strings"
"sync"
+ "github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
"android/soong/android"
@@ -114,6 +115,10 @@
// If this is an LLNDK library, the name of the equivalent llndk_library module.
Llndk_stubs *string
+
+ // If this is an LLNDK library, properties to describe the LLNDK stubs. Will be copied from
+ // the module pointed to by llndk_stubs if it is set.
+ Llndk llndkLibraryProperties
}
// StaticProperties is a properties stanza to affect only attributes of the "static" variants of a
@@ -270,12 +275,13 @@
// any module that links against this module. This is obtained from
// the export_include_dirs property in the appropriate target stanza.
func (f *flagExporter) exportedIncludes(ctx ModuleContext) android.Paths {
- // TODO(b/150902910): product variant must use Target.Product
- if ctx.useVndk() && f.Properties.Target.Vendor.Override_export_include_dirs != nil {
+ if ctx.inVendor() && f.Properties.Target.Vendor.Override_export_include_dirs != nil {
return android.PathsForModuleSrc(ctx, f.Properties.Target.Vendor.Override_export_include_dirs)
- } else {
- return android.PathsForModuleSrc(ctx, f.Properties.Export_include_dirs)
}
+ if ctx.inProduct() && f.Properties.Target.Product.Override_export_include_dirs != nil {
+ return android.PathsForModuleSrc(ctx, f.Properties.Target.Product.Override_export_include_dirs)
+ }
+ return android.PathsForModuleSrc(ctx, f.Properties.Export_include_dirs)
}
// exportIncludes registers the include directories and system include directories to be exported
@@ -382,7 +388,7 @@
versionScriptPath android.OptionalPath
- post_install_cmds []string
+ postInstallCmds []string
// If useCoreVariant is true, the vendor variant of a VNDK library is
// not installed.
@@ -570,6 +576,12 @@
}
flags = library.baseCompiler.compilerFlags(ctx, flags, deps)
+ if ctx.IsLlndk() {
+ // LLNDK libraries ignore most of the properties on the cc_library and use the
+ // LLNDK-specific properties instead.
+ // Wipe all the module-local properties, leaving only the global properties.
+ flags.Local = LocalOrGlobalFlags{}
+ }
if library.buildStubs() {
// Remove -include <file> when compiling stubs. Otherwise, the force included
// headers might cause conflicting types error with the symbols in the
@@ -603,6 +615,22 @@
}
func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
+ if ctx.IsLlndk() {
+ // This is the vendor variant of an LLNDK library, build the LLNDK stubs.
+ vndkVer := ctx.Module().(*Module).VndkVersion()
+ if !inList(vndkVer, ctx.Config().PlatformVersionActiveCodenames()) || vndkVer == "" {
+ // For non-enforcing devices, vndkVer is empty. Use "current" in that case, too.
+ vndkVer = "current"
+ }
+ if library.stubsVersion() != "" {
+ vndkVer = library.stubsVersion()
+ }
+ objs, versionScript := compileStubLibrary(ctx, flags, String(library.Properties.Llndk.Symbol_file), vndkVer, "--llndk")
+ if !Bool(library.Properties.Llndk.Unversioned) {
+ library.versionScriptPath = android.OptionalPathForPath(versionScript)
+ }
+ return objs
+ }
if library.buildStubs() {
objs, versionScript := compileStubLibrary(ctx, flags, String(library.Properties.Stubs.Symbol_file), library.MutatedProperties.StubsVersion, "--apex")
library.versionScriptPath = android.OptionalPathForPath(versionScript)
@@ -631,9 +659,9 @@
SourceAbiFlags = append(SourceAbiFlags, "-I"+reexportedInclude)
}
flags.SAbiFlags = SourceAbiFlags
- total_length := len(library.baseCompiler.Properties.Srcs) + len(deps.GeneratedSources) +
+ totalLength := len(library.baseCompiler.Properties.Srcs) + len(deps.GeneratedSources) +
len(library.SharedProperties.Shared.Srcs) + len(library.StaticProperties.Static.Srcs)
- if total_length > 0 {
+ if totalLength > 0 {
flags.SAbiDump = true
}
}
@@ -693,12 +721,13 @@
allStubsVersions() []string
implementationModuleName(name string) string
+ hasLLNDKStubs() bool
}
var _ libraryInterface = (*libraryDecorator)(nil)
var _ versionedInterface = (*libraryDecorator)(nil)
-func (library *libraryDecorator) getLibNameHelper(baseModuleName string, useVndk bool) string {
+func (library *libraryDecorator) getLibNameHelper(baseModuleName string, inVendor bool, inProduct bool) string {
name := library.libName
if name == "" {
name = String(library.Properties.Stem)
@@ -708,9 +737,10 @@
}
suffix := ""
- if useVndk {
- // TODO(b/150902910): product variant must use Target.Product
+ if inVendor {
suffix = String(library.Properties.Target.Vendor.Suffix)
+ } else if inProduct {
+ suffix = String(library.Properties.Target.Product.Suffix)
}
if suffix == "" {
suffix = String(library.Properties.Suffix)
@@ -722,7 +752,7 @@
// getLibName returns the actual canonical name of the library (the name which
// should be passed to the linker via linker flags).
func (library *libraryDecorator) getLibName(ctx BaseModuleContext) string {
- name := library.getLibNameHelper(ctx.baseModuleName(), ctx.useVndk())
+ name := library.getLibNameHelper(ctx.baseModuleName(), ctx.inVendor(), ctx.inProduct())
if ctx.IsVndkExt() {
// vndk-ext lib should have the same name with original lib
@@ -768,12 +798,27 @@
}
func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
+ if ctx.IsLlndk() {
+ // LLNDK libraries ignore most of the properties on the cc_library and use the
+ // LLNDK-specific properties instead.
+ return deps
+ }
+
deps = library.baseCompiler.compilerDeps(ctx, deps)
return deps
}
func (library *libraryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
+ if ctx.IsLlndk() {
+ // LLNDK libraries ignore most of the properties on the cc_library and use the
+ // LLNDK-specific properties instead.
+ deps.HeaderLibs = append(deps.HeaderLibs, library.Properties.Llndk.Export_llndk_headers...)
+ deps.ReexportHeaderLibHeaders = append(deps.ReexportHeaderLibHeaders,
+ library.Properties.Llndk.Export_llndk_headers...)
+ return deps
+ }
+
if library.static() {
// Compare with nil because an empty list needs to be propagated.
if library.StaticProperties.Static.System_shared_libs != nil {
@@ -808,14 +853,20 @@
deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, library.SharedProperties.Shared.Export_shared_lib_headers...)
deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, library.SharedProperties.Shared.Export_static_lib_headers...)
}
- // TODO(b/150902910): product variant must use Target.Product
- if ctx.useVndk() {
+ if ctx.inVendor() {
deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, library.baseLinker.Properties.Target.Vendor.Exclude_static_libs)
deps.SharedLibs = removeListFromList(deps.SharedLibs, library.baseLinker.Properties.Target.Vendor.Exclude_shared_libs)
deps.StaticLibs = removeListFromList(deps.StaticLibs, library.baseLinker.Properties.Target.Vendor.Exclude_static_libs)
deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, library.baseLinker.Properties.Target.Vendor.Exclude_shared_libs)
deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, library.baseLinker.Properties.Target.Vendor.Exclude_static_libs)
}
+ if ctx.inProduct() {
+ deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, library.baseLinker.Properties.Target.Product.Exclude_static_libs)
+ deps.SharedLibs = removeListFromList(deps.SharedLibs, library.baseLinker.Properties.Target.Product.Exclude_shared_libs)
+ deps.StaticLibs = removeListFromList(deps.StaticLibs, library.baseLinker.Properties.Target.Product.Exclude_static_libs)
+ deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, library.baseLinker.Properties.Target.Product.Exclude_shared_libs)
+ deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, library.baseLinker.Properties.Target.Product.Exclude_static_libs)
+ }
if ctx.inRecovery() {
deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, library.baseLinker.Properties.Target.Recovery.Exclude_static_libs)
deps.SharedLibs = removeListFromList(deps.SharedLibs, library.baseLinker.Properties.Target.Recovery.Exclude_shared_libs)
@@ -977,7 +1028,12 @@
transformSharedObjectToToc(ctx, outputFile, tocFile, builderFlags)
stripFlags := flagsToStripFlags(flags)
- if library.stripper.NeedsStrip(ctx) {
+ needsStrip := library.stripper.NeedsStrip(ctx)
+ if library.buildStubs() {
+ // No need to strip stubs libraries
+ needsStrip = false
+ }
+ if needsStrip {
if ctx.Darwin() {
stripFlags.StripUseGnuStrip = true
}
@@ -1017,7 +1073,7 @@
linkerDeps = append(linkerDeps, deps.LateSharedLibsDeps...)
linkerDeps = append(linkerDeps, objs.tidyFiles...)
- if Bool(library.Properties.Sort_bss_symbols_by_size) {
+ if Bool(library.Properties.Sort_bss_symbols_by_size) && !library.buildStubs() {
unsortedOutputFile := android.PathForModuleOut(ctx, "unsorted", fileName)
transformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs,
deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs,
@@ -1071,7 +1127,7 @@
ctx.SetProvider(SharedLibraryStubsProvider, SharedLibraryStubsInfo{
SharedStubLibraries: stubsInfo,
- IsLLNDK: ctx.isLlndk(ctx.Config()),
+ IsLLNDK: ctx.IsLlndk(),
})
}
@@ -1100,7 +1156,7 @@
func getRefAbiDumpFile(ctx ModuleContext, vndkVersion, fileName string) android.Path {
// The logic must be consistent with classifySourceAbiDump.
isNdk := ctx.isNdk(ctx.Config())
- isLlndkOrVndk := ctx.isLlndkPublic(ctx.Config()) || (ctx.useVndk() && ctx.isVndk())
+ isLlndkOrVndk := ctx.IsLlndkPublic() || (ctx.useVndk() && ctx.isVndk())
refAbiDumpTextFile := android.PathForVndkRefAbiDump(ctx, vndkVersion, fileName, isNdk, isLlndkOrVndk, false)
refAbiDumpGzipFile := android.PathForVndkRefAbiDump(ctx, vndkVersion, fileName, isNdk, isLlndkOrVndk, true)
@@ -1153,17 +1209,64 @@
library.sAbiDiff = sourceAbiDiff(ctx, library.sAbiOutputFile.Path(),
refAbiDumpFile, fileName, exportedHeaderFlags,
Bool(library.Properties.Header_abi_checker.Check_all_apis),
- ctx.isLlndk(ctx.Config()), ctx.isNdk(ctx.Config()), ctx.IsVndkExt())
+ ctx.IsLlndk(), ctx.isNdk(ctx.Config()), ctx.IsVndkExt())
}
}
}
+func processLLNDKHeaders(ctx ModuleContext, srcHeaderDir string, outDir android.ModuleGenPath) android.Path {
+ srcDir := android.PathForModuleSrc(ctx, srcHeaderDir)
+ srcFiles := ctx.GlobFiles(filepath.Join(srcDir.String(), "**/*.h"), nil)
+
+ var installPaths []android.WritablePath
+ for _, header := range srcFiles {
+ headerDir := filepath.Dir(header.String())
+ relHeaderDir, err := filepath.Rel(srcDir.String(), headerDir)
+ if err != nil {
+ ctx.ModuleErrorf("filepath.Rel(%q, %q) failed: %s",
+ srcDir.String(), headerDir, err)
+ continue
+ }
+
+ installPaths = append(installPaths, outDir.Join(ctx, relHeaderDir, header.Base()))
+ }
+
+ return processHeadersWithVersioner(ctx, srcDir, outDir, srcFiles, installPaths)
+}
+
// link registers actions to link this library, and sets various fields
// on this library to reflect information that should be exported up the build
// tree (for example, exported flags and include paths).
func (library *libraryDecorator) link(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
+ if ctx.IsLlndk() {
+ if len(library.Properties.Llndk.Export_preprocessed_headers) > 0 {
+ // This is the vendor variant of an LLNDK library with preprocessed headers.
+ genHeaderOutDir := android.PathForModuleGen(ctx, "include")
+
+ var timestampFiles android.Paths
+ for _, dir := range library.Properties.Llndk.Export_preprocessed_headers {
+ timestampFiles = append(timestampFiles, processLLNDKHeaders(ctx, dir, genHeaderOutDir))
+ }
+
+ if Bool(library.Properties.Llndk.Export_headers_as_system) {
+ library.reexportSystemDirs(genHeaderOutDir)
+ } else {
+ library.reexportDirs(genHeaderOutDir)
+ }
+
+ library.reexportDeps(timestampFiles...)
+ }
+
+ if Bool(library.Properties.Llndk.Export_headers_as_system) {
+ library.flagExporter.Properties.Export_system_include_dirs = append(
+ library.flagExporter.Properties.Export_system_include_dirs,
+ library.flagExporter.Properties.Export_include_dirs...)
+ library.flagExporter.Properties.Export_include_dirs = nil
+ }
+ }
+
// Linking this library consists of linking `deps.Objs` (.o files in dependencies
// of this library), together with `objs` (.o files created by compiling this
// library).
@@ -1246,7 +1349,7 @@
}
func (library *libraryDecorator) exportVersioningMacroIfNeeded(ctx android.BaseModuleContext) {
- if library.buildStubs() && !library.skipAPIDefine {
+ if library.buildStubs() && library.stubsVersion() != "" && !library.skipAPIDefine {
name := versioningMacroName(ctx.Module().(*Module).ImplementationModuleName(ctx))
ver := library.stubsVersion()
library.reexportFlags("-D" + name + "=" + ver)
@@ -1282,7 +1385,7 @@
dirOnDevice := android.InstallPathToOnDevicePath(ctx, dir)
target := "/" + filepath.Join("apex", "com.android.runtime", dir.Base(), "bionic", file.Base())
ctx.InstallAbsoluteSymlink(dir, file.Base(), target)
- library.post_install_cmds = append(library.post_install_cmds, makeSymlinkCmd(dirOnDevice, file.Base(), target))
+ library.postInstallCmds = append(library.postInstallCmds, makeSymlinkCmd(dirOnDevice, file.Base(), target))
}
func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) {
@@ -1297,8 +1400,9 @@
}
}
- // In some cases we want to use core variant for VNDK-Core libs
- if ctx.isVndk() && !ctx.isVndkSp() && !ctx.IsVndkExt() {
+ // In some cases we want to use core variant for VNDK-Core libs.
+ // Skip product variant since VNDKs use only the vendor variant.
+ if ctx.isVndk() && !ctx.isVndkSp() && !ctx.IsVndkExt() && !ctx.inProduct() {
mayUseCoreVariant := true
if ctx.mustUseVendorVariant() {
@@ -1334,9 +1438,9 @@
}
library.baseInstaller.subDir = "bootstrap"
}
- } else if ctx.directlyInAnyApex() && ctx.isLlndk(ctx.Config()) && !isBionic(ctx.baseModuleName()) {
+ } else if ctx.directlyInAnyApex() && ctx.IsLlndk() && !isBionic(ctx.baseModuleName()) {
// Skip installing LLNDK (non-bionic) libraries moved to APEX.
- ctx.Module().SkipInstall()
+ ctx.Module().HideFromMake()
}
library.baseInstaller.install(ctx, file)
@@ -1345,7 +1449,7 @@
if Bool(library.Properties.Static_ndk_lib) && library.static() &&
!ctx.useVndk() && !ctx.inRamdisk() && !ctx.inVendorRamdisk() && !ctx.inRecovery() && ctx.Device() &&
library.baseLinker.sanitize.isUnsanitizedVariant() &&
- !library.buildStubs() && ctx.sdkVersion() == "" {
+ ctx.isForPlatform() && !ctx.isPreventInstall() {
installPath := getNdkSysrootBase(ctx).Join(
ctx, "usr/lib", config.NDKTriple(ctx.toolchain()), file.Base())
@@ -1411,6 +1515,11 @@
library.MutatedProperties.BuildStatic = false
}
+// hasLLNDKStubs returns true if this cc_library module has a variant that will build LLNDK stubs.
+func (library *libraryDecorator) hasLLNDKStubs() bool {
+ return String(library.Properties.Llndk_stubs) != ""
+}
+
func (library *libraryDecorator) implementationModuleName(name string) string {
return name
}
@@ -1423,6 +1532,9 @@
if library.Properties.Header_abi_checker.Symbol_file != nil {
return library.Properties.Header_abi_checker.Symbol_file
}
+ if ctx.Module().(*Module).IsLlndk() {
+ return library.Properties.Llndk.Symbol_file
+ }
if library.hasStubsVariants() && library.Properties.Stubs.Symbol_file != nil {
return library.Properties.Stubs.Symbol_file
}
@@ -1579,15 +1691,17 @@
// LinkageMutator adds "static" or "shared" variants for modules depending
// on whether the module can be built as a static library or a shared library.
func LinkageMutator(mctx android.BottomUpMutatorContext) {
- cc_prebuilt := false
+ ccPrebuilt := false
if m, ok := mctx.Module().(*Module); ok && m.linker != nil {
- _, cc_prebuilt = m.linker.(prebuiltLibraryInterface)
+ _, ccPrebuilt = m.linker.(prebuiltLibraryInterface)
}
- if cc_prebuilt {
+ if ccPrebuilt {
library := mctx.Module().(*Module).linker.(prebuiltLibraryInterface)
// Differentiate between header only and building an actual static/shared library
- if library.buildStatic() || library.buildShared() {
+ buildStatic := library.buildStatic()
+ buildShared := library.buildShared()
+ if buildStatic || buildShared {
// Always create both the static and shared variants for prebuilt libraries, and then disable the one
// that is not being used. This allows them to share the name of a cc_library module, which requires that
// all the variants of the cc_library also exist on the prebuilt.
@@ -1598,16 +1712,16 @@
static.linker.(prebuiltLibraryInterface).setStatic()
shared.linker.(prebuiltLibraryInterface).setShared()
- if library.buildShared() {
+ if buildShared {
mctx.AliasVariation("shared")
- } else if library.buildStatic() {
+ } else if buildStatic {
mctx.AliasVariation("static")
}
- if !library.buildStatic() {
+ if !buildStatic {
static.linker.(prebuiltLibraryInterface).disablePrebuilt()
}
- if !library.buildShared() {
+ if !buildShared {
shared.linker.(prebuiltLibraryInterface).disablePrebuilt()
}
} else {
@@ -1622,7 +1736,18 @@
variations = append(variations, "")
}
- if library.BuildStaticVariant() && library.BuildSharedVariant() {
+ isLLNDK := false
+ if m, ok := mctx.Module().(*Module); ok {
+ isLLNDK = m.IsLlndk()
+ // Don't count the vestigial llndk_library module as isLLNDK, it needs a static
+ // variant so that a cc_library_prebuilt can depend on it.
+ if _, ok := m.linker.(*llndkStubDecorator); ok {
+ isLLNDK = false
+ }
+ }
+ buildStatic := library.BuildStaticVariant() && !isLLNDK
+ buildShared := library.BuildSharedVariant()
+ if buildStatic && buildShared {
variations := append([]string{"static", "shared"}, variations...)
modules := mctx.CreateLocalVariations(variations...)
@@ -1636,13 +1761,13 @@
reuseStaticLibrary(mctx, static.(*Module), shared.(*Module))
}
mctx.AliasVariation("shared")
- } else if library.BuildStaticVariant() {
+ } else if buildStatic {
variations := append([]string{"static"}, variations...)
modules := mctx.CreateLocalVariations(variations...)
modules[0].(LinkableInterface).SetStatic()
mctx.AliasVariation("static")
- } else if library.BuildSharedVariant() {
+ } else if buildShared {
variations := append([]string{"shared"}, variations...)
modules := mctx.CreateLocalVariations(variations...)
@@ -1675,22 +1800,32 @@
}
func createVersionVariations(mctx android.BottomUpMutatorContext, versions []string) {
- // "" is for the non-stubs (implementation) variant.
+ // "" is for the non-stubs (implementation) variant for system modules, or the LLNDK variant
+ // for LLNDK modules.
variants := append(android.CopyOf(versions), "")
+ m := mctx.Module().(*Module)
+ isLLNDK := m.IsLlndk()
+
modules := mctx.CreateLocalVariations(variants...)
for i, m := range modules {
- if variants[i] != "" {
+
+ if variants[i] != "" || isLLNDK {
+ // A stubs or LLNDK stubs variant.
c := m.(*Module)
- c.Properties.HideFromMake = true
c.sanitize = nil
c.stl = nil
c.Properties.PreventInstall = true
lib := moduleLibraryInterface(m)
lib.setBuildStubs()
- lib.setStubsVersion(variants[i])
- // The implementation depends on the stubs
- mctx.AddInterVariantDependency(stubImplDepTag, modules[len(modules)-1], modules[i])
+
+ if variants[i] != "" {
+ // A non-LLNDK stubs module is hidden from make and has a dependency from the
+ // implementation module to the stubs module.
+ c.Properties.HideFromMake = true
+ lib.setStubsVersion(variants[i])
+ mctx.AddInterVariantDependency(stubImplDepTag, modules[len(modules)-1], modules[i])
+ }
}
}
mctx.AliasVariation("")
@@ -1737,7 +1872,7 @@
module.CcLibraryInterface() && module.Shared()
}
-func moduleLibraryInterface(module android.Module) libraryInterface {
+func moduleLibraryInterface(module blueprint.Module) libraryInterface {
if m, ok := module.(*Module); ok {
return m.library
}
@@ -1758,7 +1893,15 @@
// Set the versions on the pre-mutated module so they can be read by any llndk modules that
// depend on the implementation library and haven't been mutated yet.
library.setAllStubsVersions(versions)
- return
+ }
+
+ if mctx.Module().(*Module).UseVndk() && library.hasLLNDKStubs() {
+ // Propagate the version to the llndk stubs module.
+ mctx.VisitDirectDepsWithTag(llndkStubDepTag, func(stubs android.Module) {
+ if stubsLib := moduleLibraryInterface(stubs); stubsLib != nil {
+ stubsLib.setAllStubsVersions(library.allStubsVersions())
+ }
+ })
}
}
}
diff --git a/cc/linkable.go b/cc/linkable.go
index d010985..489063f 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -43,9 +43,11 @@
UseSdk() bool
UseVndk() bool
MustUseVendorVariant() bool
+ IsLlndk() bool
+ IsLlndkPublic() bool
IsVndk() bool
IsVndkExt() bool
- IsVndkPrivate(config android.Config) bool
+ IsVndkPrivate() bool
HasVendorVariant() bool
InProduct() bool
diff --git a/cc/linker.go b/cc/linker.go
index 7bc4105..ff07224 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -263,8 +263,7 @@
deps.WholeStaticLibs = append(deps.WholeStaticLibs, "libbuildversion")
}
- // TODO(b/150902910): product variant must use Target.Product
- if ctx.useVndk() {
+ if ctx.inVendor() {
deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Target.Vendor.Shared_libs...)
deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Vendor.Exclude_shared_libs)
deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Vendor.Exclude_shared_libs)
@@ -276,6 +275,18 @@
deps.RuntimeLibs = removeListFromList(deps.RuntimeLibs, linker.Properties.Target.Vendor.Exclude_runtime_libs)
}
+ if ctx.inProduct() {
+ deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Target.Product.Shared_libs...)
+ deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Product.Exclude_shared_libs)
+ deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Product.Exclude_shared_libs)
+ deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Target.Product.Static_libs...)
+ deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Product.Exclude_static_libs)
+ deps.HeaderLibs = removeListFromList(deps.HeaderLibs, linker.Properties.Target.Product.Exclude_header_libs)
+ deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Product.Exclude_static_libs)
+ deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Product.Exclude_static_libs)
+ deps.RuntimeLibs = removeListFromList(deps.RuntimeLibs, linker.Properties.Target.Product.Exclude_runtime_libs)
+ }
+
if ctx.inRecovery() {
deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Target.Recovery.Shared_libs...)
deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Recovery.Exclude_shared_libs)
@@ -469,14 +480,14 @@
flags.Local.LdFlags = append(flags.Local.LdFlags, proptools.NinjaAndShellEscapeList(linker.Properties.Ldflags)...)
if ctx.Host() && !ctx.Windows() {
- rpath_prefix := `\$$ORIGIN/`
+ rpathPrefix := `\$$ORIGIN/`
if ctx.Darwin() {
- rpath_prefix = "@loader_path/"
+ rpathPrefix = "@loader_path/"
}
if !ctx.static() {
for _, rpath := range linker.dynamicProperties.RunPaths {
- flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,-rpath,"+rpath_prefix+rpath)
+ flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,-rpath,"+rpathPrefix+rpath)
}
}
}
@@ -500,11 +511,14 @@
versionScript := ctx.ExpandOptionalSource(
linker.Properties.Version_script, "version_script")
- // TODO(b/150902910): product variant must use Target.Product
- if ctx.useVndk() && linker.Properties.Target.Vendor.Version_script != nil {
+ if ctx.inVendor() && linker.Properties.Target.Vendor.Version_script != nil {
versionScript = ctx.ExpandOptionalSource(
linker.Properties.Target.Vendor.Version_script,
"target.vendor.version_script")
+ } else if ctx.inProduct() && linker.Properties.Target.Product.Version_script != nil {
+ versionScript = ctx.ExpandOptionalSource(
+ linker.Properties.Target.Product.Version_script,
+ "target.product.version_script")
}
if versionScript.Valid() {
@@ -580,8 +594,8 @@
// Rule to generate .bss symbol ordering file.
var (
- _ = pctx.SourcePathVariable("genSortedBssSymbolsPath", "build/soong/scripts/gen_sorted_bss_symbols.sh")
- gen_sorted_bss_symbols = pctx.AndroidStaticRule("gen_sorted_bss_symbols",
+ _ = pctx.SourcePathVariable("genSortedBssSymbolsPath", "build/soong/scripts/gen_sorted_bss_symbols.sh")
+ genSortedBssSymbols = pctx.AndroidStaticRule("gen_sorted_bss_symbols",
blueprint.RuleParams{
Command: "CROSS_COMPILE=$crossCompile $genSortedBssSymbolsPath ${in} ${out}",
CommandDeps: []string{"$genSortedBssSymbolsPath", "${crossCompile}nm"},
@@ -592,7 +606,7 @@
func (linker *baseLinker) sortBssSymbolsBySize(ctx ModuleContext, in android.Path, symbolOrderingFile android.ModuleOutPath, flags builderFlags) string {
crossCompile := gccCmd(flags.toolchain, "")
ctx.Build(pctx, android.BuildParams{
- Rule: gen_sorted_bss_symbols,
+ Rule: genSortedBssSymbols,
Description: "generate bss symbol order " + symbolOrderingFile.Base(),
Output: symbolOrderingFile,
Input: in,
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index 212720b..d0fbc48 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -15,21 +15,21 @@
package cc
import (
- "fmt"
- "path/filepath"
"strings"
"android/soong/android"
)
-var llndkImplDep = dependencyTag{name: "llndk impl"}
-
var (
llndkLibrarySuffix = ".llndk"
llndkHeadersSuffix = ".llndk"
)
-// Creates a stub shared library based on the provided version file.
+// Holds properties to describe a stub shared library based on the provided version file.
+// The stub library will actually be built by the cc_library module that points to this
+// module with the llndk_stubs property.
+// TODO(ccross): move the properties from llndk_library modules directly into the cc_library
+// modules and remove the llndk_library modules.
//
// Example:
//
@@ -64,43 +64,32 @@
// list of llndk headers to re-export include directories from.
Export_llndk_headers []string `android:"arch_variant"`
+
+ // whether this module can be directly depended upon by libs that are installed
+ // to /vendor and /product.
+ // When set to true, this module can only be depended on by VNDK libraries, not
+ // vendor nor product libraries. This effectively hides this module from
+ // non-system modules. Default value is false.
+ Private *bool
}
type llndkStubDecorator struct {
*libraryDecorator
Properties llndkLibraryProperties
-
- movedToApex bool
}
var _ versionedInterface = (*llndkStubDecorator)(nil)
func (stub *llndkStubDecorator) compilerFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags {
- flags = stub.baseCompiler.compilerFlags(ctx, flags, deps)
- return addStubLibraryCompilerFlags(flags)
+ return flags
}
func (stub *llndkStubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
- vndkVer := ctx.Module().(*Module).VndkVersion()
- if !inList(vndkVer, ctx.Config().PlatformVersionActiveCodenames()) || vndkVer == "" {
- // For non-enforcing devices, vndkVer is empty. Use "current" in that case, too.
- vndkVer = "current"
- }
- if stub.stubsVersion() != "" {
- vndkVer = stub.stubsVersion()
- }
- objs, versionScript := compileStubLibrary(ctx, flags, String(stub.Properties.Symbol_file), vndkVer, "--llndk")
- if !Bool(stub.Properties.Unversioned) {
- stub.versionScriptPath = android.OptionalPathForPath(versionScript)
- }
- return objs
+ return Objects{}
}
func (stub *llndkStubDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
- headers := addSuffix(stub.Properties.Export_llndk_headers, llndkHeadersSuffix)
- deps.HeaderLibs = append(deps.HeaderLibs, headers...)
- deps.ReexportHeaderLibHeaders = append(deps.ReexportHeaderLibHeaders, headers...)
return deps
}
@@ -116,57 +105,9 @@
return stub.libraryDecorator.linkerFlags(ctx, flags)
}
-func (stub *llndkStubDecorator) processHeaders(ctx ModuleContext, srcHeaderDir string, outDir android.ModuleGenPath) android.Path {
- srcDir := android.PathForModuleSrc(ctx, srcHeaderDir)
- srcFiles := ctx.GlobFiles(filepath.Join(srcDir.String(), "**/*.h"), nil)
-
- var installPaths []android.WritablePath
- for _, header := range srcFiles {
- headerDir := filepath.Dir(header.String())
- relHeaderDir, err := filepath.Rel(srcDir.String(), headerDir)
- if err != nil {
- ctx.ModuleErrorf("filepath.Rel(%q, %q) failed: %s",
- srcDir.String(), headerDir, err)
- continue
- }
-
- installPaths = append(installPaths, outDir.Join(ctx, relHeaderDir, header.Base()))
- }
-
- return processHeadersWithVersioner(ctx, srcDir, outDir, srcFiles, installPaths)
-}
-
func (stub *llndkStubDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps,
objs Objects) android.Path {
-
- impl := ctx.GetDirectDepWithTag(stub.implementationModuleName(ctx.ModuleName()), llndkImplDep)
- if implApexModule, ok := impl.(android.ApexModule); ok {
- stub.movedToApex = implApexModule.DirectlyInAnyApex()
- }
-
- if len(stub.Properties.Export_preprocessed_headers) > 0 {
- genHeaderOutDir := android.PathForModuleGen(ctx, "include")
-
- var timestampFiles android.Paths
- for _, dir := range stub.Properties.Export_preprocessed_headers {
- timestampFiles = append(timestampFiles, stub.processHeaders(ctx, dir, genHeaderOutDir))
- }
-
- if Bool(stub.Properties.Export_headers_as_system) {
- stub.reexportSystemDirs(genHeaderOutDir)
- } else {
- stub.reexportDirs(genHeaderOutDir)
- }
-
- stub.reexportDeps(timestampFiles...)
- }
-
- if Bool(stub.Properties.Export_headers_as_system) {
- stub.exportIncludesAsSystem(ctx)
- stub.libraryDecorator.flagExporter.Properties.Export_include_dirs = []string{}
- }
-
- return stub.libraryDecorator.link(ctx, flags, deps, objs)
+ return nil
}
func (stub *llndkStubDecorator) nativeCoverage() bool {
@@ -181,20 +122,8 @@
return true
}
-func (stub *llndkStubDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
- // Get the versions from the implementation module.
- impls := ctx.GetDirectDepsWithTag(llndkImplDep)
- if len(impls) > 1 {
- panic(fmt.Errorf("Expected single implmenetation library, got %d", len(impls)))
- } else if len(impls) == 1 {
- return moduleLibraryInterface(impls[0]).allStubsVersions()
- }
- return nil
-}
-
func NewLLndkStubLibrary() *Module {
module, library := NewLibrary(android.DeviceSupported)
- library.BuildOnlyShared()
module.stl = nil
module.sanitize = nil
library.disableStripping()
@@ -235,10 +164,6 @@
*libraryDecorator
}
-func (headers *llndkHeadersDecorator) Name(name string) string {
- return name + llndkHeadersSuffix
-}
-
// llndk_headers contains a set of c/c++ llndk headers files which are imported
// by other soongs cc modules.
func llndkHeadersFactory() android.Module {
diff --git a/cc/pgo.go b/cc/pgo.go
index 3cf550a..ada694b 100644
--- a/cc/pgo.go
+++ b/cc/pgo.go
@@ -103,7 +103,7 @@
}
func (props *PgoProperties) getPgoProfileFile(ctx BaseModuleContext) android.OptionalPath {
- profile_file := *props.Pgo.Profile_file
+ profileFile := *props.Pgo.Profile_file
// Test if the profile_file is present in any of the PGO profile projects
for _, profileProject := range getPgoProfileProjects(ctx.DeviceConfig()) {
@@ -112,24 +112,24 @@
// <profile_file>.<arbitrary-version> when available. This
// works around an issue where ccache serves stale cache
// entries when the profile file has changed.
- globPattern := filepath.Join(profileProject, profile_file+".*")
- versioned_profiles, err := ctx.GlobWithDeps(globPattern, nil)
+ globPattern := filepath.Join(profileProject, profileFile+".*")
+ versionedProfiles, err := ctx.GlobWithDeps(globPattern, nil)
if err != nil {
ctx.ModuleErrorf("glob: %s", err.Error())
}
- path := android.ExistentPathForSource(ctx, profileProject, profile_file)
+ path := android.ExistentPathForSource(ctx, profileProject, profileFile)
if path.Valid() {
- if len(versioned_profiles) != 0 {
- ctx.PropertyErrorf("pgo.profile_file", "Profile_file has multiple versions: "+filepath.Join(profileProject, profile_file)+", "+strings.Join(versioned_profiles, ", "))
+ if len(versionedProfiles) != 0 {
+ ctx.PropertyErrorf("pgo.profile_file", "Profile_file has multiple versions: "+filepath.Join(profileProject, profileFile)+", "+strings.Join(versionedProfiles, ", "))
}
return path
}
- if len(versioned_profiles) > 1 {
- ctx.PropertyErrorf("pgo.profile_file", "Profile_file has multiple versions: "+strings.Join(versioned_profiles, ", "))
- } else if len(versioned_profiles) == 1 {
- return android.OptionalPathForPath(android.PathForSource(ctx, versioned_profiles[0]))
+ if len(versionedProfiles) > 1 {
+ ctx.PropertyErrorf("pgo.profile_file", "Profile_file has multiple versions: "+strings.Join(versionedProfiles, ", "))
+ } else if len(versionedProfiles) == 1 {
+ return android.OptionalPathForPath(android.PathForSource(ctx, versionedProfiles[0]))
}
}
diff --git a/cc/sabi.go b/cc/sabi.go
index 99e718e..4a1ba3c 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -80,10 +80,10 @@
if m.IsNdk(ctx.Config()) {
return "NDK"
}
- if m.isLlndkPublic(ctx.Config()) {
+ if m.isImplementationForLLNDKPublic() {
return "LLNDK"
}
- if m.UseVndk() && m.IsVndk() && !m.IsVndkPrivate(ctx.Config()) {
+ if m.UseVndk() && m.IsVndk() && !m.IsVndkPrivate() {
if m.isVndkSp() {
if m.IsVndkExt() {
return "VNDK-SP-ext"
@@ -131,7 +131,7 @@
// Module is shared library type.
// Don't check uninstallable modules.
- if m.IsSkipInstall() {
+ if m.IsHideFromMake() {
return false
}
@@ -156,7 +156,7 @@
}
// Don't create ABI dump for stubs.
- if m.isNDKStubLibrary() || m.IsStubs() {
+ if m.isNDKStubLibrary() || m.IsLlndk() || m.IsStubs() {
return false
}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 22ee25f..0e2d01a 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -204,6 +204,13 @@
Properties SanitizeProperties
}
+// Mark this tag with a check to see if apex dependency check should be skipped
+func (t libraryDependencyTag) SkipApexAllowedDependenciesCheck() bool {
+ return t.skipApexAllowedDependenciesCheck
+}
+
+var _ android.SkipApexAllowedDependenciesCheck = (*libraryDependencyTag)(nil)
+
func init() {
android.RegisterMakeVarsProvider(pctx, cfiMakeVarsProvider)
android.RegisterMakeVarsProvider(pctx, hwasanMakeVarsProvider)
@@ -1002,9 +1009,6 @@
if runtimeLibrary != "" && (toolchain.Bionic() || c.sanitize.Properties.UbsanRuntimeDep) {
// UBSan is supported on non-bionic linux host builds as well
- if isLlndkLibrary(runtimeLibrary, mctx.Config()) && !c.static() && c.UseVndk() {
- runtimeLibrary = runtimeLibrary + llndkLibrarySuffix
- }
// Adding dependency to the runtime library. We are using *FarVariation*
// because the runtime libraries themselves are not mutated by sanitizer
@@ -1041,9 +1045,18 @@
runtimeLibrary = lib
}
}
-
+ // Skip apex dependency check for sharedLibraryDependency
+ // when sanitizer diags are enabled. Skipping the check will allow
+ // building with diag libraries without having to list the
+ // dependency in Apex's allowed_deps file.
+ diagEnabled := len(diagSanitizers) > 0
// dynamic executable and shared libs get shared runtime libs
- depTag := libraryDependencyTag{Kind: sharedLibraryDependency, Order: earlyLibraryDependency}
+ depTag := libraryDependencyTag{
+ Kind: sharedLibraryDependency,
+ Order: earlyLibraryDependency,
+
+ skipApexAllowedDependenciesCheck: diagEnabled,
+ }
variations := append(mctx.Target().Variations(),
blueprint.Variation{Mutator: "link", Variation: "shared"})
if c.Device() {
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index b291bd0..4c4e9b6 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -787,11 +787,11 @@
if !module.SocSpecific() {
// But we can't just check SocSpecific() since we already passed the image mutator.
// Check ramdisk and recovery to see if we are real "vendor: true" module.
- ramdisk_available := module.InRamdisk() && !module.OnlyInRamdisk()
- vendor_ramdisk_available := module.InVendorRamdisk() && !module.OnlyInVendorRamdisk()
- recovery_available := module.InRecovery() && !module.OnlyInRecovery()
+ ramdiskAvailable := module.InRamdisk() && !module.OnlyInRamdisk()
+ vendorRamdiskAvailable := module.InVendorRamdisk() && !module.OnlyInVendorRamdisk()
+ recoveryAvailable := module.InRecovery() && !module.OnlyInRecovery()
- if !ramdisk_available && !recovery_available && !vendor_ramdisk_available {
+ if !ramdiskAvailable && !recoveryAvailable && !vendorRamdiskAvailable {
vendorSnapshotsLock.Lock()
defer vendorSnapshotsLock.Unlock()
@@ -805,7 +805,7 @@
}
// .. and also filter out llndk library
- if module.isLlndk(ctx.Config()) {
+ if module.IsLlndk() {
return
}
@@ -836,7 +836,7 @@
// Disables source modules if corresponding snapshot exists.
if lib, ok := module.linker.(libraryInterface); ok && lib.buildStatic() && lib.buildShared() {
// But do not disable because the shared variant depends on the static variant.
- module.SkipInstall()
+ module.HideFromMake()
module.Properties.HideFromMake = true
} else {
module.Disable()
diff --git a/cc/test.go b/cc/test.go
index a9be6f9..4ff5bf6 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -211,15 +211,15 @@
// name or even their number.
testNames = append(testNames, "")
tests := mctx.CreateLocalVariations(testNames...)
- all_tests := tests[numTests]
- all_tests.(*Module).linker.(testPerSrc).unsetSrc()
+ allTests := tests[numTests]
+ allTests.(*Module).linker.(testPerSrc).unsetSrc()
// Prevent the "all tests" variation from being installable nor
// exporting to Make, as it won't create any output file.
- all_tests.(*Module).Properties.PreventInstall = true
- all_tests.(*Module).Properties.HideFromMake = true
+ allTests.(*Module).Properties.PreventInstall = true
+ allTests.(*Module).Properties.HideFromMake = true
for i, src := range test.srcs() {
tests[i].(*Module).linker.(testPerSrc).setSrc(testNames[i], src)
- mctx.AddInterVariantDependency(testPerSrcDepTag, all_tests, tests[i])
+ mctx.AddInterVariantDependency(testPerSrcDepTag, allTests, tests[i])
}
mctx.AliasVariation("")
}
@@ -369,9 +369,9 @@
}
})
- var api_level_prop string
+ var apiLevelProp string
var configs []tradefed.Config
- var min_level string
+ var minLevel string
for _, module := range test.Properties.Test_mainline_modules {
configs = append(configs, tradefed.Option{Name: "config-descriptor:metadata", Key: "mainline-param", Value: module})
}
@@ -398,16 +398,16 @@
if test.Properties.Test_min_api_level != nil && test.Properties.Test_min_sdk_version != nil {
ctx.PropertyErrorf("test_min_api_level", "'test_min_api_level' and 'test_min_sdk_version' should not be set at the same time.")
} else if test.Properties.Test_min_api_level != nil {
- api_level_prop = "ro.product.first_api_level"
- min_level = strconv.FormatInt(int64(*test.Properties.Test_min_api_level), 10)
+ apiLevelProp = "ro.product.first_api_level"
+ minLevel = strconv.FormatInt(int64(*test.Properties.Test_min_api_level), 10)
} else if test.Properties.Test_min_sdk_version != nil {
- api_level_prop = "ro.build.version.sdk"
- min_level = strconv.FormatInt(int64(*test.Properties.Test_min_sdk_version), 10)
+ apiLevelProp = "ro.build.version.sdk"
+ minLevel = strconv.FormatInt(int64(*test.Properties.Test_min_sdk_version), 10)
}
- if api_level_prop != "" {
+ if apiLevelProp != "" {
var options []tradefed.Option
- options = append(options, tradefed.Option{Name: "min-api-level", Value: min_level})
- options = append(options, tradefed.Option{Name: "api-level-prop", Value: api_level_prop})
+ options = append(options, tradefed.Option{Name: "min-api-level", Value: minLevel})
+ options = append(options, tradefed.Option{Name: "api-level-prop", Value: apiLevelProp})
configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.MinApiLevelModuleController", options})
}
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index da37d0f..d2c29d6 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -181,8 +181,8 @@
return false
}
// When android/prebuilt.go selects between source and prebuilt, it sets
- // SkipInstall on the other one to avoid duplicate install rules in make.
- if m.IsSkipInstall() {
+ // HideFromMake on the other one to avoid duplicate install rules in make.
+ if m.IsHideFromMake() {
return false
}
// skip proprietary modules, but (for the vendor snapshot only)
@@ -210,6 +210,9 @@
return false
}
// skip llndk_library and llndk_headers which are backward compatible
+ if m.IsLlndk() {
+ return false
+ }
if _, ok := m.linker.(*llndkStubDecorator); ok {
return false
}
diff --git a/cc/vndk.go b/cc/vndk.go
index 1529ac5..6bc7131 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -78,6 +78,13 @@
// VNDK-SP or LL-NDK modules only.
Support_system_process *bool
+ // declared as a VNDK-private module.
+ // This module still creates the vendor and product variants refering
+ // to the `vendor_available: true` and `product_available: true`
+ // properties. However, it is only available to the other VNDK modules
+ // but not to the non-VNDK vendor or product modules.
+ Private *bool
+
// Extending another module
Extends *string
}
@@ -135,30 +142,24 @@
return
}
if !vndk.isVndk() {
- // Non-VNDK modules those installed to /vendor or /system/vendor
- // can't depend on modules marked with vendor_available: false;
- // or those installed to /product or /system/product can't depend
- // on modules marked with product_available: false.
- violation := false
- if lib, ok := to.linker.(*llndkStubDecorator); ok && !Bool(lib.Properties.Vendor_available) {
- violation = true
- } else {
- if _, ok := to.linker.(libraryInterface); ok && to.VendorProperties.Vendor_available != nil && !Bool(to.VendorProperties.Vendor_available) {
- // Vendor_available == nil && !Bool(Vendor_available) should be okay since
- // it means a vendor-only, or product-only library which is a valid dependency
- // for non-VNDK modules.
- violation = true
- }
- }
- if violation {
- ctx.ModuleErrorf("Vendor module that is not VNDK should not link to %q which is marked as `vendor_available: false`", to.Name())
+ // Non-VNDK modules those installed to /vendor, /system/vendor,
+ // /product or /system/product cannot depend on VNDK-private modules
+ // that include VNDK-core-private, VNDK-SP-private and LLNDK-private.
+ if to.IsVndkPrivate() {
+ ctx.ModuleErrorf("non-VNDK module should not link to %q which has `private: true`", to.Name())
}
}
if lib, ok := to.linker.(*libraryDecorator); !ok || !lib.shared() {
// Check only shared libraries.
- // Other (static and LL-NDK) libraries are allowed to link.
+ // Other (static) libraries are allowed to link.
return
}
+
+ if to.IsLlndk() {
+ // LL-NDK libraries are allowed to link
+ return
+ }
+
if !to.UseVndk() {
ctx.ModuleErrorf("(%s) should not link to %q which is not a vendor-available library",
vndk.typeName(), to.Name())
@@ -177,10 +178,9 @@
to.Name())
return
}
- // TODO(b/150902910): vndk-ext for product must check product_available.
- if !Bool(to.VendorProperties.Vendor_available) {
+ if to.IsVndkPrivate() {
ctx.ModuleErrorf(
- "`extends` refers module %q which does not have `vendor_available: true`",
+ "`extends` refers module %q which has `private: true`",
to.Name())
return
}
@@ -250,22 +250,12 @@
}).(map[string]string)
}
-func isLlndkLibrary(baseModuleName string, config android.Config) bool {
- _, ok := llndkLibraries(config)[strings.TrimSuffix(baseModuleName, llndkLibrarySuffix)]
- return ok
-}
-
func llndkLibraries(config android.Config) map[string]string {
return config.Once(llndkLibrariesKey, func() interface{} {
return make(map[string]string)
}).(map[string]string)
}
-func isVndkPrivateLibrary(baseModuleName string, config android.Config) bool {
- _, ok := vndkPrivateLibraries(config)[baseModuleName]
- return ok
-}
-
func vndkPrivateLibraries(config android.Config) map[string]string {
return config.Once(vndkPrivateLibrariesKey, func() interface{} {
return make(map[string]string)
@@ -301,12 +291,10 @@
defer vndkLibrariesLock.Unlock()
llndkLibraries(mctx.Config())[name] = filename
+ m.VendorProperties.IsLLNDK = true
if !Bool(lib.Properties.Vendor_available) {
vndkPrivateLibraries(mctx.Config())[name] = filename
- }
-
- if mctx.OtherModuleExists(name) {
- mctx.AddFarVariationDependencies(m.Target().Variations(), llndkImplDep, name)
+ m.VendorProperties.IsLLNDKPrivate = true
}
}
@@ -330,6 +318,12 @@
vndkLibrariesLock.Lock()
defer vndkLibrariesLock.Unlock()
+ if m.InProduct() {
+ // We may skip the other steps for the product variants because they
+ // are already covered by the vendor variants.
+ return
+ }
+
if inList(name, vndkMustUseVendorVariantList(mctx.Config())) {
m.Properties.MustUseVendorVariant = true
}
@@ -342,9 +336,7 @@
} else {
vndkCoreLibraries(mctx.Config())[name] = filename
}
- // As `vendor_available` and `product_available` has the same value for VNDK modules,
- // we don't need to check both values.
- if !Bool(m.VendorProperties.Vendor_available) {
+ if m.IsVndkPrivate() {
vndkPrivateLibraries(mctx.Config())[name] = filename
}
}
@@ -410,10 +402,32 @@
return
}
- lib, is_lib := m.linker.(*libraryDecorator)
- prebuilt_lib, is_prebuilt_lib := m.linker.(*prebuiltLibraryLinker)
+ // This is a temporary measure to copy the properties from an llndk_library into the cc_library
+ // that will actually build the stubs. It will be removed once the properties are moved into
+ // the cc_library in the Android.bp files.
+ mergeLLNDKToLib := func(llndk *Module, llndkProperties *llndkLibraryProperties, flagExporter *flagExporter) {
+ if llndkLib := moduleLibraryInterface(llndk); llndkLib != nil {
+ *llndkProperties = llndkLib.(*llndkStubDecorator).Properties
+ flagExporter.Properties = llndkLib.(*llndkStubDecorator).flagExporter.Properties
- if (is_lib && lib.buildShared()) || (is_prebuilt_lib && prebuilt_lib.buildShared()) {
+ m.VendorProperties.IsLLNDK = llndk.VendorProperties.IsLLNDK
+ m.VendorProperties.IsLLNDKPrivate = llndk.VendorProperties.IsLLNDKPrivate
+ }
+ }
+
+ lib, isLib := m.linker.(*libraryDecorator)
+ prebuiltLib, isPrebuiltLib := m.linker.(*prebuiltLibraryLinker)
+
+ if m.UseVndk() && isLib && lib.hasLLNDKStubs() {
+ llndk := mctx.AddVariationDependencies(nil, llndkStubDepTag, String(lib.Properties.Llndk_stubs))
+ mergeLLNDKToLib(llndk[0].(*Module), &lib.Properties.Llndk, &lib.flagExporter)
+ }
+ if m.UseVndk() && isPrebuiltLib && prebuiltLib.hasLLNDKStubs() {
+ llndk := mctx.AddVariationDependencies(nil, llndkStubDepTag, String(prebuiltLib.Properties.Llndk_stubs))
+ mergeLLNDKToLib(llndk[0].(*Module), &prebuiltLib.Properties.Llndk, &prebuiltLib.flagExporter)
+ }
+
+ if (isLib && lib.buildShared()) || (isPrebuiltLib && prebuiltLib.buildShared()) {
if m.vndkdep != nil && m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() {
processVndkLibrary(mctx, m)
return
@@ -780,10 +794,10 @@
func getVndkFileName(m *Module) (string, error) {
if library, ok := m.linker.(*libraryDecorator); ok {
- return library.getLibNameHelper(m.BaseModuleName(), true) + ".so", nil
+ return library.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil
}
if prebuilt, ok := m.linker.(*prebuiltLibraryLinker); ok {
- return prebuilt.libraryDecorator.getLibNameHelper(m.BaseModuleName(), true) + ".so", nil
+ return prebuilt.libraryDecorator.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil
}
return "", fmt.Errorf("VNDK library should have libraryDecorator or prebuiltLibraryLinker as linker: %T", m.linker)
}
@@ -819,13 +833,11 @@
// they been moved to an apex.
movedToApexLlndkLibraries := make(map[string]bool)
ctx.VisitAllModules(func(module android.Module) {
- if m, ok := module.(*Module); ok {
- if llndk, ok := m.linker.(*llndkStubDecorator); ok {
- // Skip bionic libs, they are handled in different manner
- name := llndk.implementationModuleName(m.BaseModuleName())
- if llndk.movedToApex && !isBionic(name) {
- movedToApexLlndkLibraries[name] = true
- }
+ if library := moduleLibraryInterface(module); library != nil && library.hasLLNDKStubs() {
+ // Skip bionic libs, they are handled in different manner
+ name := library.implementationModuleName(module.(*Module).BaseModuleName())
+ if module.(android.ApexModule).DirectlyInAnyApex() && !isBionic(name) {
+ movedToApexLlndkLibraries[name] = true
}
}
})
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index e6e2ad8..04162cd 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -130,7 +130,7 @@
flags Flags, deps PathDeps, objs Objects) android.Path {
if !p.matchesWithDevice(ctx.DeviceConfig()) {
- ctx.Module().SkipInstall()
+ ctx.Module().HideFromMake()
return nil
}
@@ -175,7 +175,7 @@
return in
}
- ctx.Module().SkipInstall()
+ ctx.Module().HideFromMake()
return nil
}
diff --git a/cmd/host_bionic_inject/host_bionic_inject.go b/cmd/host_bionic_inject/host_bionic_inject.go
index 629f6cc..ce8b062 100644
--- a/cmd/host_bionic_inject/host_bionic_inject.go
+++ b/cmd/host_bionic_inject/host_bionic_inject.go
@@ -58,7 +58,7 @@
os.Exit(4)
}
- start_addr, err := parseElf(r, linker)
+ startAddr, err := parseElf(r, linker)
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(5)
@@ -71,7 +71,7 @@
}
defer w.Close()
- err = symbol_inject.InjectUint64Symbol(file, w, "__dlwrap_original_start", start_addr)
+ err = symbol_inject.InjectUint64Symbol(file, w, "__dlwrap_original_start", startAddr)
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(7)
@@ -128,7 +128,7 @@
// Check that all of the PT_LOAD segments have been embedded properly
func checkLinker(file, linker *elf.File, fileSyms []elf.Symbol) error {
- dlwrap_linker_offset, err := findSymbol(fileSyms, "__dlwrap_linker_offset")
+ dlwrapLinkerOffset, err := findSymbol(fileSyms, "__dlwrap_linker_offset")
if err != nil {
return err
}
@@ -138,7 +138,7 @@
continue
}
- laddr := lprog.Vaddr + dlwrap_linker_offset.Value
+ laddr := lprog.Vaddr + dlwrapLinkerOffset.Value
found := false
for _, prog := range file.Progs {
@@ -163,7 +163,7 @@
}
if !found {
return fmt.Errorf("Linker prog %d (0x%x) not found at offset 0x%x",
- i, lprog.Vaddr, dlwrap_linker_offset.Value)
+ i, lprog.Vaddr, dlwrapLinkerOffset.Value)
}
}
diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go
index c079e83..7dd50f6 100644
--- a/cmd/multiproduct_kati/main.go
+++ b/cmd/multiproduct_kati/main.go
@@ -50,12 +50,30 @@
var buildVariant = flag.String("variant", "eng", "build variant to use")
-var skipProducts = flag.String("skip-products", "", "comma-separated list of products to skip (known failures, etc)")
-var includeProducts = flag.String("products", "", "comma-separated list of products to build")
-
var shardCount = flag.Int("shard-count", 1, "split the products into multiple shards (to spread the build onto multiple machines, etc)")
var shard = flag.Int("shard", 1, "1-indexed shard to execute")
+var skipProducts multipleStringArg
+var includeProducts multipleStringArg
+
+func init() {
+ flag.Var(&skipProducts, "skip-products", "comma-separated list of products to skip (known failures, etc)")
+ flag.Var(&includeProducts, "products", "comma-separated list of products to build")
+}
+
+// multipleStringArg is a flag.Value that takes comma separated lists and converts them to a
+// []string. The argument can be passed multiple times to append more values.
+type multipleStringArg []string
+
+func (m *multipleStringArg) String() string {
+ return strings.Join(*m, `, `)
+}
+
+func (m *multipleStringArg) Set(s string) error {
+ *m = append(*m, strings.Split(s, ",")...)
+ return nil
+}
+
const errorLeadingLines = 20
const errorTrailingLines = 20
@@ -250,9 +268,9 @@
var productsList []string
allProducts := strings.Fields(vars["all_named_products"])
- if *includeProducts != "" {
- missingProducts := []string{}
- for _, product := range strings.Split(*includeProducts, ",") {
+ if len(includeProducts) > 0 {
+ var missingProducts []string
+ for _, product := range includeProducts {
if inList(product, allProducts) {
productsList = append(productsList, product)
} else {
@@ -267,9 +285,8 @@
}
finalProductsList := make([]string, 0, len(productsList))
- skipList := strings.Split(*skipProducts, ",")
skipProduct := func(p string) bool {
- for _, s := range skipList {
+ for _, s := range skipProducts {
if p == s {
return true
}
diff --git a/dexpreopt/class_loader_context.go b/dexpreopt/class_loader_context.go
index deaf77f..ab789aa 100644
--- a/dexpreopt/class_loader_context.go
+++ b/dexpreopt/class_loader_context.go
@@ -16,6 +16,7 @@
import (
"fmt"
+ "sort"
"strconv"
"strings"
@@ -238,8 +239,8 @@
AndroidTestMock,
}
var CompatUsesLibs29 = []string{
- AndroidHidlBase,
AndroidHidlManager,
+ AndroidHidlBase,
}
var OptionalCompatUsesLibs = append(android.CopyOf(OptionalCompatUsesLibs28), OptionalCompatUsesLibs30...)
var CompatUsesLibs = android.CopyOf(CompatUsesLibs29)
@@ -335,11 +336,14 @@
}
}
-// Add class loader context for the given SDK version. Fail on unknown build/install paths.
+// Add class loader context for the given SDK version. Don't fail on unknown build/install paths, as
+// libraries with unknown paths still need to be processed by manifest_fixer (which doesn't care
+// about paths). For the subset of libraries that are used in dexpreopt, their build/install paths
+// are validated later before CLC is used (in validateClassLoaderContext).
func (clcMap ClassLoaderContextMap) AddContextForSdk(ctx android.ModuleInstallPathContext, sdkVer int,
lib string, hostPath, installPath android.Path, nestedClcMap ClassLoaderContextMap) {
- clcMap.addContextOrReportError(ctx, sdkVer, lib, hostPath, installPath, true, nestedClcMap)
+ clcMap.addContextOrReportError(ctx, sdkVer, lib, hostPath, installPath, false, nestedClcMap)
}
// Merge the other class loader context map into this one, do not override existing entries.
@@ -459,7 +463,26 @@
// Perform a depth-first preorder traversal of the class loader context tree for each SDK version.
// Return the resulting string and a slice of on-host build paths to all library dependencies.
func ComputeClassLoaderContext(clcMap ClassLoaderContextMap) (clcStr string, paths android.Paths) {
- for _, sdkVer := range android.SortedIntKeys(clcMap) { // determinisitc traversal order
+ // CLC for different SDK versions should come in specific order that agrees with PackageManager.
+ // Since PackageManager processes SDK versions in ascending order and prepends compatibility
+ // libraries at the front, the required order is descending, except for AnySdkVersion that has
+ // numerically the largest order, but must be the last one. Example of correct order: [30, 29,
+ // 28, AnySdkVersion]. There are Soong tests to ensure that someone doesn't change this by
+ // accident, but there is no way to guard against changes in the PackageManager, except for
+ // grepping logcat on the first boot for absence of the following messages:
+ //
+ // `logcat | grep -E 'ClassLoaderContext [a-z ]+ mismatch`
+ //
+ versions := make([]int, 0, len(clcMap))
+ for ver, _ := range clcMap {
+ if ver != AnySdkVersion {
+ versions = append(versions, ver)
+ }
+ }
+ sort.Sort(sort.Reverse(sort.IntSlice(versions))) // descending order
+ versions = append(versions, AnySdkVersion)
+
+ for _, sdkVer := range versions {
sdkVerStr := fmt.Sprintf("%d", sdkVer)
if sdkVer == AnySdkVersion {
sdkVerStr = "any" // a special keyword that means any SDK version
diff --git a/dexpreopt/class_loader_context_test.go b/dexpreopt/class_loader_context_test.go
index be7d4c6..6b6b162 100644
--- a/dexpreopt/class_loader_context_test.go
+++ b/dexpreopt/class_loader_context_test.go
@@ -209,6 +209,48 @@
checkError(t, err, "nested class loader context shouldn't have conditional part")
}
+// Test for SDK version order in conditional CLC: no matter in what order the libraries are added,
+// they end up in the order that agrees with PackageManager.
+func TestCLCSdkVersionOrder(t *testing.T) {
+ ctx := testContext()
+ m := make(ClassLoaderContextMap)
+ m.AddContextForSdk(ctx, 28, "a", buildPath(ctx, "a"), installPath(ctx, "a"), nil)
+ m.AddContextForSdk(ctx, 29, "b", buildPath(ctx, "b"), installPath(ctx, "b"), nil)
+ m.AddContextForSdk(ctx, 30, "c", buildPath(ctx, "c"), installPath(ctx, "c"), nil)
+ m.AddContextForSdk(ctx, AnySdkVersion, "d", buildPath(ctx, "d"), installPath(ctx, "d"), nil)
+
+ valid, validationError := validateClassLoaderContext(m)
+
+ fixClassLoaderContext(m)
+
+ var haveStr string
+ if valid && validationError == nil {
+ haveStr, _ = ComputeClassLoaderContext(m)
+ }
+
+ // Test that validation is successful (all paths are known).
+ t.Run("validate", func(t *testing.T) {
+ if !(valid && validationError == nil) {
+ t.Errorf("invalid class loader context")
+ }
+ })
+
+ // Test that class loader context structure is correct.
+ t.Run("string", func(t *testing.T) {
+ wantStr := " --host-context-for-sdk 30 PCL[out/c.jar]" +
+ " --target-context-for-sdk 30 PCL[/system/c.jar]" +
+ " --host-context-for-sdk 29 PCL[out/b.jar]" +
+ " --target-context-for-sdk 29 PCL[/system/b.jar]" +
+ " --host-context-for-sdk 28 PCL[out/a.jar]" +
+ " --target-context-for-sdk 28 PCL[/system/a.jar]" +
+ " --host-context-for-sdk any PCL[out/d.jar]" +
+ " --target-context-for-sdk any PCL[/system/d.jar]"
+ if wantStr != haveStr {
+ t.Errorf("\nwant class loader context: %s\nhave class loader context: %s", wantStr, haveStr)
+ }
+ })
+}
+
func checkError(t *testing.T, have error, want string) {
if have == nil {
t.Errorf("\nwant error: '%s'\nhave: none", want)
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 594d253..8df32f2 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -139,7 +139,6 @@
// number of shards the input files are sharded into.
taskGenerator taskFunc
- deps android.Paths
rule blueprint.Rule
rawCommands []string
@@ -244,6 +243,8 @@
}
}
+ var tools android.Paths
+ var packagedTools []android.PackagingSpec
if len(g.properties.Tools) > 0 {
seenTools := make(map[string]bool)
@@ -251,37 +252,52 @@
switch tag := ctx.OtherModuleDependencyTag(module).(type) {
case hostToolDependencyTag:
tool := ctx.OtherModuleName(module)
- var path android.OptionalPath
- if t, ok := module.(android.HostToolProvider); ok {
+ switch t := module.(type) {
+ case android.HostToolProvider:
+ // A HostToolProvider provides the path to a tool, which will be copied
+ // into the sandbox.
if !t.(android.Module).Enabled() {
if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{tool})
} else {
ctx.ModuleErrorf("depends on disabled module %q", tool)
}
- break
+ return
}
- path = t.HostToolPath()
- } else if t, ok := module.(bootstrap.GoBinaryTool); ok {
+ path := t.HostToolPath()
+ if !path.Valid() {
+ ctx.ModuleErrorf("host tool %q missing output file", tool)
+ return
+ }
+ if specs := t.TransitivePackagingSpecs(); specs != nil {
+ // If the HostToolProvider has PackgingSpecs, which are definitions of the
+ // required relative locations of the tool and its dependencies, use those
+ // instead. They will be copied to those relative locations in the sbox
+ // sandbox.
+ packagedTools = append(packagedTools, specs...)
+ // Assume that the first PackagingSpec of the module is the tool.
+ addLocationLabel(tag.label, []string{android.SboxPathForPackagedTool(specs[0])})
+ } else {
+ tools = append(tools, path.Path())
+ addLocationLabel(tag.label, []string{android.SboxPathForTool(ctx, path.Path())})
+ }
+ case bootstrap.GoBinaryTool:
+ // A GoBinaryTool provides the install path to a tool, which will be copied.
if s, err := filepath.Rel(android.PathForOutput(ctx).String(), t.InstallPath()); err == nil {
- path = android.OptionalPathForPath(android.PathForOutput(ctx, s))
+ toolPath := android.PathForOutput(ctx, s)
+ tools = append(tools, toolPath)
+ addLocationLabel(tag.label, []string{android.SboxPathForTool(ctx, toolPath)})
} else {
ctx.ModuleErrorf("cannot find path for %q: %v", tool, err)
- break
+ return
}
- } else {
+ default:
ctx.ModuleErrorf("%q is not a host tool provider", tool)
- break
+ return
}
- if path.Valid() {
- g.deps = append(g.deps, path.Path())
- addLocationLabel(tag.label, []string{path.Path().String()})
- seenTools[tag.label] = true
- } else {
- ctx.ModuleErrorf("host tool %q missing output file", tool)
- }
+ seenTools[tag.label] = true
}
})
@@ -305,8 +321,12 @@
for _, toolFile := range g.properties.Tool_files {
paths := android.PathsForModuleSrc(ctx, []string{toolFile})
- g.deps = append(g.deps, paths...)
- addLocationLabel(toolFile, paths.Strings())
+ tools = append(tools, paths...)
+ var sandboxPaths []string
+ for _, path := range paths {
+ sandboxPaths = append(sandboxPaths, android.SboxPathForTool(ctx, path))
+ }
+ addLocationLabel(toolFile, sandboxPaths)
}
var srcFiles android.Paths
@@ -358,7 +378,7 @@
manifestPath := android.PathForModuleOut(ctx, manifestName)
// Use a RuleBuilder to create a rule that runs the command inside an sbox sandbox.
- rule := android.NewRuleBuilder(pctx, ctx).Sbox(task.genDir, manifestPath)
+ rule := android.NewRuleBuilder(pctx, ctx).Sbox(task.genDir, manifestPath).SandboxTools()
cmd := rule.Command()
for _, out := range task.out {
@@ -448,8 +468,9 @@
cmd.Text(rawCommand)
cmd.ImplicitOutputs(task.out)
cmd.Implicits(task.in)
- cmd.Implicits(g.deps)
- cmd.Implicits(task.extraTools)
+ cmd.ImplicitTools(tools)
+ cmd.ImplicitTools(task.extraTools)
+ cmd.ImplicitPackagedTools(packagedTools)
if Bool(g.properties.Depfile) {
cmd.ImplicitDepFile(task.depFile)
}
@@ -619,7 +640,7 @@
// TODO(ccross): this RuleBuilder is a hack to be able to call
// rule.Command().PathForOutput. Replace this with passing the rule into the
// generator.
- rule := android.NewRuleBuilder(pctx, ctx).Sbox(genDir, nil)
+ rule := android.NewRuleBuilder(pctx, ctx).Sbox(genDir, nil).SandboxTools()
for _, in := range shard {
outFile := android.GenPathWithExt(ctx, finalSubDir, in, String(properties.Output_extension))
@@ -672,7 +693,8 @@
outputDepfile = android.PathForModuleGen(ctx, genSubDir, "gensrcs.d")
depFixerTool := ctx.Config().HostToolPath(ctx, "dep_fixer")
fullCommand += fmt.Sprintf(" && %s -o $(depfile) %s",
- depFixerTool.String(), strings.Join(commandDepFiles, " "))
+ android.SboxPathForTool(ctx, depFixerTool),
+ strings.Join(commandDepFiles, " "))
extraTools = append(extraTools, depFixerTool)
}
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 6ae9a18..2f5605e 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -141,7 +141,7 @@
out: ["out"],
cmd: "$(location) > $(out)",
`,
- expect: "out/tool > __SBOX_SANDBOX_DIR__/out/out",
+ expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
},
{
name: "empty location tool2",
@@ -150,7 +150,7 @@
out: ["out"],
cmd: "$(location) > $(out)",
`,
- expect: "out/tool > __SBOX_SANDBOX_DIR__/out/out",
+ expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
},
{
name: "empty location tool file",
@@ -159,7 +159,7 @@
out: ["out"],
cmd: "$(location) > $(out)",
`,
- expect: "tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
+ expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
},
{
name: "empty location tool file fg",
@@ -168,7 +168,7 @@
out: ["out"],
cmd: "$(location) > $(out)",
`,
- expect: "tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
+ expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
},
{
name: "empty location tool and tool file",
@@ -178,7 +178,7 @@
out: ["out"],
cmd: "$(location) > $(out)",
`,
- expect: "out/tool > __SBOX_SANDBOX_DIR__/out/out",
+ expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
},
{
name: "tool",
@@ -187,7 +187,7 @@
out: ["out"],
cmd: "$(location tool) > $(out)",
`,
- expect: "out/tool > __SBOX_SANDBOX_DIR__/out/out",
+ expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
},
{
name: "tool2",
@@ -196,7 +196,7 @@
out: ["out"],
cmd: "$(location :tool) > $(out)",
`,
- expect: "out/tool > __SBOX_SANDBOX_DIR__/out/out",
+ expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
},
{
name: "tool file",
@@ -205,7 +205,7 @@
out: ["out"],
cmd: "$(location tool_file1) > $(out)",
`,
- expect: "tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
+ expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
},
{
name: "tool file fg",
@@ -214,7 +214,7 @@
out: ["out"],
cmd: "$(location :1tool_file) > $(out)",
`,
- expect: "tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
+ expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
},
{
name: "tool files",
@@ -223,7 +223,7 @@
out: ["out"],
cmd: "$(locations :tool_files) > $(out)",
`,
- expect: "tool_file1 tool_file2 > __SBOX_SANDBOX_DIR__/out/out",
+ expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 __SBOX_SANDBOX_DIR__/tools/src/tool_file2 > __SBOX_SANDBOX_DIR__/out/out",
},
{
name: "in1",
@@ -600,7 +600,7 @@
cmd: "$(location) $(in) > $(out)",
`,
cmds: []string{
- "bash -c 'out/tool in1.txt > __SBOX_SANDBOX_DIR__/out/in1.h' && bash -c 'out/tool in2.txt > __SBOX_SANDBOX_DIR__/out/in2.h'",
+ "bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in1.txt > __SBOX_SANDBOX_DIR__/out/in1.h' && bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in2.txt > __SBOX_SANDBOX_DIR__/out/in2.h'",
},
deps: []string{buildDir + "/.intermediates/gen/gen/gensrcs/in1.h", buildDir + "/.intermediates/gen/gen/gensrcs/in2.h"},
files: []string{buildDir + "/.intermediates/gen/gen/gensrcs/in1.h", buildDir + "/.intermediates/gen/gen/gensrcs/in2.h"},
@@ -614,8 +614,8 @@
shard_size: 2,
`,
cmds: []string{
- "bash -c 'out/tool in1.txt > __SBOX_SANDBOX_DIR__/out/in1.h' && bash -c 'out/tool in2.txt > __SBOX_SANDBOX_DIR__/out/in2.h'",
- "bash -c 'out/tool in3.txt > __SBOX_SANDBOX_DIR__/out/in3.h'",
+ "bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in1.txt > __SBOX_SANDBOX_DIR__/out/in1.h' && bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in2.txt > __SBOX_SANDBOX_DIR__/out/in2.h'",
+ "bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in3.txt > __SBOX_SANDBOX_DIR__/out/in3.h'",
},
deps: []string{buildDir + "/.intermediates/gen/gen/gensrcs/in1.h", buildDir + "/.intermediates/gen/gen/gensrcs/in2.h", buildDir + "/.intermediates/gen/gen/gensrcs/in3.h"},
files: []string{buildDir + "/.intermediates/gen/gen/gensrcs/in1.h", buildDir + "/.intermediates/gen/gen/gensrcs/in2.h", buildDir + "/.intermediates/gen/gen/gensrcs/in3.h"},
@@ -758,7 +758,7 @@
}
func (t *testTool) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- t.outputFile = android.PathForTesting("out", ctx.ModuleName())
+ t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName()))
}
func (t *testTool) HostToolPath() android.OptionalPath {
diff --git a/java/Android.bp b/java/Android.bp
index 39502b3..9c28968 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -22,6 +22,8 @@
"androidmk.go",
"app_builder.go",
"app.go",
+ "app_import.go",
+ "app_set.go",
"boot_jars.go",
"builder.go",
"device_host_converter.go",
@@ -46,6 +48,7 @@
"prebuilt_apis.go",
"proto.go",
"robolectric.go",
+ "rro.go",
"sdk.go",
"sdk_library.go",
"sdk_library_external.go",
@@ -57,6 +60,8 @@
],
testSrcs: [
"androidmk_test.go",
+ "app_import_test.go",
+ "app_set_test.go",
"app_test.go",
"device_host_converter_test.go",
"dexpreopt_test.go",
@@ -66,6 +71,7 @@
"jdeps_test.go",
"kotlin_test.go",
"plugin_test.go",
+ "rro_test.go",
"sdk_test.go",
],
pluginFor: ["soong_build"],
diff --git a/java/aar.go b/java/aar.go
index dfcd956..e3ad252 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -416,7 +416,6 @@
}
ctx.VisitDirectDeps(func(module android.Module) {
- depName := ctx.OtherModuleName(module)
depTag := ctx.OtherModuleDependencyTag(module)
var exportPackage android.Path
@@ -432,15 +431,6 @@
if exportPackage != nil {
sharedLibs = append(sharedLibs, exportPackage)
}
-
- // If the module is (or possibly could be) a component of a java_sdk_library
- // (including the java_sdk_library) itself then append any implicit sdk library
- // names to the list of sdk libraries to be added to the manifest.
- if component, ok := module.(SdkLibraryComponentDependency); ok {
- classLoaderContexts.MaybeAddContext(ctx, component.OptionalImplicitSdkLibrary(),
- component.DexJarBuildPath(), component.DexJarInstallPath())
- }
-
case frameworkResTag:
if exportPackage != nil {
sharedLibs = append(sharedLibs, exportPackage)
@@ -468,8 +458,7 @@
}
}
- // Merge dep's CLC after processing the dep itself (which may add its own <uses-library>).
- maybeAddCLCFromDep(module, depTag, depName, classLoaderContexts)
+ addCLCFromDep(ctx, module, classLoaderContexts)
})
deps = append(deps, sharedLibs...)
diff --git a/java/app.go b/java/app.go
index c0ac9c2..249313c 100755
--- a/java/app.go
+++ b/java/app.go
@@ -14,13 +14,12 @@
package java
-// This file contains the module types for compiling Android apps.
+// This file contains the module implementations for android_app, android_test, and some more
+// related module types, including their override variants.
import (
"path/filepath"
- "reflect"
"sort"
- "strconv"
"strings"
"github.com/google/blueprint"
@@ -32,12 +31,8 @@
"android/soong/tradefed"
)
-var supportedDpis = []string{"ldpi", "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"}
-
func init() {
RegisterAppBuildComponents(android.InitRegistrationContext)
-
- initAndroidAppImportVariantGroupTypes()
}
func RegisterAppBuildComponents(ctx android.RegistrationContext) {
@@ -47,139 +42,6 @@
ctx.RegisterModuleType("android_app_certificate", AndroidAppCertificateFactory)
ctx.RegisterModuleType("override_android_app", OverrideAndroidAppModuleFactory)
ctx.RegisterModuleType("override_android_test", OverrideAndroidTestModuleFactory)
- ctx.RegisterModuleType("override_runtime_resource_overlay", OverrideRuntimeResourceOverlayModuleFactory)
- ctx.RegisterModuleType("android_app_import", AndroidAppImportFactory)
- ctx.RegisterModuleType("android_test_import", AndroidTestImportFactory)
- ctx.RegisterModuleType("runtime_resource_overlay", RuntimeResourceOverlayFactory)
- ctx.RegisterModuleType("android_app_set", AndroidApkSetFactory)
-}
-
-type AndroidAppSetProperties struct {
- // APK Set path
- Set *string
-
- // Specifies that this app should be installed to the priv-app directory,
- // where the system will grant it additional privileges not available to
- // normal apps.
- Privileged *bool
-
- // APKs in this set use prerelease SDK version
- Prerelease *bool
-
- // Names of modules to be overridden. Listed modules can only be other apps
- // (in Make or Soong).
- Overrides []string
-}
-
-type AndroidAppSet struct {
- android.ModuleBase
- android.DefaultableModuleBase
- prebuilt android.Prebuilt
-
- properties AndroidAppSetProperties
- packedOutput android.WritablePath
- installFile string
- apkcertsFile android.ModuleOutPath
-}
-
-func (as *AndroidAppSet) Name() string {
- return as.prebuilt.Name(as.ModuleBase.Name())
-}
-
-func (as *AndroidAppSet) IsInstallable() bool {
- return true
-}
-
-func (as *AndroidAppSet) Prebuilt() *android.Prebuilt {
- return &as.prebuilt
-}
-
-func (as *AndroidAppSet) Privileged() bool {
- return Bool(as.properties.Privileged)
-}
-
-func (as *AndroidAppSet) OutputFile() android.Path {
- return as.packedOutput
-}
-
-func (as *AndroidAppSet) InstallFile() string {
- return as.installFile
-}
-
-func (as *AndroidAppSet) APKCertsFile() android.Path {
- return as.apkcertsFile
-}
-
-var TargetCpuAbi = map[string]string{
- "arm": "ARMEABI_V7A",
- "arm64": "ARM64_V8A",
- "x86": "X86",
- "x86_64": "X86_64",
-}
-
-func SupportedAbis(ctx android.ModuleContext) []string {
- abiName := func(targetIdx int, deviceArch string) string {
- if abi, found := TargetCpuAbi[deviceArch]; found {
- return abi
- }
- ctx.ModuleErrorf("Target %d has invalid Arch: %s", targetIdx, deviceArch)
- return "BAD_ABI"
- }
-
- var result []string
- for i, target := range ctx.Config().Targets[android.Android] {
- result = append(result, abiName(i, target.Arch.ArchType.String()))
- }
- return result
-}
-
-func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- as.packedOutput = android.PathForModuleOut(ctx, ctx.ModuleName()+".zip")
- as.apkcertsFile = android.PathForModuleOut(ctx, "apkcerts.txt")
- // We are assuming here that the install file in the APK
- // set has `.apk` suffix. If it doesn't the build will fail.
- // APK sets containing APEX files are handled elsewhere.
- as.installFile = as.BaseModuleName() + ".apk"
- screenDensities := "all"
- if dpis := ctx.Config().ProductAAPTPrebuiltDPI(); len(dpis) > 0 {
- screenDensities = strings.ToUpper(strings.Join(dpis, ","))
- }
- // TODO(asmundak): handle locales.
- // TODO(asmundak): do we support device features
- ctx.Build(pctx,
- android.BuildParams{
- Rule: extractMatchingApks,
- Description: "Extract APKs from APK set",
- Output: as.packedOutput,
- ImplicitOutput: as.apkcertsFile,
- Inputs: android.Paths{as.prebuilt.SingleSourcePath(ctx)},
- Args: map[string]string{
- "abis": strings.Join(SupportedAbis(ctx), ","),
- "allow-prereleased": strconv.FormatBool(proptools.Bool(as.properties.Prerelease)),
- "screen-densities": screenDensities,
- "sdk-version": ctx.Config().PlatformSdkVersion().String(),
- "stem": as.BaseModuleName(),
- "apkcerts": as.apkcertsFile.String(),
- "partition": as.PartitionTag(ctx.DeviceConfig()),
- },
- })
-}
-
-// android_app_set extracts a set of APKs based on the target device
-// configuration and installs this set as "split APKs".
-// The extracted set always contains an APK whose name is
-// _module_name_.apk and every split APK matching target device.
-// The extraction of the density-specific splits depends on
-// PRODUCT_AAPT_PREBUILT_DPI variable. If present (its value should
-// be a list density names: LDPI, MDPI, HDPI, etc.), only listed
-// splits will be extracted. Otherwise all density-specific splits
-// will be extracted.
-func AndroidApkSetFactory() android.Module {
- module := &AndroidAppSet{}
- module.AddProperties(&module.properties)
- InitJavaModule(module, android.DeviceSupported)
- android.InitSingleSourcePrebuiltModule(module, &module.properties, "Set")
- return module
}
// AndroidManifest.xml merging
@@ -273,15 +135,6 @@
Rename_resources_package *bool
}
-// runtime_resource_overlay properties that can be overridden by override_runtime_resource_overlay
-type OverridableRuntimeResourceOverlayProperties struct {
- // the package name of this app. The package name in the manifest file is used if one was not given.
- Package_name *string
-
- // the target package name of this overlay app. The target package name in the manifest file is used if one was not given.
- Target_package_name *string
-}
-
type AndroidApp struct {
Library
aapt
@@ -1298,629 +1151,6 @@
return m
}
-type OverrideRuntimeResourceOverlay struct {
- android.ModuleBase
- android.OverrideModuleBase
-}
-
-func (i *OverrideRuntimeResourceOverlay) GenerateAndroidBuildActions(_ android.ModuleContext) {
- // All the overrides happen in the base module.
- // TODO(jungjw): Check the base module type.
-}
-
-// override_runtime_resource_overlay is used to create a module based on another
-// runtime_resource_overlay module by overriding some of its properties.
-func OverrideRuntimeResourceOverlayModuleFactory() android.Module {
- m := &OverrideRuntimeResourceOverlay{}
- m.AddProperties(&OverridableRuntimeResourceOverlayProperties{})
-
- android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibCommon)
- android.InitOverrideModule(m)
- return m
-}
-
-type AndroidAppImport struct {
- android.ModuleBase
- android.DefaultableModuleBase
- android.ApexModuleBase
- prebuilt android.Prebuilt
-
- properties AndroidAppImportProperties
- dpiVariants interface{}
- archVariants interface{}
-
- outputFile android.Path
- certificate Certificate
-
- dexpreopter
-
- usesLibrary usesLibrary
-
- preprocessed bool
-
- installPath android.InstallPath
-
- hideApexVariantFromMake bool
-}
-
-type AndroidAppImportProperties struct {
- // A prebuilt apk to import
- Apk *string
-
- // The name of a certificate in the default certificate directory or an android_app_certificate
- // module name in the form ":module". Should be empty if presigned or default_dev_cert is set.
- Certificate *string
-
- // Set this flag to true if the prebuilt apk is already signed. The certificate property must not
- // be set for presigned modules.
- Presigned *bool
-
- // Name of the signing certificate lineage file.
- Lineage *string
-
- // Sign with the default system dev certificate. Must be used judiciously. Most imported apps
- // need to either specify a specific certificate or be presigned.
- Default_dev_cert *bool
-
- // Specifies that this app should be installed to the priv-app directory,
- // where the system will grant it additional privileges not available to
- // normal apps.
- Privileged *bool
-
- // Names of modules to be overridden. Listed modules can only be other binaries
- // (in Make or Soong).
- // This does not completely prevent installation of the overridden binaries, but if both
- // binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
- // from PRODUCT_PACKAGES.
- Overrides []string
-
- // Optional name for the installed app. If unspecified, it is derived from the module name.
- Filename *string
-}
-
-func (a *AndroidAppImport) IsInstallable() bool {
- return true
-}
-
-// Updates properties with variant-specific values.
-func (a *AndroidAppImport) processVariants(ctx android.LoadHookContext) {
- config := ctx.Config()
-
- dpiProps := reflect.ValueOf(a.dpiVariants).Elem().FieldByName("Dpi_variants")
- // Try DPI variant matches in the reverse-priority order so that the highest priority match
- // overwrites everything else.
- // TODO(jungjw): Can we optimize this by making it priority order?
- for i := len(config.ProductAAPTPrebuiltDPI()) - 1; i >= 0; i-- {
- MergePropertiesFromVariant(ctx, &a.properties, dpiProps, config.ProductAAPTPrebuiltDPI()[i])
- }
- if config.ProductAAPTPreferredConfig() != "" {
- MergePropertiesFromVariant(ctx, &a.properties, dpiProps, config.ProductAAPTPreferredConfig())
- }
-
- archProps := reflect.ValueOf(a.archVariants).Elem().FieldByName("Arch")
- archType := ctx.Config().AndroidFirstDeviceTarget.Arch.ArchType
- MergePropertiesFromVariant(ctx, &a.properties, archProps, archType.Name)
-
- if String(a.properties.Apk) == "" {
- // Disable this module since the apk property is still empty after processing all matching
- // variants. This likely means there is no matching variant, and the default variant doesn't
- // have an apk property value either.
- a.Disable()
- }
-}
-
-func MergePropertiesFromVariant(ctx android.EarlyModuleContext,
- dst interface{}, variantGroup reflect.Value, variant string) {
- src := variantGroup.FieldByName(proptools.FieldNameForProperty(variant))
- if !src.IsValid() {
- return
- }
-
- err := proptools.ExtendMatchingProperties([]interface{}{dst}, src.Interface(), nil, proptools.OrderAppend)
- if err != nil {
- if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
- ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
- } else {
- panic(err)
- }
- }
-}
-
-func (a *AndroidAppImport) DepsMutator(ctx android.BottomUpMutatorContext) {
- cert := android.SrcIsModule(String(a.properties.Certificate))
- if cert != "" {
- ctx.AddDependency(ctx.Module(), certificateTag, cert)
- }
-
- a.usesLibrary.deps(ctx, true)
-}
-
-func (a *AndroidAppImport) uncompressEmbeddedJniLibs(
- ctx android.ModuleContext, inputPath android.Path, outputPath android.OutputPath) {
- // Test apps don't need their JNI libraries stored uncompressed. As a matter of fact, messing
- // with them may invalidate pre-existing signature data.
- if ctx.InstallInTestcases() && (Bool(a.properties.Presigned) || a.preprocessed) {
- ctx.Build(pctx, android.BuildParams{
- Rule: android.Cp,
- Output: outputPath,
- Input: inputPath,
- })
- return
- }
- rule := android.NewRuleBuilder(pctx, ctx)
- rule.Command().
- Textf(`if (zipinfo %s 'lib/*.so' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath).
- BuiltTool("zip2zip").
- FlagWithInput("-i ", inputPath).
- FlagWithOutput("-o ", outputPath).
- FlagWithArg("-0 ", "'lib/**/*.so'").
- Textf(`; else cp -f %s %s; fi`, inputPath, outputPath)
- rule.Build("uncompress-embedded-jni-libs", "Uncompress embedded JIN libs")
-}
-
-// Returns whether this module should have the dex file stored uncompressed in the APK.
-func (a *AndroidAppImport) shouldUncompressDex(ctx android.ModuleContext) bool {
- if ctx.Config().UnbundledBuild() || a.preprocessed {
- return false
- }
-
- // Uncompress dex in APKs of privileged apps
- if ctx.Config().UncompressPrivAppDex() && a.Privileged() {
- return true
- }
-
- return shouldUncompressDex(ctx, &a.dexpreopter)
-}
-
-func (a *AndroidAppImport) uncompressDex(
- ctx android.ModuleContext, inputPath android.Path, outputPath android.OutputPath) {
- rule := android.NewRuleBuilder(pctx, ctx)
- rule.Command().
- Textf(`if (zipinfo %s '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath).
- BuiltTool("zip2zip").
- FlagWithInput("-i ", inputPath).
- FlagWithOutput("-o ", outputPath).
- FlagWithArg("-0 ", "'classes*.dex'").
- Textf(`; else cp -f %s %s; fi`, inputPath, outputPath)
- rule.Build("uncompress-dex", "Uncompress dex files")
-}
-
-func (a *AndroidAppImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- a.generateAndroidBuildActions(ctx)
-}
-
-func (a *AndroidAppImport) InstallApkName() string {
- return a.BaseModuleName()
-}
-
-func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext) {
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
- if !apexInfo.IsForPlatform() {
- a.hideApexVariantFromMake = true
- }
-
- numCertPropsSet := 0
- if String(a.properties.Certificate) != "" {
- numCertPropsSet++
- }
- if Bool(a.properties.Presigned) {
- numCertPropsSet++
- }
- if Bool(a.properties.Default_dev_cert) {
- numCertPropsSet++
- }
- if numCertPropsSet != 1 {
- ctx.ModuleErrorf("One and only one of certficate, presigned, and default_dev_cert properties must be set")
- }
-
- _, certificates := collectAppDeps(ctx, a, false, false)
-
- // TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK
- // TODO: LOCAL_PACKAGE_SPLITS
-
- srcApk := a.prebuilt.SingleSourcePath(ctx)
-
- if a.usesLibrary.enforceUsesLibraries() {
- srcApk = a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk)
- }
-
- // TODO: Install or embed JNI libraries
-
- // Uncompress JNI libraries in the apk
- jnisUncompressed := android.PathForModuleOut(ctx, "jnis-uncompressed", ctx.ModuleName()+".apk")
- a.uncompressEmbeddedJniLibs(ctx, srcApk, jnisUncompressed.OutputPath)
-
- var installDir android.InstallPath
- if Bool(a.properties.Privileged) {
- installDir = android.PathForModuleInstall(ctx, "priv-app", a.BaseModuleName())
- } else if ctx.InstallInTestcases() {
- installDir = android.PathForModuleInstall(ctx, a.BaseModuleName(), ctx.DeviceConfig().DeviceArch())
- } else {
- installDir = android.PathForModuleInstall(ctx, "app", a.BaseModuleName())
- }
-
- a.dexpreopter.installPath = installDir.Join(ctx, a.BaseModuleName()+".apk")
- a.dexpreopter.isPresignedPrebuilt = Bool(a.properties.Presigned)
- a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
-
- a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
- a.dexpreopter.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
-
- dexOutput := a.dexpreopter.dexpreopt(ctx, jnisUncompressed)
- if a.dexpreopter.uncompressedDex {
- dexUncompressed := android.PathForModuleOut(ctx, "dex-uncompressed", ctx.ModuleName()+".apk")
- a.uncompressDex(ctx, dexOutput, dexUncompressed.OutputPath)
- dexOutput = dexUncompressed
- }
-
- apkFilename := proptools.StringDefault(a.properties.Filename, a.BaseModuleName()+".apk")
-
- // TODO: Handle EXTERNAL
-
- // Sign or align the package if package has not been preprocessed
- if a.preprocessed {
- a.outputFile = srcApk
- a.certificate = PresignedCertificate
- } else if !Bool(a.properties.Presigned) {
- // If the certificate property is empty at this point, default_dev_cert must be set to true.
- // Which makes processMainCert's behavior for the empty cert string WAI.
- certificates = processMainCert(a.ModuleBase, String(a.properties.Certificate), certificates, ctx)
- if len(certificates) != 1 {
- ctx.ModuleErrorf("Unexpected number of certificates were extracted: %q", certificates)
- }
- a.certificate = certificates[0]
- signed := android.PathForModuleOut(ctx, "signed", apkFilename)
- var lineageFile android.Path
- if lineage := String(a.properties.Lineage); lineage != "" {
- lineageFile = android.PathForModuleSrc(ctx, lineage)
- }
- SignAppPackage(ctx, signed, dexOutput, certificates, nil, lineageFile)
- a.outputFile = signed
- } else {
- alignedApk := android.PathForModuleOut(ctx, "zip-aligned", apkFilename)
- TransformZipAlign(ctx, alignedApk, dexOutput)
- a.outputFile = alignedApk
- a.certificate = PresignedCertificate
- }
-
- // TODO: Optionally compress the output apk.
-
- if apexInfo.IsForPlatform() {
- a.installPath = ctx.InstallFile(installDir, apkFilename, a.outputFile)
- }
-
- // TODO: androidmk converter jni libs
-}
-
-func (a *AndroidAppImport) Prebuilt() *android.Prebuilt {
- return &a.prebuilt
-}
-
-func (a *AndroidAppImport) Name() string {
- return a.prebuilt.Name(a.ModuleBase.Name())
-}
-
-func (a *AndroidAppImport) OutputFile() android.Path {
- return a.outputFile
-}
-
-func (a *AndroidAppImport) JacocoReportClassesFile() android.Path {
- return nil
-}
-
-func (a *AndroidAppImport) Certificate() Certificate {
- return a.certificate
-}
-
-var dpiVariantGroupType reflect.Type
-var archVariantGroupType reflect.Type
-
-func initAndroidAppImportVariantGroupTypes() {
- dpiVariantGroupType = createVariantGroupType(supportedDpis, "Dpi_variants")
-
- archNames := make([]string, len(android.ArchTypeList()))
- for i, archType := range android.ArchTypeList() {
- archNames[i] = archType.Name
- }
- archVariantGroupType = createVariantGroupType(archNames, "Arch")
-}
-
-// Populates all variant struct properties at creation time.
-func (a *AndroidAppImport) populateAllVariantStructs() {
- a.dpiVariants = reflect.New(dpiVariantGroupType).Interface()
- a.AddProperties(a.dpiVariants)
-
- a.archVariants = reflect.New(archVariantGroupType).Interface()
- a.AddProperties(a.archVariants)
-}
-
-func (a *AndroidAppImport) Privileged() bool {
- return Bool(a.properties.Privileged)
-}
-
-func (a *AndroidAppImport) DepIsInSameApex(_ android.BaseModuleContext, _ android.Module) bool {
- // android_app_import might have extra dependencies via uses_libs property.
- // Don't track the dependency as we don't automatically add those libraries
- // to the classpath. It should be explicitly added to java_libs property of APEX
- return false
-}
-
-func (a *AndroidAppImport) sdkVersion() sdkSpec {
- return sdkSpecFrom("")
-}
-
-func (a *AndroidAppImport) minSdkVersion() sdkSpec {
- return sdkSpecFrom("")
-}
-
-var _ android.ApexModule = (*AndroidAppImport)(nil)
-
-// Implements android.ApexModule
-func (j *AndroidAppImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
- sdkVersion android.ApiLevel) error {
- // Do not check for prebuilts against the min_sdk_version of enclosing APEX
- return nil
-}
-
-func createVariantGroupType(variants []string, variantGroupName string) reflect.Type {
- props := reflect.TypeOf((*AndroidAppImportProperties)(nil))
-
- variantFields := make([]reflect.StructField, len(variants))
- for i, variant := range variants {
- variantFields[i] = reflect.StructField{
- Name: proptools.FieldNameForProperty(variant),
- Type: props,
- }
- }
-
- variantGroupStruct := reflect.StructOf(variantFields)
- return reflect.StructOf([]reflect.StructField{
- {
- Name: variantGroupName,
- Type: variantGroupStruct,
- },
- })
-}
-
-// android_app_import imports a prebuilt apk with additional processing specified in the module.
-// DPI-specific apk source files can be specified using dpi_variants. Example:
-//
-// android_app_import {
-// name: "example_import",
-// apk: "prebuilts/example.apk",
-// dpi_variants: {
-// mdpi: {
-// apk: "prebuilts/example_mdpi.apk",
-// },
-// xhdpi: {
-// apk: "prebuilts/example_xhdpi.apk",
-// },
-// },
-// certificate: "PRESIGNED",
-// }
-func AndroidAppImportFactory() android.Module {
- module := &AndroidAppImport{}
- module.AddProperties(&module.properties)
- module.AddProperties(&module.dexpreoptProperties)
- module.AddProperties(&module.usesLibrary.usesLibraryProperties)
- module.populateAllVariantStructs()
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
- module.processVariants(ctx)
- })
-
- android.InitApexModule(module)
- android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
- android.InitDefaultableModule(module)
- android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk")
-
- return module
-}
-
-type androidTestImportProperties struct {
- // Whether the prebuilt apk can be installed without additional processing. Default is false.
- Preprocessed *bool
-}
-
-type AndroidTestImport struct {
- AndroidAppImport
-
- testProperties testProperties
-
- testImportProperties androidTestImportProperties
-
- data android.Paths
-}
-
-func (a *AndroidTestImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- a.preprocessed = Bool(a.testImportProperties.Preprocessed)
-
- a.generateAndroidBuildActions(ctx)
-
- a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data)
-}
-
-func (a *AndroidTestImport) InstallInTestcases() bool {
- return true
-}
-
-// android_test_import imports a prebuilt test apk with additional processing specified in the
-// module. DPI or arch variant configurations can be made as with android_app_import.
-func AndroidTestImportFactory() android.Module {
- module := &AndroidTestImport{}
- module.AddProperties(&module.properties)
- module.AddProperties(&module.dexpreoptProperties)
- module.AddProperties(&module.testProperties)
- module.AddProperties(&module.testImportProperties)
- module.populateAllVariantStructs()
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
- module.processVariants(ctx)
- })
-
- module.dexpreopter.isTest = true
-
- android.InitApexModule(module)
- android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
- android.InitDefaultableModule(module)
- android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk")
-
- return module
-}
-
-type RuntimeResourceOverlay struct {
- android.ModuleBase
- android.DefaultableModuleBase
- android.OverridableModuleBase
- aapt
-
- properties RuntimeResourceOverlayProperties
- overridableProperties OverridableRuntimeResourceOverlayProperties
-
- certificate Certificate
-
- outputFile android.Path
- installDir android.InstallPath
-}
-
-type RuntimeResourceOverlayProperties struct {
- // the name of a certificate in the default certificate directory or an android_app_certificate
- // module name in the form ":module".
- Certificate *string
-
- // Name of the signing certificate lineage file.
- Lineage *string
-
- // optional theme name. If specified, the overlay package will be applied
- // only when the ro.boot.vendor.overlay.theme system property is set to the same value.
- Theme *string
-
- // if not blank, set to the version of the sdk to compile against.
- // Defaults to compiling against the current platform.
- Sdk_version *string
-
- // if not blank, set the minimum version of the sdk that the compiled artifacts will run against.
- // Defaults to sdk_version if not set.
- Min_sdk_version *string
-
- // list of android_library modules whose resources are extracted and linked against statically
- Static_libs []string
-
- // list of android_app modules whose resources are extracted and linked against
- Resource_libs []string
-
- // Names of modules to be overridden. Listed modules can only be other overlays
- // (in Make or Soong).
- // This does not completely prevent installation of the overridden overlays, but if both
- // overlays would be installed by default (in PRODUCT_PACKAGES) the other overlay will be removed
- // from PRODUCT_PACKAGES.
- Overrides []string
-}
-
-// RuntimeResourceOverlayModule interface is used by the apex package to gather information from
-// a RuntimeResourceOverlay module.
-type RuntimeResourceOverlayModule interface {
- android.Module
- OutputFile() android.Path
- Certificate() Certificate
- Theme() string
-}
-
-func (r *RuntimeResourceOverlay) DepsMutator(ctx android.BottomUpMutatorContext) {
- sdkDep := decodeSdkDep(ctx, sdkContext(r))
- if sdkDep.hasFrameworkLibs() {
- r.aapt.deps(ctx, sdkDep)
- }
-
- cert := android.SrcIsModule(String(r.properties.Certificate))
- if cert != "" {
- ctx.AddDependency(ctx.Module(), certificateTag, cert)
- }
-
- ctx.AddVariationDependencies(nil, staticLibTag, r.properties.Static_libs...)
- ctx.AddVariationDependencies(nil, libTag, r.properties.Resource_libs...)
-}
-
-func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- // Compile and link resources
- r.aapt.hasNoCode = true
- // Do not remove resources without default values nor dedupe resource configurations with the same value
- aaptLinkFlags := []string{"--no-resource-deduping", "--no-resource-removal"}
- // Allow the override of "package name" and "overlay target package name"
- manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(ctx.ModuleName())
- if overridden || r.overridableProperties.Package_name != nil {
- // The product override variable has a priority over the package_name property.
- if !overridden {
- manifestPackageName = *r.overridableProperties.Package_name
- }
- aaptLinkFlags = append(aaptLinkFlags, generateAaptRenamePackageFlags(manifestPackageName, false)...)
- }
- if r.overridableProperties.Target_package_name != nil {
- aaptLinkFlags = append(aaptLinkFlags,
- "--rename-overlay-target-package "+*r.overridableProperties.Target_package_name)
- }
- r.aapt.buildActions(ctx, r, nil, aaptLinkFlags...)
-
- // Sign the built package
- _, certificates := collectAppDeps(ctx, r, false, false)
- certificates = processMainCert(r.ModuleBase, String(r.properties.Certificate), certificates, ctx)
- signed := android.PathForModuleOut(ctx, "signed", r.Name()+".apk")
- var lineageFile android.Path
- if lineage := String(r.properties.Lineage); lineage != "" {
- lineageFile = android.PathForModuleSrc(ctx, lineage)
- }
- SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates, nil, lineageFile)
- r.certificate = certificates[0]
-
- r.outputFile = signed
- r.installDir = android.PathForModuleInstall(ctx, "overlay", String(r.properties.Theme))
- ctx.InstallFile(r.installDir, r.outputFile.Base(), r.outputFile)
-}
-
-func (r *RuntimeResourceOverlay) sdkVersion() sdkSpec {
- return sdkSpecFrom(String(r.properties.Sdk_version))
-}
-
-func (r *RuntimeResourceOverlay) systemModules() string {
- return ""
-}
-
-func (r *RuntimeResourceOverlay) minSdkVersion() sdkSpec {
- if r.properties.Min_sdk_version != nil {
- return sdkSpecFrom(*r.properties.Min_sdk_version)
- }
- return r.sdkVersion()
-}
-
-func (r *RuntimeResourceOverlay) targetSdkVersion() sdkSpec {
- return r.sdkVersion()
-}
-
-func (r *RuntimeResourceOverlay) Certificate() Certificate {
- return r.certificate
-}
-
-func (r *RuntimeResourceOverlay) OutputFile() android.Path {
- return r.outputFile
-}
-
-func (r *RuntimeResourceOverlay) Theme() string {
- return String(r.properties.Theme)
-}
-
-// runtime_resource_overlay generates a resource-only apk file that can overlay application and
-// system resources at run time.
-func RuntimeResourceOverlayFactory() android.Module {
- module := &RuntimeResourceOverlay{}
- module.AddProperties(
- &module.properties,
- &module.aaptProperties,
- &module.overridableProperties)
-
- android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
- android.InitDefaultableModule(module)
- android.InitOverridableModule(module, &module.properties.Overrides)
- return module
-}
-
type UsesLibraryProperties struct {
// A list of shared library modules that will be listed in uses-library tags in the AndroidManifest.xml file.
Uses_libs []string
@@ -1990,7 +1220,7 @@
ctx.VisitDirectDeps(func(m android.Module) {
if tag, ok := ctx.OtherModuleDependencyTag(m).(usesLibraryDependencyTag); ok {
dep := ctx.OtherModuleName(m)
- if lib, ok := m.(Dependency); ok {
+ if lib, ok := m.(UsesLibraryDependency); ok {
clcMap.AddContextForSdk(ctx, tag.sdkVersion, dep,
lib.DexJarBuildPath(), lib.DexJarInstallPath(), lib.ClassLoaderContexts())
} else if ctx.Config().AllowMissingDependencies() {
diff --git a/java/app_import.go b/java/app_import.go
new file mode 100644
index 0000000..2054785
--- /dev/null
+++ b/java/app_import.go
@@ -0,0 +1,484 @@
+// Copyright 2020 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
+
+// This file contains the module implementations for android_app_import and android_test_import.
+
+import (
+ "reflect"
+
+ "github.com/google/blueprint/proptools"
+
+ "android/soong/android"
+)
+
+func init() {
+ RegisterAppImportBuildComponents(android.InitRegistrationContext)
+
+ initAndroidAppImportVariantGroupTypes()
+}
+
+func RegisterAppImportBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("android_app_import", AndroidAppImportFactory)
+ ctx.RegisterModuleType("android_test_import", AndroidTestImportFactory)
+}
+
+type AndroidAppImport struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+ android.ApexModuleBase
+ prebuilt android.Prebuilt
+
+ properties AndroidAppImportProperties
+ dpiVariants interface{}
+ archVariants interface{}
+
+ outputFile android.Path
+ certificate Certificate
+
+ dexpreopter
+
+ usesLibrary usesLibrary
+
+ preprocessed bool
+
+ installPath android.InstallPath
+
+ hideApexVariantFromMake bool
+}
+
+type AndroidAppImportProperties struct {
+ // A prebuilt apk to import
+ Apk *string
+
+ // The name of a certificate in the default certificate directory or an android_app_certificate
+ // module name in the form ":module". Should be empty if presigned or default_dev_cert is set.
+ Certificate *string
+
+ // Set this flag to true if the prebuilt apk is already signed. The certificate property must not
+ // be set for presigned modules.
+ Presigned *bool
+
+ // Name of the signing certificate lineage file.
+ Lineage *string
+
+ // Sign with the default system dev certificate. Must be used judiciously. Most imported apps
+ // need to either specify a specific certificate or be presigned.
+ Default_dev_cert *bool
+
+ // Specifies that this app should be installed to the priv-app directory,
+ // where the system will grant it additional privileges not available to
+ // normal apps.
+ Privileged *bool
+
+ // Names of modules to be overridden. Listed modules can only be other binaries
+ // (in Make or Soong).
+ // This does not completely prevent installation of the overridden binaries, but if both
+ // binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
+ // from PRODUCT_PACKAGES.
+ Overrides []string
+
+ // Optional name for the installed app. If unspecified, it is derived from the module name.
+ Filename *string
+}
+
+func (a *AndroidAppImport) IsInstallable() bool {
+ return true
+}
+
+// Updates properties with variant-specific values.
+func (a *AndroidAppImport) processVariants(ctx android.LoadHookContext) {
+ config := ctx.Config()
+
+ dpiProps := reflect.ValueOf(a.dpiVariants).Elem().FieldByName("Dpi_variants")
+ // Try DPI variant matches in the reverse-priority order so that the highest priority match
+ // overwrites everything else.
+ // TODO(jungjw): Can we optimize this by making it priority order?
+ for i := len(config.ProductAAPTPrebuiltDPI()) - 1; i >= 0; i-- {
+ MergePropertiesFromVariant(ctx, &a.properties, dpiProps, config.ProductAAPTPrebuiltDPI()[i])
+ }
+ if config.ProductAAPTPreferredConfig() != "" {
+ MergePropertiesFromVariant(ctx, &a.properties, dpiProps, config.ProductAAPTPreferredConfig())
+ }
+
+ archProps := reflect.ValueOf(a.archVariants).Elem().FieldByName("Arch")
+ archType := ctx.Config().AndroidFirstDeviceTarget.Arch.ArchType
+ MergePropertiesFromVariant(ctx, &a.properties, archProps, archType.Name)
+
+ if String(a.properties.Apk) == "" {
+ // Disable this module since the apk property is still empty after processing all matching
+ // variants. This likely means there is no matching variant, and the default variant doesn't
+ // have an apk property value either.
+ a.Disable()
+ }
+}
+
+func MergePropertiesFromVariant(ctx android.EarlyModuleContext,
+ dst interface{}, variantGroup reflect.Value, variant string) {
+ src := variantGroup.FieldByName(proptools.FieldNameForProperty(variant))
+ if !src.IsValid() {
+ return
+ }
+
+ err := proptools.ExtendMatchingProperties([]interface{}{dst}, src.Interface(), nil, proptools.OrderAppend)
+ if err != nil {
+ if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
+ ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
+ } else {
+ panic(err)
+ }
+ }
+}
+
+func (a *AndroidAppImport) DepsMutator(ctx android.BottomUpMutatorContext) {
+ cert := android.SrcIsModule(String(a.properties.Certificate))
+ if cert != "" {
+ ctx.AddDependency(ctx.Module(), certificateTag, cert)
+ }
+
+ a.usesLibrary.deps(ctx, true)
+}
+
+func (a *AndroidAppImport) uncompressEmbeddedJniLibs(
+ ctx android.ModuleContext, inputPath android.Path, outputPath android.OutputPath) {
+ // Test apps don't need their JNI libraries stored uncompressed. As a matter of fact, messing
+ // with them may invalidate pre-existing signature data.
+ if ctx.InstallInTestcases() && (Bool(a.properties.Presigned) || a.preprocessed) {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Output: outputPath,
+ Input: inputPath,
+ })
+ return
+ }
+ rule := android.NewRuleBuilder(pctx, ctx)
+ rule.Command().
+ Textf(`if (zipinfo %s 'lib/*.so' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath).
+ BuiltTool("zip2zip").
+ FlagWithInput("-i ", inputPath).
+ FlagWithOutput("-o ", outputPath).
+ FlagWithArg("-0 ", "'lib/**/*.so'").
+ Textf(`; else cp -f %s %s; fi`, inputPath, outputPath)
+ rule.Build("uncompress-embedded-jni-libs", "Uncompress embedded JIN libs")
+}
+
+// Returns whether this module should have the dex file stored uncompressed in the APK.
+func (a *AndroidAppImport) shouldUncompressDex(ctx android.ModuleContext) bool {
+ if ctx.Config().UnbundledBuild() || a.preprocessed {
+ return false
+ }
+
+ // Uncompress dex in APKs of privileged apps
+ if ctx.Config().UncompressPrivAppDex() && a.Privileged() {
+ return true
+ }
+
+ return shouldUncompressDex(ctx, &a.dexpreopter)
+}
+
+func (a *AndroidAppImport) uncompressDex(
+ ctx android.ModuleContext, inputPath android.Path, outputPath android.OutputPath) {
+ rule := android.NewRuleBuilder(pctx, ctx)
+ rule.Command().
+ Textf(`if (zipinfo %s '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath).
+ BuiltTool("zip2zip").
+ FlagWithInput("-i ", inputPath).
+ FlagWithOutput("-o ", outputPath).
+ FlagWithArg("-0 ", "'classes*.dex'").
+ Textf(`; else cp -f %s %s; fi`, inputPath, outputPath)
+ rule.Build("uncompress-dex", "Uncompress dex files")
+}
+
+func (a *AndroidAppImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ a.generateAndroidBuildActions(ctx)
+}
+
+func (a *AndroidAppImport) InstallApkName() string {
+ return a.BaseModuleName()
+}
+
+func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext) {
+ apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ if !apexInfo.IsForPlatform() {
+ a.hideApexVariantFromMake = true
+ }
+
+ numCertPropsSet := 0
+ if String(a.properties.Certificate) != "" {
+ numCertPropsSet++
+ }
+ if Bool(a.properties.Presigned) {
+ numCertPropsSet++
+ }
+ if Bool(a.properties.Default_dev_cert) {
+ numCertPropsSet++
+ }
+ if numCertPropsSet != 1 {
+ ctx.ModuleErrorf("One and only one of certficate, presigned, and default_dev_cert properties must be set")
+ }
+
+ _, certificates := collectAppDeps(ctx, a, false, false)
+
+ // TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK
+ // TODO: LOCAL_PACKAGE_SPLITS
+
+ srcApk := a.prebuilt.SingleSourcePath(ctx)
+
+ if a.usesLibrary.enforceUsesLibraries() {
+ srcApk = a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk)
+ }
+
+ // TODO: Install or embed JNI libraries
+
+ // Uncompress JNI libraries in the apk
+ jnisUncompressed := android.PathForModuleOut(ctx, "jnis-uncompressed", ctx.ModuleName()+".apk")
+ a.uncompressEmbeddedJniLibs(ctx, srcApk, jnisUncompressed.OutputPath)
+
+ var installDir android.InstallPath
+ if Bool(a.properties.Privileged) {
+ installDir = android.PathForModuleInstall(ctx, "priv-app", a.BaseModuleName())
+ } else if ctx.InstallInTestcases() {
+ installDir = android.PathForModuleInstall(ctx, a.BaseModuleName(), ctx.DeviceConfig().DeviceArch())
+ } else {
+ installDir = android.PathForModuleInstall(ctx, "app", a.BaseModuleName())
+ }
+
+ a.dexpreopter.installPath = installDir.Join(ctx, a.BaseModuleName()+".apk")
+ a.dexpreopter.isPresignedPrebuilt = Bool(a.properties.Presigned)
+ a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
+
+ a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
+ a.dexpreopter.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
+
+ a.dexpreopter.dexpreopt(ctx, jnisUncompressed)
+ if a.dexpreopter.uncompressedDex {
+ dexUncompressed := android.PathForModuleOut(ctx, "dex-uncompressed", ctx.ModuleName()+".apk")
+ a.uncompressDex(ctx, jnisUncompressed, dexUncompressed.OutputPath)
+ jnisUncompressed = dexUncompressed
+ }
+
+ apkFilename := proptools.StringDefault(a.properties.Filename, a.BaseModuleName()+".apk")
+
+ // TODO: Handle EXTERNAL
+
+ // Sign or align the package if package has not been preprocessed
+ if a.preprocessed {
+ a.outputFile = srcApk
+ a.certificate = PresignedCertificate
+ } else if !Bool(a.properties.Presigned) {
+ // If the certificate property is empty at this point, default_dev_cert must be set to true.
+ // Which makes processMainCert's behavior for the empty cert string WAI.
+ certificates = processMainCert(a.ModuleBase, String(a.properties.Certificate), certificates, ctx)
+ if len(certificates) != 1 {
+ ctx.ModuleErrorf("Unexpected number of certificates were extracted: %q", certificates)
+ }
+ a.certificate = certificates[0]
+ signed := android.PathForModuleOut(ctx, "signed", apkFilename)
+ var lineageFile android.Path
+ if lineage := String(a.properties.Lineage); lineage != "" {
+ lineageFile = android.PathForModuleSrc(ctx, lineage)
+ }
+ SignAppPackage(ctx, signed, jnisUncompressed, certificates, nil, lineageFile)
+ a.outputFile = signed
+ } else {
+ alignedApk := android.PathForModuleOut(ctx, "zip-aligned", apkFilename)
+ TransformZipAlign(ctx, alignedApk, jnisUncompressed)
+ a.outputFile = alignedApk
+ a.certificate = PresignedCertificate
+ }
+
+ // TODO: Optionally compress the output apk.
+
+ if apexInfo.IsForPlatform() {
+ a.installPath = ctx.InstallFile(installDir, apkFilename, a.outputFile)
+ }
+
+ // TODO: androidmk converter jni libs
+}
+
+func (a *AndroidAppImport) Prebuilt() *android.Prebuilt {
+ return &a.prebuilt
+}
+
+func (a *AndroidAppImport) Name() string {
+ return a.prebuilt.Name(a.ModuleBase.Name())
+}
+
+func (a *AndroidAppImport) OutputFile() android.Path {
+ return a.outputFile
+}
+
+func (a *AndroidAppImport) JacocoReportClassesFile() android.Path {
+ return nil
+}
+
+func (a *AndroidAppImport) Certificate() Certificate {
+ return a.certificate
+}
+
+var dpiVariantGroupType reflect.Type
+var archVariantGroupType reflect.Type
+var supportedDpis = []string{"ldpi", "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"}
+
+func initAndroidAppImportVariantGroupTypes() {
+ dpiVariantGroupType = createVariantGroupType(supportedDpis, "Dpi_variants")
+
+ archNames := make([]string, len(android.ArchTypeList()))
+ for i, archType := range android.ArchTypeList() {
+ archNames[i] = archType.Name
+ }
+ archVariantGroupType = createVariantGroupType(archNames, "Arch")
+}
+
+// Populates all variant struct properties at creation time.
+func (a *AndroidAppImport) populateAllVariantStructs() {
+ a.dpiVariants = reflect.New(dpiVariantGroupType).Interface()
+ a.AddProperties(a.dpiVariants)
+
+ a.archVariants = reflect.New(archVariantGroupType).Interface()
+ a.AddProperties(a.archVariants)
+}
+
+func (a *AndroidAppImport) Privileged() bool {
+ return Bool(a.properties.Privileged)
+}
+
+func (a *AndroidAppImport) DepIsInSameApex(_ android.BaseModuleContext, _ android.Module) bool {
+ // android_app_import might have extra dependencies via uses_libs property.
+ // Don't track the dependency as we don't automatically add those libraries
+ // to the classpath. It should be explicitly added to java_libs property of APEX
+ return false
+}
+
+func (a *AndroidAppImport) sdkVersion() sdkSpec {
+ return sdkSpecFrom("")
+}
+
+func (a *AndroidAppImport) minSdkVersion() sdkSpec {
+ return sdkSpecFrom("")
+}
+
+var _ android.ApexModule = (*AndroidAppImport)(nil)
+
+// Implements android.ApexModule
+func (j *AndroidAppImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
+ sdkVersion android.ApiLevel) error {
+ // Do not check for prebuilts against the min_sdk_version of enclosing APEX
+ return nil
+}
+
+func createVariantGroupType(variants []string, variantGroupName string) reflect.Type {
+ props := reflect.TypeOf((*AndroidAppImportProperties)(nil))
+
+ variantFields := make([]reflect.StructField, len(variants))
+ for i, variant := range variants {
+ variantFields[i] = reflect.StructField{
+ Name: proptools.FieldNameForProperty(variant),
+ Type: props,
+ }
+ }
+
+ variantGroupStruct := reflect.StructOf(variantFields)
+ return reflect.StructOf([]reflect.StructField{
+ {
+ Name: variantGroupName,
+ Type: variantGroupStruct,
+ },
+ })
+}
+
+// android_app_import imports a prebuilt apk with additional processing specified in the module.
+// DPI-specific apk source files can be specified using dpi_variants. Example:
+//
+// android_app_import {
+// name: "example_import",
+// apk: "prebuilts/example.apk",
+// dpi_variants: {
+// mdpi: {
+// apk: "prebuilts/example_mdpi.apk",
+// },
+// xhdpi: {
+// apk: "prebuilts/example_xhdpi.apk",
+// },
+// },
+// certificate: "PRESIGNED",
+// }
+func AndroidAppImportFactory() android.Module {
+ module := &AndroidAppImport{}
+ module.AddProperties(&module.properties)
+ module.AddProperties(&module.dexpreoptProperties)
+ module.AddProperties(&module.usesLibrary.usesLibraryProperties)
+ module.populateAllVariantStructs()
+ android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ module.processVariants(ctx)
+ })
+
+ android.InitApexModule(module)
+ android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+ android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk")
+
+ return module
+}
+
+type androidTestImportProperties struct {
+ // Whether the prebuilt apk can be installed without additional processing. Default is false.
+ Preprocessed *bool
+}
+
+type AndroidTestImport struct {
+ AndroidAppImport
+
+ testProperties testProperties
+
+ testImportProperties androidTestImportProperties
+
+ data android.Paths
+}
+
+func (a *AndroidTestImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ a.preprocessed = Bool(a.testImportProperties.Preprocessed)
+
+ a.generateAndroidBuildActions(ctx)
+
+ a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data)
+}
+
+func (a *AndroidTestImport) InstallInTestcases() bool {
+ return true
+}
+
+// android_test_import imports a prebuilt test apk with additional processing specified in the
+// module. DPI or arch variant configurations can be made as with android_app_import.
+func AndroidTestImportFactory() android.Module {
+ module := &AndroidTestImport{}
+ module.AddProperties(&module.properties)
+ module.AddProperties(&module.dexpreoptProperties)
+ module.AddProperties(&module.testProperties)
+ module.AddProperties(&module.testImportProperties)
+ module.populateAllVariantStructs()
+ android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ module.processVariants(ctx)
+ })
+
+ module.dexpreopter.isTest = true
+
+ android.InitApexModule(module)
+ android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+ android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk")
+
+ return module
+}
diff --git a/java/app_import_test.go b/java/app_import_test.go
new file mode 100644
index 0000000..3b55c81
--- /dev/null
+++ b/java/app_import_test.go
@@ -0,0 +1,495 @@
+// Copyright 2020 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 (
+ "reflect"
+ "regexp"
+ "strings"
+ "testing"
+
+ "github.com/google/blueprint/proptools"
+
+ "android/soong/android"
+)
+
+func TestAndroidAppImport(t *testing.T) {
+ ctx, _ := testJava(t, `
+ android_app_import {
+ name: "foo",
+ apk: "prebuilts/apk/app.apk",
+ certificate: "platform",
+ dex_preopt: {
+ enabled: true,
+ },
+ }
+ `)
+
+ variant := ctx.ModuleForTests("foo", "android_common")
+
+ // Check dexpreopt outputs.
+ if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
+ variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
+ t.Errorf("can't find dexpreopt outputs")
+ }
+
+ // Check cert signing flag.
+ signedApk := variant.Output("signed/foo.apk")
+ signingFlag := signedApk.Args["certificates"]
+ expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8"
+ if expected != signingFlag {
+ t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
+ }
+}
+
+func TestAndroidAppImport_NoDexPreopt(t *testing.T) {
+ ctx, _ := testJava(t, `
+ android_app_import {
+ name: "foo",
+ apk: "prebuilts/apk/app.apk",
+ certificate: "platform",
+ dex_preopt: {
+ enabled: false,
+ },
+ }
+ `)
+
+ variant := ctx.ModuleForTests("foo", "android_common")
+
+ // Check dexpreopt outputs. They shouldn't exist.
+ if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule != nil ||
+ variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule != nil {
+ t.Errorf("dexpreopt shouldn't have run.")
+ }
+}
+
+func TestAndroidAppImport_Presigned(t *testing.T) {
+ ctx, _ := testJava(t, `
+ android_app_import {
+ name: "foo",
+ apk: "prebuilts/apk/app.apk",
+ presigned: true,
+ dex_preopt: {
+ enabled: true,
+ },
+ }
+ `)
+
+ variant := ctx.ModuleForTests("foo", "android_common")
+
+ // Check dexpreopt outputs.
+ if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
+ variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
+ t.Errorf("can't find dexpreopt outputs")
+ }
+ // Make sure signing was skipped and aligning was done.
+ if variant.MaybeOutput("signed/foo.apk").Rule != nil {
+ t.Errorf("signing rule shouldn't be included.")
+ }
+ if variant.MaybeOutput("zip-aligned/foo.apk").Rule == nil {
+ t.Errorf("can't find aligning rule")
+ }
+}
+
+func TestAndroidAppImport_SigningLineage(t *testing.T) {
+ ctx, _ := testJava(t, `
+ android_app_import {
+ name: "foo",
+ apk: "prebuilts/apk/app.apk",
+ certificate: "platform",
+ lineage: "lineage.bin",
+ }
+ `)
+
+ variant := ctx.ModuleForTests("foo", "android_common")
+
+ // Check cert signing lineage flag.
+ signedApk := variant.Output("signed/foo.apk")
+ signingFlag := signedApk.Args["flags"]
+ expected := "--lineage lineage.bin"
+ if expected != signingFlag {
+ t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
+ }
+}
+
+func TestAndroidAppImport_DefaultDevCert(t *testing.T) {
+ ctx, _ := testJava(t, `
+ android_app_import {
+ name: "foo",
+ apk: "prebuilts/apk/app.apk",
+ default_dev_cert: true,
+ dex_preopt: {
+ enabled: true,
+ },
+ }
+ `)
+
+ variant := ctx.ModuleForTests("foo", "android_common")
+
+ // Check dexpreopt outputs.
+ if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
+ variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
+ t.Errorf("can't find dexpreopt outputs")
+ }
+
+ // Check cert signing flag.
+ signedApk := variant.Output("signed/foo.apk")
+ signingFlag := signedApk.Args["certificates"]
+ expected := "build/make/target/product/security/testkey.x509.pem build/make/target/product/security/testkey.pk8"
+ if expected != signingFlag {
+ t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
+ }
+}
+
+func TestAndroidAppImport_DpiVariants(t *testing.T) {
+ bp := `
+ android_app_import {
+ name: "foo",
+ apk: "prebuilts/apk/app.apk",
+ dpi_variants: {
+ xhdpi: {
+ apk: "prebuilts/apk/app_xhdpi.apk",
+ },
+ xxhdpi: {
+ apk: "prebuilts/apk/app_xxhdpi.apk",
+ },
+ },
+ presigned: true,
+ dex_preopt: {
+ enabled: true,
+ },
+ }
+ `
+ testCases := []struct {
+ name string
+ aaptPreferredConfig *string
+ aaptPrebuiltDPI []string
+ expected string
+ }{
+ {
+ name: "no preferred",
+ aaptPreferredConfig: nil,
+ aaptPrebuiltDPI: []string{},
+ expected: "prebuilts/apk/app.apk",
+ },
+ {
+ name: "AAPTPreferredConfig matches",
+ aaptPreferredConfig: proptools.StringPtr("xhdpi"),
+ aaptPrebuiltDPI: []string{"xxhdpi", "ldpi"},
+ expected: "prebuilts/apk/app_xhdpi.apk",
+ },
+ {
+ name: "AAPTPrebuiltDPI matches",
+ aaptPreferredConfig: proptools.StringPtr("mdpi"),
+ aaptPrebuiltDPI: []string{"xxhdpi", "xhdpi"},
+ expected: "prebuilts/apk/app_xxhdpi.apk",
+ },
+ {
+ name: "non-first AAPTPrebuiltDPI matches",
+ aaptPreferredConfig: proptools.StringPtr("mdpi"),
+ aaptPrebuiltDPI: []string{"ldpi", "xhdpi"},
+ expected: "prebuilts/apk/app_xhdpi.apk",
+ },
+ {
+ name: "no matches",
+ aaptPreferredConfig: proptools.StringPtr("mdpi"),
+ aaptPrebuiltDPI: []string{"ldpi", "xxxhdpi"},
+ expected: "prebuilts/apk/app.apk",
+ },
+ }
+
+ jniRuleRe := regexp.MustCompile("^if \\(zipinfo (\\S+)")
+ for _, test := range testCases {
+ config := testAppConfig(nil, bp, nil)
+ config.TestProductVariables.AAPTPreferredConfig = test.aaptPreferredConfig
+ config.TestProductVariables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI
+ ctx := testContext(config)
+
+ run(t, ctx, config)
+
+ variant := ctx.ModuleForTests("foo", "android_common")
+ jniRuleCommand := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command
+ matches := jniRuleRe.FindStringSubmatch(jniRuleCommand)
+ if len(matches) != 2 {
+ t.Errorf("failed to extract the src apk path from %q", jniRuleCommand)
+ }
+ if test.expected != matches[1] {
+ t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1])
+ }
+ }
+}
+
+func TestAndroidAppImport_Filename(t *testing.T) {
+ ctx, config := testJava(t, `
+ android_app_import {
+ name: "foo",
+ apk: "prebuilts/apk/app.apk",
+ presigned: true,
+ }
+
+ android_app_import {
+ name: "bar",
+ apk: "prebuilts/apk/app.apk",
+ presigned: true,
+ filename: "bar_sample.apk"
+ }
+ `)
+
+ testCases := []struct {
+ name string
+ expected string
+ }{
+ {
+ name: "foo",
+ expected: "foo.apk",
+ },
+ {
+ name: "bar",
+ expected: "bar_sample.apk",
+ },
+ }
+
+ for _, test := range testCases {
+ variant := ctx.ModuleForTests(test.name, "android_common")
+ if variant.MaybeOutput(test.expected).Rule == nil {
+ t.Errorf("can't find output named %q - all outputs: %v", test.expected, variant.AllOutputs())
+ }
+
+ a := variant.Module().(*AndroidAppImport)
+ expectedValues := []string{test.expected}
+ actualValues := android.AndroidMkEntriesForTest(
+ t, config, "", a)[0].EntryMap["LOCAL_INSTALLED_MODULE_STEM"]
+ if !reflect.DeepEqual(actualValues, expectedValues) {
+ t.Errorf("Incorrect LOCAL_INSTALLED_MODULE_STEM value '%s', expected '%s'",
+ actualValues, expectedValues)
+ }
+ }
+}
+
+func TestAndroidAppImport_ArchVariants(t *testing.T) {
+ // The test config's target arch is ARM64.
+ testCases := []struct {
+ name string
+ bp string
+ expected string
+ }{
+ {
+ name: "matching arch",
+ bp: `
+ android_app_import {
+ name: "foo",
+ apk: "prebuilts/apk/app.apk",
+ arch: {
+ arm64: {
+ apk: "prebuilts/apk/app_arm64.apk",
+ },
+ },
+ presigned: true,
+ dex_preopt: {
+ enabled: true,
+ },
+ }
+ `,
+ expected: "prebuilts/apk/app_arm64.apk",
+ },
+ {
+ name: "no matching arch",
+ bp: `
+ android_app_import {
+ name: "foo",
+ apk: "prebuilts/apk/app.apk",
+ arch: {
+ arm: {
+ apk: "prebuilts/apk/app_arm.apk",
+ },
+ },
+ presigned: true,
+ dex_preopt: {
+ enabled: true,
+ },
+ }
+ `,
+ expected: "prebuilts/apk/app.apk",
+ },
+ {
+ name: "no matching arch without default",
+ bp: `
+ android_app_import {
+ name: "foo",
+ arch: {
+ arm: {
+ apk: "prebuilts/apk/app_arm.apk",
+ },
+ },
+ presigned: true,
+ dex_preopt: {
+ enabled: true,
+ },
+ }
+ `,
+ expected: "",
+ },
+ }
+
+ jniRuleRe := regexp.MustCompile("^if \\(zipinfo (\\S+)")
+ for _, test := range testCases {
+ ctx, _ := testJava(t, test.bp)
+
+ variant := ctx.ModuleForTests("foo", "android_common")
+ if test.expected == "" {
+ if variant.Module().Enabled() {
+ t.Error("module should have been disabled, but wasn't")
+ }
+ continue
+ }
+ jniRuleCommand := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command
+ matches := jniRuleRe.FindStringSubmatch(jniRuleCommand)
+ if len(matches) != 2 {
+ t.Errorf("failed to extract the src apk path from %q", jniRuleCommand)
+ }
+ if test.expected != matches[1] {
+ t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1])
+ }
+ }
+}
+
+func TestAndroidAppImport_overridesDisabledAndroidApp(t *testing.T) {
+ ctx, _ := testJava(t, `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ enabled: false,
+ }
+
+ android_app_import {
+ name: "foo",
+ apk: "prebuilts/apk/app.apk",
+ certificate: "platform",
+ prefer: true,
+ }
+ `)
+
+ variant := ctx.ModuleForTests("prebuilt_foo", "android_common")
+ a := variant.Module().(*AndroidAppImport)
+ // The prebuilt module should still be enabled and active even if the source-based counterpart
+ // is disabled.
+ if !a.prebuilt.UsePrebuilt() {
+ t.Errorf("prebuilt foo module is not active")
+ }
+ if !a.Enabled() {
+ t.Errorf("prebuilt foo module is disabled")
+ }
+}
+
+func TestAndroidTestImport(t *testing.T) {
+ ctx, config := testJava(t, `
+ android_test_import {
+ name: "foo",
+ apk: "prebuilts/apk/app.apk",
+ presigned: true,
+ data: [
+ "testdata/data",
+ ],
+ }
+ `)
+
+ test := ctx.ModuleForTests("foo", "android_common").Module().(*AndroidTestImport)
+
+ // Check android mks.
+ entries := android.AndroidMkEntriesForTest(t, config, "", test)[0]
+ expected := []string{"tests"}
+ actual := entries.EntryMap["LOCAL_MODULE_TAGS"]
+ if !reflect.DeepEqual(expected, actual) {
+ t.Errorf("Unexpected module tags - expected: %q, actual: %q", expected, actual)
+ }
+ expected = []string{"testdata/data:testdata/data"}
+ actual = entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"]
+ if !reflect.DeepEqual(expected, actual) {
+ t.Errorf("Unexpected test data - expected: %q, actual: %q", expected, actual)
+ }
+}
+
+func TestAndroidTestImport_NoJinUncompressForPresigned(t *testing.T) {
+ ctx, _ := testJava(t, `
+ android_test_import {
+ name: "foo",
+ apk: "prebuilts/apk/app.apk",
+ certificate: "cert/new_cert",
+ data: [
+ "testdata/data",
+ ],
+ }
+
+ android_test_import {
+ name: "foo_presigned",
+ apk: "prebuilts/apk/app.apk",
+ presigned: true,
+ data: [
+ "testdata/data",
+ ],
+ }
+ `)
+
+ variant := ctx.ModuleForTests("foo", "android_common")
+ jniRule := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command
+ if !strings.HasPrefix(jniRule, "if (zipinfo") {
+ t.Errorf("Unexpected JNI uncompress rule command: " + jniRule)
+ }
+
+ variant = ctx.ModuleForTests("foo_presigned", "android_common")
+ jniRule = variant.Output("jnis-uncompressed/foo_presigned.apk").BuildParams.Rule.String()
+ if jniRule != android.Cp.String() {
+ t.Errorf("Unexpected JNI uncompress rule: " + jniRule)
+ }
+ if variant.MaybeOutput("zip-aligned/foo_presigned.apk").Rule == nil {
+ t.Errorf("Presigned test apk should be aligned")
+ }
+}
+
+func TestAndroidTestImport_Preprocessed(t *testing.T) {
+ ctx, _ := testJava(t, `
+ android_test_import {
+ name: "foo",
+ apk: "prebuilts/apk/app.apk",
+ presigned: true,
+ preprocessed: true,
+ }
+
+ android_test_import {
+ name: "foo_cert",
+ apk: "prebuilts/apk/app.apk",
+ certificate: "cert/new_cert",
+ preprocessed: true,
+ }
+ `)
+
+ testModules := []string{"foo", "foo_cert"}
+ for _, m := range testModules {
+ apkName := m + ".apk"
+ variant := ctx.ModuleForTests(m, "android_common")
+ jniRule := variant.Output("jnis-uncompressed/" + apkName).BuildParams.Rule.String()
+ if jniRule != android.Cp.String() {
+ t.Errorf("Unexpected JNI uncompress rule: " + jniRule)
+ }
+
+ // Make sure signing and aligning were skipped.
+ if variant.MaybeOutput("signed/"+apkName).Rule != nil {
+ t.Errorf("signing rule shouldn't be included for preprocessed.")
+ }
+ if variant.MaybeOutput("zip-aligned/"+apkName).Rule != nil {
+ t.Errorf("aligning rule shouldn't be for preprocessed")
+ }
+ }
+}
diff --git a/java/app_set.go b/java/app_set.go
new file mode 100644
index 0000000..6b25638
--- /dev/null
+++ b/java/app_set.go
@@ -0,0 +1,162 @@
+// Copyright 2020 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
+
+// This file contains the module implementation for android_app_set.
+
+import (
+ "strconv"
+ "strings"
+
+ "github.com/google/blueprint/proptools"
+
+ "android/soong/android"
+)
+
+func init() {
+ RegisterAppSetBuildComponents(android.InitRegistrationContext)
+}
+
+func RegisterAppSetBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("android_app_set", AndroidAppSetFactory)
+}
+
+type AndroidAppSetProperties struct {
+ // APK Set path
+ Set *string
+
+ // Specifies that this app should be installed to the priv-app directory,
+ // where the system will grant it additional privileges not available to
+ // normal apps.
+ Privileged *bool
+
+ // APKs in this set use prerelease SDK version
+ Prerelease *bool
+
+ // Names of modules to be overridden. Listed modules can only be other apps
+ // (in Make or Soong).
+ Overrides []string
+}
+
+type AndroidAppSet struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+ prebuilt android.Prebuilt
+
+ properties AndroidAppSetProperties
+ packedOutput android.WritablePath
+ installFile string
+ apkcertsFile android.ModuleOutPath
+}
+
+func (as *AndroidAppSet) Name() string {
+ return as.prebuilt.Name(as.ModuleBase.Name())
+}
+
+func (as *AndroidAppSet) IsInstallable() bool {
+ return true
+}
+
+func (as *AndroidAppSet) Prebuilt() *android.Prebuilt {
+ return &as.prebuilt
+}
+
+func (as *AndroidAppSet) Privileged() bool {
+ return Bool(as.properties.Privileged)
+}
+
+func (as *AndroidAppSet) OutputFile() android.Path {
+ return as.packedOutput
+}
+
+func (as *AndroidAppSet) InstallFile() string {
+ return as.installFile
+}
+
+func (as *AndroidAppSet) APKCertsFile() android.Path {
+ return as.apkcertsFile
+}
+
+var TargetCpuAbi = map[string]string{
+ "arm": "ARMEABI_V7A",
+ "arm64": "ARM64_V8A",
+ "x86": "X86",
+ "x86_64": "X86_64",
+}
+
+func SupportedAbis(ctx android.ModuleContext) []string {
+ abiName := func(targetIdx int, deviceArch string) string {
+ if abi, found := TargetCpuAbi[deviceArch]; found {
+ return abi
+ }
+ ctx.ModuleErrorf("Target %d has invalid Arch: %s", targetIdx, deviceArch)
+ return "BAD_ABI"
+ }
+
+ var result []string
+ for i, target := range ctx.Config().Targets[android.Android] {
+ result = append(result, abiName(i, target.Arch.ArchType.String()))
+ }
+ return result
+}
+
+func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ as.packedOutput = android.PathForModuleOut(ctx, ctx.ModuleName()+".zip")
+ as.apkcertsFile = android.PathForModuleOut(ctx, "apkcerts.txt")
+ // We are assuming here that the install file in the APK
+ // set has `.apk` suffix. If it doesn't the build will fail.
+ // APK sets containing APEX files are handled elsewhere.
+ as.installFile = as.BaseModuleName() + ".apk"
+ screenDensities := "all"
+ if dpis := ctx.Config().ProductAAPTPrebuiltDPI(); len(dpis) > 0 {
+ screenDensities = strings.ToUpper(strings.Join(dpis, ","))
+ }
+ // TODO(asmundak): handle locales.
+ // TODO(asmundak): do we support device features
+ ctx.Build(pctx,
+ android.BuildParams{
+ Rule: extractMatchingApks,
+ Description: "Extract APKs from APK set",
+ Output: as.packedOutput,
+ ImplicitOutput: as.apkcertsFile,
+ Inputs: android.Paths{as.prebuilt.SingleSourcePath(ctx)},
+ Args: map[string]string{
+ "abis": strings.Join(SupportedAbis(ctx), ","),
+ "allow-prereleased": strconv.FormatBool(proptools.Bool(as.properties.Prerelease)),
+ "screen-densities": screenDensities,
+ "sdk-version": ctx.Config().PlatformSdkVersion().String(),
+ "stem": as.BaseModuleName(),
+ "apkcerts": as.apkcertsFile.String(),
+ "partition": as.PartitionTag(ctx.DeviceConfig()),
+ },
+ })
+}
+
+// android_app_set extracts a set of APKs based on the target device
+// configuration and installs this set as "split APKs".
+// The extracted set always contains an APK whose name is
+// _module_name_.apk and every split APK matching target device.
+// The extraction of the density-specific splits depends on
+// PRODUCT_AAPT_PREBUILT_DPI variable. If present (its value should
+// be a list density names: LDPI, MDPI, HDPI, etc.), only listed
+// splits will be extracted. Otherwise all density-specific splits
+// will be extracted.
+func AndroidAppSetFactory() android.Module {
+ module := &AndroidAppSet{}
+ module.AddProperties(&module.properties)
+ InitJavaModule(module, android.DeviceSupported)
+ android.InitSingleSourcePrebuiltModule(module, &module.properties, "Set")
+ return module
+}
diff --git a/java/app_set_test.go b/java/app_set_test.go
new file mode 100644
index 0000000..d31900d
--- /dev/null
+++ b/java/app_set_test.go
@@ -0,0 +1,115 @@
+// Copyright 2020 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 (
+ "reflect"
+ "testing"
+
+ "android/soong/android"
+)
+
+func TestAndroidAppSet(t *testing.T) {
+ ctx, config := testJava(t, `
+ android_app_set {
+ name: "foo",
+ set: "prebuilts/apks/app.apks",
+ prerelease: true,
+ }`)
+ module := ctx.ModuleForTests("foo", "android_common")
+ const packedSplitApks = "foo.zip"
+ params := module.Output(packedSplitApks)
+ if params.Rule == nil {
+ t.Errorf("expected output %s is missing", packedSplitApks)
+ }
+ if s := params.Args["allow-prereleased"]; s != "true" {
+ t.Errorf("wrong allow-prereleased value: '%s', expected 'true'", s)
+ }
+ if s := params.Args["partition"]; s != "system" {
+ t.Errorf("wrong partition value: '%s', expected 'system'", s)
+ }
+ mkEntries := android.AndroidMkEntriesForTest(t, config, "", module.Module())[0]
+ actualInstallFile := mkEntries.EntryMap["LOCAL_APK_SET_INSTALL_FILE"]
+ expectedInstallFile := []string{"foo.apk"}
+ if !reflect.DeepEqual(actualInstallFile, expectedInstallFile) {
+ t.Errorf("Unexpected LOCAL_APK_SET_INSTALL_FILE value: '%s', expected: '%s',",
+ actualInstallFile, expectedInstallFile)
+ }
+}
+
+func TestAndroidAppSet_Variants(t *testing.T) {
+ bp := `
+ android_app_set {
+ name: "foo",
+ set: "prebuilts/apks/app.apks",
+ }`
+ testCases := []struct {
+ name string
+ targets []android.Target
+ aaptPrebuiltDPI []string
+ sdkVersion int
+ expected map[string]string
+ }{
+ {
+ name: "One",
+ targets: []android.Target{
+ {Os: android.Android, Arch: android.Arch{ArchType: android.X86}},
+ },
+ aaptPrebuiltDPI: []string{"ldpi", "xxhdpi"},
+ sdkVersion: 29,
+ expected: map[string]string{
+ "abis": "X86",
+ "allow-prereleased": "false",
+ "screen-densities": "LDPI,XXHDPI",
+ "sdk-version": "29",
+ "stem": "foo",
+ },
+ },
+ {
+ name: "Two",
+ targets: []android.Target{
+ {Os: android.Android, Arch: android.Arch{ArchType: android.X86_64}},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.X86}},
+ },
+ aaptPrebuiltDPI: nil,
+ sdkVersion: 30,
+ expected: map[string]string{
+ "abis": "X86_64,X86",
+ "allow-prereleased": "false",
+ "screen-densities": "all",
+ "sdk-version": "30",
+ "stem": "foo",
+ },
+ },
+ }
+
+ for _, test := range testCases {
+ config := testAppConfig(nil, bp, nil)
+ config.TestProductVariables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI
+ config.TestProductVariables.Platform_sdk_version = &test.sdkVersion
+ config.Targets[android.Android] = test.targets
+ ctx := testContext(config)
+ run(t, ctx, config)
+ module := ctx.ModuleForTests("foo", "android_common")
+ const packedSplitApks = "foo.zip"
+ params := module.Output(packedSplitApks)
+ for k, v := range test.expected {
+ if actual := params.Args[k]; actual != v {
+ t.Errorf("%s: bad build arg value for '%s': '%s', expected '%s'",
+ test.name, k, actual, v)
+ }
+ }
+ }
+}
diff --git a/java/app_test.go b/java/app_test.go
index e13c6b9..b1abe3d 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -18,7 +18,6 @@
"fmt"
"path/filepath"
"reflect"
- "regexp"
"sort"
"strings"
"testing"
@@ -141,99 +140,6 @@
}
}
-func TestAndroidAppSet(t *testing.T) {
- ctx, config := testJava(t, `
- android_app_set {
- name: "foo",
- set: "prebuilts/apks/app.apks",
- prerelease: true,
- }`)
- module := ctx.ModuleForTests("foo", "android_common")
- const packedSplitApks = "foo.zip"
- params := module.Output(packedSplitApks)
- if params.Rule == nil {
- t.Errorf("expected output %s is missing", packedSplitApks)
- }
- if s := params.Args["allow-prereleased"]; s != "true" {
- t.Errorf("wrong allow-prereleased value: '%s', expected 'true'", s)
- }
- if s := params.Args["partition"]; s != "system" {
- t.Errorf("wrong partition value: '%s', expected 'system'", s)
- }
- mkEntries := android.AndroidMkEntriesForTest(t, config, "", module.Module())[0]
- actualInstallFile := mkEntries.EntryMap["LOCAL_APK_SET_INSTALL_FILE"]
- expectedInstallFile := []string{"foo.apk"}
- if !reflect.DeepEqual(actualInstallFile, expectedInstallFile) {
- t.Errorf("Unexpected LOCAL_APK_SET_INSTALL_FILE value: '%s', expected: '%s',",
- actualInstallFile, expectedInstallFile)
- }
-}
-
-func TestAndroidAppSet_Variants(t *testing.T) {
- bp := `
- android_app_set {
- name: "foo",
- set: "prebuilts/apks/app.apks",
- }`
- testCases := []struct {
- name string
- targets []android.Target
- aaptPrebuiltDPI []string
- sdkVersion int
- expected map[string]string
- }{
- {
- name: "One",
- targets: []android.Target{
- {Os: android.Android, Arch: android.Arch{ArchType: android.X86}},
- },
- aaptPrebuiltDPI: []string{"ldpi", "xxhdpi"},
- sdkVersion: 29,
- expected: map[string]string{
- "abis": "X86",
- "allow-prereleased": "false",
- "screen-densities": "LDPI,XXHDPI",
- "sdk-version": "29",
- "stem": "foo",
- },
- },
- {
- name: "Two",
- targets: []android.Target{
- {Os: android.Android, Arch: android.Arch{ArchType: android.X86_64}},
- {Os: android.Android, Arch: android.Arch{ArchType: android.X86}},
- },
- aaptPrebuiltDPI: nil,
- sdkVersion: 30,
- expected: map[string]string{
- "abis": "X86_64,X86",
- "allow-prereleased": "false",
- "screen-densities": "all",
- "sdk-version": "30",
- "stem": "foo",
- },
- },
- }
-
- for _, test := range testCases {
- config := testAppConfig(nil, bp, nil)
- config.TestProductVariables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI
- config.TestProductVariables.Platform_sdk_version = &test.sdkVersion
- config.Targets[android.Android] = test.targets
- ctx := testContext(config)
- run(t, ctx, config)
- module := ctx.ModuleForTests("foo", "android_common")
- const packedSplitApks = "foo.zip"
- params := module.Output(packedSplitApks)
- for k, v := range test.expected {
- if actual := params.Args[k]; actual != v {
- t.Errorf("%s: bad build arg value for '%s': '%s', expected '%s'",
- test.name, k, actual, v)
- }
- }
- }
-}
-
func TestPlatformAPIs(t *testing.T) {
testJava(t, `
android_app {
@@ -2226,475 +2132,6 @@
}
}
-func TestAndroidAppImport(t *testing.T) {
- ctx, _ := testJava(t, `
- android_app_import {
- name: "foo",
- apk: "prebuilts/apk/app.apk",
- certificate: "platform",
- dex_preopt: {
- enabled: true,
- },
- }
- `)
-
- variant := ctx.ModuleForTests("foo", "android_common")
-
- // Check dexpreopt outputs.
- if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
- variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
- t.Errorf("can't find dexpreopt outputs")
- }
-
- // Check cert signing flag.
- signedApk := variant.Output("signed/foo.apk")
- signingFlag := signedApk.Args["certificates"]
- expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8"
- if expected != signingFlag {
- t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
- }
-}
-
-func TestAndroidAppImport_NoDexPreopt(t *testing.T) {
- ctx, _ := testJava(t, `
- android_app_import {
- name: "foo",
- apk: "prebuilts/apk/app.apk",
- certificate: "platform",
- dex_preopt: {
- enabled: false,
- },
- }
- `)
-
- variant := ctx.ModuleForTests("foo", "android_common")
-
- // Check dexpreopt outputs. They shouldn't exist.
- if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule != nil ||
- variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule != nil {
- t.Errorf("dexpreopt shouldn't have run.")
- }
-}
-
-func TestAndroidAppImport_Presigned(t *testing.T) {
- ctx, _ := testJava(t, `
- android_app_import {
- name: "foo",
- apk: "prebuilts/apk/app.apk",
- presigned: true,
- dex_preopt: {
- enabled: true,
- },
- }
- `)
-
- variant := ctx.ModuleForTests("foo", "android_common")
-
- // Check dexpreopt outputs.
- if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
- variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
- t.Errorf("can't find dexpreopt outputs")
- }
- // Make sure signing was skipped and aligning was done.
- if variant.MaybeOutput("signed/foo.apk").Rule != nil {
- t.Errorf("signing rule shouldn't be included.")
- }
- if variant.MaybeOutput("zip-aligned/foo.apk").Rule == nil {
- t.Errorf("can't find aligning rule")
- }
-}
-
-func TestAndroidAppImport_SigningLineage(t *testing.T) {
- ctx, _ := testJava(t, `
- android_app_import {
- name: "foo",
- apk: "prebuilts/apk/app.apk",
- certificate: "platform",
- lineage: "lineage.bin",
- }
- `)
-
- variant := ctx.ModuleForTests("foo", "android_common")
-
- // Check cert signing lineage flag.
- signedApk := variant.Output("signed/foo.apk")
- signingFlag := signedApk.Args["flags"]
- expected := "--lineage lineage.bin"
- if expected != signingFlag {
- t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
- }
-}
-
-func TestAndroidAppImport_DefaultDevCert(t *testing.T) {
- ctx, _ := testJava(t, `
- android_app_import {
- name: "foo",
- apk: "prebuilts/apk/app.apk",
- default_dev_cert: true,
- dex_preopt: {
- enabled: true,
- },
- }
- `)
-
- variant := ctx.ModuleForTests("foo", "android_common")
-
- // Check dexpreopt outputs.
- if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
- variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
- t.Errorf("can't find dexpreopt outputs")
- }
-
- // Check cert signing flag.
- signedApk := variant.Output("signed/foo.apk")
- signingFlag := signedApk.Args["certificates"]
- expected := "build/make/target/product/security/testkey.x509.pem build/make/target/product/security/testkey.pk8"
- if expected != signingFlag {
- t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
- }
-}
-
-func TestAndroidAppImport_DpiVariants(t *testing.T) {
- bp := `
- android_app_import {
- name: "foo",
- apk: "prebuilts/apk/app.apk",
- dpi_variants: {
- xhdpi: {
- apk: "prebuilts/apk/app_xhdpi.apk",
- },
- xxhdpi: {
- apk: "prebuilts/apk/app_xxhdpi.apk",
- },
- },
- presigned: true,
- dex_preopt: {
- enabled: true,
- },
- }
- `
- testCases := []struct {
- name string
- aaptPreferredConfig *string
- aaptPrebuiltDPI []string
- expected string
- }{
- {
- name: "no preferred",
- aaptPreferredConfig: nil,
- aaptPrebuiltDPI: []string{},
- expected: "prebuilts/apk/app.apk",
- },
- {
- name: "AAPTPreferredConfig matches",
- aaptPreferredConfig: proptools.StringPtr("xhdpi"),
- aaptPrebuiltDPI: []string{"xxhdpi", "ldpi"},
- expected: "prebuilts/apk/app_xhdpi.apk",
- },
- {
- name: "AAPTPrebuiltDPI matches",
- aaptPreferredConfig: proptools.StringPtr("mdpi"),
- aaptPrebuiltDPI: []string{"xxhdpi", "xhdpi"},
- expected: "prebuilts/apk/app_xxhdpi.apk",
- },
- {
- name: "non-first AAPTPrebuiltDPI matches",
- aaptPreferredConfig: proptools.StringPtr("mdpi"),
- aaptPrebuiltDPI: []string{"ldpi", "xhdpi"},
- expected: "prebuilts/apk/app_xhdpi.apk",
- },
- {
- name: "no matches",
- aaptPreferredConfig: proptools.StringPtr("mdpi"),
- aaptPrebuiltDPI: []string{"ldpi", "xxxhdpi"},
- expected: "prebuilts/apk/app.apk",
- },
- }
-
- jniRuleRe := regexp.MustCompile("^if \\(zipinfo (\\S+)")
- for _, test := range testCases {
- config := testAppConfig(nil, bp, nil)
- config.TestProductVariables.AAPTPreferredConfig = test.aaptPreferredConfig
- config.TestProductVariables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI
- ctx := testContext(config)
-
- run(t, ctx, config)
-
- variant := ctx.ModuleForTests("foo", "android_common")
- jniRuleCommand := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command
- matches := jniRuleRe.FindStringSubmatch(jniRuleCommand)
- if len(matches) != 2 {
- t.Errorf("failed to extract the src apk path from %q", jniRuleCommand)
- }
- if test.expected != matches[1] {
- t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1])
- }
- }
-}
-
-func TestAndroidAppImport_Filename(t *testing.T) {
- ctx, config := testJava(t, `
- android_app_import {
- name: "foo",
- apk: "prebuilts/apk/app.apk",
- presigned: true,
- }
-
- android_app_import {
- name: "bar",
- apk: "prebuilts/apk/app.apk",
- presigned: true,
- filename: "bar_sample.apk"
- }
- `)
-
- testCases := []struct {
- name string
- expected string
- }{
- {
- name: "foo",
- expected: "foo.apk",
- },
- {
- name: "bar",
- expected: "bar_sample.apk",
- },
- }
-
- for _, test := range testCases {
- variant := ctx.ModuleForTests(test.name, "android_common")
- if variant.MaybeOutput(test.expected).Rule == nil {
- t.Errorf("can't find output named %q - all outputs: %v", test.expected, variant.AllOutputs())
- }
-
- a := variant.Module().(*AndroidAppImport)
- expectedValues := []string{test.expected}
- actualValues := android.AndroidMkEntriesForTest(
- t, config, "", a)[0].EntryMap["LOCAL_INSTALLED_MODULE_STEM"]
- if !reflect.DeepEqual(actualValues, expectedValues) {
- t.Errorf("Incorrect LOCAL_INSTALLED_MODULE_STEM value '%s', expected '%s'",
- actualValues, expectedValues)
- }
- }
-}
-
-func TestAndroidAppImport_ArchVariants(t *testing.T) {
- // The test config's target arch is ARM64.
- testCases := []struct {
- name string
- bp string
- expected string
- }{
- {
- name: "matching arch",
- bp: `
- android_app_import {
- name: "foo",
- apk: "prebuilts/apk/app.apk",
- arch: {
- arm64: {
- apk: "prebuilts/apk/app_arm64.apk",
- },
- },
- presigned: true,
- dex_preopt: {
- enabled: true,
- },
- }
- `,
- expected: "prebuilts/apk/app_arm64.apk",
- },
- {
- name: "no matching arch",
- bp: `
- android_app_import {
- name: "foo",
- apk: "prebuilts/apk/app.apk",
- arch: {
- arm: {
- apk: "prebuilts/apk/app_arm.apk",
- },
- },
- presigned: true,
- dex_preopt: {
- enabled: true,
- },
- }
- `,
- expected: "prebuilts/apk/app.apk",
- },
- {
- name: "no matching arch without default",
- bp: `
- android_app_import {
- name: "foo",
- arch: {
- arm: {
- apk: "prebuilts/apk/app_arm.apk",
- },
- },
- presigned: true,
- dex_preopt: {
- enabled: true,
- },
- }
- `,
- expected: "",
- },
- }
-
- jniRuleRe := regexp.MustCompile("^if \\(zipinfo (\\S+)")
- for _, test := range testCases {
- ctx, _ := testJava(t, test.bp)
-
- variant := ctx.ModuleForTests("foo", "android_common")
- if test.expected == "" {
- if variant.Module().Enabled() {
- t.Error("module should have been disabled, but wasn't")
- }
- continue
- }
- jniRuleCommand := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command
- matches := jniRuleRe.FindStringSubmatch(jniRuleCommand)
- if len(matches) != 2 {
- t.Errorf("failed to extract the src apk path from %q", jniRuleCommand)
- }
- if test.expected != matches[1] {
- t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1])
- }
- }
-}
-
-func TestAndroidAppImport_overridesDisabledAndroidApp(t *testing.T) {
- ctx, _ := testJava(t, `
- android_app {
- name: "foo",
- srcs: ["a.java"],
- enabled: false,
- }
-
- android_app_import {
- name: "foo",
- apk: "prebuilts/apk/app.apk",
- certificate: "platform",
- prefer: true,
- }
- `)
-
- variant := ctx.ModuleForTests("prebuilt_foo", "android_common")
- a := variant.Module().(*AndroidAppImport)
- // The prebuilt module should still be enabled and active even if the source-based counterpart
- // is disabled.
- if !a.prebuilt.UsePrebuilt() {
- t.Errorf("prebuilt foo module is not active")
- }
- if !a.Enabled() {
- t.Errorf("prebuilt foo module is disabled")
- }
-}
-
-func TestAndroidTestImport(t *testing.T) {
- ctx, config := testJava(t, `
- android_test_import {
- name: "foo",
- apk: "prebuilts/apk/app.apk",
- presigned: true,
- data: [
- "testdata/data",
- ],
- }
- `)
-
- test := ctx.ModuleForTests("foo", "android_common").Module().(*AndroidTestImport)
-
- // Check android mks.
- entries := android.AndroidMkEntriesForTest(t, config, "", test)[0]
- expected := []string{"tests"}
- actual := entries.EntryMap["LOCAL_MODULE_TAGS"]
- if !reflect.DeepEqual(expected, actual) {
- t.Errorf("Unexpected module tags - expected: %q, actual: %q", expected, actual)
- }
- expected = []string{"testdata/data:testdata/data"}
- actual = entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"]
- if !reflect.DeepEqual(expected, actual) {
- t.Errorf("Unexpected test data - expected: %q, actual: %q", expected, actual)
- }
-}
-
-func TestAndroidTestImport_NoJinUncompressForPresigned(t *testing.T) {
- ctx, _ := testJava(t, `
- android_test_import {
- name: "foo",
- apk: "prebuilts/apk/app.apk",
- certificate: "cert/new_cert",
- data: [
- "testdata/data",
- ],
- }
-
- android_test_import {
- name: "foo_presigned",
- apk: "prebuilts/apk/app.apk",
- presigned: true,
- data: [
- "testdata/data",
- ],
- }
- `)
-
- variant := ctx.ModuleForTests("foo", "android_common")
- jniRule := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command
- if !strings.HasPrefix(jniRule, "if (zipinfo") {
- t.Errorf("Unexpected JNI uncompress rule command: " + jniRule)
- }
-
- variant = ctx.ModuleForTests("foo_presigned", "android_common")
- jniRule = variant.Output("jnis-uncompressed/foo_presigned.apk").BuildParams.Rule.String()
- if jniRule != android.Cp.String() {
- t.Errorf("Unexpected JNI uncompress rule: " + jniRule)
- }
- if variant.MaybeOutput("zip-aligned/foo_presigned.apk").Rule == nil {
- t.Errorf("Presigned test apk should be aligned")
- }
-}
-
-func TestAndroidTestImport_Preprocessed(t *testing.T) {
- ctx, _ := testJava(t, `
- android_test_import {
- name: "foo",
- apk: "prebuilts/apk/app.apk",
- presigned: true,
- preprocessed: true,
- }
-
- android_test_import {
- name: "foo_cert",
- apk: "prebuilts/apk/app.apk",
- certificate: "cert/new_cert",
- preprocessed: true,
- }
- `)
-
- testModules := []string{"foo", "foo_cert"}
- for _, m := range testModules {
- apkName := m + ".apk"
- variant := ctx.ModuleForTests(m, "android_common")
- jniRule := variant.Output("jnis-uncompressed/" + apkName).BuildParams.Rule.String()
- if jniRule != android.Cp.String() {
- t.Errorf("Unexpected JNI uncompress rule: " + jniRule)
- }
-
- // Make sure signing and aligning were skipped.
- if variant.MaybeOutput("signed/"+apkName).Rule != nil {
- t.Errorf("signing rule shouldn't be included for preprocessed.")
- }
- if variant.MaybeOutput("zip-aligned/"+apkName).Rule != nil {
- t.Errorf("aligning rule shouldn't be for preprocessed")
- }
- }
-}
-
func TestStl(t *testing.T) {
ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
cc_library {
@@ -2896,8 +2333,8 @@
// Test conditional context for target SDK version 29.
if w := `--target-context-for-sdk 29` +
- ` PCL[/system/framework/android.hidl.base-V1.0-java.jar]` +
- `#PCL[/system/framework/android.hidl.manager-V1.0-java.jar] `; !strings.Contains(cmd, w) {
+ ` PCL[/system/framework/android.hidl.manager-V1.0-java.jar]` +
+ `#PCL[/system/framework/android.hidl.base-V1.0-java.jar] `; !strings.Contains(cmd, w) {
t.Errorf("wanted %q in %q", w, cmd)
}
@@ -3237,356 +2674,6 @@
}
}
-func TestRuntimeResourceOverlay(t *testing.T) {
- fs := map[string][]byte{
- "baz/res/res/values/strings.xml": nil,
- "bar/res/res/values/strings.xml": nil,
- }
- bp := `
- runtime_resource_overlay {
- name: "foo",
- certificate: "platform",
- lineage: "lineage.bin",
- product_specific: true,
- static_libs: ["bar"],
- resource_libs: ["baz"],
- aaptflags: ["--keep-raw-values"],
- }
-
- runtime_resource_overlay {
- name: "foo_themed",
- certificate: "platform",
- product_specific: true,
- theme: "faza",
- overrides: ["foo"],
- }
-
- android_library {
- name: "bar",
- resource_dirs: ["bar/res"],
- }
-
- android_app {
- name: "baz",
- sdk_version: "current",
- resource_dirs: ["baz/res"],
- }
- `
- config := testAppConfig(nil, bp, fs)
- ctx := testContext(config)
- run(t, ctx, config)
-
- m := ctx.ModuleForTests("foo", "android_common")
-
- // Check AAPT2 link flags.
- aapt2Flags := m.Output("package-res.apk").Args["flags"]
- expectedFlags := []string{"--keep-raw-values", "--no-resource-deduping", "--no-resource-removal"}
- absentFlags := android.RemoveListFromList(expectedFlags, strings.Split(aapt2Flags, " "))
- if len(absentFlags) > 0 {
- t.Errorf("expected values, %q are missing in aapt2 link flags, %q", absentFlags, aapt2Flags)
- }
-
- // Check overlay.list output for static_libs dependency.
- overlayList := m.Output("aapt2/overlay.list").Inputs.Strings()
- staticLibPackage := buildDir + "/.intermediates/bar/android_common/package-res.apk"
- if !inList(staticLibPackage, overlayList) {
- t.Errorf("Stactic lib res package %q missing in overlay list: %q", staticLibPackage, overlayList)
- }
-
- // Check AAPT2 link flags for resource_libs dependency.
- resourceLibFlag := "-I " + buildDir + "/.intermediates/baz/android_common/package-res.apk"
- if !strings.Contains(aapt2Flags, resourceLibFlag) {
- t.Errorf("Resource lib flag %q missing in aapt2 link flags: %q", resourceLibFlag, aapt2Flags)
- }
-
- // Check cert signing flag.
- signedApk := m.Output("signed/foo.apk")
- lineageFlag := signedApk.Args["flags"]
- expectedLineageFlag := "--lineage lineage.bin"
- if expectedLineageFlag != lineageFlag {
- t.Errorf("Incorrect signing lineage flags, expected: %q, got: %q", expectedLineageFlag, lineageFlag)
- }
- signingFlag := signedApk.Args["certificates"]
- expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8"
- if expected != signingFlag {
- t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
- }
- androidMkEntries := android.AndroidMkEntriesForTest(t, config, "", m.Module())[0]
- path := androidMkEntries.EntryMap["LOCAL_CERTIFICATE"]
- expectedPath := []string{"build/make/target/product/security/platform.x509.pem"}
- if !reflect.DeepEqual(path, expectedPath) {
- t.Errorf("Unexpected LOCAL_CERTIFICATE value: %v, expected: %v", path, expectedPath)
- }
-
- // Check device location.
- path = androidMkEntries.EntryMap["LOCAL_MODULE_PATH"]
- expectedPath = []string{"/tmp/target/product/test_device/product/overlay"}
- if !reflect.DeepEqual(path, expectedPath) {
- t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath)
- }
-
- // A themed module has a different device location
- m = ctx.ModuleForTests("foo_themed", "android_common")
- androidMkEntries = android.AndroidMkEntriesForTest(t, config, "", m.Module())[0]
- path = androidMkEntries.EntryMap["LOCAL_MODULE_PATH"]
- expectedPath = []string{"/tmp/target/product/test_device/product/overlay/faza"}
- if !reflect.DeepEqual(path, expectedPath) {
- t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath)
- }
-
- overrides := androidMkEntries.EntryMap["LOCAL_OVERRIDES_PACKAGES"]
- expectedOverrides := []string{"foo"}
- if !reflect.DeepEqual(overrides, expectedOverrides) {
- t.Errorf("Unexpected LOCAL_OVERRIDES_PACKAGES value: %v, expected: %v", overrides, expectedOverrides)
- }
-}
-
-func TestRuntimeResourceOverlay_JavaDefaults(t *testing.T) {
- ctx, config := testJava(t, `
- java_defaults {
- name: "rro_defaults",
- theme: "default_theme",
- product_specific: true,
- aaptflags: ["--keep-raw-values"],
- }
-
- runtime_resource_overlay {
- name: "foo_with_defaults",
- defaults: ["rro_defaults"],
- }
-
- runtime_resource_overlay {
- name: "foo_barebones",
- }
- `)
-
- //
- // RRO module with defaults
- //
- m := ctx.ModuleForTests("foo_with_defaults", "android_common")
-
- // Check AAPT2 link flags.
- aapt2Flags := strings.Split(m.Output("package-res.apk").Args["flags"], " ")
- expectedFlags := []string{"--keep-raw-values", "--no-resource-deduping", "--no-resource-removal"}
- absentFlags := android.RemoveListFromList(expectedFlags, aapt2Flags)
- if len(absentFlags) > 0 {
- t.Errorf("expected values, %q are missing in aapt2 link flags, %q", absentFlags, aapt2Flags)
- }
-
- // Check device location.
- path := android.AndroidMkEntriesForTest(t, config, "", m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
- expectedPath := []string{"/tmp/target/product/test_device/product/overlay/default_theme"}
- if !reflect.DeepEqual(path, expectedPath) {
- t.Errorf("Unexpected LOCAL_MODULE_PATH value: %q, expected: %q", path, expectedPath)
- }
-
- //
- // RRO module without defaults
- //
- m = ctx.ModuleForTests("foo_barebones", "android_common")
-
- // Check AAPT2 link flags.
- aapt2Flags = strings.Split(m.Output("package-res.apk").Args["flags"], " ")
- unexpectedFlags := "--keep-raw-values"
- if inList(unexpectedFlags, aapt2Flags) {
- t.Errorf("unexpected value, %q is present in aapt2 link flags, %q", unexpectedFlags, aapt2Flags)
- }
-
- // Check device location.
- path = android.AndroidMkEntriesForTest(t, config, "", m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
- expectedPath = []string{"/tmp/target/product/test_device/system/overlay"}
- if !reflect.DeepEqual(path, expectedPath) {
- t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath)
- }
-}
-
-func TestOverrideRuntimeResourceOverlay(t *testing.T) {
- ctx, _ := testJava(t, `
- runtime_resource_overlay {
- name: "foo_overlay",
- certificate: "platform",
- product_specific: true,
- sdk_version: "current",
- }
-
- override_runtime_resource_overlay {
- name: "bar_overlay",
- base: "foo_overlay",
- package_name: "com.android.bar.overlay",
- target_package_name: "com.android.bar",
- }
- `)
-
- expectedVariants := []struct {
- moduleName string
- variantName string
- apkPath string
- overrides []string
- targetVariant string
- packageFlag string
- targetPackageFlag string
- }{
- {
- variantName: "android_common",
- apkPath: "/target/product/test_device/product/overlay/foo_overlay.apk",
- overrides: nil,
- targetVariant: "android_common",
- packageFlag: "",
- targetPackageFlag: "",
- },
- {
- variantName: "android_common_bar_overlay",
- apkPath: "/target/product/test_device/product/overlay/bar_overlay.apk",
- overrides: []string{"foo_overlay"},
- targetVariant: "android_common_bar",
- packageFlag: "com.android.bar.overlay",
- targetPackageFlag: "com.android.bar",
- },
- }
- for _, expected := range expectedVariants {
- variant := ctx.ModuleForTests("foo_overlay", expected.variantName)
-
- // Check the final apk name
- outputs := variant.AllOutputs()
- expectedApkPath := buildDir + expected.apkPath
- found := false
- for _, o := range outputs {
- if o == expectedApkPath {
- found = true
- break
- }
- }
- if !found {
- t.Errorf("Can't find %q in output files.\nAll outputs:%v", expectedApkPath, outputs)
- }
-
- // Check if the overrides field values are correctly aggregated.
- mod := variant.Module().(*RuntimeResourceOverlay)
- if !reflect.DeepEqual(expected.overrides, mod.properties.Overrides) {
- t.Errorf("Incorrect overrides property value, expected: %q, got: %q",
- expected.overrides, mod.properties.Overrides)
- }
-
- // Check aapt2 flags.
- res := variant.Output("package-res.apk")
- aapt2Flags := res.Args["flags"]
- checkAapt2LinkFlag(t, aapt2Flags, "rename-manifest-package", expected.packageFlag)
- checkAapt2LinkFlag(t, aapt2Flags, "rename-resources-package", "")
- checkAapt2LinkFlag(t, aapt2Flags, "rename-overlay-target-package", expected.targetPackageFlag)
- }
-}
-
-func TestEnforceRRO_propagatesToDependencies(t *testing.T) {
- testCases := []struct {
- name string
- enforceRROTargets []string
- enforceRROExemptTargets []string
- rroDirs map[string][]string
- }{
- {
- name: "no RRO",
- enforceRROTargets: nil,
- enforceRROExemptTargets: nil,
- rroDirs: map[string][]string{
- "foo": nil,
- "bar": nil,
- },
- },
- {
- name: "enforce RRO on all",
- enforceRROTargets: []string{"*"},
- enforceRROExemptTargets: nil,
- rroDirs: map[string][]string{
- "foo": {"product/vendor/blah/overlay/lib2/res"},
- "bar": {"product/vendor/blah/overlay/lib2/res"},
- },
- },
- {
- name: "enforce RRO on foo",
- enforceRROTargets: []string{"foo"},
- enforceRROExemptTargets: nil,
- rroDirs: map[string][]string{
- "foo": {"product/vendor/blah/overlay/lib2/res"},
- "bar": {"product/vendor/blah/overlay/lib2/res"},
- },
- },
- {
- name: "enforce RRO on foo, bar exempted",
- enforceRROTargets: []string{"foo"},
- enforceRROExemptTargets: []string{"bar"},
- rroDirs: map[string][]string{
- "foo": {"product/vendor/blah/overlay/lib2/res"},
- "bar": nil,
- },
- },
- }
-
- productResourceOverlays := []string{
- "product/vendor/blah/overlay",
- }
-
- fs := map[string][]byte{
- "lib2/res/values/strings.xml": nil,
- "product/vendor/blah/overlay/lib2/res/values/strings.xml": nil,
- }
-
- bp := `
- android_app {
- name: "foo",
- sdk_version: "current",
- resource_dirs: [],
- static_libs: ["lib"],
- }
-
- android_app {
- name: "bar",
- sdk_version: "current",
- resource_dirs: [],
- static_libs: ["lib"],
- }
-
- android_library {
- name: "lib",
- sdk_version: "current",
- resource_dirs: [],
- static_libs: ["lib2"],
- }
-
- android_library {
- name: "lib2",
- sdk_version: "current",
- resource_dirs: ["lib2/res"],
- }
- `
-
- for _, testCase := range testCases {
- t.Run(testCase.name, func(t *testing.T) {
- config := testAppConfig(nil, bp, fs)
- config.TestProductVariables.ProductResourceOverlays = productResourceOverlays
- if testCase.enforceRROTargets != nil {
- config.TestProductVariables.EnforceRROTargets = testCase.enforceRROTargets
- }
- if testCase.enforceRROExemptTargets != nil {
- config.TestProductVariables.EnforceRROExemptedTargets = testCase.enforceRROExemptTargets
- }
-
- ctx := testContext(config)
- run(t, ctx, config)
-
- modules := []string{"foo", "bar"}
- for _, moduleName := range modules {
- module := ctx.ModuleForTests(moduleName, "android_common")
- mkEntries := android.AndroidMkEntriesForTest(t, config, "", module.Module())[0]
- actualRRODirs := mkEntries.EntryMap["LOCAL_SOONG_PRODUCT_RRO_DIRS"]
- if !reflect.DeepEqual(actualRRODirs, testCase.rroDirs[moduleName]) {
- t.Errorf("exected %s LOCAL_SOONG_PRODUCT_RRO_DIRS entry: %v\ngot:%q",
- moduleName, testCase.rroDirs[moduleName], actualRRODirs)
- }
- }
- })
- }
-}
-
func TestExportedProguardFlagFiles(t *testing.T) {
ctx, _ := testJava(t, `
android_app {
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 67738d4..b5830c7 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -112,13 +112,13 @@
return dexpreopt.OdexOnSystemOtherByName(ctx.ModuleName(), android.InstallPathToOnDevicePath(ctx, installPath), dexpreopt.GetGlobalConfig(ctx))
}
-func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.ModuleOutPath) android.ModuleOutPath {
+func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.ModuleOutPath) {
// TODO(b/148690468): The check on d.installPath is to bail out in cases where
// the dexpreopter struct hasn't been fully initialized before we're called,
// e.g. in aar.go. This keeps the behaviour that dexpreopting is effectively
// disabled, even if installable is true.
if d.dexpreoptDisabled(ctx) || d.installPath.Base() == "." {
- return dexJarFile
+ return
}
globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
@@ -213,12 +213,10 @@
dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, globalSoong, global, dexpreoptConfig)
if err != nil {
ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error())
- return dexJarFile
+ return
}
dexpreoptRule.Build("dexpreopt", "dexpreopt")
d.builtInstalled = dexpreoptRule.Installs().String()
-
- return dexJarFile
}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 9c88a3c..c74009e 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -192,24 +192,6 @@
Current ApiToCheck
- // The java_sdk_library module generates references to modules (i.e. filegroups)
- // from which information about the latest API version can be obtained. As those
- // modules may not exist (e.g. because a previous version has not been released) it
- // sets ignore_missing_latest_api=true on the droidstubs modules it creates so
- // that droidstubs can ignore those references if the modules do not yet exist.
- //
- // If true then this will ignore module references for modules that do not exist
- // in properties that supply the previous version of the API.
- //
- // There are two sets of those:
- // * Api_file, Removed_api_file in check_api.last_released
- // * New_since in check_api.api_lint.new_since
- //
- // The first two must be set as a pair, so either they should both exist or neither
- // should exist - in which case when this property is true they are ignored. If one
- // exists and the other does not then it is an error.
- Ignore_missing_latest_api *bool `blueprint:"mutated"`
-
Api_lint struct {
Enabled *bool
@@ -304,25 +286,6 @@
return false
}
-func ignoreMissingModules(ctx android.BottomUpMutatorContext, apiToCheck *ApiToCheck) {
- api_file := String(apiToCheck.Api_file)
- removed_api_file := String(apiToCheck.Removed_api_file)
-
- api_module := android.SrcIsModule(api_file)
- removed_api_module := android.SrcIsModule(removed_api_file)
-
- if api_module == "" || removed_api_module == "" {
- return
- }
-
- if ctx.OtherModuleExists(api_module) || ctx.OtherModuleExists(removed_api_module) {
- return
- }
-
- apiToCheck.Api_file = nil
- apiToCheck.Removed_api_file = nil
-}
-
// Used by xsd_config
type ApiFilePath interface {
ApiFilePath() android.Path
@@ -1079,20 +1042,6 @@
func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
d.Javadoc.addDeps(ctx)
- // If requested clear any properties that provide information about the latest version
- // of an API and which reference non-existent modules.
- if Bool(d.properties.Check_api.Ignore_missing_latest_api) {
- ignoreMissingModules(ctx, &d.properties.Check_api.Last_released)
-
- // If the new_since references a module, e.g. :module-latest-api and the module
- // does not exist then clear it.
- newSinceSrc := d.properties.Check_api.Api_lint.New_since
- newSinceSrcModule := android.SrcIsModule(proptools.String(newSinceSrc))
- if newSinceSrcModule != "" && !ctx.OtherModuleExists(newSinceSrcModule) {
- d.properties.Check_api.Api_lint.New_since = nil
- }
- }
-
if len(d.properties.Merge_annotations_dirs) != 0 {
for _, mergeAnnotationsDir := range d.properties.Merge_annotations_dirs {
ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir)
diff --git a/java/gen.go b/java/gen.go
index 5766a94..4f928d5 100644
--- a/java/gen.go
+++ b/java/gen.go
@@ -78,10 +78,7 @@
rule.Command().
Tool(ctx.Config().HostToolPath(ctx, "soong_zip")).
- // TODO(b/124333557): this can't use -srcjar for now, aidl on parcelables generates java files
- // without a package statement, which causes -srcjar to put them in the top level of the zip file.
- // Once aidl skips parcelables we can use -srcjar.
- //Flag("-srcjar").
+ Flag("-srcjar").
Flag("-write_if_changed").
FlagWithOutput("-o ", srcJarFile).
FlagWithArg("-C ", outDir.String()).
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index 34a4856..955c739 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -85,7 +85,7 @@
hiddenAPI := ctx.SingletonForTests("hiddenapi")
hiddenapiRule := hiddenAPI.Rule("hiddenapi")
- want := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/dex/foo.jar"
+ want := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/aligned/foo.jar"
if !strings.Contains(hiddenapiRule.RuleParams.Command, want) {
t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", want, hiddenapiRule.RuleParams.Command)
}
diff --git a/java/java.go b/java/java.go
index 02d78f2..18dd9bd 100644
--- a/java/java.go
+++ b/java/java.go
@@ -510,6 +510,7 @@
type UsesLibraryDependency interface {
DexJarBuildPath() android.Path
DexJarInstallPath() android.Path
+ ClassLoaderContexts() dexpreopt.ClassLoaderContextMap
}
type Dependency interface {
@@ -518,7 +519,6 @@
ImplementationJars() android.Paths
ResourceJars() android.Paths
AidlIncludeDirs() android.Paths
- ClassLoaderContexts() dexpreopt.ClassLoaderContextMap
ExportedPlugins() (android.Paths, []string, bool)
SrcJarArgs() ([]string, android.Paths)
BaseModuleName() string
@@ -1081,8 +1081,6 @@
switch tag {
case libTag:
deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
- j.classLoaderContexts.MaybeAddContext(ctx, dep.OptionalImplicitSdkLibrary(),
- dep.DexJarBuildPath(), dep.DexJarInstallPath())
case staticLibTag:
ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
}
@@ -1092,7 +1090,6 @@
deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars()...)
case libTag, instrumentationForTag:
deps.classpath = append(deps.classpath, dep.HeaderJars()...)
- j.classLoaderContexts.AddContextMap(dep.ClassLoaderContexts(), otherName)
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
pluginJars, pluginClasses, disableTurbine := dep.ExportedPlugins()
addPlugins(&deps, pluginJars, pluginClasses...)
@@ -1179,8 +1176,7 @@
}
}
- // Merge dep's CLC after processing the dep itself (which may add its own <uses-library>).
- maybeAddCLCFromDep(module, tag, otherName, j.classLoaderContexts)
+ addCLCFromDep(ctx, module, j.classLoaderContexts)
})
return deps
@@ -1509,11 +1505,11 @@
j.compiledJavaSrcs = uniqueSrcFiles
j.compiledSrcJars = srcJars
- enable_sharding := false
+ enableSharding := false
var headerJarFileWithoutJarjar android.Path
if ctx.Device() && !ctx.Config().IsEnvFalse("TURBINE_ENABLED") && !deps.disableTurbine {
if j.properties.Javac_shard_size != nil && *(j.properties.Javac_shard_size) > 0 {
- enable_sharding = true
+ enableSharding = true
// Formerly, there was a check here that prevented annotation processors
// from being used when sharding was enabled, as some annotation processors
// do not function correctly in sharded environments. It was removed to
@@ -1539,7 +1535,7 @@
extraJarDeps = append(extraJarDeps, errorprone)
}
- if enable_sharding {
+ if enableSharding {
flags.classpath = append(flags.classpath, headerJarFileWithoutJarjar)
shardSize := int(*(j.properties.Javac_shard_size))
var shardSrcs []android.Paths
@@ -1786,7 +1782,7 @@
j.dexJarFile = dexOutputFile
// Dexpreopting
- dexOutputFile = j.dexpreopt(ctx, dexOutputFile)
+ j.dexpreopt(ctx, dexOutputFile)
j.maybeStrippedDexJarFile = dexOutputFile
@@ -2137,18 +2133,6 @@
j.installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
j.Stem()+".jar", j.outputFile, extraInstallDeps...)
}
-
- // If this is a component library (stubs, etc.) for a java_sdk_library then
- // add the name of that java_sdk_library to the exported sdk libs to make sure
- // that, if necessary, a <uses-library> element for that java_sdk_library is
- // added to the Android manifest.
- j.classLoaderContexts.MaybeAddContext(ctx, j.OptionalImplicitSdkLibrary(),
- j.DexJarBuildPath(), j.DexJarInstallPath())
-
- // A non-SDK library may provide a <uses-library> (the name may be different from the module name).
- if lib := proptools.String(j.usesLibraryProperties.Provides_uses_lib); lib != "" {
- j.classLoaderContexts.AddContext(ctx, lib, j.DexJarBuildPath(), j.DexJarInstallPath())
- }
}
func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -2723,6 +2707,7 @@
hiddenAPI
dexer
+ dexpreopter
properties ImportProperties
@@ -2810,7 +2795,6 @@
var flags javaBuilderFlags
ctx.VisitDirectDeps(func(module android.Module) {
- otherName := ctx.OtherModuleName(module)
tag := ctx.OtherModuleDependencyTag(module)
switch dep := module.(type) {
@@ -2825,27 +2809,17 @@
switch tag {
case libTag:
flags.classpath = append(flags.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
- j.classLoaderContexts.AddContext(ctx, otherName, dep.DexJarBuildPath(), dep.DexJarInstallPath())
}
}
- // Merge dep's CLC after processing the dep itself (which may add its own <uses-library>).
- maybeAddCLCFromDep(module, tag, otherName, j.classLoaderContexts)
+ addCLCFromDep(ctx, module, j.classLoaderContexts)
})
- var installFile android.Path
if Bool(j.properties.Installable) {
- installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
+ ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
jarName, outputFile)
}
- // If this is a component library (impl, stubs, etc.) for a java_sdk_library then
- // add the name of that java_sdk_library to the exported sdk libs to make sure
- // that, if necessary, a <uses-library> element for that java_sdk_library is
- // added to the Android manifest.
- j.classLoaderContexts.MaybeAddContext(ctx, j.OptionalImplicitSdkLibrary(),
- outputFile, installFile)
-
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs)
if ctx.Device() && Bool(j.dexProperties.Compile_dex) {
@@ -2859,6 +2833,14 @@
}
// Dex compilation
+
+ j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", jarName)
+ if j.dexProperties.Uncompress_dex == nil {
+ // If the value was not force-set by the user, use reasonable default based on the module.
+ j.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter))
+ }
+ j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
+
var dexOutputFile android.ModuleOutPath
dexOutputFile = j.dexer.compileDex(ctx, flags, j.minSdkVersion(), outputFile, jarName)
if ctx.Failed() {
@@ -2978,6 +2960,12 @@
var _ android.PrebuiltInterface = (*Import)(nil)
+func (j *Import) IsInstallable() bool {
+ return Bool(j.properties.Installable)
+}
+
+var _ dexpreopterInterface = (*Import)(nil)
+
// java_import imports one or more `.jar` files into the build graph as if they were built by a java_library module.
//
// By default, a java_import has a single variant that expects a `.jar` file containing `.class` files that were
@@ -3123,7 +3111,7 @@
j.dexJarFile = dexOutputFile
- dexOutputFile = j.dexpreopt(ctx, dexOutputFile)
+ j.dexpreopt(ctx, dexOutputFile)
j.maybeStrippedDexJarFile = dexOutputFile
@@ -3259,30 +3247,63 @@
var String = proptools.String
var inList = android.InList
-// Add class loader context of a given dependency to the given class loader context, provided that
-// all the necessary conditions are met.
-func maybeAddCLCFromDep(depModule android.Module, depTag blueprint.DependencyTag,
- depName string, clcMap dexpreopt.ClassLoaderContextMap) {
+// TODO(b/132357300) Generalize SdkLibrarComponentDependency to non-SDK libraries and merge with
+// this interface.
+type ProvidesUsesLib interface {
+ ProvidesUsesLib() *string
+}
- if dep, ok := depModule.(Dependency); ok {
- if depTag == libTag {
- // Ok, propagate <uses-library> through non-static library dependencies.
- } else if depTag == staticLibTag {
- // Propagate <uses-library> through static library dependencies, unless it is a
- // component library (such as stubs). Component libraries have a dependency on their
- // SDK library, which should not be pulled just because of a static component library.
- if comp, isComp := depModule.(SdkLibraryComponentDependency); isComp {
- if compName := comp.OptionalImplicitSdkLibrary(); compName != nil {
- dep = nil
- }
- }
- } else {
- // Don't propagate <uses-library> for other dependency tags.
- dep = nil
- }
+func (j *Module) ProvidesUsesLib() *string {
+ return j.usesLibraryProperties.Provides_uses_lib
+}
- if dep != nil {
- clcMap.AddContextMap(dep.ClassLoaderContexts(), depName)
+// Add class loader context (CLC) of a given dependency to the current CLC.
+func addCLCFromDep(ctx android.ModuleContext, depModule android.Module,
+ clcMap dexpreopt.ClassLoaderContextMap) {
+
+ dep, ok := depModule.(UsesLibraryDependency)
+ if !ok {
+ return
+ }
+
+ // Find out if the dependency is either an SDK library or an ordinary library that is disguised
+ // as an SDK library by the means of `provides_uses_lib` property. If yes, the library is itself
+ // a <uses-library> and should be added as a node in the CLC tree, and its CLC should be added
+ // as subtree of that node. Otherwise the library is not a <uses_library> and should not be
+ // added to CLC, but the transitive <uses-library> dependencies from its CLC should be added to
+ // the current CLC.
+ var implicitSdkLib *string
+ comp, isComp := depModule.(SdkLibraryComponentDependency)
+ if isComp {
+ implicitSdkLib = comp.OptionalImplicitSdkLibrary()
+ // OptionalImplicitSdkLibrary() may be nil so need to fall through to ProvidesUsesLib().
+ }
+ if implicitSdkLib == nil {
+ if ulib, ok := depModule.(ProvidesUsesLib); ok {
+ implicitSdkLib = ulib.ProvidesUsesLib()
}
}
+
+ depTag := ctx.OtherModuleDependencyTag(depModule)
+ if depTag == libTag || depTag == usesLibTag {
+ // Ok, propagate <uses-library> through non-static library dependencies.
+ } else if depTag == staticLibTag {
+ // Propagate <uses-library> through static library dependencies, unless it is a component
+ // library (such as stubs). Component libraries have a dependency on their SDK library,
+ // which should not be pulled just because of a static component library.
+ if implicitSdkLib != nil {
+ return
+ }
+ } else {
+ // Don't propagate <uses-library> for other dependency tags.
+ return
+ }
+
+ if implicitSdkLib != nil {
+ clcMap.AddContextForSdk(ctx, dexpreopt.AnySdkVersion, *implicitSdkLib,
+ dep.DexJarBuildPath(), dep.DexJarInstallPath(), dep.ClassLoaderContexts())
+ } else {
+ depName := ctx.OtherModuleName(depModule)
+ clcMap.AddContextMap(dep.ClassLoaderContexts(), depName)
+ }
}
diff --git a/java/java_test.go b/java/java_test.go
index f7cf03f..d1ba3db 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -75,20 +75,22 @@
ctx := android.NewTestArchContext(config)
RegisterJavaBuildComponents(ctx)
RegisterAppBuildComponents(ctx)
+ RegisterAppImportBuildComponents(ctx)
+ RegisterAppSetBuildComponents(ctx)
RegisterAARBuildComponents(ctx)
RegisterGenRuleBuildComponents(ctx)
+ RegisterRuntimeResourceOverlayBuildComponents(ctx)
RegisterSystemModulesBuildComponents(ctx)
ctx.RegisterModuleType("java_plugin", PluginFactory)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("python_binary_host", python.PythonBinaryHostFactory)
RegisterDocsBuildComponents(ctx)
RegisterStubsBuildComponents(ctx)
+ RegisterPrebuiltApisBuildComponents(ctx)
RegisterSdkLibraryBuildComponents(ctx)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
ctx.PreArchMutators(android.RegisterComponentsMutator)
- RegisterPrebuiltApisBuildComponents(ctx)
-
ctx.PreDepsMutators(python.RegisterPythonPreDepsMutators)
ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
ctx.RegisterPreSingletonType("overlay", android.SingletonFactoryAdaptor(ctx.Context, OverlaySingletonFactory))
@@ -1813,7 +1815,7 @@
func TestJavaSdkLibrary_StubOrImplOnlyLibs(t *testing.T) {
ctx, _ := testJava(t, `
java_sdk_library {
- name: "sdk_lib",
+ name: "sdklib",
srcs: ["a.java"],
impl_only_libs: ["foo"],
stub_only_libs: ["bar"],
@@ -1830,13 +1832,13 @@
}
`)
- for _, implName := range []string{"sdk_lib", "sdk_lib.impl"} {
+ for _, implName := range []string{"sdklib", "sdklib.impl"} {
implJavacCp := ctx.ModuleForTests(implName, "android_common").Rule("javac").Args["classpath"]
if !strings.Contains(implJavacCp, "/foo.jar") || strings.Contains(implJavacCp, "/bar.jar") {
t.Errorf("%v javac classpath %v does not contain foo and not bar", implName, implJavacCp)
}
}
- stubName := apiScopePublic.stubsLibraryModuleName("sdk_lib")
+ stubName := apiScopePublic.stubsLibraryModuleName("sdklib")
stubsJavacCp := ctx.ModuleForTests(stubName, "android_common").Rule("javac").Args["classpath"]
if strings.Contains(stubsJavacCp, "/foo.jar") || !strings.Contains(stubsJavacCp, "/bar.jar") {
t.Errorf("stubs javac classpath %v does not contain bar and not foo", stubsJavacCp)
diff --git a/java/proto.go b/java/proto.go
index cc9abbe..dc5519f 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -49,7 +49,7 @@
// into a srcjar.
rule.Command().
BuiltTool("soong_zip").
- Flag("-jar").
+ Flag("-srcjar").
Flag("-write_if_changed").
FlagWithOutput("-o ", srcJarFile).
FlagWithArg("-C ", outDir.String()).
diff --git a/java/rro.go b/java/rro.go
new file mode 100644
index 0000000..98cd379
--- /dev/null
+++ b/java/rro.go
@@ -0,0 +1,214 @@
+// Copyright 2020 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
+
+// This file contains the module implementations for runtime_resource_overlay and
+// override_runtime_resource_overlay.
+
+import "android/soong/android"
+
+func init() {
+ RegisterRuntimeResourceOverlayBuildComponents(android.InitRegistrationContext)
+}
+
+func RegisterRuntimeResourceOverlayBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("runtime_resource_overlay", RuntimeResourceOverlayFactory)
+ ctx.RegisterModuleType("override_runtime_resource_overlay", OverrideRuntimeResourceOverlayModuleFactory)
+}
+
+type RuntimeResourceOverlay struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+ android.OverridableModuleBase
+ aapt
+
+ properties RuntimeResourceOverlayProperties
+ overridableProperties OverridableRuntimeResourceOverlayProperties
+
+ certificate Certificate
+
+ outputFile android.Path
+ installDir android.InstallPath
+}
+
+type RuntimeResourceOverlayProperties struct {
+ // the name of a certificate in the default certificate directory or an android_app_certificate
+ // module name in the form ":module".
+ Certificate *string
+
+ // Name of the signing certificate lineage file.
+ Lineage *string
+
+ // optional theme name. If specified, the overlay package will be applied
+ // only when the ro.boot.vendor.overlay.theme system property is set to the same value.
+ Theme *string
+
+ // if not blank, set to the version of the sdk to compile against.
+ // Defaults to compiling against the current platform.
+ Sdk_version *string
+
+ // if not blank, set the minimum version of the sdk that the compiled artifacts will run against.
+ // Defaults to sdk_version if not set.
+ Min_sdk_version *string
+
+ // list of android_library modules whose resources are extracted and linked against statically
+ Static_libs []string
+
+ // list of android_app modules whose resources are extracted and linked against
+ Resource_libs []string
+
+ // Names of modules to be overridden. Listed modules can only be other overlays
+ // (in Make or Soong).
+ // This does not completely prevent installation of the overridden overlays, but if both
+ // overlays would be installed by default (in PRODUCT_PACKAGES) the other overlay will be removed
+ // from PRODUCT_PACKAGES.
+ Overrides []string
+}
+
+// RuntimeResourceOverlayModule interface is used by the apex package to gather information from
+// a RuntimeResourceOverlay module.
+type RuntimeResourceOverlayModule interface {
+ android.Module
+ OutputFile() android.Path
+ Certificate() Certificate
+ Theme() string
+}
+
+func (r *RuntimeResourceOverlay) DepsMutator(ctx android.BottomUpMutatorContext) {
+ sdkDep := decodeSdkDep(ctx, sdkContext(r))
+ if sdkDep.hasFrameworkLibs() {
+ r.aapt.deps(ctx, sdkDep)
+ }
+
+ cert := android.SrcIsModule(String(r.properties.Certificate))
+ if cert != "" {
+ ctx.AddDependency(ctx.Module(), certificateTag, cert)
+ }
+
+ ctx.AddVariationDependencies(nil, staticLibTag, r.properties.Static_libs...)
+ ctx.AddVariationDependencies(nil, libTag, r.properties.Resource_libs...)
+}
+
+func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ // Compile and link resources
+ r.aapt.hasNoCode = true
+ // Do not remove resources without default values nor dedupe resource configurations with the same value
+ aaptLinkFlags := []string{"--no-resource-deduping", "--no-resource-removal"}
+ // Allow the override of "package name" and "overlay target package name"
+ manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(ctx.ModuleName())
+ if overridden || r.overridableProperties.Package_name != nil {
+ // The product override variable has a priority over the package_name property.
+ if !overridden {
+ manifestPackageName = *r.overridableProperties.Package_name
+ }
+ aaptLinkFlags = append(aaptLinkFlags, generateAaptRenamePackageFlags(manifestPackageName, false)...)
+ }
+ if r.overridableProperties.Target_package_name != nil {
+ aaptLinkFlags = append(aaptLinkFlags,
+ "--rename-overlay-target-package "+*r.overridableProperties.Target_package_name)
+ }
+ r.aapt.buildActions(ctx, r, nil, aaptLinkFlags...)
+
+ // Sign the built package
+ _, certificates := collectAppDeps(ctx, r, false, false)
+ certificates = processMainCert(r.ModuleBase, String(r.properties.Certificate), certificates, ctx)
+ signed := android.PathForModuleOut(ctx, "signed", r.Name()+".apk")
+ var lineageFile android.Path
+ if lineage := String(r.properties.Lineage); lineage != "" {
+ lineageFile = android.PathForModuleSrc(ctx, lineage)
+ }
+ SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates, nil, lineageFile)
+ r.certificate = certificates[0]
+
+ r.outputFile = signed
+ r.installDir = android.PathForModuleInstall(ctx, "overlay", String(r.properties.Theme))
+ ctx.InstallFile(r.installDir, r.outputFile.Base(), r.outputFile)
+}
+
+func (r *RuntimeResourceOverlay) sdkVersion() sdkSpec {
+ return sdkSpecFrom(String(r.properties.Sdk_version))
+}
+
+func (r *RuntimeResourceOverlay) systemModules() string {
+ return ""
+}
+
+func (r *RuntimeResourceOverlay) minSdkVersion() sdkSpec {
+ if r.properties.Min_sdk_version != nil {
+ return sdkSpecFrom(*r.properties.Min_sdk_version)
+ }
+ return r.sdkVersion()
+}
+
+func (r *RuntimeResourceOverlay) targetSdkVersion() sdkSpec {
+ return r.sdkVersion()
+}
+
+func (r *RuntimeResourceOverlay) Certificate() Certificate {
+ return r.certificate
+}
+
+func (r *RuntimeResourceOverlay) OutputFile() android.Path {
+ return r.outputFile
+}
+
+func (r *RuntimeResourceOverlay) Theme() string {
+ return String(r.properties.Theme)
+}
+
+// runtime_resource_overlay generates a resource-only apk file that can overlay application and
+// system resources at run time.
+func RuntimeResourceOverlayFactory() android.Module {
+ module := &RuntimeResourceOverlay{}
+ module.AddProperties(
+ &module.properties,
+ &module.aaptProperties,
+ &module.overridableProperties)
+
+ android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+ android.InitOverridableModule(module, &module.properties.Overrides)
+ return module
+}
+
+// runtime_resource_overlay properties that can be overridden by override_runtime_resource_overlay
+type OverridableRuntimeResourceOverlayProperties struct {
+ // the package name of this app. The package name in the manifest file is used if one was not given.
+ Package_name *string
+
+ // the target package name of this overlay app. The target package name in the manifest file is used if one was not given.
+ Target_package_name *string
+}
+
+type OverrideRuntimeResourceOverlay struct {
+ android.ModuleBase
+ android.OverrideModuleBase
+}
+
+func (i *OverrideRuntimeResourceOverlay) GenerateAndroidBuildActions(_ android.ModuleContext) {
+ // All the overrides happen in the base module.
+ // TODO(jungjw): Check the base module type.
+}
+
+// override_runtime_resource_overlay is used to create a module based on another
+// runtime_resource_overlay module by overriding some of its properties.
+func OverrideRuntimeResourceOverlayModuleFactory() android.Module {
+ m := &OverrideRuntimeResourceOverlay{}
+ m.AddProperties(&OverridableRuntimeResourceOverlayProperties{})
+
+ android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibCommon)
+ android.InitOverrideModule(m)
+ return m
+}
diff --git a/java/rro_test.go b/java/rro_test.go
new file mode 100644
index 0000000..345f2ee
--- /dev/null
+++ b/java/rro_test.go
@@ -0,0 +1,373 @@
+// Copyright 2020 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 (
+ "reflect"
+ "strings"
+ "testing"
+
+ "android/soong/android"
+)
+
+func TestRuntimeResourceOverlay(t *testing.T) {
+ fs := map[string][]byte{
+ "baz/res/res/values/strings.xml": nil,
+ "bar/res/res/values/strings.xml": nil,
+ }
+ bp := `
+ runtime_resource_overlay {
+ name: "foo",
+ certificate: "platform",
+ lineage: "lineage.bin",
+ product_specific: true,
+ static_libs: ["bar"],
+ resource_libs: ["baz"],
+ aaptflags: ["--keep-raw-values"],
+ }
+
+ runtime_resource_overlay {
+ name: "foo_themed",
+ certificate: "platform",
+ product_specific: true,
+ theme: "faza",
+ overrides: ["foo"],
+ }
+
+ android_library {
+ name: "bar",
+ resource_dirs: ["bar/res"],
+ }
+
+ android_app {
+ name: "baz",
+ sdk_version: "current",
+ resource_dirs: ["baz/res"],
+ }
+ `
+ config := testAppConfig(nil, bp, fs)
+ ctx := testContext(config)
+ run(t, ctx, config)
+
+ m := ctx.ModuleForTests("foo", "android_common")
+
+ // Check AAPT2 link flags.
+ aapt2Flags := m.Output("package-res.apk").Args["flags"]
+ expectedFlags := []string{"--keep-raw-values", "--no-resource-deduping", "--no-resource-removal"}
+ absentFlags := android.RemoveListFromList(expectedFlags, strings.Split(aapt2Flags, " "))
+ if len(absentFlags) > 0 {
+ t.Errorf("expected values, %q are missing in aapt2 link flags, %q", absentFlags, aapt2Flags)
+ }
+
+ // Check overlay.list output for static_libs dependency.
+ overlayList := m.Output("aapt2/overlay.list").Inputs.Strings()
+ staticLibPackage := buildDir + "/.intermediates/bar/android_common/package-res.apk"
+ if !inList(staticLibPackage, overlayList) {
+ t.Errorf("Stactic lib res package %q missing in overlay list: %q", staticLibPackage, overlayList)
+ }
+
+ // Check AAPT2 link flags for resource_libs dependency.
+ resourceLibFlag := "-I " + buildDir + "/.intermediates/baz/android_common/package-res.apk"
+ if !strings.Contains(aapt2Flags, resourceLibFlag) {
+ t.Errorf("Resource lib flag %q missing in aapt2 link flags: %q", resourceLibFlag, aapt2Flags)
+ }
+
+ // Check cert signing flag.
+ signedApk := m.Output("signed/foo.apk")
+ lineageFlag := signedApk.Args["flags"]
+ expectedLineageFlag := "--lineage lineage.bin"
+ if expectedLineageFlag != lineageFlag {
+ t.Errorf("Incorrect signing lineage flags, expected: %q, got: %q", expectedLineageFlag, lineageFlag)
+ }
+ signingFlag := signedApk.Args["certificates"]
+ expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8"
+ if expected != signingFlag {
+ t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
+ }
+ androidMkEntries := android.AndroidMkEntriesForTest(t, config, "", m.Module())[0]
+ path := androidMkEntries.EntryMap["LOCAL_CERTIFICATE"]
+ expectedPath := []string{"build/make/target/product/security/platform.x509.pem"}
+ if !reflect.DeepEqual(path, expectedPath) {
+ t.Errorf("Unexpected LOCAL_CERTIFICATE value: %v, expected: %v", path, expectedPath)
+ }
+
+ // Check device location.
+ path = androidMkEntries.EntryMap["LOCAL_MODULE_PATH"]
+ expectedPath = []string{"/tmp/target/product/test_device/product/overlay"}
+ if !reflect.DeepEqual(path, expectedPath) {
+ t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath)
+ }
+
+ // A themed module has a different device location
+ m = ctx.ModuleForTests("foo_themed", "android_common")
+ androidMkEntries = android.AndroidMkEntriesForTest(t, config, "", m.Module())[0]
+ path = androidMkEntries.EntryMap["LOCAL_MODULE_PATH"]
+ expectedPath = []string{"/tmp/target/product/test_device/product/overlay/faza"}
+ if !reflect.DeepEqual(path, expectedPath) {
+ t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath)
+ }
+
+ overrides := androidMkEntries.EntryMap["LOCAL_OVERRIDES_PACKAGES"]
+ expectedOverrides := []string{"foo"}
+ if !reflect.DeepEqual(overrides, expectedOverrides) {
+ t.Errorf("Unexpected LOCAL_OVERRIDES_PACKAGES value: %v, expected: %v", overrides, expectedOverrides)
+ }
+}
+
+func TestRuntimeResourceOverlay_JavaDefaults(t *testing.T) {
+ ctx, config := testJava(t, `
+ java_defaults {
+ name: "rro_defaults",
+ theme: "default_theme",
+ product_specific: true,
+ aaptflags: ["--keep-raw-values"],
+ }
+
+ runtime_resource_overlay {
+ name: "foo_with_defaults",
+ defaults: ["rro_defaults"],
+ }
+
+ runtime_resource_overlay {
+ name: "foo_barebones",
+ }
+ `)
+
+ //
+ // RRO module with defaults
+ //
+ m := ctx.ModuleForTests("foo_with_defaults", "android_common")
+
+ // Check AAPT2 link flags.
+ aapt2Flags := strings.Split(m.Output("package-res.apk").Args["flags"], " ")
+ expectedFlags := []string{"--keep-raw-values", "--no-resource-deduping", "--no-resource-removal"}
+ absentFlags := android.RemoveListFromList(expectedFlags, aapt2Flags)
+ if len(absentFlags) > 0 {
+ t.Errorf("expected values, %q are missing in aapt2 link flags, %q", absentFlags, aapt2Flags)
+ }
+
+ // Check device location.
+ path := android.AndroidMkEntriesForTest(t, config, "", m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
+ expectedPath := []string{"/tmp/target/product/test_device/product/overlay/default_theme"}
+ if !reflect.DeepEqual(path, expectedPath) {
+ t.Errorf("Unexpected LOCAL_MODULE_PATH value: %q, expected: %q", path, expectedPath)
+ }
+
+ //
+ // RRO module without defaults
+ //
+ m = ctx.ModuleForTests("foo_barebones", "android_common")
+
+ // Check AAPT2 link flags.
+ aapt2Flags = strings.Split(m.Output("package-res.apk").Args["flags"], " ")
+ unexpectedFlags := "--keep-raw-values"
+ if inList(unexpectedFlags, aapt2Flags) {
+ t.Errorf("unexpected value, %q is present in aapt2 link flags, %q", unexpectedFlags, aapt2Flags)
+ }
+
+ // Check device location.
+ path = android.AndroidMkEntriesForTest(t, config, "", m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
+ expectedPath = []string{"/tmp/target/product/test_device/system/overlay"}
+ if !reflect.DeepEqual(path, expectedPath) {
+ t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath)
+ }
+}
+
+func TestOverrideRuntimeResourceOverlay(t *testing.T) {
+ ctx, _ := testJava(t, `
+ runtime_resource_overlay {
+ name: "foo_overlay",
+ certificate: "platform",
+ product_specific: true,
+ sdk_version: "current",
+ }
+
+ override_runtime_resource_overlay {
+ name: "bar_overlay",
+ base: "foo_overlay",
+ package_name: "com.android.bar.overlay",
+ target_package_name: "com.android.bar",
+ }
+ `)
+
+ expectedVariants := []struct {
+ moduleName string
+ variantName string
+ apkPath string
+ overrides []string
+ targetVariant string
+ packageFlag string
+ targetPackageFlag string
+ }{
+ {
+ variantName: "android_common",
+ apkPath: "/target/product/test_device/product/overlay/foo_overlay.apk",
+ overrides: nil,
+ targetVariant: "android_common",
+ packageFlag: "",
+ targetPackageFlag: "",
+ },
+ {
+ variantName: "android_common_bar_overlay",
+ apkPath: "/target/product/test_device/product/overlay/bar_overlay.apk",
+ overrides: []string{"foo_overlay"},
+ targetVariant: "android_common_bar",
+ packageFlag: "com.android.bar.overlay",
+ targetPackageFlag: "com.android.bar",
+ },
+ }
+ for _, expected := range expectedVariants {
+ variant := ctx.ModuleForTests("foo_overlay", expected.variantName)
+
+ // Check the final apk name
+ outputs := variant.AllOutputs()
+ expectedApkPath := buildDir + expected.apkPath
+ found := false
+ for _, o := range outputs {
+ if o == expectedApkPath {
+ found = true
+ break
+ }
+ }
+ if !found {
+ t.Errorf("Can't find %q in output files.\nAll outputs:%v", expectedApkPath, outputs)
+ }
+
+ // Check if the overrides field values are correctly aggregated.
+ mod := variant.Module().(*RuntimeResourceOverlay)
+ if !reflect.DeepEqual(expected.overrides, mod.properties.Overrides) {
+ t.Errorf("Incorrect overrides property value, expected: %q, got: %q",
+ expected.overrides, mod.properties.Overrides)
+ }
+
+ // Check aapt2 flags.
+ res := variant.Output("package-res.apk")
+ aapt2Flags := res.Args["flags"]
+ checkAapt2LinkFlag(t, aapt2Flags, "rename-manifest-package", expected.packageFlag)
+ checkAapt2LinkFlag(t, aapt2Flags, "rename-resources-package", "")
+ checkAapt2LinkFlag(t, aapt2Flags, "rename-overlay-target-package", expected.targetPackageFlag)
+ }
+}
+
+func TestEnforceRRO_propagatesToDependencies(t *testing.T) {
+ testCases := []struct {
+ name string
+ enforceRROTargets []string
+ enforceRROExemptTargets []string
+ rroDirs map[string][]string
+ }{
+ {
+ name: "no RRO",
+ enforceRROTargets: nil,
+ enforceRROExemptTargets: nil,
+ rroDirs: map[string][]string{
+ "foo": nil,
+ "bar": nil,
+ },
+ },
+ {
+ name: "enforce RRO on all",
+ enforceRROTargets: []string{"*"},
+ enforceRROExemptTargets: nil,
+ rroDirs: map[string][]string{
+ "foo": {"product/vendor/blah/overlay/lib2/res"},
+ "bar": {"product/vendor/blah/overlay/lib2/res"},
+ },
+ },
+ {
+ name: "enforce RRO on foo",
+ enforceRROTargets: []string{"foo"},
+ enforceRROExemptTargets: nil,
+ rroDirs: map[string][]string{
+ "foo": {"product/vendor/blah/overlay/lib2/res"},
+ "bar": {"product/vendor/blah/overlay/lib2/res"},
+ },
+ },
+ {
+ name: "enforce RRO on foo, bar exempted",
+ enforceRROTargets: []string{"foo"},
+ enforceRROExemptTargets: []string{"bar"},
+ rroDirs: map[string][]string{
+ "foo": {"product/vendor/blah/overlay/lib2/res"},
+ "bar": nil,
+ },
+ },
+ }
+
+ productResourceOverlays := []string{
+ "product/vendor/blah/overlay",
+ }
+
+ fs := map[string][]byte{
+ "lib2/res/values/strings.xml": nil,
+ "product/vendor/blah/overlay/lib2/res/values/strings.xml": nil,
+ }
+
+ bp := `
+ android_app {
+ name: "foo",
+ sdk_version: "current",
+ resource_dirs: [],
+ static_libs: ["lib"],
+ }
+
+ android_app {
+ name: "bar",
+ sdk_version: "current",
+ resource_dirs: [],
+ static_libs: ["lib"],
+ }
+
+ android_library {
+ name: "lib",
+ sdk_version: "current",
+ resource_dirs: [],
+ static_libs: ["lib2"],
+ }
+
+ android_library {
+ name: "lib2",
+ sdk_version: "current",
+ resource_dirs: ["lib2/res"],
+ }
+ `
+
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ config := testAppConfig(nil, bp, fs)
+ config.TestProductVariables.ProductResourceOverlays = productResourceOverlays
+ if testCase.enforceRROTargets != nil {
+ config.TestProductVariables.EnforceRROTargets = testCase.enforceRROTargets
+ }
+ if testCase.enforceRROExemptTargets != nil {
+ config.TestProductVariables.EnforceRROExemptedTargets = testCase.enforceRROExemptTargets
+ }
+
+ ctx := testContext(config)
+ run(t, ctx, config)
+
+ modules := []string{"foo", "bar"}
+ for _, moduleName := range modules {
+ module := ctx.ModuleForTests(moduleName, "android_common")
+ mkEntries := android.AndroidMkEntriesForTest(t, config, "", module.Module())[0]
+ actualRRODirs := mkEntries.EntryMap["LOCAL_SOONG_PRODUCT_RRO_DIRS"]
+ if !reflect.DeepEqual(actualRRODirs, testCase.rroDirs[moduleName]) {
+ t.Errorf("exected %s LOCAL_SOONG_PRODUCT_RRO_DIRS entry: %v\ngot:%q",
+ moduleName, testCase.rroDirs[moduleName], actualRRODirs)
+ }
+ }
+ })
+ }
+}
diff --git a/java/sdk.go b/java/sdk.go
index 32a4b5a..a68abfb 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -371,8 +371,8 @@
jar := filepath.Join(dir, "android.jar")
// There's no aidl for other SDKs yet.
// TODO(77525052): Add aidl files for other SDKs too.
- public_dir := filepath.Join("prebuilts", "sdk", sdkVersion.version.String(), "public")
- aidl := filepath.Join(public_dir, "framework.aidl")
+ publicDir := filepath.Join("prebuilts", "sdk", sdkVersion.version.String(), "public")
+ aidl := filepath.Join(publicDir, "framework.aidl")
jarPath := android.ExistentPathForSource(ctx, jar)
aidlPath := android.ExistentPathForSource(ctx, aidl)
lambdaStubsPath := android.PathForSource(ctx, config.SdkLambdaStubsPath)
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 2e10f9c..1a655a6 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -28,6 +28,7 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/dexpreopt"
)
const (
@@ -453,6 +454,10 @@
// * Removed API specification filegroup -> <dist-stem>-removed.api.<scope>.latest
Dist_stem *string
+ // A compatibility mode that allows historical API-tracking files to not exist.
+ // Do not use.
+ Unsafe_ignore_missing_latest_api bool
+
// indicates whether system and test apis should be generated.
Generate_system_and_test_apis bool `blueprint:"mutated"`
@@ -1266,10 +1271,10 @@
Merge_annotations_dirs []string
Merge_inclusion_annotations_dirs []string
Generate_stubs *bool
+ Previous_api *string
Check_api struct {
- Current ApiToCheck
- Last_released ApiToCheck
- Ignore_missing_latest_api *bool
+ Current ApiToCheck
+ Last_released ApiToCheck
Api_lint struct {
Enabled *bool
@@ -1353,13 +1358,13 @@
props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName)
props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName)
- if !apiScope.unstable {
+ if !(apiScope.unstable || module.sdkLibraryProperties.Unsafe_ignore_missing_latest_api) {
// check against the latest released API
latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope))
+ props.Previous_api = latestApiFilegroupName
props.Check_api.Last_released.Api_file = latestApiFilegroupName
props.Check_api.Last_released.Removed_api_file = proptools.StringPtr(
module.latestRemovedApiFilegroupName(apiScope))
- props.Check_api.Ignore_missing_latest_api = proptools.BoolPtr(true)
if proptools.Bool(module.sdkLibraryProperties.Api_lint.Enabled) {
// Enable api lint.
@@ -1533,7 +1538,7 @@
hasSystemAndTestApis := sdkDep.hasStandardLibs()
module.sdkLibraryProperties.Generate_system_and_test_apis = hasSystemAndTestApis
- missing_current_api := false
+ missingCurrentApi := false
generatedScopes := module.getGeneratedApiScopes(mctx)
@@ -1544,12 +1549,12 @@
p := android.ExistentPathForSource(mctx, path)
if !p.Valid() {
mctx.ModuleErrorf("Current api file %#v doesn't exist", path)
- missing_current_api = true
+ missingCurrentApi = true
}
}
}
- if missing_current_api {
+ if missingCurrentApi {
script := "build/soong/scripts/gen-java-current-api-files.sh"
p := android.ExistentPathForSource(mctx, script)
@@ -2020,7 +2025,7 @@
return module.sdkJars(ctx, sdkVersion, false)
}
-// to satisfy SdkLibraryDependency interface
+// to satisfy UsesLibraryDependency interface
func (module *SdkLibraryImport) DexJarBuildPath() android.Path {
if module.implLibraryModule == nil {
return nil
@@ -2029,7 +2034,7 @@
}
}
-// to satisfy SdkLibraryDependency interface
+// to satisfy UsesLibraryDependency interface
func (module *SdkLibraryImport) DexJarInstallPath() android.Path {
if module.implLibraryModule == nil {
return nil
@@ -2038,6 +2043,11 @@
}
}
+// to satisfy UsesLibraryDependency interface
+func (module *SdkLibraryImport) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
+ return nil
+}
+
// to satisfy apex.javaDependency interface
func (module *SdkLibraryImport) JacocoReportClassesFile() android.Path {
if module.implLibraryModule == nil {
diff --git a/java/testing.go b/java/testing.go
index ab13121..fc4e477 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -39,59 +39,8 @@
"api/test-current.txt": nil,
"api/test-removed.txt": nil,
- "prebuilts/sdk/14/public/android.jar": nil,
- "prebuilts/sdk/14/public/framework.aidl": nil,
- "prebuilts/sdk/14/system/android.jar": nil,
- "prebuilts/sdk/17/public/android.jar": nil,
- "prebuilts/sdk/17/public/framework.aidl": nil,
- "prebuilts/sdk/17/system/android.jar": nil,
- "prebuilts/sdk/28/public/android.jar": nil,
- "prebuilts/sdk/28/public/framework.aidl": nil,
- "prebuilts/sdk/28/system/android.jar": nil,
- "prebuilts/sdk/29/public/android.jar": nil,
- "prebuilts/sdk/29/public/framework.aidl": nil,
- "prebuilts/sdk/29/system/android.jar": nil,
- "prebuilts/sdk/29/system/foo.jar": nil,
- "prebuilts/sdk/30/public/android.jar": nil,
- "prebuilts/sdk/30/public/framework.aidl": nil,
- "prebuilts/sdk/30/system/android.jar": nil,
- "prebuilts/sdk/30/system/foo.jar": nil,
- "prebuilts/sdk/30/module-lib/android.jar": nil,
- "prebuilts/sdk/30/module-lib/foo.jar": nil,
- "prebuilts/sdk/30/public/core-for-system-modules.jar": nil,
- "prebuilts/sdk/current/core/android.jar": nil,
- "prebuilts/sdk/current/public/android.jar": nil,
- "prebuilts/sdk/current/public/framework.aidl": nil,
- "prebuilts/sdk/current/public/core.jar": nil,
- "prebuilts/sdk/current/public/core-for-system-modules.jar": nil,
- "prebuilts/sdk/current/system/android.jar": nil,
- "prebuilts/sdk/current/test/android.jar": nil,
- "prebuilts/sdk/28/public/api/foo.txt": nil,
- "prebuilts/sdk/28/system/api/foo.txt": nil,
- "prebuilts/sdk/28/test/api/foo.txt": nil,
- "prebuilts/sdk/28/public/api/foo-removed.txt": nil,
- "prebuilts/sdk/28/system/api/foo-removed.txt": nil,
- "prebuilts/sdk/28/test/api/foo-removed.txt": nil,
- "prebuilts/sdk/28/public/api/bar.txt": nil,
- "prebuilts/sdk/28/system/api/bar.txt": nil,
- "prebuilts/sdk/28/test/api/bar.txt": nil,
- "prebuilts/sdk/28/public/api/bar-removed.txt": nil,
- "prebuilts/sdk/28/system/api/bar-removed.txt": nil,
- "prebuilts/sdk/28/test/api/bar-removed.txt": nil,
- "prebuilts/sdk/30/public/api/foo.txt": nil,
- "prebuilts/sdk/30/system/api/foo.txt": nil,
- "prebuilts/sdk/30/test/api/foo.txt": nil,
- "prebuilts/sdk/30/public/api/foo-removed.txt": nil,
- "prebuilts/sdk/30/system/api/foo-removed.txt": nil,
- "prebuilts/sdk/30/test/api/foo-removed.txt": nil,
- "prebuilts/sdk/30/public/api/bar.txt": nil,
- "prebuilts/sdk/30/system/api/bar.txt": nil,
- "prebuilts/sdk/30/test/api/bar.txt": nil,
- "prebuilts/sdk/30/public/api/bar-removed.txt": nil,
- "prebuilts/sdk/30/system/api/bar-removed.txt": nil,
- "prebuilts/sdk/30/test/api/bar-removed.txt": nil,
- "prebuilts/sdk/tools/core-lambda-stubs.jar": nil,
- "prebuilts/sdk/Android.bp": []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "30", "current"], imports_sdk_version: "none", imports_compile_dex:true,}`),
+ "prebuilts/sdk/tools/core-lambda-stubs.jar": nil,
+ "prebuilts/sdk/Android.bp": []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "30", "current"], imports_sdk_version: "none", imports_compile_dex:true,}`),
"bin.py": nil,
python.StubTemplateHost: []byte(`PYTHON_BINARY = '%interpreter%'
@@ -104,6 +53,16 @@
"api/system-server-removed.txt": nil,
}
+ levels := []string{"14", "28", "29", "30", "current"}
+ libs := []string{
+ "android", "foo", "bar", "sdklib", "barney", "betty", "foo-shared_library",
+ "foo-no_shared_library", "core-for-system-modules", "quuz", "qux", "fred",
+ "runtime-library",
+ }
+ for k, v := range prebuiltApisFilesForLibs(levels, libs) {
+ mockFS[k] = v
+ }
+
cc.GatherRequiredFilesForTest(mockFS)
for k, v := range fs {
@@ -121,6 +80,21 @@
return config
}
+func prebuiltApisFilesForLibs(apiLevels []string, sdkLibs []string) map[string][]byte {
+ fs := make(map[string][]byte)
+ for _, level := range apiLevels {
+ for _, lib := range sdkLibs {
+ for _, scope := range []string{"public", "system", "module-lib", "system-server", "test"} {
+ fs[fmt.Sprintf("prebuilts/sdk/%s/%s/%s.jar", level, scope, lib)] = nil
+ fs[fmt.Sprintf("prebuilts/sdk/%s/%s/api/%s.txt", level, scope, lib)] = nil
+ fs[fmt.Sprintf("prebuilts/sdk/%s/%s/api/%s-removed.txt", level, scope, lib)] = nil
+ }
+ }
+ fs[fmt.Sprintf("prebuilts/sdk/%s/public/framework.aidl", level)] = nil
+ }
+ return fs
+}
+
func GatherRequiredDepsForTest() string {
var bp string
diff --git a/rust/builder.go b/rust/builder.go
index 8ec2da2..e5f0ab5 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -137,13 +137,13 @@
var implicitOutputs android.WritablePaths
output.outputFile = outputFile
- crate_name := ctx.RustModule().CrateName()
+ crateName := ctx.RustModule().CrateName()
targetTriple := ctx.toolchain().RustTriple()
// libstd requires a specific environment variable to be set. This is
// not officially documented and may be removed in the future. See
// https://github.com/rust-lang/rust/blob/master/library/std/src/env.rs#L866.
- if crate_name == "std" {
+ if crateName == "std" {
envVars = append(envVars, "STD_ENV_ARCH="+config.StdEnvArch[ctx.RustModule().Arch().ArchType])
}
@@ -153,8 +153,8 @@
rustcFlags = append(rustcFlags, flags.GlobalRustFlags...)
rustcFlags = append(rustcFlags, flags.RustFlags...)
rustcFlags = append(rustcFlags, "--crate-type="+crate_type)
- if crate_name != "" {
- rustcFlags = append(rustcFlags, "--crate-name="+crate_name)
+ if crateName != "" {
+ rustcFlags = append(rustcFlags, "--crate-name="+crateName)
}
if targetTriple != "" {
rustcFlags = append(rustcFlags, "--target="+targetTriple)
diff --git a/rust/compiler.go b/rust/compiler.go
index 4312452..ee88a27 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -214,9 +214,9 @@
flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, ctx.toolchain().ToolchainLinkFlags())
if ctx.Host() && !ctx.Windows() {
- rpath_prefix := `\$$ORIGIN/`
+ rpathPrefix := `\$$ORIGIN/`
if ctx.Darwin() {
- rpath_prefix = "@loader_path/"
+ rpathPrefix = "@loader_path/"
}
var rpath string
@@ -225,8 +225,8 @@
} else {
rpath = "lib"
}
- flags.LinkFlags = append(flags.LinkFlags, "-Wl,-rpath,"+rpath_prefix+rpath)
- flags.LinkFlags = append(flags.LinkFlags, "-Wl,-rpath,"+rpath_prefix+"../"+rpath)
+ flags.LinkFlags = append(flags.LinkFlags, "-Wl,-rpath,"+rpathPrefix+rpath)
+ flags.LinkFlags = append(flags.LinkFlags, "-Wl,-rpath,"+rpathPrefix+"../"+rpath)
}
return flags
diff --git a/rust/image.go b/rust/image.go
index 4951d2b..af8c3b2 100644
--- a/rust/image.go
+++ b/rust/image.go
@@ -90,7 +90,7 @@
vndkVersion := ctx.DeviceConfig().VndkVersion()
if vndkVersion != "current" && vndkVersion != "" && vndkVersion != m.Properties.VndkVersion {
m.Properties.HideFromMake = true
- m.SkipInstall()
+ m.HideFromMake()
}
}
}
diff --git a/rust/rust.go b/rust/rust.go
index 21da5ae..1053846 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -189,7 +189,15 @@
return false
}
-func (c *Module) IsVndkPrivate(config android.Config) bool {
+func (c *Module) IsVndkPrivate() bool {
+ return false
+}
+
+func (c *Module) IsLlndk() bool {
+ return false
+}
+
+func (c *Module) IsLlndkPublic() bool {
return false
}
@@ -474,6 +482,16 @@
panic(fmt.Errorf("CoverageFiles called on non-library module: %q", mod.BaseModuleName()))
}
+func (mod *Module) installable(apexInfo android.ApexInfo) bool {
+ // The apex variant is not installable because it is included in the APEX and won't appear
+ // in the system partition as a standalone file.
+ if !apexInfo.IsForPlatform() {
+ return false
+ }
+
+ return mod.outputFile.Valid() && !mod.Properties.PreventInstall
+}
+
var _ cc.LinkableInterface = (*Module)(nil)
func (mod *Module) Init() android.Module {
@@ -645,7 +663,9 @@
outputFile := mod.compiler.compile(ctx, flags, deps)
mod.outputFile = android.OptionalPathForPath(outputFile)
- if mod.outputFile.Valid() && !mod.Properties.PreventInstall {
+
+ apexInfo := actx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ if mod.installable(apexInfo) {
mod.compiler.install(ctx)
}
}
@@ -678,15 +698,15 @@
type dependencyTag struct {
blueprint.BaseDependencyTag
- name string
- library bool
- proc_macro bool
+ name string
+ library bool
+ procMacro bool
}
// InstallDepNeeded returns true for rlibs, dylibs, and proc macros so that they or their transitive
// dependencies (especially C/C++ shared libs) are installed as dependencies of a rust binary.
func (d dependencyTag) InstallDepNeeded() bool {
- return d.library || d.proc_macro
+ return d.library || d.procMacro
}
var _ android.InstallNeededDependencyTag = dependencyTag{}
@@ -695,7 +715,7 @@
customBindgenDepTag = dependencyTag{name: "customBindgenTag"}
rlibDepTag = dependencyTag{name: "rlibTag", library: true}
dylibDepTag = dependencyTag{name: "dylib", library: true}
- procMacroDepTag = dependencyTag{name: "procMacro", proc_macro: true}
+ procMacroDepTag = dependencyTag{name: "procMacro", procMacro: true}
testPerSrcDepTag = dependencyTag{name: "rust_unit_tests"}
sourceDepTag = dependencyTag{name: "source"}
)
diff --git a/scripts/build-aml-prebuilts.sh b/scripts/build-aml-prebuilts.sh
index 1be3b8a..4b08ac3 100755
--- a/scripts/build-aml-prebuilts.sh
+++ b/scripts/build-aml-prebuilts.sh
@@ -82,6 +82,9 @@
# CrossHost: linux_bionic
# CrossHostArch: x86_64
# - Enable Bionic on host as ART needs prebuilts for it.
+# VendorVars.art_mdoule.source_build
+# - TODO(b/172480615): Change default to false when platform uses ART Module
+# prebuilts by default.
cat > ${SOONG_VARS}.new << EOF
{
"BuildNumberFile": "build_number.txt",
@@ -104,7 +107,7 @@
"VendorVars": {
"art_module": {
- "source_build": "${ENABLE_ART_SOURCE_BUILD:-false}"
+ "source_build": "${ENABLE_ART_SOURCE_BUILD:-true}"
}
},
diff --git a/scripts/build-ndk-prebuilts.sh b/scripts/build-ndk-prebuilts.sh
index 1a33219..c27f098 100755
--- a/scripts/build-ndk-prebuilts.sh
+++ b/scripts/build-ndk-prebuilts.sh
@@ -56,6 +56,12 @@
"Ndk_abis": true,
"Exclude_draft_ndk_apis": true,
+ "VendorVars": {
+ "art_module": {
+ "source_build": "true"
+ }
+ },
+
"MissingUsesLibraries": ${MISSING_USES_LIBRARIES}
}
EOF
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index b44f66e..d989c5b 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -44,6 +44,14 @@
"api/system-server-removed.txt": nil,
"build/soong/scripts/gen-java-current-api-files.sh": nil,
"docs/known_doctags": nil,
+ "100/public/api/myjavalib.txt": nil,
+ "100/public/api/myjavalib-removed.txt": nil,
+ "100/system/api/myjavalib.txt": nil,
+ "100/system/api/myjavalib-removed.txt": nil,
+ "100/module-lib/api/myjavalib.txt": nil,
+ "100/module-lib/api/myjavalib-removed.txt": nil,
+ "100/system-server/api/myjavalib.txt": nil,
+ "100/system-server/api/myjavalib-removed.txt": nil,
}
// for java_sdk_library tests
@@ -84,6 +92,10 @@
name: "framework",
sdk_version: "none",
}
+prebuilt_apis {
+ name: "sdk",
+ api_dirs: ["100"],
+}
` + bp
return testSdkWithFs(t, bp, fs)
diff --git a/sdk/testing.go b/sdk/testing.go
index 91aa879..38755a9 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -110,6 +110,7 @@
java.RegisterJavaBuildComponents(ctx)
java.RegisterAppBuildComponents(ctx)
java.RegisterSdkLibraryBuildComponents(ctx)
+ java.RegisterPrebuiltApisBuildComponents(ctx)
java.RegisterStubsBuildComponents(ctx)
java.RegisterSystemModulesBuildComponents(ctx)
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index f86e1fd..8db33a3 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -205,14 +205,14 @@
func (s *ShBinary) generateAndroidBuildActions(ctx android.ModuleContext) {
s.sourceFilePath = android.PathForModuleSrc(ctx, proptools.String(s.properties.Src))
filename := proptools.String(s.properties.Filename)
- filename_from_src := proptools.Bool(s.properties.Filename_from_src)
+ filenameFromSrc := proptools.Bool(s.properties.Filename_from_src)
if filename == "" {
- if filename_from_src {
+ if filenameFromSrc {
filename = s.sourceFilePath.Base()
} else {
filename = ctx.ModuleName()
}
- } else if filename_from_src {
+ } else if filenameFromSrc {
ctx.PropertyErrorf("filename_from_src", "filename is set. filename_from_src can't be true")
return
}
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 93a3fe0..42caff2 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -392,18 +392,18 @@
ctx.PropertyErrorf("srcs", "sysprop_library must specify srcs")
}
- missing_api := false
+ missingApi := false
for _, txt := range []string{"-current.txt", "-latest.txt"} {
path := path.Join(ctx.ModuleDir(), "api", m.BaseModuleName()+txt)
file := android.ExistentPathForSource(ctx, path)
if !file.Valid() {
ctx.ModuleErrorf("API file %#v doesn't exist", path)
- missing_api = true
+ missingApi = true
}
}
- if missing_api {
+ if missingApi {
script := "build/soong/scripts/gen-sysprop-api-files.sh"
p := android.ExistentPathForSource(ctx, script)
diff --git a/third_party/zip/android_test.go b/third_party/zip/android_test.go
index 5154a17..9932c1b 100644
--- a/third_party/zip/android_test.go
+++ b/third_party/zip/android_test.go
@@ -74,3 +74,69 @@
}
}
}
+
+func TestCopyFromZip64(t *testing.T) {
+ if testing.Short() {
+ t.Skip("slow test; skipping")
+ }
+
+ const size = uint32max + 1
+ fromZipBytes := &bytes.Buffer{}
+ fromZip := NewWriter(fromZipBytes)
+ w, err := fromZip.CreateHeaderAndroid(&FileHeader{
+ Name: "large",
+ Method: Store,
+ UncompressedSize64: size,
+ CompressedSize64: size,
+ })
+ if err != nil {
+ t.Fatalf("Create: %v", err)
+ }
+ _, err = w.Write(make([]byte, size))
+ if err != nil {
+ t.Fatalf("Write: %v", err)
+ }
+ err = fromZip.Close()
+ if err != nil {
+ t.Fatalf("Close: %v", err)
+ }
+ fromZip = nil
+
+ fromZipReader, err := NewReader(bytes.NewReader(fromZipBytes.Bytes()), int64(fromZipBytes.Len()))
+ if err != nil {
+ t.Fatalf("NewReader: %v", err)
+ }
+
+ toZipBytes := &bytes.Buffer{}
+ toZip := NewWriter(toZipBytes)
+ err = toZip.CopyFrom(fromZipReader.File[0], fromZipReader.File[0].Name)
+ if err != nil {
+ t.Fatalf("CopyFrom: %v", err)
+ }
+
+ err = toZip.Close()
+ if err != nil {
+ t.Fatalf("Close: %v", err)
+ }
+
+ // Save some memory
+ fromZipReader = nil
+ fromZipBytes.Reset()
+
+ toZipReader, err := NewReader(bytes.NewReader(toZipBytes.Bytes()), int64(toZipBytes.Len()))
+ if err != nil {
+ t.Fatalf("NewReader: %v", err)
+ }
+
+ if len(toZipReader.File) != 1 {
+ t.Fatalf("Expected 1 file in toZip, got %d", len(toZipReader.File))
+ }
+
+ if g, w := toZipReader.File[0].CompressedSize64, uint64(size); g != w {
+ t.Errorf("Expected CompressedSize64 %d, got %d", w, g)
+ }
+
+ if g, w := toZipReader.File[0].UncompressedSize64, uint64(size); g != w {
+ t.Errorf("Expected UnompressedSize64 %d, got %d", w, g)
+ }
+}
diff --git a/third_party/zip/writer.go b/third_party/zip/writer.go
index 4c5eb78..8dd986e 100644
--- a/third_party/zip/writer.go
+++ b/third_party/zip/writer.go
@@ -276,9 +276,6 @@
} else {
b.uint32(h.CRC32)
- if h.CompressedSize64 > uint32max || h.UncompressedSize64 > uint32max {
- panic("skipping writing the data descriptor for a 64-bit value is not yet supported")
- }
compressedSize := uint32(h.CompressedSize64)
if compressedSize == 0 {
compressedSize = h.CompressedSize
@@ -289,6 +286,21 @@
uncompressedSize = h.UncompressedSize
}
+ if h.CompressedSize64 > uint32max || h.UncompressedSize64 > uint32max {
+ // Sizes don't fit in a 32-bit field, put them in a zip64 extra instead.
+ compressedSize = uint32max
+ uncompressedSize = uint32max
+
+ // append a zip64 extra block to Extra
+ var buf [20]byte // 2x uint16 + 2x uint64
+ eb := writeBuf(buf[:])
+ eb.uint16(zip64ExtraId)
+ eb.uint16(16) // size = 2x uint64
+ eb.uint64(h.UncompressedSize64)
+ eb.uint64(h.CompressedSize64)
+ h.Extra = append(h.Extra, buf[:]...)
+ }
+
b.uint32(compressedSize)
b.uint32(uncompressedSize)
}
diff --git a/ui/build/config.go b/ui/build/config.go
index ecca4de..1152cd7 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -617,19 +617,19 @@
// For LANG and LC_*, only preserve the evaluated version of
// LC_MESSAGES
- user_lang := ""
+ userLang := ""
if lc_all, ok := c.environ.Get("LC_ALL"); ok {
- user_lang = lc_all
+ userLang = lc_all
} else if lc_messages, ok := c.environ.Get("LC_MESSAGES"); ok {
- user_lang = lc_messages
+ userLang = lc_messages
} else if lang, ok := c.environ.Get("LANG"); ok {
- user_lang = lang
+ userLang = lang
}
c.environ.UnsetWithPrefix("LC_")
- if user_lang != "" {
- c.environ.Set("LC_MESSAGES", user_lang)
+ if userLang != "" {
+ c.environ.Set("LC_MESSAGES", userLang)
}
// The for LANG, use C.UTF-8 if it exists (Debian currently, proposed
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index 999af07..fe0aca9 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -254,7 +254,7 @@
"BUILD_BROKEN_USES_BUILD_STATIC_LIBRARY",
}, exportEnvVars...), BannerVars...)
- make_vars, err := dumpMakeVars(ctx, config, config.Arguments(), allVars, true, "")
+ makeVars, err := dumpMakeVars(ctx, config, config.Arguments(), allVars, true, "")
if err != nil {
ctx.Fatalln("Error dumping make vars:", err)
}
@@ -262,24 +262,24 @@
env := config.Environment()
// Print the banner like make does
if !env.IsEnvTrue("ANDROID_QUIET_BUILD") {
- fmt.Fprintln(ctx.Writer, Banner(make_vars))
+ fmt.Fprintln(ctx.Writer, Banner(makeVars))
}
// Populate the environment
for _, name := range exportEnvVars {
- if make_vars[name] == "" {
+ if makeVars[name] == "" {
env.Unset(name)
} else {
- env.Set(name, make_vars[name])
+ env.Set(name, makeVars[name])
}
}
- config.SetKatiArgs(strings.Fields(make_vars["KATI_GOALS"]))
- config.SetNinjaArgs(strings.Fields(make_vars["NINJA_GOALS"]))
- config.SetTargetDevice(make_vars["TARGET_DEVICE"])
- config.SetTargetDeviceDir(make_vars["TARGET_DEVICE_DIR"])
+ config.SetKatiArgs(strings.Fields(makeVars["KATI_GOALS"]))
+ config.SetNinjaArgs(strings.Fields(makeVars["NINJA_GOALS"]))
+ config.SetTargetDevice(makeVars["TARGET_DEVICE"])
+ config.SetTargetDeviceDir(makeVars["TARGET_DEVICE_DIR"])
- config.SetBuildBrokenDupRules(make_vars["BUILD_BROKEN_DUP_RULES"] == "true")
- config.SetBuildBrokenUsesNetwork(make_vars["BUILD_BROKEN_USES_NETWORK"] == "true")
- config.SetBuildBrokenNinjaUsesEnvVars(strings.Fields(make_vars["BUILD_BROKEN_NINJA_USES_ENV_VARS"]))
+ config.SetBuildBrokenDupRules(makeVars["BUILD_BROKEN_DUP_RULES"] == "true")
+ config.SetBuildBrokenUsesNetwork(makeVars["BUILD_BROKEN_USES_NETWORK"] == "true")
+ config.SetBuildBrokenNinjaUsesEnvVars(strings.Fields(makeVars["BUILD_BROKEN_NINJA_USES_ENV_VARS"]))
}
diff --git a/ui/build/test_build.go b/ui/build/test_build.go
index 41acc26..a910c06 100644
--- a/ui/build/test_build.go
+++ b/ui/build/test_build.go
@@ -50,10 +50,10 @@
// Get a list of leaf nodes in the dependency graph from ninja
executable := config.PrebuiltBuildTool("ninja")
- common_args := []string{}
- common_args = append(common_args, config.NinjaArgs()...)
- common_args = append(common_args, "-f", config.CombinedNinjaFile())
- args := append(common_args, "-t", "targets", "rule")
+ commonArgs := []string{}
+ commonArgs = append(commonArgs, config.NinjaArgs()...)
+ commonArgs = append(commonArgs, "-f", config.CombinedNinjaFile())
+ args := append(commonArgs, "-t", "targets", "rule")
cmd := Command(ctx, config, "ninja", executable, args...)
stdout, err := cmd.StdoutPipe()
@@ -114,28 +114,28 @@
title := "Dependencies in out found with no rule to create them:"
fmt.Fprintln(sb, title)
- report_lines := 1
+ reportLines := 1
for i, dep := range danglingRulesList {
- if report_lines > 20 {
+ if reportLines > 20 {
fmt.Fprintf(sb, " ... and %d more\n", len(danglingRulesList)-i)
break
}
// It's helpful to see the reverse dependencies. ninja -t query is the
// best tool we got for that. Its output starts with the dependency
// itself.
- query_cmd := Command(ctx, config, "ninja", executable,
- append(common_args, "-t", "query", dep)...)
- query_stdout, err := query_cmd.StdoutPipe()
+ queryCmd := Command(ctx, config, "ninja", executable,
+ append(commonArgs, "-t", "query", dep)...)
+ queryStdout, err := queryCmd.StdoutPipe()
if err != nil {
ctx.Fatal(err)
}
- query_cmd.StartOrFatal()
- scanner := bufio.NewScanner(query_stdout)
+ queryCmd.StartOrFatal()
+ scanner := bufio.NewScanner(queryStdout)
for scanner.Scan() {
- report_lines++
+ reportLines++
fmt.Fprintln(sb, " ", scanner.Text())
}
- query_cmd.WaitOrFatal()
+ queryCmd.WaitOrFatal()
}
ts.FinishAction(status.ActionResult{
diff --git a/ui/metrics/proc/Android.bp b/ui/metrics/proc/Android.bp
new file mode 100644
index 0000000..32d8217
--- /dev/null
+++ b/ui/metrics/proc/Android.bp
@@ -0,0 +1,37 @@
+// Copyright 2020 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.
+
+bootstrap_go_package {
+ name: "soong-ui-metrics-proc",
+ pkgPath: "android/soong/ui/metrics/proc",
+ deps: [
+ "soong-finder-fs",
+ ],
+ srcs: [
+ "status.go",
+ ],
+ linux: {
+ srcs: [
+ "status_linux.go",
+ ],
+ testSrcs: [
+ "status_linux_test.go",
+ ],
+ },
+ darwin: {
+ srcs: [
+ "status_darwin.go",
+ ],
+ },
+}
diff --git a/ui/metrics/proc/status.go b/ui/metrics/proc/status.go
new file mode 100644
index 0000000..f8b734c
--- /dev/null
+++ b/ui/metrics/proc/status.go
@@ -0,0 +1,128 @@
+// package proc contains functionality to read proc status files.
+package proc
+
+import (
+ "strconv"
+ "strings"
+)
+
+// ProcStatus holds information regarding the memory usage of
+// an executing process. The memory sizes in each of the field
+// is in bytes.
+type ProcStatus struct {
+ // Process PID.
+ pid int
+
+ // Peak virtual memory size.
+ VmPeak uint64
+
+ // Virtual memory size.
+ VmSize uint64
+
+ // Locked Memory size.
+ VmLck uint64
+
+ // Pinned memory size.
+ VmPin uint64
+
+ // Peak resident set size.
+ VmHWM uint64
+
+ // Resident set size (sum of RssAnon, RssFile and RssShmem).
+ VmRss uint64
+
+ // Size of resident anonymous memory.
+ RssAnon uint64
+
+ // Size of resident shared memory.
+ RssShmem uint64
+
+ // Size of data segments.
+ VmData uint64
+
+ // Size of stack segments.
+ VmStk uint64
+
+ //Size of text segments.
+ VmExe uint64
+
+ //Shared library code size.
+ VmLib uint64
+
+ // Page table entries size.
+ VmPTE uint64
+
+ // Size of second-level page tables.
+ VmPMD uint64
+
+ // Swapped-out virtual memory size by anonymous private.
+ VmSwap uint64
+
+ // Size of hugetlb memory page size.
+ HugetlbPages uint64
+}
+
+// fillProcStatus takes the key and value, converts the value
+// to the proper size unit and is stored in the ProcStatus.
+func fillProcStatus(s *ProcStatus, key, value string) {
+ v := strToUint64(value)
+ switch key {
+ case "VmPeak":
+ s.VmPeak = v
+ case "VmSize":
+ s.VmSize = v
+ case "VmLck":
+ s.VmLck = v
+ case "VmPin":
+ s.VmPin = v
+ case "VmHWM":
+ s.VmHWM = v
+ case "VmRSS":
+ s.VmRss = v
+ case "RssAnon":
+ s.RssAnon = v
+ case "RssShmem":
+ s.RssShmem = v
+ case "VmData":
+ s.VmData = v
+ case "VmStk":
+ s.VmStk = v
+ case "VmExe":
+ s.VmExe = v
+ case "VmLib":
+ s.VmLib = v
+ case "VmPTE":
+ s.VmPTE = v
+ case "VmPMD":
+ s.VmPMD = v
+ case "VmSwap":
+ s.VmSwap = v
+ case "HugetlbPages":
+ s.HugetlbPages = v
+ }
+}
+
+// strToUint64 takes the string and converts to unsigned 64-bit integer.
+// If the string contains a memory unit such as kB and is converted to
+// bytes.
+func strToUint64(v string) uint64 {
+ // v could be "1024 kB" so scan for the empty space and
+ // split between the value and the unit.
+ var separatorIndex int
+ if separatorIndex = strings.IndexAny(v, " "); separatorIndex < 0 {
+ separatorIndex = len(v)
+ }
+ value, err := strconv.ParseUint(v[:separatorIndex], 10, 64)
+ if err != nil {
+ return 0
+ }
+
+ var scale uint64 = 1
+ switch strings.TrimSpace(v[separatorIndex:]) {
+ case "kB", "KB":
+ scale = 1024
+ case "mB", "MB":
+ scale = 1024 * 1024
+ }
+ return value * scale
+}
diff --git a/ui/metrics/proc/status_darwin.go b/ui/metrics/proc/status_darwin.go
new file mode 100644
index 0000000..5c788a5
--- /dev/null
+++ b/ui/metrics/proc/status_darwin.go
@@ -0,0 +1,11 @@
+package proc
+
+import (
+ "android/soong/finder/fs"
+)
+
+// NewProcStatus returns a zero filled value of ProcStatus as it
+// is not supported for darwin distribution based.
+func NewProcStatus(pid int, _ fs.FileSystem) (*ProcStatus, error) {
+ return &ProcStatus{}, nil
+}
diff --git a/ui/metrics/proc/status_linux.go b/ui/metrics/proc/status_linux.go
new file mode 100644
index 0000000..dc0f943
--- /dev/null
+++ b/ui/metrics/proc/status_linux.go
@@ -0,0 +1,46 @@
+package proc
+
+import (
+ "io/ioutil"
+ "path/filepath"
+ "strconv"
+ "strings"
+
+ "android/soong/finder/fs"
+)
+
+// NewProcStatus returns an instance of the ProcStatus that contains memory
+// information of the process. The memory information is extracted from the
+// "/proc/<pid>/status" text file. This is only available for Linux
+// distribution that supports /proc.
+func NewProcStatus(pid int, fileSystem fs.FileSystem) (*ProcStatus, error) {
+ statusFname := filepath.Join("/proc", strconv.Itoa(pid), "status")
+ r, err := fileSystem.Open(statusFname)
+ if err != nil {
+ return &ProcStatus{}, err
+ }
+ defer r.Close()
+
+ data, err := ioutil.ReadAll(r)
+ if err != nil {
+ return &ProcStatus{}, err
+ }
+
+ s := &ProcStatus{
+ pid: pid,
+ }
+
+ for _, l := range strings.Split(string(data), "\n") {
+ // If the status file does not contain "key: values", just skip the line
+ // as the information we are looking for is not needed.
+ if !strings.Contains(l, ":") {
+ continue
+ }
+
+ // At this point, we're only considering entries that has key, single value pairs.
+ kv := strings.SplitN(l, ":", 2)
+ fillProcStatus(s, strings.TrimSpace(kv[0]), strings.TrimSpace(kv[1]))
+ }
+
+ return s, nil
+}
diff --git a/ui/metrics/proc/status_linux_test.go b/ui/metrics/proc/status_linux_test.go
new file mode 100644
index 0000000..6709850
--- /dev/null
+++ b/ui/metrics/proc/status_linux_test.go
@@ -0,0 +1,112 @@
+package proc
+
+import (
+ "fmt"
+ "path/filepath"
+ "reflect"
+ "strconv"
+ "testing"
+
+ "android/soong/finder/fs"
+)
+
+func TestNewProcStatus(t *testing.T) {
+ fs := fs.NewMockFs(nil)
+
+ pid := 4032827
+ procDir := filepath.Join("/proc", strconv.Itoa(pid))
+ if err := fs.MkDirs(procDir); err != nil {
+ t.Fatalf("failed to create proc pid dir %s: %v", procDir, err)
+ }
+ statusFilename := filepath.Join(procDir, "status")
+
+ if err := fs.WriteFile(statusFilename, statusData, 0644); err != nil {
+ t.Fatalf("failed to write proc file %s: %v", statusFilename, err)
+ }
+
+ status, err := NewProcStatus(pid, fs)
+ if err != nil {
+ t.Fatalf("got %v, want nil for error", err)
+ }
+
+ fmt.Printf("%d %d\b", status.VmPeak, expectedStatus.VmPeak)
+ if !reflect.DeepEqual(status, expectedStatus) {
+ t.Errorf("got %v, expecting %v for ProcStatus", status, expectedStatus)
+ }
+}
+
+var statusData = []byte(`Name: fake_process
+Umask: 0022
+State: S (sleeping)
+Tgid: 4032827
+Ngid: 0
+Pid: 4032827
+PPid: 1
+TracerPid: 0
+Uid: 0 0 0 0
+Gid: 0 0 0 0
+FDSize: 512
+Groups:
+NStgid: 4032827
+NSpid: 4032827
+NSpgid: 4032827
+NSsid: 4032827
+VmPeak: 733232 kB
+VmSize: 733232 kB
+VmLck: 132 kB
+VmPin: 130 kB
+VmHWM: 69156 kB
+VmRSS: 69156 kB
+RssAnon: 50896 kB
+RssFile: 18260 kB
+RssShmem: 122 kB
+VmData: 112388 kB
+VmStk: 132 kB
+VmExe: 9304 kB
+VmLib: 8 kB
+VmPTE: 228 kB
+VmSwap: 10 kB
+HugetlbPages: 22 kB
+CoreDumping: 0
+THP_enabled: 1
+Threads: 46
+SigQ: 2/767780
+SigPnd: 0000000000000000
+ShdPnd: 0000000000000000
+SigBlk: fffffffe3bfa3a00
+SigIgn: 0000000000000000
+SigCgt: fffffffe7fc1feff
+CapInh: 0000000000000000
+CapPrm: 0000003fffffffff
+CapEff: 0000003fffffffff
+CapBnd: 0000003fffffffff
+CapAmb: 0000000000000000
+NoNewPrivs: 0
+Seccomp: 0
+Speculation_Store_Bypass: thread vulnerable
+Cpus_allowed: ff,ffffffff,ffffffff
+Cpus_allowed_list: 0-71
+Mems_allowed: 00000000,00000003
+Mems_allowed_list: 0-1
+voluntary_ctxt_switches: 1635
+nonvoluntary_ctxt_switches: 32
+`)
+
+var expectedStatus = &ProcStatus{
+ pid: 4032827,
+ VmPeak: 750829568,
+ VmSize: 750829568,
+ VmLck: 135168,
+ VmPin: 133120,
+ VmHWM: 70815744,
+ VmRss: 70815744,
+ RssAnon: 52117504,
+ RssShmem: 124928,
+ VmData: 115085312,
+ VmStk: 135168,
+ VmExe: 9527296,
+ VmLib: 8192,
+ VmPTE: 233472,
+ VmSwap: 10240,
+ HugetlbPages: 22528,
+}
diff --git a/ui/terminal/util.go b/ui/terminal/util.go
index 7a603d7..28d97fe 100644
--- a/ui/terminal/util.go
+++ b/ui/terminal/util.go
@@ -41,13 +41,13 @@
func termSize(w io.Writer) (width int, height int, ok bool) {
if f, ok := w.(*os.File); ok {
var winsize struct {
- ws_row, ws_column uint16
- ws_xpixel, ws_ypixel uint16
+ wsRow, wsColumn uint16
+ wsXpixel, wsYpixel uint16
}
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, f.Fd(),
syscall.TIOCGWINSZ, uintptr(unsafe.Pointer(&winsize)),
0, 0, 0)
- return int(winsize.ws_column), int(winsize.ws_row), err == 0
+ return int(winsize.wsColumn), int(winsize.wsRow), err == 0
} else if f, ok := w.(*fakeSmartTerminal); ok {
return f.termWidth, f.termHeight, true
}