Merge "Touch up manifest if there's no source code."
This commit is contained in:
commit
96eac767df
|
@ -85,6 +85,7 @@ type aapt struct {
|
|||
useEmbeddedDex bool
|
||||
usesNonSdkApis bool
|
||||
sdkLibraries []string
|
||||
hasNoCode bool
|
||||
|
||||
splitNames []string
|
||||
splits []split
|
||||
|
@ -204,7 +205,7 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, ex
|
|||
manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile)
|
||||
|
||||
manifestPath := manifestFixer(ctx, manifestSrcPath, sdkContext, sdkLibraries,
|
||||
a.isLibrary, a.useEmbeddedNativeLibs, a.usesNonSdkApis, a.useEmbeddedDex)
|
||||
a.isLibrary, a.useEmbeddedNativeLibs, a.usesNonSdkApis, a.useEmbeddedDex, a.hasNoCode)
|
||||
|
||||
a.transitiveManifestPaths = append(android.Paths{manifestPath}, transitiveStaticLibManifests...)
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ var optionalUsesLibs = []string{
|
|||
|
||||
// Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml
|
||||
func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext, sdkLibraries []string,
|
||||
isLibrary, useEmbeddedNativeLibs, usesNonSdkApis, useEmbeddedDex bool) android.Path {
|
||||
isLibrary, useEmbeddedNativeLibs, usesNonSdkApis, useEmbeddedDex, hasNoCode bool) android.Path {
|
||||
|
||||
var args []string
|
||||
if isLibrary {
|
||||
|
@ -87,6 +87,10 @@ func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext
|
|||
}
|
||||
}
|
||||
|
||||
if hasNoCode {
|
||||
args = append(args, "--has-no-code")
|
||||
}
|
||||
|
||||
var deps android.Paths
|
||||
targetSdkVersion := sdkVersionOrDefault(ctx, sdkContext.targetSdkVersion())
|
||||
if targetSdkVersion == ctx.Config().PlatformSdkCodename() &&
|
||||
|
|
|
@ -243,6 +243,9 @@ func (a *AndroidApp) shouldEmbedJnis(ctx android.BaseModuleContext) bool {
|
|||
func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) {
|
||||
a.aapt.usesNonSdkApis = Bool(a.Module.deviceProperties.Platform_apis)
|
||||
|
||||
// Ask manifest_fixer to add or update the application element indicating this app has no code.
|
||||
a.aapt.hasNoCode = !a.hasCode(ctx)
|
||||
|
||||
aaptLinkFlags := []string{}
|
||||
|
||||
// Add TARGET_AAPT_CHARACTERISTICS values to AAPT link flags if they exist and --product flags were not provided.
|
||||
|
|
|
@ -1327,3 +1327,73 @@ func TestUsesLibraries(t *testing.T) {
|
|||
t.Errorf("wanted %q in %q", w, cmd)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCodelessApp(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
bp string
|
||||
noCode bool
|
||||
}{
|
||||
{
|
||||
name: "normal",
|
||||
bp: `
|
||||
android_app {
|
||||
name: "foo",
|
||||
srcs: ["a.java"],
|
||||
}
|
||||
`,
|
||||
noCode: false,
|
||||
},
|
||||
{
|
||||
name: "app without sources",
|
||||
bp: `
|
||||
android_app {
|
||||
name: "foo",
|
||||
}
|
||||
`,
|
||||
noCode: true,
|
||||
},
|
||||
{
|
||||
name: "app with libraries",
|
||||
bp: `
|
||||
android_app {
|
||||
name: "foo",
|
||||
static_libs: ["lib"],
|
||||
}
|
||||
|
||||
java_library {
|
||||
name: "lib",
|
||||
srcs: ["a.java"],
|
||||
}
|
||||
`,
|
||||
noCode: false,
|
||||
},
|
||||
{
|
||||
name: "app with sourceless libraries",
|
||||
bp: `
|
||||
android_app {
|
||||
name: "foo",
|
||||
static_libs: ["lib"],
|
||||
}
|
||||
|
||||
java_library {
|
||||
name: "lib",
|
||||
}
|
||||
`,
|
||||
// TODO(jungjw): this should probably be true
|
||||
noCode: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
ctx := testApp(t, test.bp)
|
||||
|
||||
foo := ctx.ModuleForTests("foo", "android_common")
|
||||
manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
|
||||
if strings.Contains(manifestFixerArgs, "--has-no-code") != test.noCode {
|
||||
t.Errorf("unexpected manifest_fixer args: %q", manifestFixerArgs)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
13
java/java.go
13
java/java.go
|
@ -969,8 +969,6 @@ func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaB
|
|||
|
||||
func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
|
||||
|
||||
hasSrcs := false
|
||||
|
||||
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)
|
||||
|
||||
deps := j.collectDeps(ctx)
|
||||
|
@ -985,9 +983,6 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
|
|||
}
|
||||
|
||||
srcFiles = j.genSources(ctx, srcFiles, flags)
|
||||
if len(srcFiles) > 0 {
|
||||
hasSrcs = true
|
||||
}
|
||||
|
||||
srcJars := srcFiles.FilterByExt(".srcjar")
|
||||
srcJars = append(srcJars, deps.srcJars...)
|
||||
|
@ -1184,7 +1179,6 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
|
|||
|
||||
if len(deps.staticJars) > 0 {
|
||||
jars = append(jars, deps.staticJars...)
|
||||
hasSrcs = true
|
||||
}
|
||||
|
||||
manifest := j.overrideManifest
|
||||
|
@ -1296,7 +1290,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
|
|||
|
||||
j.implementationAndResourcesJar = implementationAndResourcesJar
|
||||
|
||||
if ctx.Device() && hasSrcs &&
|
||||
if ctx.Device() && j.hasCode(ctx) &&
|
||||
(Bool(j.properties.Installable) || Bool(j.deviceProperties.Compile_dex)) {
|
||||
// Dex compilation
|
||||
var dexOutputFile android.ModuleOutPath
|
||||
|
@ -1501,6 +1495,11 @@ func (j *Module) CompilerDeps() []string {
|
|||
return jdeps
|
||||
}
|
||||
|
||||
func (j *Module) hasCode(ctx android.ModuleContext) bool {
|
||||
srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
|
||||
return len(srcFiles) > 0 || len(ctx.GetDirectDepsWithTag(staticLibTag)) > 0
|
||||
}
|
||||
|
||||
//
|
||||
// Java libraries (.jar file)
|
||||
//
|
||||
|
|
|
@ -59,6 +59,9 @@ def parse_args():
|
|||
default=None, type=lambda x: (str(x).lower() == 'true'),
|
||||
help=('specify if the app wants to use embedded native libraries. Must not conflict '
|
||||
'if already declared in the manifest.'))
|
||||
parser.add_argument('--has-no-code', dest='has_no_code', action='store_true',
|
||||
help=('adds hasCode="false" attribute to application. Ignored if application elem '
|
||||
'already has a hasCode attribute.'))
|
||||
parser.add_argument('input', help='input AndroidManifest.xml file')
|
||||
parser.add_argument('output', help='output AndroidManifest.xml file')
|
||||
return parser.parse_args()
|
||||
|
@ -245,6 +248,28 @@ def add_extract_native_libs(doc, extract_native_libs):
|
|||
(attr.value, value))
|
||||
|
||||
|
||||
def set_has_code_to_false(doc):
|
||||
manifest = parse_manifest(doc)
|
||||
elems = get_children_with_tag(manifest, 'application')
|
||||
application = elems[0] if len(elems) == 1 else None
|
||||
if len(elems) > 1:
|
||||
raise RuntimeError('found multiple <application> tags')
|
||||
elif not elems:
|
||||
application = doc.createElement('application')
|
||||
indent = get_indent(manifest.firstChild, 1)
|
||||
first = manifest.firstChild
|
||||
manifest.insertBefore(doc.createTextNode(indent), first)
|
||||
manifest.insertBefore(application, first)
|
||||
|
||||
attr = application.getAttributeNodeNS(android_ns, 'hasCode')
|
||||
if attr is not None:
|
||||
# Do nothing if the application already has a hasCode attribute.
|
||||
return
|
||||
attr = doc.createAttributeNS(android_ns, 'android:hasCode')
|
||||
attr.value = 'false'
|
||||
application.setAttributeNode(attr)
|
||||
|
||||
|
||||
def main():
|
||||
"""Program entry point."""
|
||||
try:
|
||||
|
@ -269,6 +294,9 @@ def main():
|
|||
if args.use_embedded_dex:
|
||||
add_use_embedded_dex(doc)
|
||||
|
||||
if args.has_no_code:
|
||||
set_has_code_to_false(doc)
|
||||
|
||||
if args.extract_native_libs is not None:
|
||||
add_extract_native_libs(doc, args.extract_native_libs)
|
||||
|
||||
|
|
|
@ -424,5 +424,47 @@ class AddExtractNativeLibsTest(unittest.TestCase):
|
|||
self.assertRaises(RuntimeError, self.run_test, manifest_input, False)
|
||||
|
||||
|
||||
class AddNoCodeApplicationTest(unittest.TestCase):
|
||||
"""Unit tests for set_has_code_to_false function."""
|
||||
|
||||
def run_test(self, input_manifest):
|
||||
doc = minidom.parseString(input_manifest)
|
||||
manifest_fixer.set_has_code_to_false(doc)
|
||||
output = StringIO.StringIO()
|
||||
manifest_fixer.write_xml(output, doc)
|
||||
return output.getvalue()
|
||||
|
||||
manifest_tmpl = (
|
||||
'<?xml version="1.0" encoding="utf-8"?>\n'
|
||||
'<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
|
||||
'%s'
|
||||
'</manifest>\n')
|
||||
|
||||
def test_no_application(self):
|
||||
manifest_input = self.manifest_tmpl % ''
|
||||
expected = self.manifest_tmpl % ' <application android:hasCode="false"/>\n'
|
||||
output = self.run_test(manifest_input)
|
||||
self.assertEqual(output, expected)
|
||||
|
||||
def test_has_application_no_has_code(self):
|
||||
manifest_input = self.manifest_tmpl % ' <application/>\n'
|
||||
expected = self.manifest_tmpl % ' <application android:hasCode="false"/>\n'
|
||||
output = self.run_test(manifest_input)
|
||||
self.assertEqual(output, expected)
|
||||
|
||||
def test_has_application_has_code_false(self):
|
||||
""" Do nothing if there's already an application elemeent. """
|
||||
manifest_input = self.manifest_tmpl % ' <application android:hasCode="false"/>\n'
|
||||
output = self.run_test(manifest_input)
|
||||
self.assertEqual(output, manifest_input)
|
||||
|
||||
def test_has_application_has_code_true(self):
|
||||
""" Do nothing if there's already an application elemeent even if its
|
||||
hasCode attribute is true. """
|
||||
manifest_input = self.manifest_tmpl % ' <application android:hasCode="true"/>\n'
|
||||
output = self.run_test(manifest_input)
|
||||
self.assertEqual(output, manifest_input)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
||||
|
|
Loading…
Reference in New Issue