Merge "Bp2build support for JNI deps of android_app." into main
diff --git a/aconfig/rust_aconfig_library_test.go b/aconfig/rust_aconfig_library_test.go
index 17385c3..90b09c8 100644
--- a/aconfig/rust_aconfig_library_test.go
+++ b/aconfig/rust_aconfig_library_test.go
@@ -50,11 +50,11 @@
 	}
 
 	for _, variant := range variants {
-		android.AssertStringEquals(
+		android.AssertStringListContains(
 			t,
 			"dylib variant builds from generated rust code",
+			variant.Rule("rustc").Implicits.RelativeToTop().Strings(),
 			"out/soong/.intermediates/libmy_rust_aconfig_library/android_arm64_armv8-a_source/gen/src/lib.rs",
-			variant.Rule("rustc").Inputs[0].RelativeToTop().String(),
 		)
 	}
 }
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 9997f54..bcb580a 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -340,6 +340,7 @@
 		"prebuilts/clang/host/linux-x86":                   Bp2BuildDefaultTrueRecursively,
 		"prebuilts/gradle-plugin":                          Bp2BuildDefaultTrueRecursively,
 		"prebuilts/runtime/mainline/platform/sdk":          Bp2BuildDefaultTrueRecursively,
+		"prebuilts/module_sdk":                             Bp2BuildDefaultTrueRecursively,
 		"prebuilts/sdk":                                    Bp2BuildDefaultTrue,
 		"prebuilts/sdk/current/androidx":                   Bp2BuildDefaultTrue,
 		"prebuilts/sdk/current/androidx-legacy":            Bp2BuildDefaultTrue,
@@ -432,6 +433,7 @@
 
 		"tools/apifinder":                             Bp2BuildDefaultTrue,
 		"tools/apksig":                                Bp2BuildDefaultTrue,
+		"tools/dexter/slicer":                         Bp2BuildDefaultTrueRecursively,
 		"tools/external_updater":                      Bp2BuildDefaultTrueRecursively,
 		"tools/metalava":                              Bp2BuildDefaultTrueRecursively,
 		"tools/platform-compat/java/android/compat":   Bp2BuildDefaultTrueRecursively,
@@ -918,9 +920,15 @@
 		"androidx.test.monitor-nodeps",
 		"androidx.test.annotation",
 		"androidx.test.annotation-nodeps",
+
+		// jni deps of an internal android_test (b/297405812)
+		"libdexmakerjvmtiagent",
+		"libopenjdkjvmti_headers",
+		"libstaticjvmtiagent",
 	}
 
 	Bp2buildModuleTypeAlwaysConvertList = []string{
+		// go/keep-sorted start
 		"aconfig_declarations",
 		"aconfig_value_set",
 		"aconfig_values",
@@ -940,6 +948,7 @@
 		"linker_config",
 		"sysprop_library",
 		"xsd_config",
+		// go/keep-sorted end
 	}
 
 	// Add the names of modules that bp2build should never convert, if it is
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index ac862d4..4ac5840 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -487,6 +487,9 @@
 	if moduleDir == Bp2BuildTopLevel {
 		moduleDir = ""
 	}
+	if a, ok := module.(Module); ok && IsModulePrebuilt(a) {
+		moduleName = RemoveOptionalPrebuiltPrefix(moduleName)
+	}
 	return fmt.Sprintf("//%s:%s", moduleDir, moduleName)
 }
 
diff --git a/android/config.go b/android/config.go
index 445c6cd..a70fad0 100644
--- a/android/config.go
+++ b/android/config.go
@@ -2073,6 +2073,11 @@
 	return c.apiLibraries
 }
 
+// Bp2buildMode indicates whether the config is for bp2build mode of Soong
+func (c *config) Bp2buildMode() bool {
+	return c.BuildMode == Bp2build
+}
+
 func (c *deviceConfig) CheckVendorSeappViolations() bool {
 	return Bool(c.config.productVariables.CheckVendorSeappViolations)
 }
diff --git a/android/module.go b/android/module.go
index f4b51ea..f48af4a 100644
--- a/android/module.go
+++ b/android/module.go
@@ -3100,11 +3100,21 @@
 	if !b.isBazelConversionMode() {
 		panic("cannot call ModuleFromName if not in bazel conversion mode")
 	}
+	var m blueprint.Module
+	var ok bool
 	if moduleName, _ := SrcIsModuleWithTag(name); moduleName != "" {
-		return b.bp.ModuleFromName(moduleName)
+		m, ok = b.bp.ModuleFromName(moduleName)
 	} else {
-		return b.bp.ModuleFromName(name)
+		m, ok = b.bp.ModuleFromName(name)
 	}
+	if !ok {
+		return m, ok
+	}
+	// If this module is not preferred, tried to get the prebuilt version instead
+	if a, aOk := m.(Module); aOk && !IsModulePrebuilt(a) && !IsModulePreferred(a) {
+		return b.ModuleFromName("prebuilt_" + name)
+	}
+	return m, ok
 }
 
 func (b *baseModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) {
diff --git a/android/mutator.go b/android/mutator.go
index 0284794..336f8f7 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -56,6 +56,7 @@
 		// TODO(b/165114590): this is required to resolve deps that are only prebuilts, but we should
 		// evaluate the impact on conversion.
 		RegisterPrebuiltsPreArchMutators,
+		RegisterPrebuiltsPostDepsMutators,
 	},
 		bp2buildMutators...)
 
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 95b772d..e7b7979 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -483,20 +483,55 @@
 // 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, prebuilt Module) bool {
-	if p.srcsSupplier != nil && len(p.srcsSupplier(ctx, prebuilt)) == 0 {
-		return false
-	}
+	if !ctx.Config().Bp2buildMode() {
+		if p.srcsSupplier != nil && len(p.srcsSupplier(ctx, prebuilt)) == 0 {
+			return false
+		}
 
-	// Skip prebuilt modules under unexported namespaces so that we won't
-	// end up shadowing non-prebuilt module when prebuilt module under same
-	// name happens to have a `Prefer` property set to true.
-	if ctx.Config().KatiEnabled() && !prebuilt.ExportedToMake() {
-		return false
+		// Skip prebuilt modules under unexported namespaces so that we won't
+		// end up shadowing non-prebuilt module when prebuilt module under same
+		// name happens to have a `Prefer` property set to true.
+		if ctx.Config().KatiEnabled() && !prebuilt.ExportedToMake() {
+			return false
+		}
 	}
 
 	// If source is not available or is disabled then always use the prebuilt.
 	if source == nil || !source.Enabled() {
-		return true
+		// If in bp2build mode, we need to check product variables & Soong config variables, which may
+		// have overridden the "enabled" property but have not been merged into the property value as
+		// they would in a non-bp2build mode invocation
+		if ctx.Config().Bp2buildMode() && source != nil {
+			productVariableProps, errs := ProductVariableProperties(ctx, source)
+			if productConfigProps, exists := productVariableProps["Enabled"]; len(errs) == 0 && exists && len(productConfigProps) == 1 {
+				var prop ProductConfigOrSoongConfigProperty
+				var value bool
+				for p, v := range productConfigProps {
+					prop = p
+					actual, ok := v.(*bool)
+					if ok {
+						value = proptools.Bool(actual)
+					}
+				}
+				if scv, ok := prop.(SoongConfigProperty); ok {
+					// If the product config var is enabled but the value of enabled is false still, the
+					// prebuilt is preferred. Otherwise, check if the prebulit is explicitly preferred
+					if ctx.Config().VendorConfig(scv.namespace).Bool(strings.ToLower(scv.name)) && !value {
+						return true
+					}
+				} else {
+					// TODO: b/300998219 - handle product vars
+					// We don't handle product variables yet, so return based on the non-product specific
+					// value of enabled
+					return true
+				}
+			} else {
+				// No "enabled" property override, return true since this module isn't enabled
+				return true
+			}
+		} else {
+			return true
+		}
 	}
 
 	// If the use_source_config_var property is set then it overrides the prefer property setting.
diff --git a/bazel/properties.go b/bazel/properties.go
index 9c63bc0..29e44af 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -1296,6 +1296,42 @@
 	return len(sla.Value) == 0 && !sla.HasConfigurableValues()
 }
 
+// RemoveFromAllConfigs removes all instances of the specified value from all configurations
+// of the givenStringListAttribute
+func (sla *StringListAttribute) RemoveFromAllConfigs(toRemove string) {
+	if removed, removalResult := removeFromList(toRemove, sla.Value); removed {
+		if len(removalResult) > 0 {
+			sla.Value = removalResult
+		} else {
+			sla.Value = nil
+		}
+	}
+	for axis, slsv := range sla.ConfigurableValues {
+		for config, sl := range slsv {
+			if removed, removalResult := removeFromList(toRemove, sl); removed {
+				if len(removalResult) > 0 {
+					sla.SetSelectValue(axis, config, removalResult)
+				} else {
+					sla.SetSelectValue(axis, config, nil)
+				}
+			}
+		}
+	}
+}
+
+func removeFromList(s string, list []string) (bool, []string) {
+	result := make([]string, 0, len(list))
+	var removed bool
+	for _, item := range list {
+		if item != s {
+			result = append(result, item)
+		} else {
+			removed = true
+		}
+	}
+	return removed, result
+}
+
 type configurableStringLists map[ConfigurationAxis]stringListSelectValues
 
 func (csl configurableStringLists) Append(other configurableStringLists) {
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index ec603c2..556fc37 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -4593,7 +4593,6 @@
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
-				"features":       `["android_cfi"]`,
 				"local_includes": `["."]`,
 			}),
 			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
@@ -4622,10 +4621,6 @@
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
-				"features": `select({
-        "//build/bazel/platforms/os:android": ["android_cfi"],
-        "//conditions:default": [],
-    })`,
 				"local_includes": `["."]`,
 			}),
 			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
@@ -4656,10 +4651,7 @@
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
-				"features": `[
-        "android_cfi",
-        "android_cfi_assembly_support",
-    ]`,
+				"features":       `["android_cfi_assembly_support"]`,
 				"local_includes": `["."]`,
 			}),
 			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index bf3351a..fde4c97 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -58,6 +58,7 @@
 func registerCcLibraryHeadersModuleTypes(ctx android.RegistrationContext) {
 	cc.RegisterCCBuildComponents(ctx)
 	cc.RegisterLibraryHeadersBuildComponents(ctx)
+	ctx.RegisterModuleType("cc_library_shared", cc.LibrarySharedFactory)
 }
 
 func runCcLibraryHeadersTestCase(t *testing.T, tc Bp2buildTestCase) {
@@ -417,3 +418,67 @@
 		},
 	})
 }
+
+func TestPrebuiltCcLibraryHeadersPreferredRdepUpdated(t *testing.T) {
+	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
+		Description:             "cc_library_headers prebuilt preferred is used as rdep",
+		StubbedBuildDefinitions: []string{"foo_export"},
+		Filesystem: map[string]string{
+			"foo/bar/Android.bp": simpleModule("cc_library_headers", "foo_headers"),
+		},
+		Blueprint: soongCcLibraryHeadersPreamble + `
+cc_prebuilt_library_headers {
+		name: "foo_headers",
+		whole_static_libs: ["foo_export"],
+		bazel_module: { bp2build_available: true },
+		prefer: true,
+}
+
+cc_library_shared {
+	name: "foo",
+	header_libs: ["foo_headers"],
+	include_build_directory: false,
+}
+` + simpleModule("cc_library_headers", "foo_export"),
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
+				"deps": `[":foo_export"]`,
+			}),
+			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+				"implementation_deps": `[":foo_headers"]`,
+			}),
+		},
+	})
+}
+
+func TestPrebuiltCcLibraryHeadersRdepUpdated(t *testing.T) {
+	runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
+		Description:             "cc_library_headers not preferred is not used for rdep",
+		StubbedBuildDefinitions: []string{"foo_export"},
+		Filesystem: map[string]string{
+			"foo/bar/Android.bp": simpleModule("cc_library_headers", "foo_headers"),
+		},
+		Blueprint: soongCcLibraryHeadersPreamble + `
+cc_prebuilt_library_headers {
+		name: "foo_headers",
+		whole_static_libs: ["foo_export"],
+		bazel_module: { bp2build_available: true },
+		prefer: false,
+}
+
+cc_library_shared {
+	name: "foo",
+	header_libs: ["foo_headers"],
+	include_build_directory: false,
+}
+` + simpleModule("cc_library_headers", "foo_export"),
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
+				"deps": `[":foo_export"]`,
+			}),
+			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+				"implementation_deps": `["//foo/bar:foo_headers"]`,
+			}),
+		},
+	})
+}
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index 6f600da..78f21ba 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -1519,7 +1519,7 @@
 	runCcLibrarySharedTestCase(t, Bp2buildTestCase{
 		Description: "cc_library_shared has correct features when cfi is enabled with cfi assembly support",
 		Blueprint: `
-cc_library_static {
+cc_library_shared {
 	name: "foo",
 	sanitize: {
 		cfi: true,
@@ -1529,7 +1529,7 @@
 	},
 }`,
 		ExpectedBazelTargets: []string{
-			MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+			MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
 				"features": `[
         "android_cfi",
         "android_cfi_assembly_support",
@@ -1635,7 +1635,7 @@
         ],
         "//build/bazel/rules/apex:unbundled_app": [
             ":libHasApexStubs",
-            "//.:libHasApexAndNdkStubs.ndk_stub_libs",
+            "//.:libHasApexAndNdkStubs.ndk_stub_libs-current",
         ],
         "//conditions:default": [
             ":libHasApexStubs",
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index 0587aae..e64b141 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -2134,9 +2134,9 @@
 	})
 }
 
-func TestCcLibraryStaticWithCfi(t *testing.T) {
+func TestCcLibraryStaticNoCfi(t *testing.T) {
 	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
-		Description: "cc_library_static has correct features when cfi is enabled",
+		Description: "cc_library_static never explicitly enables CFI",
 		Blueprint: `
 cc_library_static {
 	name: "foo",
@@ -2146,7 +2146,6 @@
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
-				"features":       `["android_cfi"]`,
 				"local_includes": `["."]`,
 			}),
 		},
@@ -2155,7 +2154,7 @@
 
 func TestCcLibraryStaticWithCfiOsSpecific(t *testing.T) {
 	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
-		Description: "cc_library_static has correct features when cfi is enabled for specific variants",
+		Description: "cc_library_static never explicitly enables CFI even for specific variants",
 		Blueprint: `
 cc_library_static {
 	name: "foo",
@@ -2169,10 +2168,6 @@
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
-				"features": `select({
-        "//build/bazel/platforms/os:android": ["android_cfi"],
-        "//conditions:default": [],
-    })`,
 				"local_includes": `["."]`,
 			}),
 		},
@@ -2181,7 +2176,7 @@
 
 func TestCcLibraryStaticWithCfiAndCfiAssemblySupport(t *testing.T) {
 	runCcLibraryStaticTestCase(t, Bp2buildTestCase{
-		Description: "cc_library_static has correct features when cfi is enabled with cfi_assembly_support",
+		Description: "cc_library_static will specify cfi_assembly_support feature but not cfi feature",
 		Blueprint: `
 cc_library_static {
 	name: "foo",
@@ -2194,10 +2189,7 @@
 }`,
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
-				"features": `[
-        "android_cfi",
-        "android_cfi_assembly_support",
-    ]`,
+				"features":       `["android_cfi_assembly_support"]`,
 				"local_includes": `["."]`,
 			}),
 		},
diff --git a/cc/Android.bp b/cc/Android.bp
index c32d854..8f6709f 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -30,6 +30,7 @@
         "cc.go",
         "ccdeps.go",
         "check.go",
+        "constants.go",
         "coverage.go",
         "gen.go",
         "generated_cc_library.go",
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 6a49915..8248a55 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -1657,9 +1657,11 @@
 			if depC, ok := dep.(*Module); ok && hasNdkStubs(ctx, depC) {
 				// If the dependency has ndk stubs, build against the ndk stubs
 				// https://cs.android.com/android/_/android/platform/build/soong/+/main:cc/cc.go;l=2642-2643;drc=e12d252e22dd8afa654325790d3298a0d67bd9d6;bpv=1;bpt=0
+				ver := proptools.String(c.Properties.Sdk_version)
+				// TODO - b/298085502: Add bp2build support for sdk_version: "minimum"
 				ndkLibModule, _ := ctx.ModuleFromName(dep.Name() + ndkLibrarySuffix)
 				label = bazel.Label{
-					Label: "//" + ctx.OtherModuleDir(ndkLibModule) + ":" + ndkLibModule.Name() + "_stub_libs",
+					Label: "//" + ctx.OtherModuleDir(ndkLibModule) + ":" + ndkLibModule.Name() + "_stub_libs-" + ver,
 				}
 			}
 			// add the ndk lib label to this axis
@@ -1985,9 +1987,9 @@
 				sanitizerCompilerInputs.SetSelectValue(bazel.SanitizersEnabledAxis, bazel.SanitizersEnabled, bazel.MakeLabelListFromTargetNames([]string{*blocklist}))
 			}
 			if sanitizerProps.Sanitize.Cfi != nil && !proptools.Bool(sanitizerProps.Sanitize.Cfi) {
-				features = append(features, "-android_cfi")
+				features = append(features, "-"+cfiFeatureName)
 			} else if proptools.Bool(sanitizerProps.Sanitize.Cfi) {
-				features = append(features, "android_cfi")
+				features = append(features, cfiFeatureName)
 				if proptools.Bool(sanitizerProps.Sanitize.Config.Cfi_assembly_support) {
 					features = append(features, "android_cfi_assembly_support")
 				}
diff --git a/cc/constants.go b/cc/constants.go
new file mode 100644
index 0000000..f188d4e
--- /dev/null
+++ b/cc/constants.go
@@ -0,0 +1,19 @@
+// Copyright 2016 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 cc
+
+var (
+	cfiFeatureName = "android_cfi"
+)
diff --git a/cc/library.go b/cc/library.go
index b9dc71b..0522376 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -331,6 +331,7 @@
 	sharedFeatures.DeduplicateAxesFromBase()
 	staticFeatures := baseAttributes.features.Clone().Append(staticAttrs.Features)
 	staticFeatures.DeduplicateAxesFromBase()
+	staticFeatures.RemoveFromAllConfigs(cfiFeatureName)
 
 	staticCommonAttrs := staticOrSharedAttributes{
 		Srcs:    *srcs.Clone().Append(staticAttrs.Srcs),
@@ -2947,6 +2948,9 @@
 
 	features := baseAttributes.features.Clone().Append(libSharedOrStaticAttrs.Features)
 	features.DeduplicateAxesFromBase()
+	if isStatic {
+		features.RemoveFromAllConfigs(cfiFeatureName)
+	}
 
 	commonAttrs := staticOrSharedAttributes{
 		Srcs:    compilerAttrs.srcs,
diff --git a/java/app.go b/java/app.go
index 611d0a6..e552950 100755
--- a/java/app.go
+++ b/java/app.go
@@ -31,6 +31,7 @@
 	"android/soong/dexpreopt"
 	"android/soong/genrule"
 	"android/soong/tradefed"
+	"android/soong/ui/metrics/bp2build_metrics_proto"
 )
 
 func init() {
@@ -1639,6 +1640,21 @@
 	if !supported {
 		return false, android.CommonAttributes{}, &bazelAndroidAppAttributes{}
 	}
+	if a.appProperties.Jni_uses_platform_apis != nil {
+		ctx.MarkBp2buildUnconvertible(
+			bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED,
+			"TODO - b/299360988: Add bp2build support for jni_uses_platform_apis",
+		)
+		return false, android.CommonAttributes{}, &bazelAndroidAppAttributes{}
+	}
+	if a.appProperties.Jni_uses_sdk_apis != nil {
+		ctx.MarkBp2buildUnconvertible(
+			bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED,
+			"TODO - b/299360988: Add bp2build support for jni_uses_sdk_apis",
+		)
+		return false, android.CommonAttributes{}, &bazelAndroidAppAttributes{}
+	}
+
 	certificate, certificateName := android.BazelStringOrLabelFromProp(ctx, a.overridableAppProperties.Certificate)
 
 	manifestValues := &manifestValueAttribute{}
diff --git a/java/base.go b/java/base.go
index a007717..a110aff 100644
--- a/java/base.go
+++ b/java/base.go
@@ -1077,8 +1077,8 @@
 
 }
 
-func (module *Module) addGeneratedSrcJars(path android.Path) {
-	module.properties.Generated_srcjars = append(module.properties.Generated_srcjars, path)
+func (j *Module) addGeneratedSrcJars(path android.Path) {
+	j.properties.Generated_srcjars = append(j.properties.Generated_srcjars, path)
 }
 
 func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspathJars, extraCombinedJars android.Paths) {
diff --git a/java/kotlin.go b/java/kotlin.go
index 3637e2e..aa2db0e 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -145,7 +145,7 @@
 			`$kaptProcessorPath ` +
 			`$kaptProcessor ` +
 			`-Xbuild-file=$kotlinBuildFile && ` +
-			`${config.SoongZipCmd} -jar -o $out -C $kaptDir/stubs -D $kaptDir/stubs && ` +
+			`${config.SoongZipCmd} -jar -write_if_changed -o $out -C $kaptDir/stubs -D $kaptDir/stubs && ` +
 			`rm -rf "$srcJarDir"`,
 		CommandDeps: []string{
 			"${config.KotlincCmd}",
@@ -157,6 +157,7 @@
 		},
 		Rspfile:        "$out.rsp",
 		RspfileContent: `$in`,
+		Restat:         true,
 	},
 	"kotlincFlags", "encodedJavacFlags", "kaptProcessorPath", "kaptProcessor",
 	"classpath", "srcJars", "commonSrcFilesArg", "srcJarDir", "kaptDir", "kotlinJvmTarget",