Merge "Add last released API check to checkapi for public Android API"
diff --git a/Android.bp b/Android.bp
index 62e276a..3215fa2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -71,6 +71,7 @@
         "android/env.go",
     ],
     testSrcs: [
+        "android/arch_test.go",
         "android/config_test.go",
         "android/expand_test.go",
         "android/namespace_test.go",
diff --git a/android/arch.go b/android/arch.go
index de19dbe..6aeccb0 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -616,10 +616,10 @@
 	}
 }
 
-func filterArchStructFields(fields []reflect.StructField) []reflect.StructField {
-	var ret []reflect.StructField
+func filterArchStructFields(fields []reflect.StructField) (filteredFields []reflect.StructField, filtered bool) {
 	for _, field := range fields {
 		if !proptools.HasTag(field, "android", "arch_variant") {
+			filtered = true
 			continue
 		}
 
@@ -637,15 +637,17 @@
 		// Recurse into structs
 		switch field.Type.Kind() {
 		case reflect.Struct:
-			var ok bool
-			field.Type, ok = filterArchStruct(field.Type)
-			if !ok {
+			var subFiltered bool
+			field.Type, subFiltered = filterArchStruct(field.Type)
+			filtered = filtered || subFiltered
+			if field.Type == nil {
 				continue
 			}
 		case reflect.Ptr:
 			if field.Type.Elem().Kind() == reflect.Struct {
-				nestedType, ok := filterArchStruct(field.Type.Elem())
-				if !ok {
+				nestedType, subFiltered := filterArchStruct(field.Type.Elem())
+				filtered = filtered || subFiltered
+				if nestedType == nil {
 					continue
 				}
 				field.Type = reflect.PtrTo(nestedType)
@@ -654,13 +656,17 @@
 			panic("Interfaces are not supported in arch_variant properties")
 		}
 
-		ret = append(ret, field)
+		filteredFields = append(filteredFields, field)
 	}
 
-	return ret
+	return filteredFields, filtered
 }
 
-func filterArchStruct(prop reflect.Type) (reflect.Type, bool) {
+// filterArchStruct takes a reflect.Type that is either a sturct or a pointer to a struct, and returns a reflect.Type
+// that only contains the fields in the original type that have an `android:"arch_variant"` struct tag, and a bool
+// that is true if the new struct type has fewer fields than the original type.  If there are no fields in the
+// original type with the struct tag it returns nil and true.
+func filterArchStruct(prop reflect.Type) (filteredProp reflect.Type, filtered bool) {
 	var fields []reflect.StructField
 
 	ptr := prop.Kind() == reflect.Ptr
@@ -672,13 +678,20 @@
 		fields = append(fields, prop.Field(i))
 	}
 
-	fields = filterArchStructFields(fields)
+	filteredFields, filtered := filterArchStructFields(fields)
 
-	if len(fields) == 0 {
-		return nil, false
+	if len(filteredFields) == 0 {
+		return nil, true
 	}
 
-	ret := reflect.StructOf(fields)
+	if !filtered {
+		if ptr {
+			return reflect.PtrTo(prop), false
+		}
+		return prop, false
+	}
+
+	ret := reflect.StructOf(filteredFields)
 	if ptr {
 		ret = reflect.PtrTo(ret)
 	}
@@ -686,7 +699,13 @@
 	return ret, true
 }
 
-func filterArchStructSharded(prop reflect.Type) ([]reflect.Type, bool) {
+// filterArchStruct takes a reflect.Type that is either a sturct or a pointer to a struct, and returns a list of
+// reflect.Type that only contains the fields in the original type that have an `android:"arch_variant"` struct tag,
+// and a bool that is true if the new struct type has fewer fields than the original type.  If there are no fields in
+// the original type with the struct tag it returns nil and true.  Each returned struct type will have a maximum of
+// 10 top level fields in it to attempt to avoid hitting the reflect.StructOf name length limit, although the limit
+// can still be reached with a single struct field with many fields in it.
+func filterArchStructSharded(prop reflect.Type) (filteredProp []reflect.Type, filtered bool) {
 	var fields []reflect.StructField
 
 	ptr := prop.Kind() == reflect.Ptr
@@ -698,24 +717,29 @@
 		fields = append(fields, prop.Field(i))
 	}
 
-	fields = filterArchStructFields(fields)
+	fields, filtered = filterArchStructFields(fields)
+	if !filtered {
+		if ptr {
+			return []reflect.Type{reflect.PtrTo(prop)}, false
+		}
+		return []reflect.Type{prop}, false
+	}
 
 	if len(fields) == 0 {
-		return nil, false
+		return nil, true
 	}
 
 	shards := shardFields(fields, 10)
 
-	var ret []reflect.Type
 	for _, shard := range shards {
 		s := reflect.StructOf(shard)
 		if ptr {
 			s = reflect.PtrTo(s)
 		}
-		ret = append(ret, s)
+		filteredProp = append(filteredProp, s)
 	}
 
-	return ret, true
+	return filteredProp, true
 }
 
 func shardFields(fields []reflect.StructField, shardSize int) [][]reflect.StructField {
@@ -730,9 +754,12 @@
 	return ret
 }
 
+// createArchType takes a reflect.Type that is either a struct or a pointer to a struct, and returns a list of
+// reflect.Type that contains the arch-variant properties inside structs for each architecture, os, target, multilib,
+// etc.
 func createArchType(props reflect.Type) []reflect.Type {
-	propShards, ok := filterArchStructSharded(props)
-	if !ok {
+	propShards, _ := filterArchStructSharded(props)
+	if len(propShards) == 0 {
 		return nil
 	}
 
diff --git a/android/arch_test.go b/android/arch_test.go
new file mode 100644
index 0000000..0589e6c
--- /dev/null
+++ b/android/arch_test.go
@@ -0,0 +1,232 @@
+// Copyright 2019 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 android
+
+import (
+	"reflect"
+	"testing"
+)
+
+type Named struct {
+	A *string `android:"arch_variant"`
+	B *string
+}
+
+type NamedAllFiltered struct {
+	A *string
+}
+
+type NamedNoneFiltered struct {
+	A *string `android:"arch_variant"`
+}
+
+func TestFilterArchStruct(t *testing.T) {
+	tests := []struct {
+		name     string
+		in       interface{}
+		out      interface{}
+		filtered bool
+	}{
+		// Property tests
+		{
+			name: "basic",
+			in: &struct {
+				A *string `android:"arch_variant"`
+				B *string
+			}{},
+			out: &struct {
+				A *string
+			}{},
+			filtered: true,
+		},
+		{
+			name: "all filtered",
+			in: &struct {
+				A *string
+			}{},
+			out:      nil,
+			filtered: true,
+		},
+		{
+			name: "none filtered",
+			in: &struct {
+				A *string `android:"arch_variant"`
+			}{},
+			out: &struct {
+				A *string `android:"arch_variant"`
+			}{},
+			filtered: false,
+		},
+
+		// Sub-struct tests
+		{
+			name: "substruct",
+			in: &struct {
+				A struct {
+					A *string `android:"arch_variant"`
+					B *string
+				} `android:"arch_variant"`
+			}{},
+			out: &struct {
+				A struct {
+					A *string
+				}
+			}{},
+			filtered: true,
+		},
+		{
+			name: "substruct all filtered",
+			in: &struct {
+				A struct {
+					A *string
+				} `android:"arch_variant"`
+			}{},
+			out:      nil,
+			filtered: true,
+		},
+		{
+			name: "substruct none filtered",
+			in: &struct {
+				A struct {
+					A *string `android:"arch_variant"`
+				} `android:"arch_variant"`
+			}{},
+			out: &struct {
+				A struct {
+					A *string `android:"arch_variant"`
+				} `android:"arch_variant"`
+			}{},
+			filtered: false,
+		},
+
+		// Named sub-struct tests
+		{
+			name: "named substruct",
+			in: &struct {
+				A Named `android:"arch_variant"`
+			}{},
+			out: &struct {
+				A struct {
+					A *string
+				}
+			}{},
+			filtered: true,
+		},
+		{
+			name: "substruct all filtered",
+			in: &struct {
+				A NamedAllFiltered `android:"arch_variant"`
+			}{},
+			out:      nil,
+			filtered: true,
+		},
+		{
+			name: "substruct none filtered",
+			in: &struct {
+				A NamedNoneFiltered `android:"arch_variant"`
+			}{},
+			out: &struct {
+				A NamedNoneFiltered `android:"arch_variant"`
+			}{},
+			filtered: false,
+		},
+
+		// Pointer to sub-struct tests
+		{
+			name: "pointer substruct",
+			in: &struct {
+				A *struct {
+					A *string `android:"arch_variant"`
+					B *string
+				} `android:"arch_variant"`
+			}{},
+			out: &struct {
+				A *struct {
+					A *string
+				}
+			}{},
+			filtered: true,
+		},
+		{
+			name: "pointer substruct all filtered",
+			in: &struct {
+				A *struct {
+					A *string
+				} `android:"arch_variant"`
+			}{},
+			out:      nil,
+			filtered: true,
+		},
+		{
+			name: "pointer substruct none filtered",
+			in: &struct {
+				A *struct {
+					A *string `android:"arch_variant"`
+				} `android:"arch_variant"`
+			}{},
+			out: &struct {
+				A *struct {
+					A *string `android:"arch_variant"`
+				} `android:"arch_variant"`
+			}{},
+			filtered: false,
+		},
+
+		// Pointer to named sub-struct tests
+		{
+			name: "pointer named substruct",
+			in: &struct {
+				A *Named `android:"arch_variant"`
+			}{},
+			out: &struct {
+				A *struct {
+					A *string
+				}
+			}{},
+			filtered: true,
+		},
+		{
+			name: "pointer substruct all filtered",
+			in: &struct {
+				A *NamedAllFiltered `android:"arch_variant"`
+			}{},
+			out:      nil,
+			filtered: true,
+		},
+		{
+			name: "pointer substruct none filtered",
+			in: &struct {
+				A *NamedNoneFiltered `android:"arch_variant"`
+			}{},
+			out: &struct {
+				A *NamedNoneFiltered `android:"arch_variant"`
+			}{},
+			filtered: false,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			out, filtered := filterArchStruct(reflect.TypeOf(test.in))
+			if filtered != test.filtered {
+				t.Errorf("expected filtered %v, got %v", test.filtered, filtered)
+			}
+			expected := reflect.TypeOf(test.out)
+			if out != expected {
+				t.Errorf("expected type %v, got %v", expected, out)
+			}
+		})
+	}
+}
diff --git a/android/config.go b/android/config.go
index 6d81a38..122b99b 100644
--- a/android/config.go
+++ b/android/config.go
@@ -918,6 +918,17 @@
 		"invalid override rule %q in PRODUCT_CERTIFICATE_OVERRIDES should be <module_name>:<certificate_module_name>")
 }
 
+func (c *deviceConfig) OverridePackageNameFor(name string) string {
+	newName, overridden := findOverrideValue(
+		c.config.productVariables.PackageNameOverrides,
+		name,
+		"invalid override rule %q in PRODUCT_PACKAGE_NAME_OVERRIDES should be <module_name>:<package_name>")
+	if overridden {
+		return newName
+	}
+	return name
+}
+
 func findOverrideValue(overrides []string, name string, errorMsg string) (newValue string, overridden bool) {
 	if overrides == nil || len(overrides) == 0 {
 		return "", false
diff --git a/android/testing.go b/android/testing.go
index d318839..b7a043e 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -190,14 +190,14 @@
 	return BuildParams{}, searchedOutputs
 }
 
-// MaybeOutput finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputspath whose String() or Rel()
+// MaybeOutput finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
 // value matches the provided string.  Returns an empty BuildParams if no rule is found.
 func (m TestingModule) MaybeOutput(file string) BuildParams {
 	p, _ := m.maybeOutput(file)
 	return p
 }
 
-// Output finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputspath whose String() or Rel()
+// Output finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
 // value matches the provided string.  Panics if no rule is found.
 func (m TestingModule) Output(file string) BuildParams {
 	p, searchedOutputs := m.maybeOutput(file)
@@ -208,6 +208,19 @@
 	return p
 }
 
+// AllOutputs returns all 'BuildParams.Output's and 'BuildParams.Outputs's in their full path string forms.
+func (m TestingModule) AllOutputs() []string {
+	var outputFullPaths []string
+	for _, p := range m.module.BuildParamsForTests() {
+		outputs := append(WritablePaths(nil), p.Outputs...)
+		if p.Output != nil {
+			outputs = append(outputs, p.Output)
+		}
+		outputFullPaths = append(outputFullPaths, outputs.Strings()...)
+	}
+	return outputFullPaths
+}
+
 func FailIfErrored(t *testing.T, errs []error) {
 	t.Helper()
 	if len(errs) > 0 {
diff --git a/android/variable.go b/android/variable.go
index 67e876a..2cccd50 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -271,6 +271,7 @@
 
 	ManifestPackageNameOverrides []string `json:",omitempty"`
 	CertificateOverrides         []string `json:",omitempty"`
+	PackageNameOverrides         []string `json:",omitempty"`
 
 	EnforceSystemCertificate          *bool    `json:",omitempty"`
 	EnforceSystemCertificateWhitelist []string `json:",omitempty"`
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index e7f2531..aef8944 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -56,6 +56,7 @@
 	"LOCAL_CFLAGS":                cflags,
 	"LOCAL_UNINSTALLABLE_MODULE":  invert("installable"),
 	"LOCAL_PROGUARD_ENABLED":      proguardEnabled,
+	"LOCAL_MODULE_PATH":           prebuiltModulePath,
 
 	// composite functions
 	"LOCAL_MODULE_TAGS": includeVariableIf(bpVariable{"tags", bpparser.ListType}, not(valueDumpEquals("optional"))),
@@ -519,6 +520,55 @@
 	return nil
 }
 
+func makeBlueprintStringAssignment(file *bpFile, prefix string, suffix string, value string) error {
+	val, err := makeVariableToBlueprint(file, mkparser.SimpleMakeString(value, mkparser.NoPos), bpparser.StringType)
+	if err == nil {
+		err = setVariable(file, false, prefix, suffix, val, true)
+	}
+	return err
+}
+
+// If variable is a literal variable name, return the name, otherwise return ""
+func varLiteralName(variable mkparser.Variable) string {
+	if len(variable.Name.Variables) == 0 {
+		return variable.Name.Strings[0]
+	}
+	return ""
+}
+
+func prebuiltModulePath(ctx variableAssignmentContext) error {
+	// Cannot handle appending
+	if ctx.append {
+		return fmt.Errorf("Cannot handle appending to LOCAL_MODULE_PATH")
+	}
+	// Analyze value in order to set the correct values for the 'device_specific',
+	// 'product_specific', 'product_services_specific' 'vendor'/'soc_specific',
+	// 'product_services_specific' attribute. Two cases are allowed:
+	//   $(VAR)/<literal-value>
+	//   $(PRODUCT_OUT)/$(TARGET_COPY_OUT_VENDOR)/<literal-value>
+	// The last case is equivalent to $(TARGET_OUT_VENDOR)/<literal-value>
+	// Map the variable name if present to `local_module_path_var`
+	// Map literal-path to local_module_path_fixed
+	varname := ""
+	fixed := ""
+	val := ctx.mkvalue
+	if len(val.Variables) == 1 && varLiteralName(val.Variables[0]) != "" && len(val.Strings) == 2 && val.Strings[0] == "" {
+		fixed = val.Strings[1]
+		varname = val.Variables[0].Name.Strings[0]
+	} else if len(val.Variables) == 2 && varLiteralName(val.Variables[0]) == "PRODUCT_OUT" && varLiteralName(val.Variables[1]) == "TARGET_COPY_OUT_VENDOR" &&
+		len(val.Strings) == 3 && val.Strings[0] == "" && val.Strings[1] == "/" {
+		fixed = val.Strings[2]
+		varname = "TARGET_OUT_VENDOR"
+	} else {
+		return fmt.Errorf("LOCAL_MODULE_PATH value should start with $(<some-varaible>)/ or $(PRODUCT_OUT)/$(TARGET_COPY_VENDOR)/")
+	}
+	err := makeBlueprintStringAssignment(ctx.file, "local_module_path", "var", varname)
+	if err == nil && fixed != "" {
+		err = makeBlueprintStringAssignment(ctx.file, "local_module_path", "fixed", fixed)
+	}
+	return err
+}
+
 func ldflags(ctx variableAssignmentContext) error {
 	val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType)
 	if err != nil {
@@ -816,6 +866,7 @@
 	"STATIC_LIBRARIES": "cc_prebuilt_library_static",
 	"EXECUTABLES":      "cc_prebuilt_binary",
 	"JAVA_LIBRARIES":   "java_import",
+	"ETC":              "prebuilt_etc",
 }
 
 var soongModuleTypes = map[string]bool{}
@@ -834,7 +885,6 @@
 	globalScope.SetFunc("first-makefiles-under", includeIgnored)
 	globalScope.SetFunc("all-named-subdir-makefiles", includeIgnored)
 	globalScope.SetFunc("all-subdir-makefiles", includeIgnored)
-
 	for k, v := range moduleTypes {
 		globalScope.Set(k, v)
 		soongModuleTypes[v] = true
diff --git a/androidmk/cmd/androidmk/androidmk_test.go b/androidmk/cmd/androidmk/androidmk_test.go
index 5fbe62a0..52b8476 100644
--- a/androidmk/cmd/androidmk/androidmk_test.go
+++ b/androidmk/cmd/androidmk/androidmk_test.go
@@ -824,6 +824,210 @@
 }
 `,
 	},
+	{
+		desc: "prebuilt_etc_TARGET_OUT_ETC",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := etc.test1
+LOCAL_SRC_FILES := mymod
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/foo/bar
+include $(BUILD_PREBUILT)
+`,
+		expected: `
+prebuilt_etc {
+	name: "etc.test1",
+	src: "mymod",
+	sub_dir: "foo/bar",
+
+}
+`,
+	},
+
+	{
+		desc: "prebuilt_etc_PRODUCT_OUT/system/etc",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := etc.test1
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/etc/foo/bar
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
+`,
+		expected: `
+prebuilt_etc {
+	name: "etc.test1",
+
+	src: "etc.test1",
+	sub_dir: "foo/bar",
+
+}
+`,
+	},
+	{
+		desc: "prebuilt_etc_TARGET_OUT_ODM/etc",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := etc.test1
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_ODM)/etc/foo/bar
+include $(BUILD_PREBUILT)
+`,
+		expected: `
+prebuilt_etc {
+	name: "etc.test1",
+	sub_dir: "foo/bar",
+    device_specific: true,
+
+}
+`,
+	},
+	{
+		desc: "prebuilt_etc_TARGET_OUT_PRODUCT/etc",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := etc.test1
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT)/etc/foo/bar
+include $(BUILD_PREBUILT)
+`,
+		expected: `
+prebuilt_etc {
+	name: "etc.test1",
+	sub_dir: "foo/bar",
+	product_specific: true,
+
+
+}
+`,
+	},
+	{
+		desc: "prebuilt_etc_TARGET_OUT_PRODUCT_ETC",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := etc.test1
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)/foo/bar
+include $(BUILD_PREBUILT)
+`,
+		expected: `
+prebuilt_etc {
+	name: "etc.test1",
+	sub_dir: "foo/bar",
+	product_specific: true,
+
+}
+`,
+	},
+	{
+		desc: "prebuilt_etc_TARGET_OUT_PRODUCT_SERVICES/etc",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := etc.test1
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_SERVICES)/etc/foo/bar
+include $(BUILD_PREBUILT)
+`,
+		expected: `
+prebuilt_etc {
+	name: "etc.test1",
+	sub_dir: "foo/bar",
+	product_services_specific: true,
+
+}
+`,
+	},
+	{
+		desc: "prebuilt_etc_TARGET_OUT_PRODUCT_SERVICES_ETC",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := etc.test1
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_SERVICES_ETC)/foo/bar
+include $(BUILD_PREBUILT)
+`,
+		expected: `
+prebuilt_etc {
+	name: "etc.test1",
+	sub_dir: "foo/bar",
+	product_services_specific: true,
+
+
+}
+`,
+	},
+	{
+		desc: "prebuilt_etc_TARGET_OUT_VENDOR/etc",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := etc.test1
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/foo/bar
+include $(BUILD_PREBUILT)
+`,
+		expected: `
+prebuilt_etc {
+	name: "etc.test1",
+	sub_dir: "foo/bar",
+	proprietary: true,
+
+}
+`,
+	},
+	{
+		desc: "prebuilt_etc_PRODUCT_OUT/TARGET_COPY_OUT_VENDOR/etc",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := etc.test1
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_VENDOR)/etc/foo/bar
+include $(BUILD_PREBUILT)
+`,
+		expected: `
+prebuilt_etc {
+	name: "etc.test1",
+	sub_dir: "foo/bar",
+	proprietary: true,
+
+}
+`,
+	},
+	{
+		desc: "prebuilt_etc_TARGET_OUT_VENDOR_ETC",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := etc.test1
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/foo/bar
+include $(BUILD_PREBUILT)
+`,
+		expected: `
+prebuilt_etc {
+	name: "etc.test1",
+	sub_dir: "foo/bar",
+	proprietary: true,
+
+}
+`,
+	},
+	{
+		desc: "prebuilt_etc_TARGET_RECOVERY_ROOT_OUT/system/etc",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := etc.test1
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/system/etc/foo/bar
+include $(BUILD_PREBUILT)
+`,
+		expected: `
+prebuilt_etc {
+	name: "etc.test1",
+	sub_dir: "foo/bar",
+	recovery: true,
+
+}
+`,
+	},
 }
 
 func TestEndToEnd(t *testing.T) {
diff --git a/apex/apex.go b/apex/apex.go
index 0aedb1a..96a4bd5 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -333,6 +333,7 @@
 	installDir string
 	class      apexFileClass
 	module     android.Module
+	symlinks   []string
 }
 
 type apexBundle struct {
@@ -396,7 +397,8 @@
 			a.properties.Multilib.Both.Binaries, target.String(),
 			a.getImageVariation(config))
 
-		if i == 0 {
+		isPrimaryAbi := i == 0
+		if isPrimaryAbi {
 			// When multilib.* is omitted for binaries, it implies
 			// multilib.first.
 			ctx.AddFarVariationDependencies([]blueprint.Variation{
@@ -483,9 +485,17 @@
 	}
 }
 
-func (a *apexBundle) IsSanitizerEnabled() bool {
-	// APEX can be mutated for sanitizers
-	return true
+func (a *apexBundle) IsSanitizerEnabled(ctx android.BaseModuleContext, sanitizerName string) bool {
+	globalSanitizerNames := []string{}
+	if a.Host() {
+		globalSanitizerNames = ctx.Config().SanitizeHost()
+	} else {
+		arches := ctx.Config().SanitizeDeviceArch()
+		if len(arches) == 0 || android.InList(a.Arch().ArchType.Name, arches) {
+			globalSanitizerNames = ctx.Config().SanitizeDevice()
+		}
+	}
+	return android.InList(sanitizerName, globalSanitizerNames)
 }
 
 func getCopyManifestForNativeLibrary(cc *cc.Module) (fileToCopy android.Path, dirInApex string) {
@@ -563,15 +573,20 @@
 			case sharedLibTag:
 				if cc, ok := child.(*cc.Module); ok {
 					fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc)
-					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, cc.Arch().ArchType, dirInApex, nativeSharedLib, cc})
+					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, cc.Arch().ArchType, dirInApex, nativeSharedLib, cc, nil})
 					return true
 				} else {
 					ctx.PropertyErrorf("native_shared_libs", "%q is not a cc_library or cc_library_shared module", depName)
 				}
 			case executableTag:
 				if cc, ok := child.(*cc.Module); ok {
+					if !cc.Arch().Native {
+						// There is only one 'bin' directory so we shouldn't bother copying in
+						// native-bridge'd binaries and only use main ones.
+						return true
+					}
 					fileToCopy, dirInApex := getCopyManifestForExecutable(cc)
-					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, cc.Arch().ArchType, dirInApex, nativeExecutable, cc})
+					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, cc.Arch().ArchType, dirInApex, nativeExecutable, cc, cc.Symlinks()})
 					return true
 				} else {
 					ctx.PropertyErrorf("binaries", "%q is not a cc_binary module", depName)
@@ -582,7 +597,7 @@
 					if fileToCopy == nil {
 						ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName)
 					} else {
-						filesInfo = append(filesInfo, apexFile{fileToCopy, depName, java.Arch().ArchType, dirInApex, javaSharedLib, java})
+						filesInfo = append(filesInfo, apexFile{fileToCopy, depName, java.Arch().ArchType, dirInApex, javaSharedLib, java, nil})
 					}
 					return true
 				} else {
@@ -591,7 +606,7 @@
 			case prebuiltTag:
 				if prebuilt, ok := child.(*android.PrebuiltEtc); ok {
 					fileToCopy, dirInApex := getCopyManifestForPrebuiltEtc(prebuilt)
-					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, prebuilt.Arch().ArchType, dirInApex, etc, prebuilt})
+					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, prebuilt.Arch().ArchType, dirInApex, etc, prebuilt, nil})
 					return true
 				} else {
 					ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
@@ -626,7 +641,7 @@
 					}
 					depName := ctx.OtherModuleName(child)
 					fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc)
-					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, cc.Arch().ArchType, dirInApex, nativeSharedLib, cc})
+					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, cc.Arch().ArchType, dirInApex, nativeSharedLib, cc, nil})
 					return true
 				}
 			}
@@ -719,6 +734,10 @@
 		dest_path := filepath.Join(android.PathForModuleOut(ctx, "image"+suffix).String(), dest)
 		copyCommands = append(copyCommands, "mkdir -p "+filepath.Dir(dest_path))
 		copyCommands = append(copyCommands, "cp "+src.String()+" "+dest_path)
+		for _, sym := range a.filesInfo[i].symlinks {
+			symlinkDest := filepath.Join(filepath.Dir(dest_path), sym)
+			copyCommands = append(copyCommands, "ln -s "+filepath.Base(dest)+" "+symlinkDest)
+		}
 	}
 	implicitInputs := append(android.Paths(nil), filesToCopy...)
 	implicitInputs = append(implicitInputs, manifest)
@@ -734,6 +753,9 @@
 			pathInApex := filepath.Join(f.installDir, f.builtFile.Base())
 			if f.installDir == "bin" {
 				executablePaths = append(executablePaths, pathInApex)
+				for _, s := range f.symlinks {
+					executablePaths = append(executablePaths, filepath.Join("bin", s))
+				}
 			} else {
 				readOnlyPaths = append(readOnlyPaths, pathInApex)
 			}
@@ -866,7 +888,7 @@
 			Input:  manifest,
 			Output: copiedManifest,
 		})
-		a.filesInfo = append(a.filesInfo, apexFile{copiedManifest, ctx.ModuleName() + ".apex_manifest.json", android.Common, ".", etc, nil})
+		a.filesInfo = append(a.filesInfo, apexFile{copiedManifest, ctx.ModuleName() + ".apex_manifest.json", android.Common, ".", etc, nil, nil})
 
 		for _, fi := range a.filesInfo {
 			dir := filepath.Join("apex", ctx.ModuleName(), fi.installDir)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index dbc85d9..7ae49f6 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -41,6 +41,7 @@
 
 	ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
 	ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(cc.LibrarySharedFactory))
+	ctx.RegisterModuleType("cc_library_headers", android.ModuleFactoryAdaptor(cc.LibraryHeaderFactory))
 	ctx.RegisterModuleType("cc_binary", android.ModuleFactoryAdaptor(cc.BinaryFactory))
 	ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory))
 	ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(cc.LlndkLibraryFactory))
@@ -106,6 +107,16 @@
 			recovery_available: true,
 		}
 
+		cc_object {
+			name: "crtbegin_static",
+			stl: "none",
+		}
+
+		cc_object {
+			name: "crtend_android",
+			stl: "none",
+		}
+
 		llndk_library {
 			name: "libc",
 			symbol_file: "",
@@ -123,16 +134,18 @@
 	`
 
 	ctx.MockFileSystem(map[string][]byte{
-		"Android.bp":                                []byte(bp),
-		"build/target/product/security":             nil,
-		"apex_manifest.json":                        nil,
-		"system/sepolicy/apex/myapex-file_contexts": nil,
-		"mylib.cpp":                                 nil,
-		"myprebuilt":                                nil,
-		"vendor/foo/devkeys/test.x509.pem":          nil,
-		"vendor/foo/devkeys/test.pk8":               nil,
-		"vendor/foo/devkeys/testkey.avbpubkey":      nil,
-		"vendor/foo/devkeys/testkey.pem":            nil,
+		"Android.bp":                                   []byte(bp),
+		"build/target/product/security":                nil,
+		"apex_manifest.json":                           nil,
+		"system/sepolicy/apex/myapex-file_contexts":    nil,
+		"system/sepolicy/apex/otherapex-file_contexts": nil,
+		"mylib.cpp":                                    nil,
+		"myprebuilt":                                   nil,
+		"my_include":                                   nil,
+		"vendor/foo/devkeys/test.x509.pem":             nil,
+		"vendor/foo/devkeys/test.pk8":                  nil,
+		"vendor/foo/devkeys/testkey.avbpubkey":         nil,
+		"vendor/foo/devkeys/testkey.pem":               nil,
 	})
 	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
 	android.FailIfErrored(t, errs)
@@ -191,6 +204,11 @@
 			name: "myapex",
 			key: "myapex.key",
 			native_shared_libs: ["mylib"],
+			multilib: {
+				both: {
+					binaries: ["foo",],
+				}
+			}
 		}
 
 		apex_key {
@@ -207,6 +225,25 @@
 			stl: "none",
 		}
 
+		cc_binary {
+			name: "foo",
+			srcs: ["mylib.cpp"],
+			compile_multilib: "both",
+			multilib: {
+					lib32: {
+							suffix: "32",
+					},
+					lib64: {
+							suffix: "64",
+					},
+			},
+			symlinks: ["foo_link_"],
+			symlink_preferred_arch: true,
+			system_shared_libs: [],
+			static_executable: true,
+			stl: "none",
+		}
+
 		cc_library {
 			name: "mylib2",
 			srcs: ["mylib.cpp"],
@@ -234,6 +271,23 @@
 	// Ensure that the platform variant ends with _core_shared
 	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_core_shared")
 	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_core_shared")
+
+	// Ensure that all symlinks are present.
+	found_foo_link_64 := false
+	found_foo := false
+	for _, cmd := range strings.Split(copyCmds, " && ") {
+		if strings.HasPrefix(cmd, "ln -s foo64") {
+			if strings.HasSuffix(cmd, "bin/foo") {
+				found_foo = true
+			} else if strings.HasSuffix(cmd, "bin/foo_link_64") {
+				found_foo_link_64 = true
+			}
+		}
+	}
+	good := found_foo && found_foo_link_64
+	if !good {
+		t.Errorf("Could not find all expected symlinks! foo: %t, foo_link_64: %t. Command was %s", found_foo, found_foo_link_64, copyCmds)
+	}
 }
 
 func TestBasicZipApex(t *testing.T) {
@@ -668,17 +722,6 @@
 			system_shared_libs: [],
 			stl: "none",
 		}
-
-		cc_object {
-			name: "crtbegin_static",
-			stl: "none",
-		}
-
-		cc_object {
-			name: "crtend_android",
-			stl: "none",
-		}
-
 	`)
 
 	ldFlags := ctx.ModuleForTests("not_in_apex", "android_arm64_armv8-a_core").Rule("ld").Args["libFlags"]
@@ -729,3 +772,95 @@
 			"vendor/foo/devkeys/test.x509.pem vendor/foo/devkeys/test.pk8")
 	}
 }
+
+func TestMacro(t *testing.T) {
+	ctx := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			native_shared_libs: ["mylib"],
+		}
+
+		apex {
+			name: "otherapex",
+			key: "myapex.key",
+			native_shared_libs: ["mylib"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_library {
+			name: "mylib",
+			srcs: ["mylib.cpp"],
+			system_shared_libs: [],
+			stl: "none",
+		}
+	`)
+
+	// non-APEX variant does not have __ANDROID__APEX__ defined
+	mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static").Rule("cc").Args["cFlags"]
+	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=myapex")
+	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=otherapex")
+
+	// APEX variant has __ANDROID_APEX__=<apexname> defined
+	mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static_myapex").Rule("cc").Args["cFlags"]
+	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__=myapex")
+	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=otherapex")
+
+	// APEX variant has __ANDROID_APEX__=<apexname> defined
+	mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static_otherapex").Rule("cc").Args["cFlags"]
+	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=myapex")
+	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__=otherapex")
+}
+
+func TestHeaderLibsDependency(t *testing.T) {
+	ctx := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			native_shared_libs: ["mylib"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_library_headers {
+			name: "mylib_headers",
+			export_include_dirs: ["my_include"],
+			system_shared_libs: [],
+			stl: "none",
+		}
+
+		cc_library {
+			name: "mylib",
+			srcs: ["mylib.cpp"],
+			system_shared_libs: [],
+			stl: "none",
+			header_libs: ["mylib_headers"],
+			export_header_lib_headers: ["mylib_headers"],
+			stubs: {
+				versions: ["1", "2", "3"],
+			},
+		}
+
+		cc_library {
+			name: "otherlib",
+			srcs: ["mylib.cpp"],
+			system_shared_libs: [],
+			stl: "none",
+			shared_libs: ["mylib"],
+		}
+	`)
+
+	cFlags := ctx.ModuleForTests("otherlib", "android_arm64_armv8-a_core_static").Rule("cc").Args["cFlags"]
+
+	// Ensure that the include path of the header lib is exported to 'otherlib'
+	ensureContains(t, cFlags, "-Imy_include")
+}
diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go
index 6a75517..11f1877 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -83,6 +83,10 @@
 		fix:  rewriteJavaStaticLibs,
 	},
 	{
+		name: "rewritePrebuiltEtc",
+		fix:  rewriteAndroidmkPrebuiltEtc,
+	},
+	{
 		name: "mergeMatchingModuleProperties",
 		fix:  runPatchListMod(mergeMatchingModuleProperties),
 	},
@@ -407,6 +411,156 @@
 	return nil
 }
 
+// Helper function to get the value of a string-valued property in a given compound property.
+func getStringProperty(prop *parser.Property, fieldName string) string {
+	if propsAsMap, ok := prop.Value.(*parser.Map); ok {
+		for _, propField := range propsAsMap.Properties {
+			if fieldName == propField.Name {
+				if propFieldAsString, ok := propField.Value.(*parser.String); ok {
+					return propFieldAsString.Value
+				} else {
+					return ""
+				}
+			}
+		}
+	}
+	return ""
+}
+
+// Create sub_dir: attribute for the given path
+func makePrebuiltEtcDestination(mod *parser.Module, path string) {
+	mod.Properties = append(mod.Properties, &parser.Property{
+		Name:  "sub_dir",
+		Value: &parser.String{Value: path},
+	})
+}
+
+// Set the value of the given attribute to the error message
+func indicateAttributeError(mod *parser.Module, attributeName string, format string, a ...interface{}) error {
+	msg := fmt.Sprintf(format, a...)
+	mod.Properties = append(mod.Properties, &parser.Property{
+		Name:  attributeName,
+		Value: &parser.String{Value: "ERROR: " + msg},
+	})
+	return errors.New(msg)
+}
+
+// If a variable is LOCAL_MODULE, get its value from the 'name' attribute.
+// This handles the statement
+//    LOCAL_SRC_FILES := $(LOCAL_MODULE)
+// which occurs often.
+func resolveLocalModule(mod *parser.Module, val parser.Expression) parser.Expression {
+	if varLocalName, ok := val.(*parser.Variable); ok {
+		if varLocalName.Name == "LOCAL_MODULE" {
+			if v, ok := getLiteralStringProperty(mod, "name"); ok {
+				return v
+			}
+		}
+	}
+	return val
+}
+
+// A prefix to strip before setting 'filename' attribute and an array of boolean attributes to set.
+type filenamePrefixToFlags struct {
+	prefix string
+	flags  []string
+}
+
+var localModulePathRewrite = map[string][]filenamePrefixToFlags{
+	"HOST_OUT":                        {{prefix: "/etc"}},
+	"PRODUCT_OUT":                     {{prefix: "/system/etc"}, {prefix: "/vendor/etc", flags: []string{"proprietary"}}},
+	"TARGET_OUT":                      {{prefix: "/etc"}},
+	"TARGET_OUT_ETC":                  {{prefix: ""}},
+	"TARGET_OUT_PRODUCT":              {{prefix: "/etc", flags: []string{"product_specific"}}},
+	"TARGET_OUT_PRODUCT_ETC":          {{prefix: "", flags: []string{"product_specific"}}},
+	"TARGET_OUT_ODM":                  {{prefix: "/etc", flags: []string{"device_specific"}}},
+	"TARGET_OUT_PRODUCT_SERVICES":     {{prefix: "/etc", flags: []string{"product_services_specific"}}},
+	"TARGET_OUT_PRODUCT_SERVICES_ETC": {{prefix: "", flags: []string{"product_services_specific"}}},
+	"TARGET_OUT_VENDOR":               {{prefix: "/etc", flags: []string{"proprietary"}}},
+	"TARGET_OUT_VENDOR_ETC":           {{prefix: "", flags: []string{"proprietary"}}},
+	"TARGET_RECOVERY_ROOT_OUT":        {{prefix: "/system/etc", flags: []string{"recovery"}}},
+}
+
+// rewriteAndroidPrebuiltEtc fixes prebuilt_etc rule
+func rewriteAndroidmkPrebuiltEtc(f *Fixer) error {
+	for _, def := range f.tree.Defs {
+		mod, ok := def.(*parser.Module)
+		if !ok {
+			continue
+		}
+
+		if mod.Type != "prebuilt_etc" && mod.Type != "prebuilt_etc_host" {
+			continue
+		}
+
+		// The rewriter converts LOCAL_SRC_FILES to `srcs` attribute. Convert
+		// it to 'src' attribute (which is where the file is installed). If the
+		// value 'srcs' is a list, we can convert it only if it contains a single
+		// element.
+		if srcs, ok := mod.GetProperty("srcs"); ok {
+			if srcList, ok := srcs.Value.(*parser.List); ok {
+				removeProperty(mod, "srcs")
+				if len(srcList.Values) == 1 {
+					mod.Properties = append(mod.Properties,
+						&parser.Property{Name: "src", NamePos: srcs.NamePos, ColonPos: srcs.ColonPos, Value: resolveLocalModule(mod, srcList.Values[0])})
+				} else if len(srcList.Values) > 1 {
+					indicateAttributeError(mod, "src", "LOCAL_SRC_FILES should contain at most one item")
+				}
+			} else if _, ok = srcs.Value.(*parser.Variable); ok {
+				removeProperty(mod, "srcs")
+				mod.Properties = append(mod.Properties,
+					&parser.Property{Name: "src", NamePos: srcs.NamePos, ColonPos: srcs.ColonPos, Value: resolveLocalModule(mod, srcs.Value)})
+			} else {
+				renameProperty(mod, "srcs", "src")
+			}
+		}
+
+		// The rewriter converts LOCAL_MODULE_PATH attribute into a struct attribute
+		// 'local_module_path'. Analyze its contents and create the correct sub_dir:,
+		// filename: and boolean attributes combination
+		const local_module_path = "local_module_path"
+		if prop_local_module_path, ok := mod.GetProperty(local_module_path); ok {
+			removeProperty(mod, local_module_path)
+			prefixVariableName := getStringProperty(prop_local_module_path, "var")
+			path := getStringProperty(prop_local_module_path, "fixed")
+			if prefixRewrites, ok := localModulePathRewrite[prefixVariableName]; ok {
+				rewritten := false
+				for _, prefixRewrite := range prefixRewrites {
+					if path == prefixRewrite.prefix {
+						rewritten = true
+					} else if trimmedPath := strings.TrimPrefix(path, prefixRewrite.prefix+"/"); trimmedPath != path {
+						makePrebuiltEtcDestination(mod, trimmedPath)
+						rewritten = true
+					}
+					if rewritten {
+						for _, flag := range prefixRewrite.flags {
+							mod.Properties = append(mod.Properties, &parser.Property{Name: flag, Value: &parser.Bool{Value: true, Token: "true"}})
+						}
+						break
+					}
+				}
+				if !rewritten {
+					expectedPrefices := ""
+					sep := ""
+					for _, prefixRewrite := range prefixRewrites {
+						expectedPrefices += sep
+						sep = ", "
+						expectedPrefices += prefixRewrite.prefix
+					}
+					return indicateAttributeError(mod, "filename",
+						"LOCAL_MODULE_PATH value under $(%s) should start with %s", prefixVariableName, expectedPrefices)
+				}
+				if prefixVariableName == "HOST_OUT" {
+					mod.Type = "prebuilt_etc_host"
+				}
+			} else {
+				return indicateAttributeError(mod, "filename", "Cannot handle $(%s) for the prebuilt_etc", prefixVariableName)
+			}
+		}
+	}
+	return nil
+}
+
 func runPatchListMod(modFunc func(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error) func(*Fixer) error {
 	return func(f *Fixer) error {
 		// Make sure all the offsets are accurate
diff --git a/bpfix/bpfix/bpfix_test.go b/bpfix/bpfix/bpfix_test.go
index 5224ee3..1394223 100644
--- a/bpfix/bpfix/bpfix_test.go
+++ b/bpfix/bpfix/bpfix_test.go
@@ -692,3 +692,62 @@
 		})
 	}
 }
+
+func TestRewritePrebuiltEtc(t *testing.T) {
+	tests := []struct {
+		name string
+		in   string
+		out  string
+	}{
+		{
+			name: "prebuilt_etc src",
+			in: `
+			prebuilt_etc {
+			name: "foo",
+			srcs: ["bar"],
+		}
+		`,
+			out: `prebuilt_etc {
+			name: "foo",
+			src: "bar",
+		}
+		`,
+		},
+		{
+			name: "prebuilt_etc src",
+			in: `
+			prebuilt_etc {
+			name: "foo",
+			srcs: FOO,
+		}
+		`,
+			out: `prebuilt_etc {
+			name: "foo",
+			src: FOO,
+		}
+		`,
+		},
+		{
+			name: "prebuilt_etc src",
+			in: `
+			prebuilt_etc {
+			name: "foo",
+			srcs: ["bar", "baz"],
+		}
+		`,
+			out: `prebuilt_etc {
+			name: "foo",
+			src: "ERROR: LOCAL_SRC_FILES should contain at most one item",
+
+		}
+		`,
+		},
+	}
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			runPass(t, test.in, test.out, func(fixer *Fixer) error {
+				return rewriteAndroidmkPrebuiltEtc(fixer)
+			})
+		})
+	}
+}
diff --git a/cc/binary.go b/cc/binary.go
index 65e8eb5..4c86371 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -382,11 +382,8 @@
 	objs.coverageFiles = append(objs.coverageFiles, deps.WholeStaticLibObjs.coverageFiles...)
 	binary.coverageOutputFile = TransformCoverageFilesToLib(ctx, objs, builderFlags, binary.getStem(ctx))
 
-	return ret
-}
-
-func (binary *binaryDecorator) install(ctx ModuleContext, file android.Path) {
-	binary.baseInstaller.install(ctx, file)
+	// Need to determine symlinks early since some targets (ie APEX) need this
+	// information but will not call 'install'
 	for _, symlink := range binary.Properties.Symlinks {
 		binary.symlinks = append(binary.symlinks,
 			symlink+String(binary.Properties.Suffix)+ctx.toolchain().ExecutableSuffix())
@@ -401,6 +398,15 @@
 		}
 	}
 
+	return ret
+}
+
+func (binary *binaryDecorator) symlinkList() []string {
+	return binary.symlinks
+}
+
+func (binary *binaryDecorator) install(ctx ModuleContext, file android.Path) {
+	binary.baseInstaller.install(ctx, file)
 	for _, symlink := range binary.symlinks {
 		ctx.InstallSymlink(binary.baseInstaller.installDir(ctx), symlink, binary.baseInstaller.path)
 	}
diff --git a/cc/builder.go b/cc/builder.go
index 5dbd23e..b012d6f 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -199,7 +199,7 @@
 			// TODO(b/78139997): Add -check-all-apis back
 			commandStr := "($sAbiDiffer $allowFlags -lib $libName -arch $arch -o ${out} -new $in -old $referenceDump)"
 			commandStr += "|| (echo ' ---- Please update abi references by running $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l ${libName} ----'"
-			commandStr += " && (mkdir -p $$DIST_DIR/abidiffs && cp ${out} $$DIST_DIR/abidiff/)"
+			commandStr += " && (mkdir -p $$DIST_DIR/abidiffs && cp ${out} $$DIST_DIR/abidiffs/)"
 			commandStr += " && exit 1)"
 			return blueprint.RuleParams{
 				Command:     commandStr,
diff --git a/cc/cc.go b/cc/cc.go
index baee70a..a30708a 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -258,7 +258,7 @@
 	getVndkExtendsModuleName() string
 	isPgoCompile() bool
 	useClangLld(actx ModuleContext) bool
-	isApex() bool
+	apexName() string
 	hasStubsVariants() bool
 	isStubs() bool
 }
@@ -720,9 +720,8 @@
 	return ctx.mod.getVndkExtendsModuleName()
 }
 
-// Tests if this module is built for APEX
-func (ctx *moduleContextImpl) isApex() bool {
-	return ctx.mod.ApexName() != ""
+func (ctx *moduleContextImpl) apexName() string {
+	return ctx.mod.ApexName()
 }
 
 func (ctx *moduleContextImpl) hasStubsVariants() bool {
@@ -773,6 +772,15 @@
 	return name
 }
 
+func (c *Module) Symlinks() []string {
+	if p, ok := c.installer.(interface {
+		symlinkList() []string
+	}); ok {
+		return p.symlinkList()
+	}
+	return nil
+}
+
 // orderDeps reorders dependencies into a list such that if module A depends on B, then
 // A will precede B in the resultant list.
 // This is convenient for passing into a linker.
@@ -1143,11 +1151,11 @@
 		deps.ReexportSharedLibHeaders, _ = rewriteNdkLibs(deps.ReexportSharedLibHeaders)
 	}
 
+	buildStubs := false
 	if c.linker != nil {
 		if library, ok := c.linker.(*libraryDecorator); ok {
 			if library.buildStubs() {
-				// Stubs lib does not have dependency to other libraries. Don't proceed.
-				return
+				buildStubs = true
 			}
 		}
 	}
@@ -1157,7 +1165,26 @@
 		if inList(lib, deps.ReexportHeaderLibHeaders) {
 			depTag = headerExportDepTag
 		}
-		actx.AddVariationDependencies(nil, depTag, lib)
+		if buildStubs {
+			imageVariation := "core"
+			if c.useVndk() {
+				imageVariation = "vendor"
+			} else if c.inRecovery() {
+				imageVariation = "recovery"
+			}
+			actx.AddFarVariationDependencies([]blueprint.Variation{
+				{Mutator: "arch", Variation: ctx.Target().String()},
+				{Mutator: "image", Variation: imageVariation},
+			}, depTag, lib)
+		} else {
+			actx.AddVariationDependencies(nil, depTag, lib)
+		}
+	}
+
+	if buildStubs {
+		// Stubs lib does not have dependency to other static/shared libraries.
+		// Don't proceed.
+		return
 	}
 
 	actx.AddVariationDependencies([]blueprint.Variation{
diff --git a/cc/compdb.go b/cc/compdb.go
index 4dfc55b..1102651 100644
--- a/cc/compdb.go
+++ b/cc/compdb.go
@@ -170,14 +170,14 @@
 		return
 	}
 
-	pathToCC, err := ctx.Eval(pctx, "${config.ClangBin}/")
+	rootDir := getCompdbAndroidSrcRootDirectory(ctx)
+	pathToCC, err := ctx.Eval(pctx, rootDir+"/${config.ClangBin}/")
 	ccPath := "/bin/false"
 	cxxPath := "/bin/false"
 	if err == nil {
 		ccPath = pathToCC + "clang"
 		cxxPath = pathToCC + "clang++"
 	}
-	rootDir := getCompdbAndroidSrcRootDirectory(ctx)
 	for _, src := range srcs {
 		if _, ok := builds[src.String()]; !ok {
 			builds[src.String()] = compDbEntry{
diff --git a/cc/compiler.go b/cc/compiler.go
index 63d2ade..fbe10b5 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -341,6 +341,10 @@
 		flags.GlobalFlags = append(flags.GlobalFlags, "-D__ANDROID_RECOVERY__")
 	}
 
+	if ctx.apexName() != "" {
+		flags.GlobalFlags = append(flags.GlobalFlags, "-D__ANDROID_APEX__="+ctx.apexName())
+	}
+
 	instructionSet := String(compiler.Properties.Instruction_set)
 	if flags.RequiredInstructionSet != "" {
 		instructionSet = flags.RequiredInstructionSet
diff --git a/cc/config/global.go b/cc/config/global.go
index ff11a8a..e3d36bd 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -176,7 +176,6 @@
 			"hardware/libhardware/include",
 			"hardware/libhardware_legacy/include",
 			"hardware/ril/include",
-			"libnativehelper/include",
 			"frameworks/native/include",
 			"frameworks/native/opengl/include",
 			"frameworks/av/include",
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index 8da21b3..f072f34 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -111,14 +111,22 @@
 )
 
 const (
-	linuxGccVersion = "4.8"
+	linuxGccVersion   = "4.8.3"
+	linuxGlibcVersion = "2.17"
 )
 
 func init() {
 	pctx.StaticVariable("LinuxGccVersion", linuxGccVersion)
+	pctx.StaticVariable("LinuxGlibcVersion", linuxGlibcVersion)
+	// Most places use the full GCC version. A few only use up to the first two numbers.
+	if p := strings.Split(linuxGccVersion, "."); len(p) > 2 {
+		pctx.StaticVariable("ShortLinuxGccVersion", strings.Join(p[:2], "."))
+	} else {
+		pctx.StaticVariable("ShortLinuxGccVersion", linuxGccVersion)
+	}
 
 	pctx.SourcePathVariable("LinuxGccRoot",
-		"prebuilts/gcc/${HostPrebuiltTag}/host/x86_64-linux-glibc2.15-${LinuxGccVersion}")
+		"prebuilts/gcc/${HostPrebuiltTag}/host/x86_64-linux-glibc${LinuxGlibcVersion}-${ShortLinuxGccVersion}")
 
 	pctx.StaticVariable("LinuxGccTriple", "x86_64-linux")
 
diff --git a/cc/library.go b/cc/library.go
index 09e5b50..ad07db4 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -29,27 +29,23 @@
 	"android/soong/genrule"
 )
 
+type StaticSharedLibraryProperties struct {
+	Srcs   []string `android:"arch_variant"`
+	Cflags []string `android:"arch_variant"`
+
+	Enabled            *bool    `android:"arch_variant"`
+	Whole_static_libs  []string `android:"arch_variant"`
+	Static_libs        []string `android:"arch_variant"`
+	Shared_libs        []string `android:"arch_variant"`
+	System_shared_libs []string `android:"arch_variant"`
+
+	Export_shared_lib_headers []string `android:"arch_variant"`
+	Export_static_lib_headers []string `android:"arch_variant"`
+}
+
 type LibraryProperties struct {
-	Static struct {
-		Srcs   []string `android:"arch_variant"`
-		Cflags []string `android:"arch_variant"`
-
-		Enabled            *bool    `android:"arch_variant"`
-		Whole_static_libs  []string `android:"arch_variant"`
-		Static_libs        []string `android:"arch_variant"`
-		Shared_libs        []string `android:"arch_variant"`
-		System_shared_libs []string `android:"arch_variant"`
-	} `android:"arch_variant"`
-	Shared struct {
-		Srcs   []string `android:"arch_variant"`
-		Cflags []string `android:"arch_variant"`
-
-		Enabled            *bool    `android:"arch_variant"`
-		Whole_static_libs  []string `android:"arch_variant"`
-		Static_libs        []string `android:"arch_variant"`
-		Shared_libs        []string `android:"arch_variant"`
-		System_shared_libs []string `android:"arch_variant"`
-	} `android:"arch_variant"`
+	Static StaticSharedLibraryProperties `android:"arch_variant"`
+	Shared StaticSharedLibraryProperties `android:"arch_variant"`
 
 	// local file name to pass to the linker as -unexported_symbols_list
 	Unexported_symbols_list *string `android:"arch_variant"`
@@ -539,6 +535,9 @@
 			library.Properties.Static.Whole_static_libs...)
 		deps.StaticLibs = append(deps.StaticLibs, library.Properties.Static.Static_libs...)
 		deps.SharedLibs = append(deps.SharedLibs, library.Properties.Static.Shared_libs...)
+
+		deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, library.Properties.Static.Export_shared_lib_headers...)
+		deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, library.Properties.Static.Export_static_lib_headers...)
 	} else if library.shared() {
 		if ctx.toolchain().Bionic() && !Bool(library.baseLinker.Properties.Nocrt) {
 			if !ctx.useSdk() {
@@ -560,6 +559,9 @@
 		deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.Properties.Shared.Whole_static_libs...)
 		deps.StaticLibs = append(deps.StaticLibs, library.Properties.Shared.Static_libs...)
 		deps.SharedLibs = append(deps.SharedLibs, library.Properties.Shared.Shared_libs...)
+
+		deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, library.Properties.Shared.Export_shared_lib_headers...)
+		deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, library.Properties.Shared.Export_static_lib_headers...)
 	}
 	if ctx.useVndk() {
 		deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, library.baseLinker.Properties.Target.Vendor.Exclude_static_libs)
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 90656da..b95e2a8 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -820,7 +820,7 @@
 
 type Sanitizeable interface {
 	android.Module
-	IsSanitizerEnabled() bool
+	IsSanitizerEnabled(ctx android.BaseModuleContext, sanitizerName string) bool
 }
 
 // Create sanitized variants for modules that need them
@@ -924,7 +924,7 @@
 				}
 			}
 			c.sanitize.Properties.SanitizeDep = false
-		} else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok && sanitizeable.IsSanitizerEnabled() {
+		} else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok && sanitizeable.IsSanitizerEnabled(mctx, t.String()) {
 			// APEX modules fall here
 			mctx.CreateVariations(t.String())
 		}
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 503af7e..3725146 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -87,14 +87,14 @@
 }
 
 type ModuleConfig struct {
-	Name                string
-	DexLocation         string // dex location on device
-	BuildPath           string
-	DexPath             string
-	PreferCodeIntegrity bool
-	UncompressedDex     bool
-	HasApkLibraries     bool
-	PreoptFlags         []string
+	Name            string
+	DexLocation     string // dex location on device
+	BuildPath       string
+	DexPath         string
+	UseEmbeddedDex  bool
+	UncompressedDex bool
+	HasApkLibraries bool
+	PreoptFlags     []string
 
 	ProfileClassListing  string
 	ProfileIsTextListing bool
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index f218d01..073d463 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -66,7 +66,7 @@
 	DexLocation:            "",
 	BuildPath:              "",
 	DexPath:                "",
-	PreferCodeIntegrity:    false,
+	UseEmbeddedDex:         false,
 	UncompressedDex:        false,
 	HasApkLibraries:        false,
 	PreoptFlags:            nil,
diff --git a/java/aar.go b/java/aar.go
index a108ba0..d08e487 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -332,7 +332,7 @@
 
 	a.Module.compile(ctx, a.aaptSrcJar)
 
-	a.aarFile = android.PathForOutput(ctx, ctx.ModuleName()+".aar")
+	a.aarFile = android.PathForModuleOut(ctx, ctx.ModuleName()+".aar")
 	var res android.Paths
 	if a.androidLibraryProperties.BuildAAR {
 		BuildAAR(ctx, a.aarFile, a.outputFile, a.manifestPath, a.rTxt, res)
diff --git a/java/app.go b/java/app.go
index 45ef489..cc863e6 100644
--- a/java/app.go
+++ b/java/app.go
@@ -82,6 +82,9 @@
 	installJniLibs []jniLib
 
 	bundleFile android.Path
+
+	// the install APK name is normally the same as the module name, but can be overridden with PRODUCT_PACKAGE_NAME_OVERRIDES.
+	installApkName string
 }
 
 func (a *AndroidApp) ExportedProguardFlagFiles() android.Paths {
@@ -215,11 +218,11 @@
 		// framework-res.apk is installed as system/framework/framework-res.apk
 		installDir = "framework"
 	} else if Bool(a.appProperties.Privileged) {
-		installDir = filepath.Join("priv-app", ctx.ModuleName())
+		installDir = filepath.Join("priv-app", a.installApkName)
 	} else {
-		installDir = filepath.Join("app", ctx.ModuleName())
+		installDir = filepath.Join("app", a.installApkName)
 	}
-	a.dexpreopter.installPath = android.PathForModuleInstall(ctx, installDir, ctx.ModuleName()+".apk")
+	a.dexpreopter.installPath = android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk")
 
 	if ctx.ModuleName() != "framework-res" {
 		a.Module.compile(ctx, a.aaptSrcJar)
@@ -276,6 +279,9 @@
 }
 
 func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
+	// Check if the install APK name needs to be overridden.
+	a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(ctx.ModuleName())
+
 	// Process all building blocks, from AAPT to certificates.
 	a.aaptBuildActions(ctx)
 
@@ -307,9 +313,9 @@
 		// 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()), ctx.ModuleName()+".apk", a.outputFile)
+		ctx.InstallFile(android.PathForModuleInstall(ctx, "priv-app", a.installApkName), a.installApkName+".apk", a.outputFile)
 	} else {
-		ctx.InstallFile(android.PathForModuleInstall(ctx, "app", ctx.ModuleName()), ctx.ModuleName()+".apk", a.outputFile)
+		ctx.InstallFile(android.PathForModuleInstall(ctx, "app", a.installApkName), a.installApkName+".apk", a.outputFile)
 	}
 }
 
diff --git a/java/app_builder.go b/java/app_builder.go
index 28fc4c4..5b999d8 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -122,9 +122,10 @@
 	}
 
 	ctx.Build(pctx, android.BuildParams{
-		Rule:      buildAAR,
-		Implicits: deps,
-		Output:    outputFile,
+		Rule:        buildAAR,
+		Description: "aar",
+		Implicits:   deps,
+		Output:      outputFile,
 		Args: map[string]string{
 			"manifest":   manifest.String(),
 			"classesJar": classesJarPath,
diff --git a/java/app_test.go b/java/app_test.go
index 9d7ed0a..7e06dba 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -530,3 +530,66 @@
 		})
 	}
 }
+
+func TestPackageNameOverride(t *testing.T) {
+	testCases := []struct {
+		name                string
+		bp                  string
+		packageNameOverride string
+		expected            []string
+	}{
+		{
+			name: "default",
+			bp: `
+				android_app {
+					name: "foo",
+					srcs: ["a.java"],
+				}
+			`,
+			packageNameOverride: "",
+			expected: []string{
+				buildDir + "/.intermediates/foo/android_common/foo.apk",
+				buildDir + "/target/product/test_device/system/app/foo/foo.apk",
+			},
+		},
+		{
+			name: "overridden",
+			bp: `
+				android_app {
+					name: "foo",
+					srcs: ["a.java"],
+				}
+			`,
+			packageNameOverride: "foo:bar",
+			expected: []string{
+				// The package apk should be still be the original name for test dependencies.
+				buildDir + "/.intermediates/foo/android_common/foo.apk",
+				buildDir + "/target/product/test_device/system/app/bar/bar.apk",
+			},
+		},
+	}
+
+	for _, test := range testCases {
+		t.Run(test.name, func(t *testing.T) {
+			config := testConfig(nil)
+			if test.packageNameOverride != "" {
+				config.TestProductVariables.PackageNameOverrides = []string{test.packageNameOverride}
+			}
+			ctx := testAppContext(config, test.bp, nil)
+
+			run(t, ctx, config)
+			foo := ctx.ModuleForTests("foo", "android_common")
+
+			outputs := foo.AllOutputs()
+			outputMap := make(map[string]bool)
+			for _, o := range outputs {
+				outputMap[o] = true
+			}
+			for _, e := range test.expected {
+				if _, exist := outputMap[e]; !exist {
+					t.Errorf("Can't find %q in output files.\nAll outputs:%v", e, outputs)
+				}
+			}
+		})
+	}
+}
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 2c8de55..6e46bc9 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -149,14 +149,14 @@
 	}
 
 	dexpreoptConfig := dexpreopt.ModuleConfig{
-		Name:                ctx.ModuleName(),
-		DexLocation:         dexLocation,
-		BuildPath:           android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").String(),
-		DexPath:             dexJarFile.String(),
-		PreferCodeIntegrity: false,
-		UncompressedDex:     d.uncompressedDex,
-		HasApkLibraries:     false,
-		PreoptFlags:         nil,
+		Name:            ctx.ModuleName(),
+		DexLocation:     dexLocation,
+		BuildPath:       android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").String(),
+		DexPath:         dexJarFile.String(),
+		UseEmbeddedDex:  false,
+		UncompressedDex: d.uncompressedDex,
+		HasApkLibraries: false,
+		PreoptFlags:     nil,
 
 		ProfileClassListing:  profileClassListing.String(),
 		ProfileIsTextListing: profileIsTextListing,
diff --git a/python/androidmk.go b/python/androidmk.go
index c1eaa5e..1e51e7b 100644
--- a/python/androidmk.go
+++ b/python/androidmk.go
@@ -96,5 +96,6 @@
 		fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX := "+filepath.Ext(file))
 		fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(OUT_DIR)/"+filepath.Clean(dir))
 		fmt.Fprintln(w, "LOCAL_MODULE_STEM := "+stem)
+		fmt.Fprintln(w, "LOCAL_SHARED_LIBRARIES := "+strings.Join(installer.androidMkSharedLibs, " "))
 	})
 }
diff --git a/python/installer.go b/python/installer.go
index ab3d9b4..62f36f4 100644
--- a/python/installer.go
+++ b/python/installer.go
@@ -34,6 +34,8 @@
 	relative string
 
 	path android.OutputPath
+
+	androidMkSharedLibs []string
 }
 
 func NewPythonInstaller(dir, dir64 string) *pythonInstaller {
@@ -59,3 +61,7 @@
 func (installer *pythonInstaller) install(ctx android.ModuleContext, file android.Path) {
 	installer.path = ctx.InstallFile(installer.installDir(ctx), file.Base(), file)
 }
+
+func (installer *pythonInstaller) setAndroidMkSharedLibs(sharedLibs []string) {
+	installer.androidMkSharedLibs = sharedLibs
+}
diff --git a/python/python.go b/python/python.go
index e8b4713..ddc3f1f 100644
--- a/python/python.go
+++ b/python/python.go
@@ -160,6 +160,7 @@
 
 type installer interface {
 	install(ctx android.ModuleContext, path android.Path)
+	setAndroidMkSharedLibs(sharedLibs []string)
 }
 
 type PythonDependency interface {
@@ -203,18 +204,19 @@
 }
 
 var (
-	pythonLibTag       = dependencyTag{name: "pythonLib"}
-	launcherTag        = dependencyTag{name: "launcher"}
-	pyIdentifierRegexp = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_-]*$`)
-	pyExt              = ".py"
-	protoExt           = ".proto"
-	pyVersion2         = "PY2"
-	pyVersion3         = "PY3"
-	initFileName       = "__init__.py"
-	mainFileName       = "__main__.py"
-	entryPointFile     = "entry_point.txt"
-	parFileExt         = ".zip"
-	internal           = "internal"
+	pythonLibTag         = dependencyTag{name: "pythonLib"}
+	launcherTag          = dependencyTag{name: "launcher"}
+	launcherSharedLibTag = dependencyTag{name: "launcherSharedLib"}
+	pyIdentifierRegexp   = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_-]*$`)
+	pyExt                = ".py"
+	protoExt             = ".proto"
+	pyVersion2           = "PY2"
+	pyVersion3           = "PY3"
+	initFileName         = "__init__.py"
+	mainFileName         = "__main__.py"
+	entryPointFile       = "entry_point.txt"
+	parFileExt           = ".zip"
+	internal             = "internal"
 )
 
 // create version variants for modules.
@@ -308,6 +310,20 @@
 			ctx.AddFarVariationDependencies([]blueprint.Variation{
 				{Mutator: "arch", Variation: ctx.Target().String()},
 			}, launcherTag, "py2-launcher")
+
+			// Add py2-launcher shared lib dependencies. Ideally, these should be
+			// derived from the `shared_libs` property of "py2-launcher". However, we
+			// cannot read the property at this stage and it will be too late to add
+			// dependencies later.
+			ctx.AddFarVariationDependencies([]blueprint.Variation{
+				{Mutator: "arch", Variation: ctx.Target().String()},
+			}, launcherSharedLibTag, "libsqlite")
+
+			if ctx.Target().Os.Bionic() {
+				ctx.AddFarVariationDependencies([]blueprint.Variation{
+					{Mutator: "arch", Variation: ctx.Target().String()},
+				}, launcherSharedLibTag, "libc", "libdl", "libm")
+			}
 		}
 
 	case pyVersion3:
@@ -374,8 +390,18 @@
 			embeddedLauncher, p.srcsPathMappings, p.srcsZip, p.depsSrcsZips)
 	}
 
-	if p.installer != nil && p.installSource.Valid() {
-		p.installer.install(ctx, p.installSource.Path())
+	if p.installer != nil {
+		var sharedLibs []string
+		ctx.VisitDirectDeps(func(dep android.Module) {
+			if ctx.OtherModuleDependencyTag(dep) == launcherSharedLibTag {
+				sharedLibs = append(sharedLibs, ctx.OtherModuleName(dep))
+			}
+		})
+		p.installer.setAndroidMkSharedLibs(sharedLibs)
+
+		if p.installSource.Valid() {
+			p.installer.install(ctx, p.installSource.Path())
+		}
 	}
 
 }
diff --git a/scripts/OWNERS b/scripts/OWNERS
new file mode 100644
index 0000000..076b3f5
--- /dev/null
+++ b/scripts/OWNERS
@@ -0,0 +1 @@
+per-file system-clang-format,system-clang-format-2 = enh@google.com,smoreland@google.com
diff --git a/scripts/manifest_fixer.py b/scripts/manifest_fixer.py
index ebfc4d8..917f55b 100755
--- a/scripts/manifest_fixer.py
+++ b/scripts/manifest_fixer.py
@@ -61,9 +61,10 @@
                       help='specify additional <uses-library> tag to add. android:requred is set to false')
   parser.add_argument('--uses-non-sdk-api', dest='uses_non_sdk_api', action='store_true',
                       help='manifest is for a package built against the platform')
-  parser.add_argument('--prefer-code-integrity', dest='prefer_code_integrity', action='store_true',
-                      help=('specify if the app prefers strict code integrity. Should not be conflict '
-                            'if already declared in the manifest.'))
+  parser.add_argument('--use-embedded-dex', dest='use_embedded_dex', action='store_true',
+                      help=('specify if the app wants to use embedded dex and avoid extracted,'
+                            'locally compiled code. Should not be conflict if already declared '
+                            'in the manifest.'))
   parser.add_argument('input', help='input AndroidManifest.xml file')
   parser.add_argument('output', help='output AndroidManifest.xml file')
   return parser.parse_args()
@@ -272,7 +273,7 @@
     application.setAttributeNode(attr)
 
 
-def add_prefer_code_integrity(doc):
+def add_use_embedded_dex(doc):
   manifest = parse_manifest(doc)
   elems = get_children_with_tag(manifest, 'application')
   application = elems[0] if len(elems) == 1 else None
@@ -285,13 +286,13 @@
     manifest.insertBefore(doc.createTextNode(indent), first)
     manifest.insertBefore(application, first)
 
-  attr = application.getAttributeNodeNS(android_ns, 'preferCodeIntegrity')
+  attr = application.getAttributeNodeNS(android_ns, 'useEmbeddedDex')
   if attr is None:
-    attr = doc.createAttributeNS(android_ns, 'android:preferCodeIntegrity')
+    attr = doc.createAttributeNS(android_ns, 'android:useEmbeddedDex')
     attr.value = 'true'
     application.setAttributeNode(attr)
   elif attr.value != 'true':
-    raise RuntimeError('existing attribute mismatches the option of --prefer-code-integrity')
+    raise RuntimeError('existing attribute mismatches the option of --use-embedded-dex')
 
 
 def write_xml(f, doc):
@@ -321,8 +322,8 @@
     if args.uses_non_sdk_api:
       add_uses_non_sdk_api(doc)
 
-    if args.prefer_code_integrity:
-      add_prefer_code_integrity(doc)
+    if args.use_embedded_dex:
+      add_use_embedded_dex(doc)
 
     with open(args.output, 'wb') as f:
       write_xml(f, doc)
diff --git a/scripts/manifest_fixer_test.py b/scripts/manifest_fixer_test.py
index edc98cd..1d8de55 100755
--- a/scripts/manifest_fixer_test.py
+++ b/scripts/manifest_fixer_test.py
@@ -346,12 +346,12 @@
     self.assertEqual(output, expected)
 
 
-class PreferCodeIntegrityTest(unittest.TestCase):
-  """Unit tests for add_prefer_code_integrity function."""
+class UseEmbeddedDexTest(unittest.TestCase):
+  """Unit tests for add_use_embedded_dex function."""
 
   def run_test(self, input_manifest):
     doc = minidom.parseString(input_manifest)
-    manifest_fixer.add_prefer_code_integrity(doc)
+    manifest_fixer.add_use_embedded_dex(doc)
     output = StringIO.StringIO()
     manifest_fixer.write_xml(output, doc)
     return output.getvalue()
@@ -362,23 +362,23 @@
       '    <application%s/>\n'
       '</manifest>\n')
 
-  def prefer_code_integrity(self, value):
-    return ' android:preferCodeIntegrity="%s"' % value
+  def use_embedded_dex(self, value):
+    return ' android:useEmbeddedDex="%s"' % value
 
   def test_manifest_with_undeclared_preference(self):
     manifest_input = self.manifest_tmpl % ''
-    expected = self.manifest_tmpl % self.prefer_code_integrity('true')
+    expected = self.manifest_tmpl % self.use_embedded_dex('true')
     output = self.run_test(manifest_input)
     self.assertEqual(output, expected)
 
-  def test_manifest_with_prefer_code_integrity(self):
-    manifest_input = self.manifest_tmpl % self.prefer_code_integrity('true')
+  def test_manifest_with_use_embedded_dex(self):
+    manifest_input = self.manifest_tmpl % self.use_embedded_dex('true')
     expected = manifest_input
     output = self.run_test(manifest_input)
     self.assertEqual(output, expected)
 
-  def test_manifest_with_not_prefer_code_integrity(self):
-    manifest_input = self.manifest_tmpl % self.prefer_code_integrity('false')
+  def test_manifest_with_not_use_embedded_dex(self):
+    manifest_input = self.manifest_tmpl % self.use_embedded_dex('false')
     self.assertRaises(RuntimeError, self.run_test, manifest_input)
 
 if __name__ == '__main__':
diff --git a/scripts/system-clang-format b/scripts/system-clang-format
new file mode 100644
index 0000000..55773a2
--- /dev/null
+++ b/scripts/system-clang-format
@@ -0,0 +1,11 @@
+BasedOnStyle: Google
+AccessModifierOffset: -2
+AllowShortFunctionsOnASingleLine: Inline
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IndentWidth: 4
+ContinuationIndentWidth: 8
+PointerAlignment: Left
+TabWidth: 4
+UseTab: Never
diff --git a/scripts/system-clang-format-2 b/scripts/system-clang-format-2
new file mode 100644
index 0000000..ede5d7e
--- /dev/null
+++ b/scripts/system-clang-format-2
@@ -0,0 +1,9 @@
+BasedOnStyle: Google
+AllowShortFunctionsOnASingleLine: Inline
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IndentWidth: 2
+PointerAlignment: Left
+TabWidth: 2
+UseTab: Never
diff --git a/ui/build/kati.go b/ui/build/kati.go
index 439c928..f924b9c 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -81,6 +81,7 @@
 		"--werror_suffix_rules",
 		"--warn_real_to_phony",
 		"--warn_phony_looks_real",
+		"--top_level_phony",
 		"--kati_stats",
 	}, args...)
 
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index 531c5d5..17decd0 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -78,7 +78,6 @@
 	"bash":      Allowed,
 	"bc":        Allowed,
 	"bzip2":     Allowed,
-	"cp":        Allowed,
 	"date":      Allowed,
 	"dd":        Allowed,
 	"diff":      Allowed,
@@ -90,7 +89,6 @@
 	"grep":      Allowed,
 	"gzip":      Allowed,
 	"hexdump":   Allowed,
-	"hostname":  Allowed,
 	"jar":       Allowed,
 	"java":      Allowed,
 	"javap":     Allowed,
@@ -133,6 +131,7 @@
 	"cat":       Toybox,
 	"chmod":     Toybox,
 	"cmp":       Toybox,
+	"cp":        Toybox,
 	"comm":      Toybox,
 	"cut":       Toybox,
 	"dirname":   Toybox,
@@ -142,6 +141,7 @@
 	"expr":      Toybox,
 	"head":      Toybox,
 	"getconf":   Toybox,
+	"hostname":  Toybox,
 	"id":        Toybox,
 	"ln":        Toybox,
 	"ls":        Toybox,
diff --git a/ui/logger/logger.go b/ui/logger/logger.go
index c763e50..58890e9 100644
--- a/ui/logger/logger.go
+++ b/ui/logger/logger.go
@@ -73,7 +73,9 @@
 }
 
 // fatalLog is the type used when Fatal[f|ln]
-type fatalLog error
+type fatalLog struct {
+	error
+}
 
 func fileRotation(from, baseName, ext string, cur, max int) error {
 	newName := baseName + "." + strconv.Itoa(cur) + ext
@@ -273,7 +275,7 @@
 func (s *stdLogger) Fatal(v ...interface{}) {
 	output := fmt.Sprint(v...)
 	s.Output(2, output)
-	panic(fatalLog(errors.New(output)))
+	panic(fatalLog{errors.New(output)})
 }
 
 // Fatalf is equivalent to Printf() followed by a call to panic() that
@@ -281,7 +283,7 @@
 func (s *stdLogger) Fatalf(format string, v ...interface{}) {
 	output := fmt.Sprintf(format, v...)
 	s.Output(2, output)
-	panic(fatalLog(errors.New(output)))
+	panic(fatalLog{errors.New(output)})
 }
 
 // Fatalln is equivalent to Println() followed by a call to panic() that
@@ -289,7 +291,7 @@
 func (s *stdLogger) Fatalln(v ...interface{}) {
 	output := fmt.Sprintln(v...)
 	s.Output(2, output)
-	panic(fatalLog(errors.New(output)))
+	panic(fatalLog{errors.New(output)})
 }
 
 // Panic is equivalent to Print() followed by a call to panic().
diff --git a/ui/logger/logger_test.go b/ui/logger/logger_test.go
index bdf0231..044e6f0 100644
--- a/ui/logger/logger_test.go
+++ b/ui/logger/logger_test.go
@@ -196,3 +196,17 @@
 	log.Panic("Test")
 	t.Errorf("Should not get here")
 }
+
+func TestRuntimePanic(t *testing.T) {
+	defer func() {
+		if p := recover(); p == nil {
+			t.Errorf("Panic not thrown")
+		}
+	}()
+	defer Recover(func(err error) {
+		t.Errorf("Recover function should not be called")
+	})
+	var i *int
+	*i = 0
+	t.Errorf("Should not get here")
+}