Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 525443aa authored by Jaewoong Jung's avatar Jaewoong Jung
Browse files

Add override_android_app module type.

This is a new implementation of overriding module types that makes use
of local variants. With this, product owners can use PRODUCT_PACKAGES to
decide which override module to include in their products.

Bug: 122957760
Bug: 123640028
Test: app_test.go
Change-Id: Ie65e97f615d006b6e9475193b6017ea9d97e8e97
parent 53c88448
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ bootstrap_go_package {
        "android/namespace.go",
        "android/neverallow.go",
        "android/onceper.go",
        "android/override_module.go",
        "android/package_ctx.go",
        "android/path_properties.go",
        "android/paths.go",
+1 −0
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@ var preArch = []RegisterMutatorFunc{
	RegisterNamespaceMutator,
	RegisterPrebuiltsPreArchMutators,
	RegisterDefaultsPreArchMutators,
	RegisterOverridePreArchMutators,
}

func registerArchMutator(ctx RegisterMutatorsContext) {
+213 −0
Original line number Diff line number Diff line
// Copyright (C) 2019 The Android Open Source Project
//
// 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

// This file contains all the foundation components for override modules and their base module
// types. Override modules are a kind of opposite of default modules in that they override certain
// properties of an existing base module whereas default modules provide base module data to be
// overridden. However, unlike default and defaultable module pairs, both override and overridable
// modules generate and output build actions, and it is up to product make vars to decide which one
// to actually build and install in the end. In other words, default modules and defaultable modules
// can be compared to abstract classes and concrete classes in C++ and Java. By the same analogy,
// both override and overridable modules act like concrete classes.
//
// There is one more crucial difference from the logic perspective. Unlike default pairs, most Soong
// actions happen in the base (overridable) module by creating a local variant for each override
// module based on it.

import (
	"sync"

	"github.com/google/blueprint"
	"github.com/google/blueprint/proptools"
)

// Interface for override module types, e.g. override_android_app, override_apex
type OverrideModule interface {
	Module

	getOverridingProperties() []interface{}
	setOverridingProperties(properties []interface{})

	getOverrideModuleProperties() *OverrideModuleProperties
}

// Base module struct for override module types
type OverrideModuleBase struct {
	moduleProperties OverrideModuleProperties

	overridingProperties []interface{}
}

type OverrideModuleProperties struct {
	// Name of the base module to be overridden
	Base *string

	// TODO(jungjw): Add an optional override_name bool flag.
}

func (o *OverrideModuleBase) getOverridingProperties() []interface{} {
	return o.overridingProperties
}

func (o *OverrideModuleBase) setOverridingProperties(properties []interface{}) {
	o.overridingProperties = properties
}

func (o *OverrideModuleBase) getOverrideModuleProperties() *OverrideModuleProperties {
	return &o.moduleProperties
}

func InitOverrideModule(m OverrideModule) {
	m.setOverridingProperties(m.GetProperties())

	m.AddProperties(m.getOverrideModuleProperties())
}

// Interface for overridable module types, e.g. android_app, apex
type OverridableModule interface {
	setOverridableProperties(prop []interface{})

	addOverride(o OverrideModule)
	getOverrides() []OverrideModule

	override(ctx BaseModuleContext, o OverrideModule)

	setOverridesProperty(overridesProperties *[]string)
}

// Base module struct for overridable module types
type OverridableModuleBase struct {
	ModuleBase

	// List of OverrideModules that override this base module
	overrides []OverrideModule
	// Used to parallelize registerOverrideMutator executions. Note that only addOverride locks this
	// mutex. It is because addOverride and getOverride are used in different mutators, and so are
	// guaranteed to be not mixed. (And, getOverride only reads from overrides, and so don't require
	// mutex locking.)
	overridesLock sync.Mutex

	overridableProperties []interface{}

	// If an overridable module has a property to list other modules that itself overrides, it should
	// set this to a pointer to the property through the InitOverridableModule function, so that
	// override information is propagated and aggregated correctly.
	overridesProperty *[]string
}

func InitOverridableModule(m OverridableModule, overridesProperty *[]string) {
	m.setOverridableProperties(m.(Module).GetProperties())
	m.setOverridesProperty(overridesProperty)
}

func (b *OverridableModuleBase) setOverridableProperties(prop []interface{}) {
	b.overridableProperties = prop
}

func (b *OverridableModuleBase) addOverride(o OverrideModule) {
	b.overridesLock.Lock()
	b.overrides = append(b.overrides, o)
	b.overridesLock.Unlock()
}

// Should NOT be used in the same mutator as addOverride.
func (b *OverridableModuleBase) getOverrides() []OverrideModule {
	return b.overrides
}

func (b *OverridableModuleBase) setOverridesProperty(overridesProperty *[]string) {
	b.overridesProperty = overridesProperty
}

// Overrides a base module with the given OverrideModule.
func (b *OverridableModuleBase) override(ctx BaseModuleContext, o OverrideModule) {
	for _, p := range b.overridableProperties {
		for _, op := range o.getOverridingProperties() {
			if proptools.TypeEqual(p, op) {
				err := proptools.PrependProperties(p, op, nil)
				if err != nil {
					if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
						ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
					} else {
						panic(err)
					}
				}
			}
		}
	}
	// Adds the base module to the overrides property, if exists, of the overriding module. See the
	// comment on OverridableModuleBase.overridesProperty for details.
	if b.overridesProperty != nil {
		*b.overridesProperty = append(*b.overridesProperty, b.Name())
	}
	// The base module name property has to be updated separately for Name() to work as intended.
	b.module.base().nameProperties.Name = proptools.StringPtr(o.Name())
}

// Mutators for override/overridable modules. All the fun happens in these functions. It is critical
// to keep them in this order and not put any order mutators between them.
func RegisterOverridePreArchMutators(ctx RegisterMutatorsContext) {
	ctx.BottomUp("override_deps", overrideModuleDepsMutator).Parallel()
	ctx.TopDown("register_override", registerOverrideMutator).Parallel()
	ctx.BottomUp("perform_override", performOverrideMutator).Parallel()
}

type overrideBaseDependencyTag struct {
	blueprint.BaseDependencyTag
}

var overrideBaseDepTag overrideBaseDependencyTag

// Adds dependency on the base module to the overriding module so that they can be visited in the
// next phase.
func overrideModuleDepsMutator(ctx BottomUpMutatorContext) {
	if module, ok := ctx.Module().(OverrideModule); ok {
		ctx.AddDependency(ctx.Module(), overrideBaseDepTag, *module.getOverrideModuleProperties().Base)
	}
}

// Visits the base module added as a dependency above, checks the module type, and registers the
// overriding module.
func registerOverrideMutator(ctx TopDownMutatorContext) {
	ctx.VisitDirectDepsWithTag(overrideBaseDepTag, func(base Module) {
		if o, ok := base.(OverridableModule); ok {
			o.addOverride(ctx.Module().(OverrideModule))
		} else {
			ctx.PropertyErrorf("base", "unsupported base module type")
		}
	})
}

// Now, goes through all overridable modules, finds all modules overriding them, creates a local
// variant for each of them, and performs the actual overriding operation by calling override().
func performOverrideMutator(ctx BottomUpMutatorContext) {
	if b, ok := ctx.Module().(OverridableModule); ok {
		overrides := b.getOverrides()
		if len(overrides) == 0 {
			return
		}
		variants := make([]string, len(overrides)+1)
		// The first variant is for the original, non-overridden, base module.
		variants[0] = ""
		for i, o := range overrides {
			variants[i+1] = o.(Module).Name()
		}
		mods := ctx.CreateLocalVariations(variants...)
		for i, o := range overrides {
			mods[i+1].(OverridableModule).override(ctx, o)
		}
	}
}
+41 −8
Original line number Diff line number Diff line
@@ -33,16 +33,13 @@ func init() {
	android.RegisterModuleType("android_test", AndroidTestFactory)
	android.RegisterModuleType("android_test_helper_app", AndroidTestHelperAppFactory)
	android.RegisterModuleType("android_app_certificate", AndroidAppCertificateFactory)
	android.RegisterModuleType("override_android_app", OverrideAndroidAppModuleFactory)
}

// AndroidManifest.xml merging
// package splits

type appProperties struct {
	// The name of a certificate in the default certificate directory, blank to use the default product certificate,
	// or an android_app_certificate module name in the form ":module".
	Certificate *string

	// Names of extra android_app_certificate modules to sign the apk with in the form ":module".
	Additional_certificates []string

@@ -79,14 +76,24 @@ type appProperties struct {
	Use_embedded_dex *bool
}

// android_app properties that can be overridden by override_android_app
type overridableAppProperties struct {
	// The name of a certificate in the default certificate directory, blank to use the default product certificate,
	// or an android_app_certificate module name in the form ":module".
	Certificate *string
}

type AndroidApp struct {
	Library
	aapt
	android.OverridableModuleBase

	certificate Certificate

	appProperties appProperties

	overridableAppProperties overridableAppProperties

	installJniLibs []jniLib

	bundleFile android.Path
@@ -320,7 +327,7 @@ func (a *AndroidApp) certificateBuildActions(certificateDeps []Certificate, ctx

func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
	// Check if the install APK name needs to be overridden.
	a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(ctx.ModuleName())
	a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(a.Name())

	// Process all building blocks, from AAPT to certificates.
	a.aaptBuildActions(ctx)
@@ -339,6 +346,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
	certificates := a.certificateBuildActions(certificateDeps, ctx)

	// Build a final signed app package.
	// TODO(jungjw): Consider changing this to installApkName.
	packageFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".apk")
	CreateAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates)
	a.outputFile = packageFile
@@ -413,7 +421,7 @@ func (a *AndroidApp) getCertString(ctx android.BaseContext) string {
	if overridden {
		return ":" + certificate
	}
	return String(a.appProperties.Certificate)
	return String(a.overridableAppProperties.Certificate)
}

// android_app compiles sources and Android resources into an Android application package `.apk` file.
@@ -432,7 +440,8 @@ func AndroidAppFactory() android.Module {
		&module.Module.dexpreoptProperties,
		&module.Module.protoProperties,
		&module.aaptProperties,
		&module.appProperties)
		&module.appProperties,
		&module.overridableAppProperties)

	module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
		return class == android.Device && ctx.Config().DevicePrefer32BitApps()
@@ -440,6 +449,7 @@ func AndroidAppFactory() android.Module {

	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
	android.InitDefaultableModule(module)
	android.InitOverridableModule(module, &module.appProperties.Overrides)

	return module
}
@@ -503,6 +513,7 @@ func AndroidTestFactory() android.Module {
		&module.aaptProperties,
		&module.appProperties,
		&module.appTestProperties,
		&module.overridableAppProperties,
		&module.testProperties)

	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
@@ -541,7 +552,8 @@ func AndroidTestHelperAppFactory() android.Module {
		&module.Module.protoProperties,
		&module.aaptProperties,
		&module.appProperties,
		&module.appTestHelperAppProperties)
		&module.appTestHelperAppProperties,
		&module.overridableAppProperties)

	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
	android.InitDefaultableModule(module)
@@ -575,3 +587,24 @@ func (c *AndroidAppCertificate) GenerateAndroidBuildActions(ctx android.ModuleCo
		android.PathForModuleSrc(ctx, cert+".pk8"),
	}
}

type OverrideAndroidApp struct {
	android.ModuleBase
	android.OverrideModuleBase
}

func (i *OverrideAndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	// All the overrides happen in the base module.
	// TODO(jungjw): Check the base module type.
}

// override_android_app is used to create an android_app module based on another android_app by overriding
// some of its properties.
func OverrideAndroidAppModuleFactory() android.Module {
	m := &OverrideAndroidApp{}
	m.AddProperties(&overridableAppProperties{})

	android.InitAndroidModule(m)
	android.InitOverrideModule(m)
	return m
}
+72 −0
Original line number Diff line number Diff line
@@ -827,3 +827,75 @@ func TestInstrumentationTargetOverridden(t *testing.T) {
		t.Errorf("target package renaming flag, %q is missing in aapt2 link flags, %q", e, aapt2Flags)
	}
}

func TestOverrideAndroidApp(t *testing.T) {
	ctx := testJava(t, `
		android_app {
			name: "foo",
			srcs: ["a.java"],
			overrides: ["baz"],
		}

		override_android_app {
			name: "bar",
			base: "foo",
			certificate: ":new_certificate",
		}

		android_app_certificate {
			name: "new_certificate",
			certificate: "cert/new_cert",
		}
		`)

	expectedVariants := []struct {
		variantName string
		apkName     string
		apkPath     string
		signFlag    string
		overrides   []string
	}{
		{
			variantName: "android_common",
			apkPath:     "/target/product/test_device/system/app/foo/foo.apk",
			signFlag:    "build/target/product/security/testkey.x509.pem build/target/product/security/testkey.pk8",
			overrides:   []string{"baz"},
		},
		{
			variantName: "bar_android_common",
			apkPath:     "/target/product/test_device/system/app/bar/bar.apk",
			signFlag:    "cert/new_cert.x509.pem cert/new_cert.pk8",
			overrides:   []string{"baz", "foo"},
		},
	}
	for _, expected := range expectedVariants {
		variant := ctx.ModuleForTests("foo", expected.variantName)

		// Check the final apk name
		outputs := variant.AllOutputs()
		expectedApkPath := buildDir + expected.apkPath
		found := false
		for _, o := range outputs {
			if o == expectedApkPath {
				found = true
				break
			}
		}
		if !found {
			t.Errorf("Can't find %q in output files.\nAll outputs:%v", expectedApkPath, outputs)
		}

		// Check the certificate paths
		signapk := variant.Output("foo.apk")
		signFlag := signapk.Args["certificates"]
		if expected.signFlag != signFlag {
			t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected.signFlag, signFlag)
		}

		mod := variant.Module().(*AndroidApp)
		if !reflect.DeepEqual(expected.overrides, mod.appProperties.Overrides) {
			t.Errorf("Incorrect overrides property value, expected: %q, got: %q",
				expected.overrides, mod.appProperties.Overrides)
		}
	}
}
Loading