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

Commit 387ad5c5 authored by Jaewoong Jung's avatar Jaewoong Jung Committed by Gerrit Code Review
Browse files

Merge "Add rules to handle asset resources."

parents 86a5dc55 6431ca7a
Loading
Loading
Loading
Loading
+13 −2
Original line number Diff line number Diff line
@@ -121,8 +121,19 @@ func InList(s string, list []string) bool {
	return IndexList(s, list) != -1
}

func PrefixInList(s string, list []string) bool {
	for _, prefix := range list {
// Returns true if the given string s is prefixed with any string in the given prefix list.
func PrefixInList(s string, prefixList []string) bool {
	for _, prefix := range prefixList {
		if strings.HasPrefix(s, prefix) {
			return true
		}
	}
	return false
}

// Returns true if any string in the given list has the given prefix.
func PrefixedStringInList(list []string, prefix string) bool {
	for _, s := range list {
		if strings.HasPrefix(s, prefix) {
			return true
		}
+21 −2
Original line number Diff line number Diff line
@@ -147,10 +147,16 @@ var fileListToFileRule = pctx.AndroidStaticRule("fileListToFile",
		RspfileContent: "$in",
	})

var mergeAssetsRule = pctx.AndroidStaticRule("mergeAssets",
	blueprint.RuleParams{
		Command:     `${config.MergeZipsCmd} ${out} ${in}`,
		CommandDeps: []string{"${config.MergeZipsCmd}"},
	})

func aapt2Link(ctx android.ModuleContext,
	packageRes, genJar, proguardOptions, rTxt, extraPackages android.WritablePath,
	flags []string, deps android.Paths,
	compiledRes, compiledOverlay android.Paths, splitPackages android.WritablePaths) {
	compiledRes, compiledOverlay, assetPackages android.Paths, splitPackages android.WritablePaths) {

	genDir := android.PathForModuleGen(ctx, "aapt2", "R")

@@ -186,12 +192,25 @@ func aapt2Link(ctx android.ModuleContext,
	}

	implicitOutputs := append(splitPackages, proguardOptions, genJar, rTxt, extraPackages)
	linkOutput := packageRes

	// AAPT2 ignores assets in overlays. Merge them after linking.
	if len(assetPackages) > 0 {
		linkOutput = android.PathForModuleOut(ctx, "aapt2", "package-res.apk")
		inputZips := append(android.Paths{linkOutput}, assetPackages...)
		ctx.Build(pctx, android.BuildParams{
			Rule:        mergeAssetsRule,
			Inputs:      inputZips,
			Output:      packageRes,
			Description: "merge assets from dependencies",
		})
	}

	ctx.Build(pctx, android.BuildParams{
		Rule:            aapt2LinkRule,
		Description:     "aapt2 link",
		Implicits:       deps,
		Output:          packageRes,
		Output:          linkOutput,
		ImplicitOutputs: implicitOutputs,
		Args: map[string]string{
			"flags":           strings.Join(flags, " "),
+39 −6
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ type AndroidLibraryDependency interface {
	ExportedRRODirs() []rroDir
	ExportedStaticPackages() android.Paths
	ExportedManifests() android.Paths
	ExportedAssets() android.OptionalPath
}

func init() {
@@ -93,6 +94,7 @@ type aapt struct {
	extraAaptPackagesFile   android.Path
	mergedManifestFile      android.Path
	noticeFile              android.OptionalPath
	assetPackage            android.OptionalPath
	isLibrary               bool
	useEmbeddedNativeLibs   bool
	useEmbeddedDex          bool
@@ -124,6 +126,10 @@ func (a *aapt) ExportedManifests() android.Paths {
	return a.transitiveManifestPaths
}

func (a *aapt) ExportedAssets() android.OptionalPath {
	return a.assetPackage
}

func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext,
	manifestPath android.Path) (compileFlags, linkFlags []string, linkDeps android.Paths,
	resDirs, overlayDirs []globbedResourceDir, rroDirs []rroDir, resZips android.Paths) {
@@ -219,9 +225,15 @@ func (a *aapt) deps(ctx android.BottomUpMutatorContext, sdkDep sdkDep) {
	}
}

var extractAssetsRule = pctx.AndroidStaticRule("extractAssets",
	blueprint.RuleParams{
		Command:     `${config.Zip2ZipCmd} -i ${in} -o ${out} "assets/**/*"`,
		CommandDeps: []string{"${config.Zip2ZipCmd}"},
	})

func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, extraLinkFlags ...string) {

	transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, libDeps, libFlags, sdkLibraries :=
	transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assetPackages, libDeps, libFlags, sdkLibraries :=
		aaptLibs(ctx, sdkContext)

	// App manifest file
@@ -321,7 +333,20 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, ex
	}

	aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt, extraPackages,
		linkFlags, linkDeps, compiledRes, compiledOverlay, splitPackages)
		linkFlags, linkDeps, compiledRes, compiledOverlay, assetPackages, splitPackages)

	// Extract assets from the resource package output so that they can be used later in aapt2link
	// for modules that depend on this one.
	if android.PrefixedStringInList(linkFlags, "-A ") || len(assetPackages) > 0 {
		assets := android.PathForModuleOut(ctx, "assets.zip")
		ctx.Build(pctx, android.BuildParams{
			Rule:        extractAssetsRule,
			Input:       packageRes,
			Output:      assets,
			Description: "extract assets from built resource file",
		})
		a.assetPackage = android.OptionalPathForPath(assets)
	}

	a.aaptSrcJar = srcJar
	a.exportPackage = packageRes
@@ -335,7 +360,7 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, ex

// aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStaticLibs, transitiveStaticLibManifests android.Paths,
	staticRRODirs []rroDir, deps android.Paths, flags []string, sdkLibraries []string) {
	staticRRODirs []rroDir, assets, deps android.Paths, flags []string, sdkLibraries []string) {

	var sharedLibs android.Paths

@@ -373,6 +398,9 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati
				transitiveStaticLibs = append(transitiveStaticLibs, exportPackage)
				transitiveStaticLibManifests = append(transitiveStaticLibManifests, aarDep.ExportedManifests()...)
				sdkLibraries = append(sdkLibraries, aarDep.ExportedSdkLibs()...)
				if aarDep.ExportedAssets().Valid() {
					assets = append(assets, aarDep.ExportedAssets().Path())
				}

			outer:
				for _, d := range aarDep.ExportedRRODirs() {
@@ -402,7 +430,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati
	transitiveStaticLibManifests = android.FirstUniquePaths(transitiveStaticLibManifests)
	sdkLibraries = android.FirstUniqueStrings(sdkLibraries)

	return transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, deps, flags, sdkLibraries
	return transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assets, deps, flags, sdkLibraries
}

type AndroidLibrary struct {
@@ -572,6 +600,11 @@ func (a *AARImport) ExportedManifests() android.Paths {
	return android.Paths{a.manifest}
}

// TODO(jungjw): Decide whether we want to implement this.
func (a *AARImport) ExportedAssets() android.OptionalPath {
	return android.OptionalPath{}
}

func (a *AARImport) Prebuilt() *android.Prebuilt {
	return &a.prebuilt
}
@@ -660,7 +693,7 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	linkFlags = append(linkFlags, "--manifest "+a.manifest.String())
	linkDeps = append(linkDeps, a.manifest)

	transitiveStaticLibs, staticLibManifests, staticRRODirs, libDeps, libFlags, sdkLibraries :=
	transitiveStaticLibs, staticLibManifests, staticRRODirs, transitiveAssets, libDeps, libFlags, sdkLibraries :=
		aaptLibs(ctx, sdkContext(a))

	_ = staticLibManifests
@@ -673,7 +706,7 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	overlayRes := append(android.Paths{flata}, transitiveStaticLibs...)

	aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile, rTxt, a.extraAaptPackagesFile,
		linkFlags, linkDeps, nil, overlayRes, nil)
		linkFlags, linkDeps, nil, overlayRes, transitiveAssets, nil)
}

var _ Dependency = (*AARImport)(nil)
+101 −0
Original line number Diff line number Diff line
@@ -323,6 +323,107 @@ func TestResourceDirs(t *testing.T) {
	}
}

func TestLibraryAssets(t *testing.T) {
	bp := `
			android_app {
				name: "foo",
				sdk_version: "current",
				static_libs: ["lib1", "lib2", "lib3"],
			}

			android_library {
				name: "lib1",
				sdk_version: "current",
				asset_dirs: ["assets_a"],
			}

			android_library {
				name: "lib2",
				sdk_version: "current",
			}

			android_library {
				name: "lib3",
				sdk_version: "current",
				static_libs: ["lib4"],
			}

			android_library {
				name: "lib4",
				sdk_version: "current",
				asset_dirs: ["assets_b"],
			}
		`

	testCases := []struct {
		name          string
		assetFlag     string
		assetPackages []string
	}{
		{
			name: "foo",
			// lib1 has its own asset. lib3 doesn't have any, but provides lib4's transitively.
			assetPackages: []string{
				buildDir + "/.intermediates/foo/android_common/aapt2/package-res.apk",
				buildDir + "/.intermediates/lib1/android_common/assets.zip",
				buildDir + "/.intermediates/lib3/android_common/assets.zip",
			},
		},
		{
			name:      "lib1",
			assetFlag: "-A assets_a",
		},
		{
			name: "lib2",
		},
		{
			name: "lib3",
			assetPackages: []string{
				buildDir + "/.intermediates/lib3/android_common/aapt2/package-res.apk",
				buildDir + "/.intermediates/lib4/android_common/assets.zip",
			},
		},
		{
			name:      "lib4",
			assetFlag: "-A assets_b",
		},
	}
	ctx := testApp(t, bp)

	for _, test := range testCases {
		t.Run(test.name, func(t *testing.T) {
			m := ctx.ModuleForTests(test.name, "android_common")

			// Check asset flag in aapt2 link flags
			var aapt2link android.TestingBuildParams
			if len(test.assetPackages) > 0 {
				aapt2link = m.Output("aapt2/package-res.apk")
			} else {
				aapt2link = m.Output("package-res.apk")
			}
			aapt2Flags := aapt2link.Args["flags"]
			if test.assetFlag != "" {
				if !strings.Contains(aapt2Flags, test.assetFlag) {
					t.Errorf("Can't find asset flag %q in aapt2 link flags %q", test.assetFlag, aapt2Flags)
				}
			} else {
				if strings.Contains(aapt2Flags, " -A ") {
					t.Errorf("aapt2 link flags %q contain unexpected asset flag", aapt2Flags)
				}
			}

			// Check asset merge rule.
			if len(test.assetPackages) > 0 {
				mergeAssets := m.Output("package-res.apk")
				if !reflect.DeepEqual(test.assetPackages, mergeAssets.Inputs.Strings()) {
					t.Errorf("Unexpected mergeAssets inputs: %v, expected: %v",
						mergeAssets.Inputs.Strings(), test.assetPackages)
				}
			}
		})
	}
}

func TestAndroidResources(t *testing.T) {
	testCases := []struct {
		name                       string
+2 −0
Original line number Diff line number Diff line
@@ -49,6 +49,8 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string
		"api/test-current.txt":   nil,
		"api/test-removed.txt":   nil,
		"framework/aidl/a.aidl":  nil,
		"assets_a/a":             nil,
		"assets_b/b":             nil,

		"prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so": nil,