From 0ba5c94a94a1b9dd98c72296e1a919d20acff810 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Tue, 14 Aug 2018 22:20:22 -0700 Subject: [PATCH] Add recovery_available to prebuilt_etc. The property is similar to the ones for cc_*, where it can additionally create a recovery variant of the module when used. Bug: 112780007 Test: Build mke2fs.conf with `recovery_available: true`. Test: `go test -run TestPrebuiltEtc` Change-Id: Ia04360d00453fa1f80022301feb369514f5e2b0b --- android/prebuilt_etc.go | 70 ++++++++++++++++++++++++++- android/prebuilt_etc_test.go | 93 ++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 android/prebuilt_etc_test.go diff --git a/android/prebuilt_etc.go b/android/prebuilt_etc.go index 55a72a6a0..12fefab7f 100644 --- a/android/prebuilt_etc.go +++ b/android/prebuilt_etc.go @@ -24,6 +24,10 @@ import ( func init() { RegisterModuleType("prebuilt_etc", PrebuiltEtcFactory) + + PreDepsMutators(func(ctx RegisterMutatorsContext) { + ctx.BottomUp("prebuilt_etc", prebuiltEtcMutator).Parallel() + }) } type prebuiltEtcProperties struct { @@ -32,6 +36,11 @@ type prebuiltEtcProperties struct { // optional subdirectory under which this file is installed into Sub_dir *string `android:"arch_variant"` + + // Make this module available when building for recovery. + Recovery_available *bool + + InRecovery bool `blueprint:"mutated"` } type PrebuiltEtc struct { @@ -44,6 +53,18 @@ type PrebuiltEtc struct { additionalDependencies *Paths } +func (p *PrebuiltEtc) inRecovery() bool { + return p.properties.InRecovery || p.ModuleBase.InstallInRecovery() +} + +func (p *PrebuiltEtc) onlyInRecovery() bool { + return p.ModuleBase.InstallInRecovery() +} + +func (p *PrebuiltEtc) InstallInRecovery() bool { + return p.inRecovery() +} + func (p *PrebuiltEtc) DepsMutator(ctx BottomUpMutatorContext) { if p.properties.Src == nil { ctx.PropertyErrorf("src", "missing prebuilt source file") @@ -71,9 +92,13 @@ func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx ModuleContext) { func (p *PrebuiltEtc) AndroidMk() AndroidMkData { return AndroidMkData{ Custom: func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData) { + nameSuffix := "" + if p.inRecovery() && !p.onlyInRecovery() { + nameSuffix = ".recovery" + } fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)") fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir) - fmt.Fprintln(w, "LOCAL_MODULE :=", name) + fmt.Fprintln(w, "LOCAL_MODULE :=", name+nameSuffix) fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC") fmt.Fprintln(w, "LOCAL_MODULE_TAGS := optional") fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", p.sourceFilePath.String()) @@ -101,3 +126,46 @@ func PrebuiltEtcFactory() Module { InitAndroidArchModule(module, DeviceSupported, MultilibCommon) return module } + +const ( + // coreMode is the variant for modules to be installed to system. + coreMode = "core" + + // recoveryMode means a module to be installed to recovery image. + recoveryMode = "recovery" +) + +// prebuiltEtcMutator creates the needed variants to install the module to +// system or recovery. +func prebuiltEtcMutator(mctx BottomUpMutatorContext) { + m, ok := mctx.Module().(*PrebuiltEtc) + if !ok { + return + } + + var coreVariantNeeded bool = true + var recoveryVariantNeeded bool = false + if Bool(m.properties.Recovery_available) { + recoveryVariantNeeded = true + } + + if m.ModuleBase.InstallInRecovery() { + recoveryVariantNeeded = true + coreVariantNeeded = false + } + + var variants []string + if coreVariantNeeded { + variants = append(variants, coreMode) + } + if recoveryVariantNeeded { + variants = append(variants, recoveryMode) + } + mod := mctx.CreateVariations(variants...) + for i, v := range variants { + if v == recoveryMode { + m := mod[i].(*PrebuiltEtc) + m.properties.InRecovery = true + } + } +} diff --git a/android/prebuilt_etc_test.go b/android/prebuilt_etc_test.go new file mode 100644 index 000000000..9244647c6 --- /dev/null +++ b/android/prebuilt_etc_test.go @@ -0,0 +1,93 @@ +// Copyright 2018 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 ( + "io/ioutil" + "os" + "testing" +) + +func testPrebuiltEtc(t *testing.T, bp string) *TestContext { + config, buildDir := setUp(t) + defer tearDown(buildDir) + ctx := NewTestArchContext() + ctx.RegisterModuleType("prebuilt_etc", ModuleFactoryAdaptor(PrebuiltEtcFactory)) + ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) { + ctx.BottomUp("prebuilt_etc", prebuiltEtcMutator).Parallel() + }) + ctx.Register() + mockFiles := map[string][]byte{ + "Android.bp": []byte(bp), + "foo.conf": nil, + "bar.conf": nil, + "baz.conf": nil, + } + ctx.MockFileSystem(mockFiles) + _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) + FailIfErrored(t, errs) + _, errs = ctx.PrepareBuildActions(config) + FailIfErrored(t, errs) + + return ctx +} + +func setUp(t *testing.T) (config Config, buildDir string) { + buildDir, err := ioutil.TempDir("", "soong_prebuilt_etc_test") + if err != nil { + t.Fatal(err) + } + + config = TestArchConfig(buildDir, nil) + return +} + +func tearDown(buildDir string) { + os.RemoveAll(buildDir) +} + +func TestPrebuiltEtcVariants(t *testing.T) { + ctx := testPrebuiltEtc(t, ` + prebuilt_etc { + name: "foo.conf", + src: "foo.conf", + } + prebuilt_etc { + name: "bar.conf", + src: "bar.conf", + recovery_available: true, + } + prebuilt_etc { + name: "baz.conf", + src: "baz.conf", + recovery: true, + } + `) + + foo_variants := ctx.ModuleVariantsForTests("foo.conf") + if len(foo_variants) != 1 { + t.Errorf("expected 1, got %#v", foo_variants) + } + + bar_variants := ctx.ModuleVariantsForTests("bar.conf") + if len(bar_variants) != 2 { + t.Errorf("expected 2, got %#v", bar_variants) + } + + baz_variants := ctx.ModuleVariantsForTests("baz.conf") + if len(baz_variants) != 1 { + t.Errorf("expected 1, got %#v", bar_variants) + } +}