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

Commit 5b425e2e authored by Jaewoong Jung's avatar Jaewoong Jung
Browse files

Optionally embed NOTICE files in apks.

If embed_notices or ALWAYS_EMBED_NOTICES is set, collect NOTICE files
from all dependencies of the android_app, merge them with the app's own
one (if exists), transform it to HTML, gzip it, and put it as an asset
in the final APK output.

Bug: 135460391
Test: app_test.go
Change-Id: I52d92e2fd19b3f5f396100424665c5cc344190d8
parent 0b4ca860
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ bootstrap_go_package {
        "android/mutator.go",
        "android/namespace.go",
        "android/neverallow.go",
        "android/notices.go",
        "android/onceper.go",
        "android/override_module.go",
        "android/package_ctx.go",
+8 −8
Original line number Diff line number Diff line
@@ -901,14 +901,6 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
	}

	if m.Enabled() {
		m.module.GenerateAndroidBuildActions(ctx)
		if ctx.Failed() {
			return
		}

		m.installFiles = append(m.installFiles, ctx.installFiles...)
		m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...)

		notice := proptools.StringDefault(m.commonProperties.Notice, "NOTICE")
		if module := SrcIsModule(notice); module != "" {
			m.noticeFile = ctx.ExpandOptionalSource(&notice, "notice")
@@ -916,6 +908,14 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
			noticePath := filepath.Join(ctx.ModuleDir(), notice)
			m.noticeFile = ExistentPathForSource(ctx, noticePath)
		}

		m.module.GenerateAndroidBuildActions(ctx)
		if ctx.Failed() {
			return
		}

		m.installFiles = append(m.installFiles, ctx.installFiles...)
		m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...)
	} else if ctx.Config().AllowMissingDependencies() {
		// If the module is not enabled it will not create any build rules, nothing will call
		// ctx.GetMissingDependencies(), and blueprint will consider the missing dependencies to be unhandled

android/notices.go

0 → 100644
+87 −0
Original line number Diff line number Diff line
// Copyright 2019 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 (
	"path/filepath"

	"github.com/google/blueprint"
)

func init() {
	pctx.SourcePathVariable("merge_notices", "build/soong/scripts/mergenotice.py")
	pctx.SourcePathVariable("generate_notice", "build/make/tools/generate-notice-files.py")

	pctx.HostBinToolVariable("minigzip", "minigzip")
}

var (
	mergeNoticesRule = pctx.AndroidStaticRule("mergeNoticesRule", blueprint.RuleParams{
		Command:     `${merge_notices} --output $out $in`,
		CommandDeps: []string{"${merge_notices}"},
		Description: "merge notice files into $out",
	})

	generateNoticeRule = pctx.AndroidStaticRule("generateNoticeRule", blueprint.RuleParams{
		Command: `rm -rf $tmpDir $$(dirname $out) && ` +
			`mkdir -p $tmpDir $$(dirname $out) && ` +
			`${generate_notice} --text-output $tmpDir/NOTICE.txt --html-output $tmpDir/NOTICE.html -t "$title" -s $inputDir && ` +
			`${minigzip} -c $tmpDir/NOTICE.html > $out`,
		CommandDeps: []string{"${generate_notice}", "${minigzip}"},
		Description: "produce notice file $out",
	}, "tmpDir", "title", "inputDir")
)

func MergeNotices(ctx ModuleContext, mergedNotice WritablePath, noticePaths []Path) {
	ctx.Build(pctx, BuildParams{
		Rule:        mergeNoticesRule,
		Description: "merge notices",
		Inputs:      noticePaths,
		Output:      mergedNotice,
	})
}

func BuildNoticeOutput(ctx ModuleContext, installPath OutputPath, installFilename string,
	noticePaths []Path) ModuleOutPath {
	// Merge all NOTICE files into one.
	// TODO(jungjw): We should just produce a well-formatted NOTICE.html file in a single pass.
	//
	// generate-notice-files.py, which processes the merged NOTICE file, has somewhat strict rules
	// about input NOTICE file paths.
	// 1. Their relative paths to the src root become their NOTICE index titles. We want to use
	// on-device paths as titles, and so output the merged NOTICE file the corresponding location.
	// 2. They must end with .txt extension. Otherwise, they're ignored.
	noticeRelPath := InstallPathToOnDevicePath(ctx, installPath.Join(ctx, installFilename+".txt"))
	mergedNotice := PathForModuleOut(ctx, filepath.Join("NOTICE_FILES/src", noticeRelPath))
	MergeNotices(ctx, mergedNotice, noticePaths)

	// Transform the merged NOTICE file into a gzipped HTML file.
	noticeOutput := PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
	tmpDir := PathForModuleOut(ctx, "NOTICE_tmp")
	title := "Notices for " + ctx.ModuleName()
	ctx.Build(pctx, BuildParams{
		Rule:        generateNoticeRule,
		Description: "generate notice output",
		Input:       mergedNotice,
		Output:      noticeOutput,
		Args: map[string]string{
			"tmpDir":   tmpDir.String(),
			"title":    title,
			"inputDir": PathForModuleOut(ctx, "NOTICE_FILES/src").String(),
		},
	})

	return noticeOutput
}
+1 −19
Original line number Diff line number Diff line
@@ -90,12 +90,6 @@ var (
		CommandDeps: []string{"${zip2zip}"},
		Description: "app bundle",
	}, "abi")

	apexMergeNoticeRule = pctx.StaticRule("apexMergeNoticeRule", blueprint.RuleParams{
		Command:     `${mergenotice} --output $out $inputs`,
		CommandDeps: []string{"${mergenotice}"},
		Description: "merge notice files into $out",
	}, "inputs")
)

var imageApexSuffix = ".apex"
@@ -144,8 +138,6 @@ func init() {
	pctx.HostBinToolVariable("zip2zip", "zip2zip")
	pctx.HostBinToolVariable("zipalign", "zipalign")

	pctx.SourcePathVariable("mergenotice", "build/soong/scripts/mergenotice.py")

	android.RegisterModuleType("apex", apexBundleFactory)
	android.RegisterModuleType("apex_test", testApexBundleFactory)
	android.RegisterModuleType("apex_defaults", defaultsFactory)
@@ -853,32 +845,22 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {

func (a *apexBundle) buildNoticeFile(ctx android.ModuleContext) {
	noticeFiles := []android.Path{}
	noticeFilesString := []string{}
	for _, f := range a.filesInfo {
		if f.module != nil {
			notice := f.module.NoticeFile()
			if notice.Valid() {
				noticeFiles = append(noticeFiles, notice.Path())
				noticeFilesString = append(noticeFilesString, notice.Path().String())
			}
		}
	}
	// append the notice file specified in the apex module itself
	if a.NoticeFile().Valid() {
		noticeFiles = append(noticeFiles, a.NoticeFile().Path())
		noticeFilesString = append(noticeFilesString, a.NoticeFile().Path().String())
	}

	if len(noticeFiles) > 0 {
		a.mergedNoticeFile = android.PathForModuleOut(ctx, "NOTICE")
		ctx.Build(pctx, android.BuildParams{
			Rule:   apexMergeNoticeRule,
			Inputs: noticeFiles,
			Output: a.mergedNoticeFile,
			Args: map[string]string{
				"inputs": strings.Join(noticeFilesString, " "),
			},
		})
		android.MergeNotices(ctx, a.mergedNoticeFile, noticeFiles)
	}
}

+4 −4
Original line number Diff line number Diff line
@@ -347,10 +347,10 @@ func TestBasicApex(t *testing.T) {
		t.Errorf("Could not find all expected symlinks! foo: %t, foo_link_64: %t. Command was %s", found_foo, found_foo_link_64, copyCmds)
	}

	apexMergeNoticeRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexMergeNoticeRule")
	noticeInputs := strings.Split(apexMergeNoticeRule.Args["inputs"], " ")
	if len(noticeInputs) != 3 {
		t.Errorf("number of input notice files: expected = 3, actual = %d", len(noticeInputs))
	mergeNoticesRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("mergeNoticesRule")
	noticeInputs := mergeNoticesRule.Inputs.Strings()
	if len(noticeInputs) != 4 {
		t.Errorf("number of input notice files: expected = 4, actual = %q", len(noticeInputs))
	}
	ensureListContains(t, noticeInputs, "NOTICE")
	ensureListContains(t, noticeInputs, "custom_notice")
Loading