Merge "Allow arch-specific `symlink_preferred_arch` properties."
diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go
index 026ff22..fb16887 100644
--- a/cc/ndk_prebuilt.go
+++ b/cc/ndk_prebuilt.go
@@ -25,7 +25,7 @@
 func init() {
 	android.RegisterModuleType("ndk_prebuilt_object", ndkPrebuiltObjectFactory)
 	android.RegisterModuleType("ndk_prebuilt_static_stl", ndkPrebuiltStaticStlFactory)
-	android.RegisterModuleType("ndk_prebuilt_shared_stl", ndkPrebuiltSharedStlFactory)
+	android.RegisterModuleType("ndk_prebuilt_shared_stl", NdkPrebuiltSharedStlFactory)
 }
 
 // NDK prebuilt libraries.
@@ -107,7 +107,7 @@
 // library (stl) library for linking operation. The soong's module name format
 // is ndk_<NAME>.so where the library is located under
 // ./prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs/$(HOST_ARCH)/<NAME>.so.
-func ndkPrebuiltSharedStlFactory() android.Module {
+func NdkPrebuiltSharedStlFactory() android.Module {
 	module, library := NewLibrary(android.DeviceSupported)
 	library.BuildOnlyShared()
 	module.compiler = nil
diff --git a/java/aar.go b/java/aar.go
index 65a7c2a..1b84a47 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -85,6 +85,7 @@
 	useEmbeddedDex          bool
 	usesNonSdkApis          bool
 	sdkLibraries            []string
+	hasNoCode               bool
 
 	splitNames []string
 	splits     []split
@@ -204,7 +205,7 @@
 	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...)
 
diff --git a/java/android_manifest.go b/java/android_manifest.go
index b5921be..021883e 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -53,7 +53,7 @@
 
 // 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 @@
 		}
 	}
 
+	if hasNoCode {
+		args = append(args, "--has-no-code")
+	}
+
 	var deps android.Paths
 	targetSdkVersion := sdkVersionOrDefault(ctx, sdkContext.targetSdkVersion())
 	if targetSdkVersion == ctx.Config().PlatformSdkCodename() &&
diff --git a/java/app.go b/java/app.go
index 2d817fe..3c8f847 100644
--- a/java/app.go
+++ b/java/app.go
@@ -175,7 +175,7 @@
 		ctx.AddFarVariationDependencies(variation, tag, a.appProperties.Jni_libs...)
 		if String(a.appProperties.Stl) == "c++_shared" {
 			if embedJni {
-				ctx.AddFarVariationDependencies(variation, tag, "libc++")
+				ctx.AddFarVariationDependencies(variation, tag, "ndk_libc++_shared")
 			}
 		}
 	}
@@ -243,6 +243,9 @@
 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.
diff --git a/java/app_test.go b/java/app_test.go
index 9aedebd..bb39c16 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -1203,6 +1203,10 @@
 			compile_multilib: "both",
 			sdk_version: "current",
 		}
+
+		ndk_prebuilt_shared_stl {
+			name: "ndk_libc++_shared",
+		}
 		`)
 
 	testCases := []struct {
@@ -1212,7 +1216,7 @@
 		{"stl",
 			[]string{
 				"libjni.so",
-				"libc++.so",
+				"libc++_shared.so",
 			},
 		},
 		{"system",
@@ -1323,3 +1327,73 @@
 		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)
+			}
+		})
+	}
+}
diff --git a/java/java.go b/java/java.go
index bfbd98c..5544f57 100644
--- a/java/java.go
+++ b/java/java.go
@@ -355,6 +355,8 @@
 	switch tag {
 	case "":
 		return append(android.Paths{j.outputFile}, j.extraOutputFiles...), nil
+	case ".jar":
+		return android.Paths{j.implementationAndResourcesJar}, nil
 	default:
 		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
 	}
@@ -967,8 +969,6 @@
 
 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)
@@ -983,9 +983,6 @@
 	}
 
 	srcFiles = j.genSources(ctx, srcFiles, flags)
-	if len(srcFiles) > 0 {
-		hasSrcs = true
-	}
 
 	srcJars := srcFiles.FilterByExt(".srcjar")
 	srcJars = append(srcJars, deps.srcJars...)
@@ -1182,7 +1179,6 @@
 
 	if len(deps.staticJars) > 0 {
 		jars = append(jars, deps.staticJars...)
-		hasSrcs = true
 	}
 
 	manifest := j.overrideManifest
@@ -1294,7 +1290,7 @@
 
 	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
@@ -1499,6 +1495,11 @@
 	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)
 //
diff --git a/java/java_test.go b/java/java_test.go
index 3a7ed4e..4d161c5 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -105,6 +105,7 @@
 	ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory))
 	ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory))
 	ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(cc.LlndkLibraryFactory))
+	ctx.RegisterModuleType("ndk_prebuilt_shared_stl", android.ModuleFactoryAdaptor(cc.NdkPrebuiltSharedStlFactory))
 	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
 		ctx.BottomUp("link", cc.LinkageMutator).Parallel()
 		ctx.BottomUp("begin", cc.BeginMutator).Parallel()
@@ -134,6 +135,8 @@
 		"api/test-removed.txt":   nil,
 		"framework/aidl/a.aidl":  nil,
 
+		"prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so": nil,
+
 		"prebuilts/sdk/14/public/android.jar":         nil,
 		"prebuilts/sdk/14/public/framework.aidl":      nil,
 		"prebuilts/sdk/14/system/android.jar":         nil,
diff --git a/java/sdk.go b/java/sdk.go
index e93f8fb..506edfb 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -151,7 +151,7 @@
 		}
 
 		if m == "core.current.stubs" {
-			ret.systemModules = "core-system-modules"
+			ret.systemModules = "core-current-stubs-system-modules"
 		} else if m == "core.platform.api.stubs" {
 			ret.systemModules = "core-platform-api-stubs-system-modules"
 		}
diff --git a/java/testing.go b/java/testing.go
index fc7842d..e1b06a0 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -108,6 +108,7 @@
 
 	systemModules := []string{
 		"core-system-modules",
+		"core-current-stubs-system-modules",
 		"core-platform-api-stubs-system-modules",
 		"android_stubs_current_system_modules",
 		"android_system_stubs_current_system_modules",
diff --git a/scripts/manifest_fixer.py b/scripts/manifest_fixer.py
index bb14851..945bc18 100755
--- a/scripts/manifest_fixer.py
+++ b/scripts/manifest_fixer.py
@@ -59,6 +59,9 @@
                       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 @@
                        (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 @@
     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)
 
diff --git a/scripts/manifest_fixer_test.py b/scripts/manifest_fixer_test.py
index 2035421..ea8095e 100755
--- a/scripts/manifest_fixer_test.py
+++ b/scripts/manifest_fixer_test.py
@@ -424,5 +424,47 @@
     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)
diff --git a/scripts/system-clang-format b/scripts/system-clang-format
index 55773a2..14abd93 100644
--- a/scripts/system-clang-format
+++ b/scripts/system-clang-format
@@ -4,6 +4,7 @@
 ColumnLimit: 100
 CommentPragmas: NOLINT:.*
 DerivePointerAlignment: false
+IncludeBlocks: Preserve
 IndentWidth: 4
 ContinuationIndentWidth: 8
 PointerAlignment: Left
diff --git a/scripts/system-clang-format-2 b/scripts/system-clang-format-2
index ede5d7e..e28b379 100644
--- a/scripts/system-clang-format-2
+++ b/scripts/system-clang-format-2
@@ -3,6 +3,7 @@
 ColumnLimit: 100
 CommentPragmas: NOLINT:.*
 DerivePointerAlignment: false
+IncludeBlocks: Preserve
 IndentWidth: 2
 PointerAlignment: Left
 TabWidth: 2