Merge "track static deps when gatherint notices for apex"
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 2d16f65..c902ec8 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -50,12 +50,9 @@
 
 type Prebuilt struct {
 	properties PrebuiltProperties
-	module     Module
-	srcs       *[]string
 
-	// Metadata for single source Prebuilt modules.
-	srcProps reflect.Value
-	srcField reflect.StructField
+	srcsSupplier     PrebuiltSrcsSupplier
+	srcsPropertyName string
 }
 
 func (p *Prebuilt) Name(name string) string {
@@ -72,31 +69,26 @@
 // preference configs. We'll want to add native support for dynamic source cases if we end up having
 // more modules like this.
 func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path {
-	if p.srcs != nil {
-		if len(*p.srcs) == 0 {
-			ctx.PropertyErrorf("srcs", "missing prebuilt source file")
+	if p.srcsSupplier != nil {
+		srcs := p.srcsSupplier()
+
+		if len(srcs) == 0 {
+			ctx.PropertyErrorf(p.srcsPropertyName, "missing prebuilt source file")
 			return nil
 		}
 
-		if len(*p.srcs) > 1 {
-			ctx.PropertyErrorf("srcs", "multiple prebuilt source files")
+		if len(srcs) > 1 {
+			ctx.PropertyErrorf(p.srcsPropertyName, "multiple prebuilt source files")
 			return nil
 		}
 
 		// Return the singleton source after expanding any filegroup in the
 		// sources.
-		return PathForModuleSrc(ctx, (*p.srcs)[0])
-	} else {
-		if !p.srcProps.IsValid() {
-			ctx.ModuleErrorf("prebuilt source was not set")
-		}
-		src := p.getSingleSourceFieldValue()
-		if src == "" {
-			ctx.PropertyErrorf(proptools.FieldNameForProperty(p.srcField.Name),
-				"missing prebuilt source file")
-			return nil
-		}
+		src := srcs[0]
 		return PathForModuleSrc(ctx, src)
+	} else {
+		ctx.ModuleErrorf("prebuilt source was not set")
+		return nil
 	}
 }
 
@@ -104,18 +96,80 @@
 	return p.properties.UsePrebuilt
 }
 
-func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) {
+// Called to provide the srcs value for the prebuilt module.
+//
+// Return the src value or nil if it is not available.
+type PrebuiltSrcsSupplier func() []string
+
+// Initialize the module as a prebuilt module that uses the provided supplier to access the
+// prebuilt sources of the module.
+//
+// The supplier will be called multiple times and must return the same values each time it
+// is called. If it returns an empty array (or nil) then the prebuilt module will not be used
+// as a replacement for a source module with the same name even if prefer = true.
+//
+// If the Prebuilt.SingleSourcePath() is called on the module then this must return an array
+// containing exactly one source file.
+//
+// The provided property name is used to provide helpful error messages in the event that
+// a problem arises, e.g. calling SingleSourcePath() when more than one source is provided.
+func InitPrebuiltModuleWithSrcSupplier(module PrebuiltInterface, srcsSupplier PrebuiltSrcsSupplier, srcsPropertyName string) {
 	p := module.Prebuilt()
 	module.AddProperties(&p.properties)
-	p.srcs = srcs
+
+	if srcsSupplier == nil {
+		panic(fmt.Errorf("srcsSupplier must not be nil"))
+	}
+	if srcsPropertyName == "" {
+		panic(fmt.Errorf("srcsPropertyName must not be empty"))
+	}
+
+	p.srcsSupplier = srcsSupplier
+	p.srcsPropertyName = srcsPropertyName
+}
+
+func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) {
+	if srcs == nil {
+		panic(fmt.Errorf("srcs must not be nil"))
+	}
+
+	srcsSupplier := func() []string {
+		return *srcs
+	}
+
+	InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs")
 }
 
 func InitSingleSourcePrebuiltModule(module PrebuiltInterface, srcProps interface{}, srcField string) {
-	p := module.Prebuilt()
-	module.AddProperties(&p.properties)
-	p.srcProps = reflect.ValueOf(srcProps).Elem()
-	p.srcField, _ = p.srcProps.Type().FieldByName(srcField)
-	p.checkSingleSourceProperties()
+	srcPropsValue := reflect.ValueOf(srcProps).Elem()
+	srcStructField, _ := srcPropsValue.Type().FieldByName(srcField)
+	if !srcPropsValue.IsValid() || srcStructField.Name == "" {
+		panic(fmt.Errorf("invalid single source prebuilt %+v", module))
+	}
+
+	if srcPropsValue.Kind() != reflect.Struct && srcPropsValue.Kind() != reflect.Interface {
+		panic(fmt.Errorf("invalid single source prebuilt %+v", srcProps))
+	}
+
+	srcFieldIndex := srcStructField.Index
+	srcPropertyName := proptools.PropertyNameForField(srcField)
+
+	srcsSupplier := func() []string {
+		value := srcPropsValue.FieldByIndex(srcFieldIndex)
+		if value.Kind() == reflect.Ptr {
+			value = value.Elem()
+		}
+		if value.Kind() != reflect.String {
+			panic(fmt.Errorf("prebuilt src field %q should be a string or a pointer to one but was %d %q", srcPropertyName, value.Kind(), value))
+		}
+		src := value.String()
+		if src == "" {
+			return nil
+		}
+		return []string{src}
+	}
+
+	InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, srcPropertyName)
 }
 
 type PrebuiltInterface interface {
@@ -152,7 +206,7 @@
 func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) {
 	if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
 		p := m.Prebuilt()
-		if p.srcs == nil && !p.srcProps.IsValid() {
+		if p.srcsSupplier == nil {
 			panic(fmt.Errorf("prebuilt module did not have InitPrebuiltModule called on it"))
 		}
 		if !p.properties.SourceExists {
@@ -191,11 +245,7 @@
 // usePrebuilt returns true if a prebuilt should be used instead of the source module.  The prebuilt
 // will be used if it is marked "prefer" or if the source module is disabled.
 func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module) bool {
-	if p.srcs != nil && len(*p.srcs) == 0 {
-		return false
-	}
-
-	if p.srcProps.IsValid() && p.getSingleSourceFieldValue() == "" {
+	if p.srcsSupplier != nil && len(p.srcsSupplier()) == 0 {
 		return false
 	}
 
@@ -210,24 +260,3 @@
 func (p *Prebuilt) SourceExists() bool {
 	return p.properties.SourceExists
 }
-
-func (p *Prebuilt) checkSingleSourceProperties() {
-	if !p.srcProps.IsValid() || p.srcField.Name == "" {
-		panic(fmt.Errorf("invalid single source prebuilt %+v", p))
-	}
-
-	if p.srcProps.Kind() != reflect.Struct && p.srcProps.Kind() != reflect.Interface {
-		panic(fmt.Errorf("invalid single source prebuilt %+v", p.srcProps))
-	}
-}
-
-func (p *Prebuilt) getSingleSourceFieldValue() string {
-	value := p.srcProps.FieldByIndex(p.srcField.Index)
-	if value.Kind() == reflect.Ptr {
-		value = value.Elem()
-	}
-	if value.Kind() != reflect.String {
-		panic(fmt.Errorf("prebuilt src field %q should be a string or a pointer to one", p.srcField.Name))
-	}
-	return value.String()
-}
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 2c18ac3..7f21721 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -23,6 +23,7 @@
 }
 
 func RegisterPrebuiltBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("cc_prebuilt_library", PrebuiltLibraryFactory)
 	ctx.RegisterModuleType("cc_prebuilt_library_shared", PrebuiltSharedLibraryFactory)
 	ctx.RegisterModuleType("cc_prebuilt_library_static", PrebuiltStaticLibraryFactory)
 	ctx.RegisterModuleType("cc_prebuilt_binary", prebuiltBinaryFactory)
@@ -96,10 +97,16 @@
 	p.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
 
 	// TODO(ccross): verify shared library dependencies
-	if len(p.properties.Srcs) > 0 {
+	srcs := p.prebuiltSrcs()
+	if len(srcs) > 0 {
 		builderFlags := flagsToBuilderFlags(flags)
 
-		in := p.Prebuilt.SingleSourcePath(ctx)
+		if len(srcs) > 1 {
+			ctx.PropertyErrorf("srcs", "multiple prebuilt source files")
+			return nil
+		}
+
+		in := android.PathForModuleSrc(ctx, srcs[0])
 
 		if p.shared() {
 			p.unstrippedOutputFile = in
@@ -123,6 +130,18 @@
 	return nil
 }
 
+func (p *prebuiltLibraryLinker) prebuiltSrcs() []string {
+	srcs := p.properties.Srcs
+	if p.static() {
+		srcs = append(srcs, p.libraryDecorator.StaticProperties.Static.Srcs...)
+	}
+	if p.shared() {
+		srcs = append(srcs, p.libraryDecorator.SharedProperties.Shared.Srcs...)
+	}
+
+	return srcs
+}
+
 func (p *prebuiltLibraryLinker) shared() bool {
 	return p.libraryDecorator.shared()
 }
@@ -146,13 +165,28 @@
 
 	module.AddProperties(&prebuilt.properties)
 
-	android.InitPrebuiltModule(module, &prebuilt.properties.Srcs)
+	srcsSupplier := func() []string {
+		return prebuilt.prebuiltSrcs()
+	}
+
+	android.InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs")
 
 	// Prebuilt libraries can be used in SDKs.
 	android.InitSdkAwareModule(module)
 	return module, library
 }
 
+// cc_prebuilt_library installs a precompiled shared library that are
+// listed in the srcs property in the device's directory.
+func PrebuiltLibraryFactory() android.Module {
+	module, _ := NewPrebuiltLibrary(android.HostAndDeviceSupported)
+
+	// Prebuilt shared libraries can be included in APEXes
+	android.InitApexModule(module)
+
+	return module.Init()
+}
+
 // cc_prebuilt_library_shared installs a precompiled shared library that are
 // listed in the srcs property in the device's directory.
 func PrebuiltSharedLibraryFactory() android.Module {
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index 3d809fc..0eca97f 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -59,36 +59,38 @@
 			name: "libe",
 			srcs: ["libe.a"],
 		}
+
+		cc_library {
+			name: "libf",
+		}
+
+		cc_prebuilt_library {
+			name: "libf",
+			static: {
+				srcs: ["libf.a"],
+			},
+			shared: {
+				srcs: ["libf.so"],
+			},
+		}
 	`
 
-	fs := map[string][]byte{
-		"liba.so": nil,
-		"libb.a":  nil,
-		"libd.so": nil,
-		"libe.a":  nil,
-	}
-
-	config := TestConfig(buildDir, android.Android, nil, bp, fs)
-
-	ctx := CreateTestContext()
-
-	ctx.Register(config)
-
-	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
-	android.FailIfErrored(t, errs)
-	_, errs = ctx.PrepareBuildActions(config)
-	android.FailIfErrored(t, errs)
+	ctx := testPrebuilt(t, bp)
 
 	// Verify that all the modules exist and that their dependencies were connected correctly
 	liba := ctx.ModuleForTests("liba", "android_arm64_armv8-a_shared").Module()
 	libb := ctx.ModuleForTests("libb", "android_arm64_armv8-a_static").Module()
 	libd := ctx.ModuleForTests("libd", "android_arm64_armv8-a_shared").Module()
 	libe := ctx.ModuleForTests("libe", "android_arm64_armv8-a_static").Module()
+	libfStatic := ctx.ModuleForTests("libf", "android_arm64_armv8-a_static").Module()
+	libfShared := ctx.ModuleForTests("libf", "android_arm64_armv8-a_shared").Module()
 
 	prebuiltLiba := ctx.ModuleForTests("prebuilt_liba", "android_arm64_armv8-a_shared").Module()
 	prebuiltLibb := ctx.ModuleForTests("prebuilt_libb", "android_arm64_armv8-a_static").Module()
 	prebuiltLibd := ctx.ModuleForTests("prebuilt_libd", "android_arm64_armv8-a_shared").Module()
 	prebuiltLibe := ctx.ModuleForTests("prebuilt_libe", "android_arm64_armv8-a_static").Module()
+	prebuiltLibfStatic := ctx.ModuleForTests("prebuilt_libf", "android_arm64_armv8-a_static").Module()
+	prebuiltLibfShared := ctx.ModuleForTests("prebuilt_libf", "android_arm64_armv8-a_shared").Module()
 
 	hasDep := func(m android.Module, wantDep android.Module) bool {
 		t.Helper()
@@ -116,4 +118,89 @@
 	if !hasDep(libe, prebuiltLibe) {
 		t.Errorf("libe missing dependency on prebuilt_libe")
 	}
+
+	if !hasDep(libfStatic, prebuiltLibfStatic) {
+		t.Errorf("libf static missing dependency on prebuilt_libf")
+	}
+
+	if !hasDep(libfShared, prebuiltLibfShared) {
+		t.Errorf("libf shared missing dependency on prebuilt_libf")
+	}
+}
+
+func testPrebuilt(t *testing.T, bp string) *android.TestContext {
+	fs := map[string][]byte{
+		"liba.so": nil,
+		"libb.a":  nil,
+		"libd.so": nil,
+		"libe.a":  nil,
+		"libf.a":  nil,
+		"libf.so": nil,
+	}
+	config := TestConfig(buildDir, android.Android, nil, bp, fs)
+	ctx := CreateTestContext()
+
+	// Enable androidmk support.
+	// * Register the singleton
+	// * Configure that we are inside make
+	// * Add CommonOS to ensure that androidmk processing works.
+	android.RegisterAndroidMkBuildComponents(ctx)
+	android.SetInMakeForTests(config)
+
+	ctx.Register(config)
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	android.FailIfErrored(t, errs)
+	_, errs = ctx.PrepareBuildActions(config)
+	android.FailIfErrored(t, errs)
+	return ctx
+}
+
+func TestPrebuiltLibraryShared(t *testing.T) {
+	ctx := testPrebuilt(t, `
+	cc_prebuilt_library_shared {
+		name: "libtest",
+		srcs: ["libf.so"],
+    strip: {
+        none: true,
+    },
+	}
+	`)
+
+	shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
+	assertString(t, shared.OutputFile().String(), "libf.so")
+}
+
+func TestPrebuiltLibraryStatic(t *testing.T) {
+	ctx := testPrebuilt(t, `
+	cc_prebuilt_library_static {
+		name: "libtest",
+		srcs: ["libf.a"],
+	}
+	`)
+
+	static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
+	assertString(t, static.OutputFile().String(), "libf.a")
+}
+
+func TestPrebuiltLibrary(t *testing.T) {
+	ctx := testPrebuilt(t, `
+	cc_prebuilt_library {
+		name: "libtest",
+		static: {
+			srcs: ["libf.a"],
+		},
+		shared: {
+			srcs: ["libf.so"],
+		},
+    strip: {
+        none: true,
+    },
+	}
+	`)
+
+	shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
+	assertString(t, shared.OutputFile().String(), "libf.so")
+
+	static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
+	assertString(t, static.OutputFile().String(), "libf.a")
 }
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index ae0dc0b..a3b264e 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -546,7 +546,11 @@
 	var allPhonies android.Paths
 	for _, image := range image.variants {
 		arch := image.target.Arch.ArchType
-		suffix := image.target.String()
+		suffix := arch.String()
+		// Host and target might both use x86 arch. We need to ensure the names are unique.
+		if image.target.Os.Class == android.Host {
+			suffix = "host-" + suffix
+		}
 		// Create a rule to call oatdump.
 		output := android.PathForOutput(ctx, "boot."+suffix+".oatdump.txt")
 		rule := android.NewRuleBuilder()
@@ -569,7 +573,10 @@
 			Text("echo").FlagWithArg("Output in ", output.String())
 		rule.Build(pctx, ctx, "phony-dump-oat-boot-"+suffix, "dump oat boot "+arch.String())
 
-		allPhonies = append(allPhonies, phony)
+		// TODO: We need to make imageLocations per-variant to make oatdump work on host.
+		if image.target.Os == android.Android {
+			allPhonies = append(allPhonies, phony)
+		}
 	}
 
 	phony := android.PathForPhony(ctx, "dump-oat-boot")