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

Commit 4d886189 authored by Spandan Das's avatar Spandan Das Committed by Gerrit Code Review
Browse files

Merge "Introduce module type to autogenerate RROS" into main

parents 5cb0cf40 e2f98da5
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ func init() {
	AddNeverAllowRules(createFilesystemIsAutoGeneratedRule())
	AddNeverAllowRules(createKotlinPluginRule()...)
	AddNeverAllowRules(createPrebuiltEtcBpDefineRule())
	AddNeverAllowRules(createAutogenRroBpDefineRule())
}

// Add a NeverAllow rule to the set of rules to apply.
@@ -345,6 +346,15 @@ func createPrebuiltEtcBpDefineRule() Rule {
		Because("module type not allowed to be defined in bp file")
}

func createAutogenRroBpDefineRule() Rule {
	return NeverAllow().
		ModuleType(
			"autogen_runtime_resource_overlay",
		).
		DefinedInBpFile().
		Because("Module type will be autogenerated by soong. Use runtime_resource_overlay instead")
}

func neverallowMutator(ctx BottomUpMutatorContext) {
	m, ok := ctx.Module().(Module)
	if !ok {
+85 −11
Original line number Diff line number Diff line
@@ -417,6 +417,25 @@ type aaptBuildActionOptions struct {
	extraLinkFlags                 []string
	aconfigTextFiles               android.Paths
	usesLibrary                    *usesLibrary
	// If rroDirs is provided, it will be used to generate package-res.apk
	rroDirs *android.Paths
	// If manifestForAapt is not nil, it will be used for aapt instead of the default source manifest.
	manifestForAapt android.Path
}

func filterRRO(rroDirsDepSet depset.DepSet[rroDir], filter overlayType) android.Paths {
	var paths android.Paths
	seen := make(map[android.Path]bool)
	for _, d := range rroDirsDepSet.ToList() {
		if d.overlayType == filter {
			if seen[d.path] {
				continue
			}
			seen[d.path] = true
			paths = append(paths, d.path)
		}
	}
	return paths
}

func (a *aapt) buildActions(ctx android.ModuleContext, opts aaptBuildActionOptions) {
@@ -428,10 +447,15 @@ func (a *aapt) buildActions(ctx android.ModuleContext, opts aaptBuildActionOptio
	opts.classLoaderContexts = opts.classLoaderContexts.ExcludeLibs(opts.excludedLibs)

	// App manifest file
	var manifestFilePath android.Path
	if opts.manifestForAapt != nil {
		manifestFilePath = opts.manifestForAapt
	} else {
		manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
	manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile)
		manifestFilePath = android.PathForModuleSrc(ctx, manifestFile)
	}

	manifestPath := ManifestFixer(ctx, manifestSrcPath, ManifestFixerParams{
	manifestPath := ManifestFixer(ctx, manifestFilePath, ManifestFixerParams{
		SdkContext:                     opts.sdkContext,
		ClassLoaderContexts:            opts.classLoaderContexts,
		IsLibrary:                      a.isLibrary,
@@ -472,6 +496,10 @@ func (a *aapt) buildActions(ctx android.ModuleContext, opts aaptBuildActionOptio

	compileFlags, linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resZips := a.aapt2Flags(ctx, opts.sdkContext, manifestPath)

	a.rroDirsDepSet = depset.NewBuilder[rroDir](depset.TOPOLOGICAL).
		Direct(rroDirs...).
		Transitive(staticRRODirsDepSet).Build()

	linkFlags = append(linkFlags, libFlags...)
	linkDeps = append(linkDeps, sharedExportPackages...)
	linkDeps = append(linkDeps, staticDeps.resPackages()...)
@@ -565,6 +593,11 @@ func (a *aapt) buildActions(ctx android.ModuleContext, opts aaptBuildActionOptio
			compileFlags, a.filterProduct(), opts.aconfigTextFiles).Paths()...)
	}

	var compiledRro, compiledRroOverlay android.Paths
	if opts.rroDirs != nil {
		compiledRro, compiledRroOverlay = a.compileResInDir(ctx, *opts.rroDirs, compileFlags, opts.aconfigTextFiles)
	}

	var splitPackages android.WritablePaths
	var splits []split

@@ -591,10 +624,20 @@ func (a *aapt) buildActions(ctx android.ModuleContext, opts aaptBuildActionOptio
	if !a.isLibrary {
		transitiveAssets = android.ReverseSliceInPlace(staticDeps.assets())
	}
	if opts.rroDirs == nil { // link resources and overlay
		aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt,
			linkFlags, linkDeps, compiledRes, compiledOverlay, transitiveAssets, splitPackages,
			opts.aconfigTextFiles)
		ctx.CheckbuildFile(packageRes)
	} else { // link autogenerated rro
		if len(compiledRro) == 0 {
			return
		}
		aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt,
			linkFlags, linkDeps, compiledRro, compiledRroOverlay, nil, nil,
			opts.aconfigTextFiles)
		ctx.CheckbuildFile(packageRes)
	}

	// Extract assets from the resource package output so that they can be used later in aapt2link
	// for modules that depend on this one.
@@ -652,15 +695,46 @@ func (a *aapt) buildActions(ctx android.ModuleContext, opts aaptBuildActionOptio
			usedResourceProcessor: a.useResourceProcessorBusyBox(ctx),
		}).
		Transitive(staticResourcesNodesDepSet).Build()
	a.rroDirsDepSet = depset.NewBuilder[rroDir](depset.TOPOLOGICAL).
		Direct(rroDirs...).
		Transitive(staticRRODirsDepSet).Build()
	a.manifestsDepSet = depset.NewBuilder[android.Path](depset.TOPOLOGICAL).
		Direct(a.manifestPath).
		DirectSlice(additionalManifests).
		Transitive(staticManifestsDepSet).Build()
}

// comileResInDir finds the resource files in dirs by globbing and then compiles them using aapt2
// returns the file paths of compiled resources
// dirs[0] is used as compileRes
// dirs[1:] is used as compileOverlay
func (a *aapt) compileResInDir(ctx android.ModuleContext, dirs android.Paths, compileFlags []string, aconfig android.Paths) (android.Paths, android.Paths) {
	filesInDir := func(dir android.Path) android.Paths {
		files, err := ctx.GlobWithDeps(filepath.Join(dir.String(), "**/*"), androidResourceIgnoreFilenames)
		if err != nil {
			ctx.ModuleErrorf("failed to glob overlay resource dir %q: %s", dir, err.Error())
			return nil
		}
		var filePaths android.Paths
		for _, file := range files {
			if strings.HasSuffix(file, "/") {
				continue // ignore directories
			}
			filePaths = append(filePaths, android.PathForSource(ctx, file))
		}
		return filePaths
	}

	var compiledRes, compiledOverlay android.Paths
	if len(dirs) == 0 {
		return nil, nil
	}
	compiledRes = append(compiledRes, aapt2Compile(ctx, dirs[0], filesInDir(dirs[0]), compileFlags, a.filterProduct(), aconfig).Paths()...)
	if len(dirs) > 0 {
		for _, dir := range dirs[1:] {
			compiledOverlay = append(compiledOverlay, aapt2Compile(ctx, dir, filesInDir(dir), compileFlags, a.filterProduct(), aconfig).Paths()...)
		}
	}
	return compiledRes, compiledOverlay
}

var resourceProcessorBusyBox = pctx.AndroidStaticRule("resourceProcessorBusyBox",
	blueprint.RuleParams{
		Command: "${config.JavaCmd} -cp ${config.ResourceProcessorBusyBox} " +
@@ -805,7 +879,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext,
		switch depTag {
		case instrumentationForTag:
			// Nothing, instrumentationForTag is treated as libTag for javac but not for aapt2.
		case sdkLibTag, libTag:
		case sdkLibTag, libTag, rroDepTag:
			if exportPackage != nil {
				sharedResourcesNodeDepSets = append(sharedResourcesNodeDepSets, aarDep.ResourcesNodeDepSet())
				sharedLibs = append(sharedLibs, exportPackage)
+18 −0
Original line number Diff line number Diff line
@@ -425,6 +425,24 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
	}
}

func (a *AutogenRuntimeResourceOverlay) AndroidMkEntries() []android.AndroidMkEntries {
	if a.IsHideFromMake() || a.outputFile == nil {
		return []android.AndroidMkEntries{android.AndroidMkEntries{
			Disabled: true,
		}}
	}
	return []android.AndroidMkEntries{android.AndroidMkEntries{
		Class:      "APPS",
		OutputFile: android.OptionalPathForPath(a.outputFile),
		Include:    "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
				entries.SetString("LOCAL_CERTIFICATE", "presigned") // The apk will be signed by soong
			},
		},
	}}
}

func (a *AndroidApp) getOverriddenPackages() []string {
	var overridden []string
	if len(a.overridableAppProperties.Overrides) > 0 {
+144 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ package java
import (
	"android/soong/android"

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

@@ -29,6 +30,7 @@ func init() {

func RegisterRuntimeResourceOverlayBuildComponents(ctx android.RegistrationContext) {
	ctx.RegisterModuleType("runtime_resource_overlay", RuntimeResourceOverlayFactory)
	ctx.RegisterModuleType("autogen_runtime_resource_overlay", AutogenRuntimeResourceOverlayFactory)
	ctx.RegisterModuleType("override_runtime_resource_overlay", OverrideRuntimeResourceOverlayModuleFactory)
}

@@ -269,3 +271,145 @@ func OverrideRuntimeResourceOverlayModuleFactory() android.Module {
	android.InitOverrideModule(m)
	return m
}

var (
	generateOverlayManifestFile = pctx.AndroidStaticRule("generate_overlay_manifest",
		blueprint.RuleParams{
			Command: "build/make/tools/generate-enforce-rro-android-manifest.py " +
				"--package-info $in " +
				"--partition ${partition} " +
				"--priority ${priority} -o $out",
			CommandDeps: []string{"build/make/tools/generate-enforce-rro-android-manifest.py"},
		}, "partition", "priority",
	)
)

type AutogenRuntimeResourceOverlay struct {
	android.ModuleBase
	aapt

	properties AutogenRuntimeResourceOverlayProperties

	outputFile android.Path
}

type AutogenRuntimeResourceOverlayProperties struct {
	Base        *string
	Sdk_version *string
	Manifest    *string `android:"path"`
}

func AutogenRuntimeResourceOverlayFactory() android.Module {
	m := &AutogenRuntimeResourceOverlay{}
	m.AddProperties(&m.properties)
	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)

	return m
}

type rroDependencyTag struct {
	blueprint.DependencyTag
}

// Autogenerated RROs should always depend on the source android_app that created it.
func (tag rroDependencyTag) ReplaceSourceWithPrebuilt() bool {
	return false
}

var rroDepTag = rroDependencyTag{}

func (a *AutogenRuntimeResourceOverlay) DepsMutator(ctx android.BottomUpMutatorContext) {
	sdkDep := decodeSdkDep(ctx, android.SdkContext(a))
	if sdkDep.hasFrameworkLibs() {
		a.aapt.deps(ctx, sdkDep)
	}
	ctx.AddDependency(ctx.Module(), rroDepTag, proptools.String(a.properties.Base))
}

func (a *AutogenRuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	if !a.Enabled(ctx) {
		return
	}
	var rroDirs android.Paths
	// Get rro dirs of the base app
	ctx.VisitDirectDepsWithTag(rroDepTag, func(m android.Module) {
		aarDep, _ := m.(AndroidLibraryDependency)
		if ctx.InstallInProduct() {
			rroDirs = filterRRO(aarDep.RRODirsDepSet(), product)
		} else {
			rroDirs = filterRRO(aarDep.RRODirsDepSet(), device)
		}
	})

	if len(rroDirs) == 0 {
		return
	}

	// Generate a manifest file
	genManifest := android.PathForModuleGen(ctx, "AndroidManifest.xml")
	partition := "vendor"
	priority := "0"
	if ctx.InstallInProduct() {
		partition = "product"
		priority = "1"
	}
	ctx.Build(pctx, android.BuildParams{
		Rule:   generateOverlayManifestFile,
		Input:  android.PathForModuleSrc(ctx, proptools.String(a.properties.Manifest)),
		Output: genManifest,
		Args: map[string]string{
			"partition": partition,
			"priority":  priority,
		},
	})

	// Compile and link resources into package-res.apk
	a.aapt.hasNoCode = true
	aaptLinkFlags := []string{"--auto-add-overlay", "--keep-raw-values", "--no-resource-deduping", "--no-resource-removal"}

	a.aapt.buildActions(ctx,
		aaptBuildActionOptions{
			sdkContext:      a,
			extraLinkFlags:  aaptLinkFlags,
			rroDirs:         &rroDirs,
			manifestForAapt: genManifest,
		},
	)

	if a.exportPackage == nil {
		return
	}
	// Sign the built package
	_, certificates := processMainCert(a.ModuleBase, "", nil, ctx)
	signed := android.PathForModuleOut(ctx, "signed", a.Name()+".apk")
	SignAppPackage(ctx, signed, a.exportPackage, certificates, nil, nil, "")
	a.outputFile = signed

	// Install the signed apk
	installDir := android.PathForModuleInstall(ctx, "overlay")
	ctx.InstallFile(installDir, signed.Base(), signed)
}

func (a *AutogenRuntimeResourceOverlay) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
	return android.SdkSpecFrom(ctx, String(a.properties.Sdk_version))
}

func (a *AutogenRuntimeResourceOverlay) SystemModules() string {
	return ""
}

func (a *AutogenRuntimeResourceOverlay) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
	return a.SdkVersion(ctx).ApiLevel
}

func (r *AutogenRuntimeResourceOverlay) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel {
	return android.SdkSpecPrivate.ApiLevel
}

func (a *AutogenRuntimeResourceOverlay) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
	return a.SdkVersion(ctx).ApiLevel
}

func (a *AutogenRuntimeResourceOverlay) InstallInProduct() bool {
	return a.ProductSpecific()
}