Merge "Allow NDK static libraries to use the NDK sysroot."
diff --git a/android/config.go b/android/config.go
index bf8edca..56e9525 100644
--- a/android/config.go
+++ b/android/config.go
@@ -511,12 +511,13 @@
 	}
 }
 
-func (c *config) DefaultAppCertificate(ctx PathContext) SourcePath {
+func (c *config) DefaultAppCertificate(ctx PathContext) (pem, key SourcePath) {
 	defaultCert := String(c.ProductVariables.DefaultAppCertificate)
 	if defaultCert != "" {
-		return PathForSource(ctx, defaultCert)
+		return PathForSource(ctx, defaultCert+".x509.pem"), PathForSource(ctx, defaultCert+".pk8")
 	} else {
-		return c.DefaultAppCertificateDir(ctx).Join(ctx, "testkey")
+		defaultDir := c.DefaultAppCertificateDir(ctx)
+		return defaultDir.Join(ctx, "testkey.x509.pem"), defaultDir.Join(ctx, "testkey.pk8")
 	}
 }
 
diff --git a/android/variable.go b/android/variable.go
index 6815438..b8aad18 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -67,10 +67,17 @@
 			Cflags []string
 		}
 
-		// treble is true when a build is a Treble compliant device.  This is automatically set when
-		// a build is shipped with Android O, but can be overriden.  This controls such things as
-		// the sepolicy split and enabling the Treble linker namespaces.
-		Treble struct {
+		// treble_linker_namespaces is true when the system/vendor linker namespace separation is
+		// enabled.
+		Treble_linker_namespaces struct {
+			Cflags []string
+		}
+		// sepolicy_split is true when system/vendor sepolicy split is enabled.
+		Sepolicy_split struct {
+			Cflags []string
+		}
+		// enforce_vintf_manifest is true when a device is required to have a vintf manifest.
+		Enforce_vintf_manifest struct {
 			Cflags []string
 		}
 
@@ -157,7 +164,9 @@
 	Debuggable                 *bool `json:",omitempty"`
 	Eng                        *bool `json:",omitempty"`
 	Device_uses_hwc2           *bool `json:",omitempty"`
-	Treble                     *bool `json:",omitempty"`
+	Treble_linker_namespaces   *bool `json:",omitempty"`
+	Sepolicy_split             *bool `json:",omitempty"`
+	Enforce_vintf_manifest     *bool `json:",omitempty"`
 	Pdk                        *bool `json:",omitempty"`
 	Uml                        *bool `json:",omitempty"`
 	MinimizeJavaDebugInfo      *bool `json:",omitempty"`
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index 4022a5e..c6e90f0 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -153,6 +153,7 @@
 			"LOCAL_PROPRIETARY_MODULE":       "proprietary",
 			"LOCAL_VENDOR_MODULE":            "vendor",
 			"LOCAL_EXPORT_PACKAGE_RESOURCES": "export_package_resources",
+			"LOCAL_PRIVILEGED_MODULE":        "privileged",
 
 			"LOCAL_DEX_PREOPT":                  "dex_preopt.enabled",
 			"LOCAL_DEX_PREOPT_APP_IMAGE":        "dex_preopt.app_image",
@@ -636,22 +637,15 @@
 	return "."
 }
 
-func allJavaFilesUnder(args []string) string {
-	dir := ""
-	if len(args) > 0 {
-		dir = strings.TrimSpace(args[0])
+func allFilesUnder(wildcard string) func(args []string) string {
+	return func(args []string) string {
+		dir := ""
+		if len(args) > 0 {
+			dir = strings.TrimSpace(args[0])
+		}
+
+		return fmt.Sprintf("%s/**/"+wildcard, dir)
 	}
-
-	return fmt.Sprintf("%s/**/*.java", dir)
-}
-
-func allProtoFilesUnder(args []string) string {
-	dir := ""
-	if len(args) > 0 {
-		dir = strings.TrimSpace(args[0])
-	}
-
-	return fmt.Sprintf("%s/**/*.proto", dir)
 }
 
 func allSubdirJavaFiles(args []string) string {
@@ -695,8 +689,11 @@
 	globalScope := mkparser.NewScope(nil)
 	globalScope.Set("CLEAR_VARS", clear_vars)
 	globalScope.SetFunc("my-dir", mydir)
-	globalScope.SetFunc("all-java-files-under", allJavaFilesUnder)
-	globalScope.SetFunc("all-proto-files-under", allProtoFilesUnder)
+	globalScope.SetFunc("all-java-files-under", allFilesUnder("*.java"))
+	globalScope.SetFunc("all-proto-files-under", allFilesUnder("*.proto"))
+	globalScope.SetFunc("all-aidl-files-under", allFilesUnder("*.aidl"))
+	globalScope.SetFunc("all-Iaidl-files-under", allFilesUnder("I*.aidl"))
+	globalScope.SetFunc("all-logtags-files-under", allFilesUnder("*.logtags"))
 	globalScope.SetFunc("all-subdir-java-files", allSubdirJavaFiles)
 	globalScope.SetFunc("all-makefiles-under", includeIgnored)
 	globalScope.SetFunc("first-makefiles-under", includeIgnored)
diff --git a/cc/builder.go b/cc/builder.go
index b5f4c5c..e583834 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -231,27 +231,28 @@
 }
 
 type builderFlags struct {
-	globalFlags   string
-	arFlags       string
-	asFlags       string
-	cFlags        string
-	toolingCFlags string // A separate set of Cflags for clang LibTooling tools
-	conlyFlags    string
-	cppFlags      string
-	ldFlags       string
-	libFlags      string
-	yaccFlags     string
-	protoFlags    string
-	tidyFlags     string
-	sAbiFlags     string
-	yasmFlags     string
-	aidlFlags     string
-	rsFlags       string
-	toolchain     config.Toolchain
-	clang         bool
-	tidy          bool
-	coverage      bool
-	sAbiDump      bool
+	globalFlags    string
+	arFlags        string
+	asFlags        string
+	cFlags         string
+	toolingCFlags  string // A separate set of Cflags for clang LibTooling tools
+	conlyFlags     string
+	cppFlags       string
+	ldFlags        string
+	libFlags       string
+	yaccFlags      string
+	protoFlags     string
+	protoOutParams string
+	tidyFlags      string
+	sAbiFlags      string
+	yasmFlags      string
+	aidlFlags      string
+	rsFlags        string
+	toolchain      config.Toolchain
+	clang          bool
+	tidy           bool
+	coverage       bool
+	sAbiDump       bool
 
 	systemIncludeFlags string
 
diff --git a/cc/cc.go b/cc/cc.go
index fa33bc6..04aa6a6 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -116,6 +116,7 @@
 	ToolingCppFlags []string // Flags that apply to C++ source files parsed by clang LibTooling tools
 	YaccFlags       []string // Flags that apply to Yacc source files
 	protoFlags      []string // Flags that apply to proto source files
+	protoOutParams  []string // Flags that modify the output of proto generated files
 	aidlFlags       []string // Flags that apply to aidl source files
 	rsFlags         []string // Flags that apply to renderscript source files
 	LdFlags         []string // Flags that apply to linker command lines
@@ -1035,6 +1036,27 @@
 		ctx.ModuleErrorf("links %q built against newer API version %q",
 			ctx.OtherModuleName(to), String(to.Properties.Sdk_version))
 	}
+
+	// Also check that the two STL choices are compatible.
+	fromStl := from.stl.Properties.SelectedStl
+	toStl := to.stl.Properties.SelectedStl
+	if fromStl == "" || toStl == "" {
+		// Libraries that don't use the STL are unrestricted.
+		return
+	}
+
+	if fromStl == "ndk_system" || toStl == "ndk_system" {
+		// We can be permissive with the system "STL" since it is only the C++
+		// ABI layer, but in the future we should make sure that everyone is
+		// using either libc++ or nothing.
+		return
+	}
+
+	if getNdkStlFamily(ctx, from) != getNdkStlFamily(ctx, to) {
+		ctx.ModuleErrorf("uses %q and depends on %q which uses incompatible %q",
+			from.stl.Properties.SelectedStl, ctx.OtherModuleName(to),
+			to.stl.Properties.SelectedStl)
+	}
 }
 
 // Convert dependencies to paths.  Returns a PathDeps containing paths
@@ -1422,7 +1444,9 @@
 		mctx.CreateVariations(vendorMode)
 	} else if _, ok := m.linker.(*llndkHeadersDecorator); ok {
 		// ... and LL-NDK headers as well
-		mctx.CreateVariations(vendorMode)
+		mod := mctx.CreateVariations(vendorMode)
+		vendor := mod[0].(*Module)
+		vendor.Properties.UseVndk = true
 	} else if _, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok {
 		// Make vendor variants only for the versions in BOARD_VNDK_VERSION and
 		// PRODUCT_EXTRA_VNDK_VERSIONS.
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 148b4dd..15e45d0 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -61,6 +61,7 @@
 	ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(LibrarySharedFactory))
 	ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(toolchainLibraryFactory))
 	ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(llndkLibraryFactory))
+	ctx.RegisterModuleType("llndk_headers", android.ModuleFactoryAdaptor(llndkHeadersFactory))
 	ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(objectFactory))
 	ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(genrule.FileGroupFactory))
 	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
@@ -138,6 +139,7 @@
 		"bar.c":      nil,
 		"a.proto":    nil,
 		"b.aidl":     nil,
+		"my_include": nil,
 	})
 
 	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
@@ -583,6 +585,34 @@
 	}
 }
 
+func TestLlndkHeaders(t *testing.T) {
+	ctx := testCc(t, `
+	llndk_headers {
+		name: "libllndk_headers",
+		export_include_dirs: ["my_include"],
+	}
+	llndk_library {
+		name: "libllndk",
+		export_llndk_headers: ["libllndk_headers"],
+	}
+	cc_library {
+		name: "libvendor",
+		shared_libs: ["libllndk"],
+		vendor: true,
+		srcs: ["foo.c"],
+		no_libgcc : true,
+		nocrt : true,
+	}
+	`)
+
+	// _static variant is used since _shared reuses *.o from the static variant
+	cc := ctx.ModuleForTests("libvendor", "android_arm_armv7-a-neon_vendor_static").Rule("cc")
+	cflags := cc.Args["cFlags"]
+	if !strings.Contains(cflags, "-Imy_include") {
+		t.Errorf("cflags for libvendor must contain -Imy_include, but was %#v.", cflags)
+	}
+}
+
 var compilerFlagsTestCases = []struct {
 	in  string
 	out bool
diff --git a/cc/config/global.go b/cc/config/global.go
index 4734498..6de1300 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -120,19 +120,14 @@
 	ClangDefaultShortVersion = "5.0.1"
 
 	WarningAllowedProjects = []string{
-		"external/libese/third_party/NXPNFC_P61_JCOP_Kit/",
-		"external/skia/",
 		"device/",
-		"frameworks/av/media/libstagefright/codecs/",
 		"vendor/",
 	}
 
 	// Some Android.mk files still have warnings.
 	WarningAllowedOldProjects = []string{
-		"frameworks/av/drm/mediacas/plugins/",
 		"hardware/libhardware/modules/",
 		"hardware/qcom/",
-		"tools/adt/idea/android/ultimate/get_modification_time/jni/",
 	}
 )
 
diff --git a/cc/gen.go b/cc/gen.go
index 15b37b5..e9d1e2a 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -153,7 +153,8 @@
 			srcFiles[i] = cppFile
 			genLex(ctx, srcFile, cppFile)
 		case ".proto":
-			ccFile, headerFile := genProto(ctx, srcFile, buildFlags.protoFlags)
+			ccFile, headerFile := genProto(ctx, srcFile, buildFlags.protoFlags,
+				buildFlags.protoOutParams)
 			srcFiles[i] = ccFile
 			deps = append(deps, headerFile)
 		case ".aidl":
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index 9a29964..e824d0f 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -191,7 +191,6 @@
 func llndkHeadersFactory() android.Module {
 	module, library := NewLibrary(android.DeviceSupported)
 	library.HeaderOnly()
-	library.setStatic()
 
 	decorator := &llndkHeadersDecorator{
 		libraryDecorator: library,
diff --git a/cc/lto.go b/cc/lto.go
index fdb7688..b1e7cfa 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -40,10 +40,15 @@
 	// Lto must violate capitialization style for acronyms so that it can be
 	// referred to in blueprint files as "lto"
 	Lto struct {
-		Full *bool `android:"arch_variant"`
-		Thin *bool `android:"arch_variant"`
+		Never *bool `android:"arch_variant"`
+		Full  *bool `android:"arch_variant"`
+		Thin  *bool `android:"arch_variant"`
 	} `android:"arch_variant"`
-	LTODep bool `blueprint:"mutated"`
+
+	// Dep properties indicate that this module needs to be built with LTO
+	// since it is an object dependency of an LTO module.
+	FullDep bool `blueprint:"mutated"`
+	ThinDep bool `blueprint:"mutated"`
 }
 
 type lto struct {
@@ -84,7 +89,7 @@
 
 // Can be called with a null receiver
 func (lto *lto) LTO() bool {
-	if lto == nil {
+	if lto == nil || lto.Disabled() {
 		return false
 	}
 
@@ -93,41 +98,91 @@
 	return full || thin
 }
 
+// Is lto.never explicitly set to true?
+func (lto *lto) Disabled() bool {
+	return lto.Properties.Lto.Never != nil && *lto.Properties.Lto.Never
+}
+
 // Propagate lto requirements down from binaries
 func ltoDepsMutator(mctx android.TopDownMutatorContext) {
-	if c, ok := mctx.Module().(*Module); ok && c.lto.LTO() {
-		full := Bool(c.lto.Properties.Lto.Full)
-		thin := Bool(c.lto.Properties.Lto.Thin)
+	if m, ok := mctx.Module().(*Module); ok && m.lto.LTO() {
+		full := Bool(m.lto.Properties.Lto.Full)
+		thin := Bool(m.lto.Properties.Lto.Thin)
 		if full && thin {
 			mctx.PropertyErrorf("LTO", "FullLTO and ThinLTO are mutually exclusive")
 		}
 
-		mctx.VisitDepsDepthFirst(func(m android.Module) {
-			tag := mctx.OtherModuleDependencyTag(m)
+		mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
+			tag := mctx.OtherModuleDependencyTag(dep)
 			switch tag {
 			case staticDepTag, staticExportDepTag, lateStaticDepTag, wholeStaticDepTag, objDepTag, reuseObjTag:
-				if cc, ok := m.(*Module); ok && cc.lto != nil {
-					cc.lto.Properties.LTODep = true
+				if dep, ok := dep.(*Module); ok && dep.lto != nil &&
+					!dep.lto.Disabled() {
+					if full && !Bool(dep.lto.Properties.Lto.Full) {
+						dep.lto.Properties.FullDep = true
+					}
+					if thin && !Bool(dep.lto.Properties.Lto.Thin) {
+						dep.lto.Properties.ThinDep = true
+					}
 				}
+
+				// Recursively walk static dependencies
+				return true
 			}
+
+			// Do not recurse down non-static dependencies
+			return false
 		})
 	}
 }
 
 // Create lto variants for modules that need them
 func ltoMutator(mctx android.BottomUpMutatorContext) {
-	if c, ok := mctx.Module().(*Module); ok && c.lto != nil {
-		if c.lto.LTO() {
-			mctx.SetDependencyVariation("lto")
-		} else if c.lto.Properties.LTODep {
-			modules := mctx.CreateVariations("", "lto")
-			modules[0].(*Module).lto.Properties.Lto.Full = boolPtr(false)
-			modules[0].(*Module).lto.Properties.Lto.Thin = boolPtr(false)
-			modules[0].(*Module).lto.Properties.LTODep = false
-			modules[1].(*Module).lto.Properties.LTODep = false
-			modules[1].(*Module).Properties.PreventInstall = true
-			modules[1].(*Module).Properties.HideFromMake = true
+	if m, ok := mctx.Module().(*Module); ok && m.lto != nil {
+		// Create variations for LTO types required as static
+		// dependencies
+		variationNames := []string{""}
+		if m.lto.Properties.FullDep && !Bool(m.lto.Properties.Lto.Full) {
+			variationNames = append(variationNames, "lto-full")
 		}
-		c.lto.Properties.LTODep = false
+		if m.lto.Properties.ThinDep && !Bool(m.lto.Properties.Lto.Thin) {
+			variationNames = append(variationNames, "lto-thin")
+		}
+
+		// Use correct dependencies if LTO property is explicitly set
+		// (mutually exclusive)
+		if Bool(m.lto.Properties.Lto.Full) {
+			mctx.SetDependencyVariation("lto-full")
+		}
+		if Bool(m.lto.Properties.Lto.Thin) {
+			mctx.SetDependencyVariation("lto-thin")
+		}
+
+		if len(variationNames) > 1 {
+			modules := mctx.CreateVariations(variationNames...)
+			for i, name := range variationNames {
+				variation := modules[i].(*Module)
+				// Default module which will be
+				// installed. Variation set above according to
+				// explicit LTO properties
+				if name == "" {
+					continue
+				}
+
+				// LTO properties for dependencies
+				if name == "lto-full" {
+					variation.lto.Properties.Lto.Full = boolPtr(true)
+					variation.lto.Properties.Lto.Thin = boolPtr(false)
+				}
+				if name == "lto-thin" {
+					variation.lto.Properties.Lto.Full = boolPtr(false)
+					variation.lto.Properties.Lto.Thin = boolPtr(true)
+				}
+				variation.Properties.PreventInstall = true
+				variation.Properties.HideFromMake = true
+				variation.lto.Properties.FullDep = false
+				variation.lto.Properties.ThinDep = false
+			}
+		}
 	}
 }
diff --git a/cc/pgo.go b/cc/pgo.go
index 9fea154..fef962e 100644
--- a/cc/pgo.go
+++ b/cc/pgo.go
@@ -42,6 +42,9 @@
 		Profile_file       *string `android:"arch_variant"`
 		Benchmarks         []string
 		Enable_profile_use *bool `android:"arch_variant"`
+		// Additional compiler flags to use when building this module
+		// for profiling (either instrumentation or sampling).
+		Cflags []string `android:"arch_variant"`
 	} `android:"arch_variant"`
 
 	PgoPresent          bool `blueprint:"mutated"`
@@ -65,6 +68,8 @@
 }
 
 func (props *PgoProperties) addProfileGatherFlags(ctx ModuleContext, flags Flags) Flags {
+	flags.CFlags = append(flags.CFlags, props.Pgo.Cflags...)
+
 	if props.isInstrumentation() {
 		flags.CFlags = append(flags.CFlags, profileInstrumentFlag)
 		// The profile runtime is added below in deps().  Add the below
diff --git a/cc/proto.go b/cc/proto.go
index e7f1d41..3b5fd3b 100644
--- a/cc/proto.go
+++ b/cc/proto.go
@@ -16,6 +16,7 @@
 
 import (
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
 )
@@ -27,15 +28,15 @@
 var (
 	proto = pctx.AndroidStaticRule("protoc",
 		blueprint.RuleParams{
-			Command:     "$protocCmd --cpp_out=$outDir $protoFlags $in",
+			Command:     "$protocCmd --cpp_out=$protoOutParams:$outDir $protoFlags $in",
 			CommandDeps: []string{"$protocCmd"},
-		}, "protoFlags", "outDir")
+		}, "protoFlags", "protoOutParams", "outDir")
 )
 
 // genProto creates a rule to convert a .proto file to generated .pb.cc and .pb.h files and returns
 // the paths to the generated files.
 func genProto(ctx android.ModuleContext, protoFile android.Path,
-	protoFlags string) (ccFile, headerFile android.WritablePath) {
+	protoFlags string, protoOutParams string) (ccFile, headerFile android.WritablePath) {
 
 	ccFile = android.GenPathWithExt(ctx, "proto", protoFile, "pb.cc")
 	headerFile = android.GenPathWithExt(ctx, "proto", protoFile, "pb.h")
@@ -46,8 +47,9 @@
 		Outputs:     android.WritablePaths{ccFile, headerFile},
 		Input:       protoFile,
 		Args: map[string]string{
-			"outDir":     android.ProtoDir(ctx).String(),
-			"protoFlags": protoFlags,
+			"outDir":         android.ProtoDir(ctx).String(),
+			"protoFlags":     protoFlags,
+			"protoOutParams": protoOutParams,
 		},
 	})
 
@@ -97,5 +99,9 @@
 
 	flags.protoFlags = android.ProtoFlags(ctx, p)
 
+	if proptools.String(p.Proto.Type) == "lite" {
+		flags.protoOutParams = []string{"lite"}
+	}
+
 	return flags
 }
diff --git a/cc/stl.go b/cc/stl.go
index 347db99..338db84 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -19,6 +19,25 @@
 	"fmt"
 )
 
+func getNdkStlFamily(ctx android.ModuleContext, m *Module) string {
+	stl := m.stl.Properties.SelectedStl
+	switch stl {
+	case "ndk_libc++_shared", "ndk_libc++_static":
+		return "libc++"
+	case "ndk_libstlport_shared", "ndk_libstlport_static":
+		return "stlport"
+	case "ndk_libgnustl_static":
+		return "gnustl"
+	case "ndk_system":
+		return "system"
+	case "":
+		return "none"
+	default:
+		ctx.ModuleErrorf("stl: %q is not a valid STL", stl)
+		return ""
+	}
+}
+
 type StlProperties struct {
 	// select the STL library to use.  Possible values are "libc++", "libc++_static",
 	// "stlport", "stlport_static", "ndk", "libstdc++", or "none".  Leave blank to select the
diff --git a/cc/util.go b/cc/util.go
index cc89af6..7041029 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -97,27 +97,28 @@
 
 func flagsToBuilderFlags(in Flags) builderFlags {
 	return builderFlags{
-		globalFlags:   strings.Join(in.GlobalFlags, " "),
-		arFlags:       strings.Join(in.ArFlags, " "),
-		asFlags:       strings.Join(in.AsFlags, " "),
-		cFlags:        strings.Join(in.CFlags, " "),
-		toolingCFlags: strings.Join(in.ToolingCFlags, " "),
-		conlyFlags:    strings.Join(in.ConlyFlags, " "),
-		cppFlags:      strings.Join(in.CppFlags, " "),
-		yaccFlags:     strings.Join(in.YaccFlags, " "),
-		protoFlags:    strings.Join(in.protoFlags, " "),
-		aidlFlags:     strings.Join(in.aidlFlags, " "),
-		rsFlags:       strings.Join(in.rsFlags, " "),
-		ldFlags:       strings.Join(in.LdFlags, " "),
-		libFlags:      strings.Join(in.libFlags, " "),
-		tidyFlags:     strings.Join(in.TidyFlags, " "),
-		sAbiFlags:     strings.Join(in.SAbiFlags, " "),
-		yasmFlags:     strings.Join(in.YasmFlags, " "),
-		toolchain:     in.Toolchain,
-		clang:         in.Clang,
-		coverage:      in.Coverage,
-		tidy:          in.Tidy,
-		sAbiDump:      in.SAbiDump,
+		globalFlags:    strings.Join(in.GlobalFlags, " "),
+		arFlags:        strings.Join(in.ArFlags, " "),
+		asFlags:        strings.Join(in.AsFlags, " "),
+		cFlags:         strings.Join(in.CFlags, " "),
+		toolingCFlags:  strings.Join(in.ToolingCFlags, " "),
+		conlyFlags:     strings.Join(in.ConlyFlags, " "),
+		cppFlags:       strings.Join(in.CppFlags, " "),
+		yaccFlags:      strings.Join(in.YaccFlags, " "),
+		protoFlags:     strings.Join(in.protoFlags, " "),
+		protoOutParams: strings.Join(in.protoOutParams, ":"),
+		aidlFlags:      strings.Join(in.aidlFlags, " "),
+		rsFlags:        strings.Join(in.rsFlags, " "),
+		ldFlags:        strings.Join(in.LdFlags, " "),
+		libFlags:       strings.Join(in.libFlags, " "),
+		tidyFlags:      strings.Join(in.TidyFlags, " "),
+		sAbiFlags:      strings.Join(in.SAbiFlags, " "),
+		yasmFlags:      strings.Join(in.YasmFlags, " "),
+		toolchain:      in.Toolchain,
+		clang:          in.Clang,
+		coverage:       in.Coverage,
+		tidy:           in.Tidy,
+		sAbiDump:       in.SAbiDump,
 
 		systemIncludeFlags: strings.Join(in.SystemIncludeFlags, " "),
 
diff --git a/java/androidmk.go b/java/androidmk.go
index af91a33..24fe43a 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -152,30 +152,42 @@
 		Include:    "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
 		Extra: []android.AndroidMkExtraFunc{
 			func(w io.Writer, outputFile android.Path) {
-				if Bool(app.appProperties.Export_package_resources) {
-					if app.dexJarFile != nil {
-						fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", app.dexJarFile.String())
-					}
-					fmt.Fprintln(w, "LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE :=", app.exportPackage.String())
-
-					if app.jacocoReportClassesFile != nil {
-						fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", app.jacocoReportClassesFile.String())
-					}
-
-					if app.Name() == "framework-res" {
-						fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(TARGET_OUT_JAVA_LIBRARIES)")
-						// Make base_rules.mk not put framework-res in a subdirectory called
-						// framework_res.
-						fmt.Fprintln(w, "LOCAL_NO_STANDARD_LIBRARIES := true")
-					}
-
-					if len(app.rroDirs) > 0 {
-						fmt.Fprintln(w, "LOCAL_SOONG_RRO_DIRS :=", strings.Join(app.rroDirs.Strings(), " "))
-					}
-					fmt.Fprintln(w, "LOCAL_EXPORT_PACKAGE_RESOURCES :=",
-						Bool(app.appProperties.Export_package_resources))
-					fmt.Fprintln(w, "LOCAL_FULL_MANIFEST_FILE :=", app.manifestPath.String())
+				fmt.Fprintln(w, "LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE :=", app.exportPackage.String())
+				if app.dexJarFile != nil {
+					fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", app.dexJarFile.String())
 				}
+				if app.implementationJarFile != nil {
+					fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", app.implementationJarFile)
+				}
+				if app.headerJarFile != nil {
+					fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", app.headerJarFile.String())
+				}
+				if app.jacocoReportClassesFile != nil {
+					fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", app.jacocoReportClassesFile.String())
+				}
+
+				if app.Name() == "framework-res" {
+					fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(TARGET_OUT_JAVA_LIBRARIES)")
+					// Make base_rules.mk not put framework-res in a subdirectory called
+					// framework_res.
+					fmt.Fprintln(w, "LOCAL_NO_STANDARD_LIBRARIES := true")
+				}
+
+				if len(app.rroDirs) > 0 {
+					fmt.Fprintln(w, "LOCAL_SOONG_RRO_DIRS :=", strings.Join(app.rroDirs.Strings(), " "))
+				}
+
+				if Bool(app.appProperties.Export_package_resources) {
+					fmt.Fprintln(w, "LOCAL_EXPORT_PACKAGE_RESOURCES := true")
+				}
+
+				fmt.Fprintln(w, "LOCAL_FULL_MANIFEST_FILE :=", app.manifestPath.String())
+
+				if Bool(app.appProperties.Privileged) {
+					fmt.Fprintln(w, "LOCAL_PRIVILEGED_MODULE := true")
+				}
+
+				fmt.Fprintln(w, "LOCAL_CERTIFICATE :=", app.certificate.pem.String())
 			},
 		},
 	}
diff --git a/java/app.go b/java/app.go
index ed6a9db..df53375 100644
--- a/java/app.go
+++ b/java/app.go
@@ -61,6 +61,11 @@
 	Resource_dirs []string
 
 	Instrumentation_for *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
 }
 
 type AndroidApp struct {
@@ -72,6 +77,11 @@
 	exportPackage android.Path
 	rroDirs       android.Paths
 	manifestPath  android.Path
+	certificate   certificate
+}
+
+type certificate struct {
+	pem, key android.Path
 }
 
 func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -127,18 +137,30 @@
 		a.Module.compile(ctx, a.aaptSrcJar)
 	}
 
-	certificate := String(a.appProperties.Certificate)
-	if certificate == "" {
-		certificate = ctx.Config().DefaultAppCertificate(ctx).String()
-	} else if dir, _ := filepath.Split(certificate); dir == "" {
-		certificate = filepath.Join(ctx.Config().DefaultAppCertificateDir(ctx).String(), certificate)
-	} else {
-		certificate = filepath.Join(android.PathForSource(ctx).String(), certificate)
+	c := String(a.appProperties.Certificate)
+	switch {
+	case c == "":
+		pem, key := ctx.Config().DefaultAppCertificate(ctx)
+		a.certificate = certificate{pem, key}
+	case strings.ContainsRune(c, '/'):
+		a.certificate = certificate{
+			android.PathForSource(ctx, c+".x509.pem"),
+			android.PathForSource(ctx, c+".pk8"),
+		}
+	default:
+		defaultDir := ctx.Config().DefaultAppCertificateDir(ctx)
+		a.certificate = certificate{
+			defaultDir.Join(ctx, c+".x509.pem"),
+			defaultDir.Join(ctx, c+".pk8"),
+		}
 	}
 
-	certificates := []string{certificate}
+	certificates := []certificate{a.certificate}
 	for _, c := range a.appProperties.Additional_certificates {
-		certificates = append(certificates, filepath.Join(android.PathForSource(ctx).String(), c))
+		certificates = append(certificates, certificate{
+			android.PathForSource(ctx, c+".x509.pem"),
+			android.PathForSource(ctx, c+".pk8"),
+		})
 	}
 
 	packageFile := android.PathForModuleOut(ctx, "package.apk")
@@ -152,6 +174,8 @@
 	if ctx.ModuleName() == "framework-res" {
 		// framework-res.apk is installed as system/framework/framework-res.apk
 		ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"), ctx.ModuleName()+".apk", a.outputFile)
+	} else if Bool(a.appProperties.Privileged) {
+		ctx.InstallFile(android.PathForModuleInstall(ctx, "priv-app"), ctx.ModuleName()+".apk", a.outputFile)
 	} else {
 		ctx.InstallFile(android.PathForModuleInstall(ctx, "app"), ctx.ModuleName()+".apk", a.outputFile)
 	}
diff --git a/java/app_builder.go b/java/app_builder.go
index 676ed58..945d7bd 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -61,7 +61,7 @@
 	})
 
 func CreateAppPackage(ctx android.ModuleContext, outputFile android.WritablePath,
-	resJarFile, dexJarFile android.Path, certificates []string) {
+	resJarFile, dexJarFile android.Path, certificates []certificate) {
 
 	// TODO(ccross): JNI libs
 
@@ -80,7 +80,7 @@
 
 	var certificateArgs []string
 	for _, c := range certificates {
-		certificateArgs = append(certificateArgs, c+".x509.pem", c+".pk8")
+		certificateArgs = append(certificateArgs, c.pem.String(), c.key.String())
 	}
 
 	// TODO(ccross): sometimes uncompress dex
diff --git a/java/builder.go b/java/builder.go
index 10dfe06..48fba23 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -200,8 +200,9 @@
 	kotlincFlags     string
 	kotlincClasspath classpath
 
-	protoFlags   []string
-	protoOutFlag string
+	protoFlags       []string
+	protoOutTypeFlag string // The flag itself: --java_out
+	protoOutParams   string // Parameters to that flag: --java_out=$protoOutParams:$outDir
 }
 
 func TransformKotlinToClasses(ctx android.ModuleContext, outputFile android.WritablePath,
diff --git a/java/gen.go b/java/gen.go
index 7a0dcac..4893e88 100644
--- a/java/gen.go
+++ b/java/gen.go
@@ -107,7 +107,7 @@
 	if len(protoFiles) > 0 {
 		protoSrcJar := android.PathForModuleGen(ctx, "proto.srcjar")
 		genProto(ctx, protoSrcJar, protoFiles,
-			flags.protoFlags, flags.protoOutFlag, "")
+			flags.protoFlags, flags.protoOutTypeFlag, flags.protoOutParams)
 
 		outSrcFiles = append(outSrcFiles, protoSrcJar)
 	}
diff --git a/java/java.go b/java/java.go
index d9075b1..9b345fd 100644
--- a/java/java.go
+++ b/java/java.go
@@ -142,6 +142,11 @@
 		Exclude_filter []string
 	}
 
+	Proto struct {
+		// List of extra options that will be passed to the proto generator.
+		Output_params []string
+	}
+
 	Instrument bool `blueprint:"mutated"`
 }
 
@@ -620,7 +625,7 @@
 	}
 	srcFiles := ctx.ExpandSources(j.properties.Srcs, j.properties.Exclude_srcs)
 	if hasSrcExt(srcFiles.Strings(), ".proto") {
-		flags = protoFlags(ctx, &j.protoProperties, flags)
+		flags = protoFlags(ctx, &j.properties, &j.protoProperties, flags)
 	}
 
 	srcFiles = j.genSources(ctx, srcFiles, flags)
diff --git a/java/proto.go b/java/proto.go
index 17f02a3..226fac0 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -31,17 +31,17 @@
 	proto = pctx.AndroidStaticRule("protoc",
 		blueprint.RuleParams{
 			Command: `rm -rf $outDir && mkdir -p $outDir && ` +
-				`$protocCmd $protoOut=$protoOutFlags:$outDir $protoFlags $in && ` +
+				`$protocCmd $protoOut=$protoOutParams:$outDir $protoFlags $in && ` +
 				`${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`,
 			CommandDeps: []string{
 				"$protocCmd",
 				"${config.SoongZipCmd}",
 			},
-		}, "protoFlags", "protoOut", "protoOutFlags", "outDir")
+		}, "protoFlags", "protoOut", "protoOutParams", "outDir")
 )
 
 func genProto(ctx android.ModuleContext, outputSrcJar android.WritablePath,
-	protoFiles android.Paths, protoFlags []string, protoOut, protoOutFlags string) {
+	protoFiles android.Paths, protoFlags []string, protoOut, protoOutParams string) {
 
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        proto,
@@ -49,10 +49,10 @@
 		Output:      outputSrcJar,
 		Inputs:      protoFiles,
 		Args: map[string]string{
-			"outDir":        android.ProtoDir(ctx).String(),
-			"protoOut":      protoOut,
-			"protoOutFlags": protoOutFlags,
-			"protoFlags":    strings.Join(protoFlags, " "),
+			"outDir":         android.ProtoDir(ctx).String(),
+			"protoOut":       protoOut,
+			"protoOutParams": protoOutParams,
+			"protoFlags":     strings.Join(protoFlags, " "),
 		},
 	})
 }
@@ -77,19 +77,31 @@
 	}
 }
 
-func protoFlags(ctx android.ModuleContext, p *android.ProtoProperties, flags javaBuilderFlags) javaBuilderFlags {
+func protoFlags(ctx android.ModuleContext, j *CompilerProperties, p *android.ProtoProperties,
+	flags javaBuilderFlags) javaBuilderFlags {
+
 	switch proptools.String(p.Proto.Type) {
 	case "micro":
-		flags.protoOutFlag = "--javamicro_out"
+		flags.protoOutTypeFlag = "--javamicro_out"
 	case "nano":
-		flags.protoOutFlag = "--javanano_out"
-	case "lite", "full", "":
-		flags.protoOutFlag = "--java_out"
+		flags.protoOutTypeFlag = "--javanano_out"
+	case "lite":
+		flags.protoOutTypeFlag = "--java_out"
+		flags.protoOutParams = "lite"
+	case "full", "":
+		flags.protoOutTypeFlag = "--java_out"
 	default:
 		ctx.PropertyErrorf("proto.type", "unknown proto type %q",
 			proptools.String(p.Proto.Type))
 	}
 
+	if len(j.Proto.Output_params) > 0 {
+		if flags.protoOutParams != "" {
+			flags.protoOutParams += ","
+		}
+		flags.protoOutParams += strings.Join(j.Proto.Output_params, ",")
+	}
+
 	flags.protoFlags = android.ProtoFlags(ctx, p)
 
 	return flags