Merge "Touch up manifest if there's no source code." am: 96eac767df
am: c831a0a895
Change-Id: I19cba0c3017eff6f309dae04aacdb7e0aee1613d
This commit is contained in:
commit
c0ed71ccf8
|
@ -85,6 +85,7 @@ type aapt struct {
|
||||||
useEmbeddedDex bool
|
useEmbeddedDex bool
|
||||||
usesNonSdkApis bool
|
usesNonSdkApis bool
|
||||||
sdkLibraries []string
|
sdkLibraries []string
|
||||||
|
hasNoCode bool
|
||||||
|
|
||||||
splitNames []string
|
splitNames []string
|
||||||
splits []split
|
splits []split
|
||||||
|
@ -204,7 +205,7 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, ex
|
||||||
manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile)
|
manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile)
|
||||||
|
|
||||||
manifestPath := manifestFixer(ctx, manifestSrcPath, sdkContext, sdkLibraries,
|
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...)
|
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
|
// Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml
|
||||||
func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext, sdkLibraries []string,
|
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
|
var args []string
|
||||||
if isLibrary {
|
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
|
var deps android.Paths
|
||||||
targetSdkVersion := sdkVersionOrDefault(ctx, sdkContext.targetSdkVersion())
|
targetSdkVersion := sdkVersionOrDefault(ctx, sdkContext.targetSdkVersion())
|
||||||
if targetSdkVersion == ctx.Config().PlatformSdkCodename() &&
|
if targetSdkVersion == ctx.Config().PlatformSdkCodename() &&
|
||||||
|
|
|
@ -243,6 +243,9 @@ func (a *AndroidApp) shouldEmbedJnis(ctx android.BaseModuleContext) bool {
|
||||||
func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) {
|
func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) {
|
||||||
a.aapt.usesNonSdkApis = Bool(a.Module.deviceProperties.Platform_apis)
|
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{}
|
aaptLinkFlags := []string{}
|
||||||
|
|
||||||
// Add TARGET_AAPT_CHARACTERISTICS values to AAPT link flags if they exist and --product flags were not provided.
|
// 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)
|
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) {
|
func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
|
||||||
|
|
||||||
hasSrcs := false
|
|
||||||
|
|
||||||
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)
|
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)
|
||||||
|
|
||||||
deps := j.collectDeps(ctx)
|
deps := j.collectDeps(ctx)
|
||||||
|
@ -985,9 +983,6 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
srcFiles = j.genSources(ctx, srcFiles, flags)
|
srcFiles = j.genSources(ctx, srcFiles, flags)
|
||||||
if len(srcFiles) > 0 {
|
|
||||||
hasSrcs = true
|
|
||||||
}
|
|
||||||
|
|
||||||
srcJars := srcFiles.FilterByExt(".srcjar")
|
srcJars := srcFiles.FilterByExt(".srcjar")
|
||||||
srcJars = append(srcJars, deps.srcJars...)
|
srcJars = append(srcJars, deps.srcJars...)
|
||||||
|
@ -1184,7 +1179,6 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
|
||||||
|
|
||||||
if len(deps.staticJars) > 0 {
|
if len(deps.staticJars) > 0 {
|
||||||
jars = append(jars, deps.staticJars...)
|
jars = append(jars, deps.staticJars...)
|
||||||
hasSrcs = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
manifest := j.overrideManifest
|
manifest := j.overrideManifest
|
||||||
|
@ -1296,7 +1290,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
|
||||||
|
|
||||||
j.implementationAndResourcesJar = implementationAndResourcesJar
|
j.implementationAndResourcesJar = implementationAndResourcesJar
|
||||||
|
|
||||||
if ctx.Device() && hasSrcs &&
|
if ctx.Device() && j.hasCode(ctx) &&
|
||||||
(Bool(j.properties.Installable) || Bool(j.deviceProperties.Compile_dex)) {
|
(Bool(j.properties.Installable) || Bool(j.deviceProperties.Compile_dex)) {
|
||||||
// Dex compilation
|
// Dex compilation
|
||||||
var dexOutputFile android.ModuleOutPath
|
var dexOutputFile android.ModuleOutPath
|
||||||
|
@ -1501,6 +1495,11 @@ func (j *Module) CompilerDeps() []string {
|
||||||
return jdeps
|
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)
|
// Java libraries (.jar file)
|
||||||
//
|
//
|
||||||
|
|
|
@ -59,6 +59,9 @@ def parse_args():
|
||||||
default=None, type=lambda x: (str(x).lower() == 'true'),
|
default=None, type=lambda x: (str(x).lower() == 'true'),
|
||||||
help=('specify if the app wants to use embedded native libraries. Must not conflict '
|
help=('specify if the app wants to use embedded native libraries. Must not conflict '
|
||||||
'if already declared in the manifest.'))
|
'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('input', help='input AndroidManifest.xml file')
|
||||||
parser.add_argument('output', help='output AndroidManifest.xml file')
|
parser.add_argument('output', help='output AndroidManifest.xml file')
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
@ -245,6 +248,28 @@ def add_extract_native_libs(doc, extract_native_libs):
|
||||||
(attr.value, value))
|
(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():
|
def main():
|
||||||
"""Program entry point."""
|
"""Program entry point."""
|
||||||
try:
|
try:
|
||||||
|
@ -269,6 +294,9 @@ def main():
|
||||||
if args.use_embedded_dex:
|
if args.use_embedded_dex:
|
||||||
add_use_embedded_dex(doc)
|
add_use_embedded_dex(doc)
|
||||||
|
|
||||||
|
if args.has_no_code:
|
||||||
|
set_has_code_to_false(doc)
|
||||||
|
|
||||||
if args.extract_native_libs is not None:
|
if args.extract_native_libs is not None:
|
||||||
add_extract_native_libs(doc, args.extract_native_libs)
|
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)
|
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__':
|
if __name__ == '__main__':
|
||||||
unittest.main(verbosity=2)
|
unittest.main(verbosity=2)
|
||||||
|
|
Loading…
Reference in New Issue