Merge "Prevent apex from using preferred prebuilt_boot_image"
diff --git a/kernel/prebuilt_kernel_modules.go b/kernel/prebuilt_kernel_modules.go
index 14ac021..5bcca04 100644
--- a/kernel/prebuilt_kernel_modules.go
+++ b/kernel/prebuilt_kernel_modules.go
@@ -27,8 +27,12 @@
 )
 
 func init() {
-	android.RegisterModuleType("prebuilt_kernel_modules", prebuiltKernelModulesFactory)
 	pctx.Import("android/soong/cc/config")
+	registerKernelBuildComponents(android.InitRegistrationContext)
+}
+
+func registerKernelBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("prebuilt_kernel_modules", prebuiltKernelModulesFactory)
 }
 
 type prebuiltKernelModules struct {
diff --git a/kernel/prebuilt_kernel_modules_test.go b/kernel/prebuilt_kernel_modules_test.go
index 433548b..90b9886 100644
--- a/kernel/prebuilt_kernel_modules_test.go
+++ b/kernel/prebuilt_kernel_modules_test.go
@@ -15,73 +15,29 @@
 package kernel
 
 import (
-	"io/ioutil"
 	"os"
-	"reflect"
-	"strings"
 	"testing"
 
 	"android/soong/android"
 	"android/soong/cc"
 )
 
-func testKernelModules(t *testing.T, bp string, fs map[string][]byte) (*android.TestContext, android.Config) {
-	bp = bp + `
-		cc_binary_host {
-			name: "depmod",
-			srcs: ["depmod.cpp"],
-			stl: "none",
-			static_executable: true,
-			system_shared_libs: [],
-		}
-	`
-	bp = bp + cc.GatherRequiredDepsForTest(android.Android)
-
-	fs["depmod.cpp"] = nil
-	cc.GatherRequiredFilesForTest(fs)
-
-	config := android.TestArchConfig(buildDir, nil, bp, fs)
-
-	ctx := android.NewTestArchContext(config)
-	ctx.RegisterModuleType("prebuilt_kernel_modules", prebuiltKernelModulesFactory)
-	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
-	cc.RegisterRequiredBuildComponentsForTest(ctx)
-
-	ctx.Register()
-	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
-	android.FailIfErrored(t, errs)
-	_, errs = ctx.PrepareBuildActions(config)
-	android.FailIfErrored(t, errs)
-
-	return ctx, config
-}
-
-func ensureListContains(t *testing.T, result []string, expected string) {
-	t.Helper()
-	if !android.InList(expected, result) {
-		t.Errorf("%q is not found in %v", expected, result)
-	}
-}
-
-func ensureContains(t *testing.T, result string, expected string) {
-	t.Helper()
-	if !strings.Contains(result, expected) {
-		t.Errorf("%q is not found in %q", expected, result)
-	}
-}
-
 func TestKernelModulesFilelist(t *testing.T) {
-	ctx, _ := testKernelModules(t, `
+	ctx := android.GroupFixturePreparers(
+		cc.PrepareForTestWithCcDefaultModules,
+		android.FixtureRegisterWithContext(registerKernelBuildComponents),
+		android.MockFS{
+			"depmod.cpp": nil,
+			"mod1.ko":    nil,
+			"mod2.ko":    nil,
+		}.AddToFixture(),
+	).RunTestWithBp(t, `
 		prebuilt_kernel_modules {
 			name: "foo",
 			srcs: ["*.ko"],
 			kernel_version: "5.10",
 		}
-	`,
-		map[string][]byte{
-			"mod1.ko": nil,
-			"mod2.ko": nil,
-		})
+	`)
 
 	expected := []string{
 		"lib/modules/5.10/mod1.ko",
@@ -98,32 +54,9 @@
 	}
 	actual = android.SortedUniqueStrings(actual)
 	expected = android.SortedUniqueStrings(expected)
-	if !reflect.DeepEqual(actual, expected) {
-		t.Errorf("\ngot: %v\nexpected: %v\n", actual, expected)
-	}
-}
-
-var buildDir string
-
-func setUp() {
-	var err error
-	buildDir, err = ioutil.TempDir("", "soong_kernel_test")
-	if err != nil {
-		panic(err)
-	}
-}
-
-func tearDown() {
-	os.RemoveAll(buildDir)
+	android.AssertDeepEquals(t, "foo packaging specs", expected, actual)
 }
 
 func TestMain(m *testing.M) {
-	run := func() int {
-		setUp()
-		defer tearDown()
-
-		return m.Run()
-	}
-
-	os.Exit(run())
+	os.Exit(m.Run())
 }
diff --git a/rust/project_json.go b/rust/project_json.go
index 8d3d250..c28bc7b 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -49,7 +49,7 @@
 	RootModule  string            `json:"root_module"`
 	Edition     string            `json:"edition,omitempty"`
 	Deps        []rustProjectDep  `json:"deps"`
-	Cfgs        []string          `json:"cfgs"`
+	Cfg         []string          `json:"cfg"`
 	Env         map[string]string `json:"env"`
 }
 
@@ -230,7 +230,7 @@
 		RootModule:  rootModule,
 		Edition:     comp.edition(),
 		Deps:        make([]rustProjectDep, 0),
-		Cfgs:        make([]string, 0),
+		Cfg:         make([]string, 0),
 		Env:         make(map[string]string),
 	}
 
@@ -238,6 +238,10 @@
 		crate.Env["OUT_DIR"] = comp.CargoOutDir().String()
 	}
 
+	for _, feature := range comp.Properties.Features {
+		crate.Cfg = append(crate.Cfg, "feature=\""+feature+"\"")
+	}
+
 	deps := make(map[string]int)
 	singleton.mergeDependencies(ctx, rModule, &crate, deps)
 
diff --git a/rust/project_json_test.go b/rust/project_json_test.go
index 8f64f56..7af4635 100644
--- a/rust/project_json_test.go
+++ b/rust/project_json_test.go
@@ -18,6 +18,7 @@
 	"encoding/json"
 	"io/ioutil"
 	"path/filepath"
+	"sort"
 	"strings"
 	"testing"
 
@@ -115,6 +116,41 @@
 	validateJsonCrates(t, jsonContent)
 }
 
+func TestProjectJsonFeature(t *testing.T) {
+	bp := `
+	rust_library {
+		name: "liba",
+		srcs: ["a/src/lib.rs"],
+		crate_name: "a",
+		features: ["f1", "f2"]
+	}
+	`
+	jsonContent := testProjectJson(t, bp)
+	crates := validateJsonCrates(t, jsonContent)
+	for _, c := range crates {
+		crate := validateCrate(t, c)
+		cfgs, ok := crate["cfg"].([]interface{})
+		if !ok {
+			t.Fatalf("Unexpected type for cfgs: %v", crate)
+		}
+		expectedCfgs := []string{"feature=\"f1\"", "feature=\"f2\""}
+		foundCfgs := []string{}
+		for _, cfg := range cfgs {
+			cfg, ok := cfg.(string)
+			if !ok {
+				t.Fatalf("Unexpected type for cfg: %v", cfg)
+			}
+			foundCfgs = append(foundCfgs, cfg)
+		}
+		sort.Strings(foundCfgs)
+		for i, foundCfg := range foundCfgs {
+			if foundCfg != expectedCfgs[i] {
+				t.Errorf("Incorrect features: got %v; want %v", foundCfg, expectedCfgs[i])
+			}
+		}
+	}
+}
+
 func TestProjectJsonBinary(t *testing.T) {
 	bp := `
 	rust_binary {