Merge "Allowlist sdkextensions proto lib"
diff --git a/OWNERS b/OWNERS
index 3a5a8a7..e851bf7 100644
--- a/OWNERS
+++ b/OWNERS
@@ -11,10 +11,8 @@
joeo@google.com
jungjw@google.com
lberki@google.com
-patricearruda@google.com
ruperts@google.com
# To expedite LON reviews
hansson@google.com
paulduffin@google.com
-
diff --git a/android/Android.bp b/android/Android.bp
index f8c1d55..69aa037 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -30,6 +30,9 @@
"filegroup.go",
"hooks.go",
"image.go",
+ "license.go",
+ "license_kind.go",
+ "licenses.go",
"makefile_goal.go",
"makevars.go",
"metrics.go",
@@ -77,6 +80,9 @@
"depset_test.go",
"deptag_test.go",
"expand_test.go",
+ "license_kind_test.go",
+ "license_test.go",
+ "licenses_test.go",
"module_test.go",
"mutator_test.go",
"namespace_test.go",
diff --git a/android/androidmk.go b/android/androidmk.go
index 73f60d0..5856851 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -28,6 +28,7 @@
"io/ioutil"
"os"
"path/filepath"
+ "reflect"
"sort"
"strings"
@@ -434,6 +435,17 @@
return generateDistContributionsForMake(distContributions)
}
+// Write the license variables to Make for AndroidMkData.Custom(..) methods that do not call WriteAndroidMkData(..)
+// It's required to propagate the license metadata even for module types that have non-standard interfaces to Make.
+func (a *AndroidMkEntries) WriteLicenseVariables(w io.Writer) {
+ fmt.Fprintln(w, "LOCAL_LICENSE_KINDS :=", strings.Join(a.EntryMap["LOCAL_LICENSE_KINDS"], " "))
+ fmt.Fprintln(w, "LOCAL_LICENSE_CONDITIONS :=", strings.Join(a.EntryMap["LOCAL_LICENSE_CONDITIONS"], " "))
+ fmt.Fprintln(w, "LOCAL_NOTICE_FILE :=", strings.Join(a.EntryMap["LOCAL_NOTICE_FILE"], " "))
+ if pn, ok := a.EntryMap["LOCAL_LICENSE_PACKAGE_NAME"]; ok {
+ fmt.Fprintln(w, "LOCAL_LICENSE_PACKAGE_NAME :=", strings.Join(pn, " "))
+ }
+}
+
// fillInEntries goes through the common variable processing and calls the extra data funcs to
// generate and fill in AndroidMkEntries's in-struct data, ready to be flushed to a file.
func (a *AndroidMkEntries) fillInEntries(config Config, bpPath string, mod blueprint.Module) {
@@ -460,6 +472,13 @@
// Collect make variable assignment entries.
a.SetString("LOCAL_PATH", filepath.Dir(bpPath))
a.SetString("LOCAL_MODULE", name+a.SubName)
+ a.AddStrings("LOCAL_LICENSE_KINDS", amod.commonProperties.Effective_license_kinds...)
+ a.AddStrings("LOCAL_LICENSE_CONDITIONS", amod.commonProperties.Effective_license_conditions...)
+ a.AddStrings("LOCAL_NOTICE_FILE", amod.commonProperties.Effective_license_text...)
+ // TODO(b/151177513): Does this code need to set LOCAL_MODULE_IS_CONTAINER ?
+ if amod.commonProperties.Effective_package_name != nil {
+ a.SetString("LOCAL_LICENSE_PACKAGE_NAME", *amod.commonProperties.Effective_package_name)
+ }
a.SetString("LOCAL_MODULE_CLASS", a.Class)
a.SetString("LOCAL_PREBUILT_MODULE_FILE", a.OutputFile.String())
a.AddStrings("LOCAL_REQUIRED_MODULES", a.Required...)
@@ -682,6 +701,7 @@
}
}()
+ // Additional cases here require review for correct license propagation to make.
switch x := mod.(type) {
case AndroidMkDataProvider:
return translateAndroidModule(ctx, w, mod, x)
@@ -690,6 +710,7 @@
case AndroidMkEntriesProvider:
return translateAndroidMkEntriesModule(ctx, w, mod, x)
default:
+ // Not exported to make so no make variables to set.
return nil
}
}
@@ -703,6 +724,10 @@
fmt.Fprintln(w, ".PHONY:", name)
fmt.Fprintln(w, name+":", goBinary.InstallPath())
fmt.Fprintln(w, "")
+ // Assuming no rules in make include go binaries in distributables.
+ // If the assumption is wrong, make will fail to build without the necessary .meta_lic and .meta_module files.
+ // In that case, add the targets and rules here to build a .meta_lic file for `name` and a .meta_module for
+ // `goBinary.InstallPath()` pointing to the `name`.meta_lic file.
return nil
}
@@ -768,6 +793,25 @@
blueprintDir := filepath.Dir(ctx.BlueprintFile(mod))
if data.Custom != nil {
+ // List of module types allowed to use .Custom(...)
+ // Additions to the list require careful review for proper license handling.
+ switch reflect.TypeOf(mod).String() { // ctx.ModuleType(mod) doesn't work: aidl_interface creates phony without type
+ case "*aidl.aidlApi": // writes non-custom before adding .phony
+ case "*aidl.aidlMapping": // writes non-custom before adding .phony
+ case "*android.customModule": // appears in tests only
+ case "*apex.apexBundle": // license properties written
+ case "*bpf.bpf": // license properties written (both for module and objs)
+ case "*genrule.Module": // writes non-custom before adding .phony
+ case "*java.SystemModules": // doesn't go through base_rules
+ case "*java.systemModulesImport": // doesn't go through base_rules
+ case "*phony.phony": // license properties written
+ case "*selinux.selinuxContextsModule": // license properties written
+ case "*sysprop.syspropLibrary": // license properties written
+ default:
+ if ctx.Config().IsEnvTrue("ANDROID_REQUIRE_LICENSES") {
+ return fmt.Errorf("custom make rules not allowed for %q (%q) module %q", ctx.ModuleType(mod), reflect.TypeOf(mod), ctx.ModuleName(mod))
+ }
+ }
data.Custom(w, name, prefix, blueprintDir, data)
} else {
WriteAndroidMkData(w, data)
@@ -804,6 +848,7 @@
return nil
}
+ // Any new or special cases here need review to verify correct propagation of license information.
for _, entries := range provider.AndroidMkEntries() {
entries.fillInEntries(ctx.Config(), ctx.BlueprintFile(mod), mod)
entries.write(w)
diff --git a/android/config.go b/android/config.go
index 58372ec..ddb2de3 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1053,6 +1053,10 @@
return String(c.config.productVariables.DeviceVndkVersion)
}
+func (c *deviceConfig) RecoverySnapshotVersion() string {
+ return String(c.config.productVariables.RecoverySnapshotVersion)
+}
+
func (c *deviceConfig) CurrentApiLevelForVendorModules() string {
return StringDefault(c.config.productVariables.DeviceCurrentApiLevelForVendorModules, "current")
}
diff --git a/android/defaults.go b/android/defaults.go
index 44753ce..aacfbac 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -204,6 +204,9 @@
// its checking phase and parsing phase so add it to the list as a normal property.
AddVisibilityProperty(module, "visibility", &commonProperties.Visibility)
+ // The applicable licenses property for defaults is 'licenses'.
+ setPrimaryLicensesProperty(module, "licenses", &commonProperties.Licenses)
+
base.module = module
}
diff --git a/android/license.go b/android/license.go
new file mode 100644
index 0000000..b140b55
--- /dev/null
+++ b/android/license.go
@@ -0,0 +1,82 @@
+// Copyright 2020 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 (
+ "github.com/google/blueprint"
+)
+
+type licenseKindDependencyTag struct {
+ blueprint.BaseDependencyTag
+}
+
+var (
+ licenseKindTag = licenseKindDependencyTag{}
+)
+
+func init() {
+ RegisterLicenseBuildComponents(InitRegistrationContext)
+}
+
+// Register the license module type.
+func RegisterLicenseBuildComponents(ctx RegistrationContext) {
+ ctx.RegisterModuleType("license", LicenseFactory)
+}
+
+type licenseProperties struct {
+ // Specifies the kinds of license that apply.
+ License_kinds []string
+ // Specifies a short copyright notice to use for the license.
+ Copyright_notice *string
+ // Specifies the path or label for the text of the license.
+ License_text []string `android:"path"`
+ // Specifies the package name to which the license applies.
+ Package_name *string
+ // Specifies where this license can be used
+ Visibility []string
+}
+
+type licenseModule struct {
+ ModuleBase
+ DefaultableModuleBase
+
+ properties licenseProperties
+}
+
+func (m *licenseModule) DepsMutator(ctx BottomUpMutatorContext) {
+ ctx.AddVariationDependencies(nil, licenseKindTag, m.properties.License_kinds...)
+}
+
+func (m *licenseModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ // Nothing to do.
+}
+
+func LicenseFactory() Module {
+ module := &licenseModule{}
+
+ base := module.base()
+ module.AddProperties(&base.nameProperties, &module.properties)
+
+ base.generalProperties = module.GetProperties()
+ base.customizableProperties = module.GetProperties()
+
+ // The visibility property needs to be checked and parsed by the visibility module.
+ setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
+
+ initAndroidModuleBase(module)
+ InitDefaultableModule(module)
+
+ return module
+}
diff --git a/android/license_kind.go b/android/license_kind.go
new file mode 100644
index 0000000..ddecd77
--- /dev/null
+++ b/android/license_kind.go
@@ -0,0 +1,66 @@
+// Copyright 2020 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
+
+func init() {
+ RegisterLicenseKindBuildComponents(InitRegistrationContext)
+}
+
+// Register the license_kind module type.
+func RegisterLicenseKindBuildComponents(ctx RegistrationContext) {
+ ctx.RegisterModuleType("license_kind", LicenseKindFactory)
+}
+
+type licenseKindProperties struct {
+ // Specifies the conditions for all licenses of the kind.
+ Conditions []string
+ // Specifies the url to the canonical license definition.
+ Url string
+ // Specifies where this license can be used
+ Visibility []string
+}
+
+type licenseKindModule struct {
+ ModuleBase
+ DefaultableModuleBase
+
+ properties licenseKindProperties
+}
+
+func (m *licenseKindModule) DepsMutator(ctx BottomUpMutatorContext) {
+ // Nothing to do.
+}
+
+func (m *licenseKindModule) GenerateAndroidBuildActions(ModuleContext) {
+ // Nothing to do.
+}
+
+func LicenseKindFactory() Module {
+ module := &licenseKindModule{}
+
+ base := module.base()
+ module.AddProperties(&base.nameProperties, &module.properties)
+
+ base.generalProperties = module.GetProperties()
+ base.customizableProperties = module.GetProperties()
+
+ // The visibility property needs to be checked and parsed by the visibility module.
+ setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
+
+ initAndroidModuleBase(module)
+ InitDefaultableModule(module)
+
+ return module
+}
diff --git a/android/license_kind_test.go b/android/license_kind_test.go
new file mode 100644
index 0000000..767b64e
--- /dev/null
+++ b/android/license_kind_test.go
@@ -0,0 +1,174 @@
+package android
+
+import (
+ "testing"
+
+ "github.com/google/blueprint"
+)
+
+var licenseKindTests = []struct {
+ name string
+ fs map[string][]byte
+ expectedErrors []string
+}{
+ {
+ name: "license_kind must not accept licenses property",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ license_kind {
+ name: "top_license",
+ licenses: ["other_license"],
+ }`),
+ },
+ expectedErrors: []string{
+ `top/Blueprints:4:14: unrecognized property "licenses"`,
+ },
+ },
+ {
+ name: "bad license_kind",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ license_kind {
+ name: "top_notice",
+ conditions: ["notice"],
+ }`),
+ "other/Blueprints": []byte(`
+ mock_license {
+ name: "other_notice",
+ license_kinds: ["notice"],
+ }`),
+ },
+ expectedErrors: []string{
+ `other/Blueprints:2:5: "other_notice" depends on undefined module "notice"`,
+ },
+ },
+ {
+ name: "good license kind",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ license_kind {
+ name: "top_by_exception_only",
+ conditions: ["by_exception_only"],
+ }
+
+ mock_license {
+ name: "top_proprietary",
+ license_kinds: ["top_by_exception_only"],
+ }`),
+ "other/Blueprints": []byte(`
+ mock_license {
+ name: "other_proprietary",
+ license_kinds: ["top_proprietary"],
+ }`),
+ },
+ },
+ {
+ name: "multiple license kinds",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ license_kind {
+ name: "top_notice",
+ conditions: ["notice"],
+ }
+
+ license_kind {
+ name: "top_by_exception_only",
+ conditions: ["by_exception_only"],
+ }
+
+ mock_license {
+ name: "top_allowed_as_notice",
+ license_kinds: ["top_notice"],
+ }
+
+ mock_license {
+ name: "top_proprietary",
+ license_kinds: ["top_by_exception_only"],
+ }`),
+ "other/Blueprints": []byte(`
+ mock_license {
+ name: "other_rule",
+ license_kinds: ["top_by_exception_only"],
+ }`),
+ },
+ },
+}
+
+func TestLicenseKind(t *testing.T) {
+ for _, test := range licenseKindTests {
+ t.Run(test.name, func(t *testing.T) {
+ _, errs := testLicenseKind(test.fs)
+
+ expectedErrors := test.expectedErrors
+ if expectedErrors == nil {
+ FailIfErrored(t, errs)
+ } else {
+ for _, expectedError := range expectedErrors {
+ FailIfNoMatchingErrors(t, expectedError, errs)
+ }
+ if len(errs) > len(expectedErrors) {
+ t.Errorf("additional errors found, expected %d, found %d", len(expectedErrors), len(errs))
+ for i, expectedError := range expectedErrors {
+ t.Errorf("expectedErrors[%d] = %s", i, expectedError)
+ }
+ for i, err := range errs {
+ t.Errorf("errs[%d] = %s", i, err)
+ }
+ }
+ }
+ })
+ }
+}
+
+func testLicenseKind(fs map[string][]byte) (*TestContext, []error) {
+
+ // Create a new config per test as license_kind information is stored in the config.
+ config := TestArchConfig(buildDir, nil, "", fs)
+
+ ctx := NewTestArchContext(config)
+ RegisterLicenseKindBuildComponents(ctx)
+ ctx.RegisterModuleType("mock_license", newMockLicenseModule)
+ ctx.Register()
+
+ _, errs := ctx.ParseBlueprintsFiles(".")
+ if len(errs) > 0 {
+ return ctx, errs
+ }
+
+ _, errs = ctx.PrepareBuildActions(config)
+ return ctx, errs
+}
+
+type mockLicenseProperties struct {
+ License_kinds []string
+}
+
+type mockLicenseModule struct {
+ ModuleBase
+ DefaultableModuleBase
+
+ properties mockLicenseProperties
+}
+
+func newMockLicenseModule() Module {
+ m := &mockLicenseModule{}
+ m.AddProperties(&m.properties)
+ InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon)
+ InitDefaultableModule(m)
+ return m
+}
+
+type licensekindTag struct {
+ blueprint.BaseDependencyTag
+}
+
+func (j *mockLicenseModule) DepsMutator(ctx BottomUpMutatorContext) {
+ m, ok := ctx.Module().(Module)
+ if !ok {
+ return
+ }
+ ctx.AddDependency(m, licensekindTag{}, j.properties.License_kinds...)
+}
+
+func (p *mockLicenseModule) GenerateAndroidBuildActions(ModuleContext) {
+}
diff --git a/android/license_test.go b/android/license_test.go
new file mode 100644
index 0000000..552bbae
--- /dev/null
+++ b/android/license_test.go
@@ -0,0 +1,233 @@
+package android
+
+import (
+ "testing"
+)
+
+var licenseTests = []struct {
+ name string
+ fs map[string][]byte
+ expectedErrors []string
+}{
+ {
+ name: "license must not accept licenses property",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ license {
+ name: "top_license",
+ visibility: ["//visibility:private"],
+ licenses: ["other_license"],
+ }`),
+ },
+ expectedErrors: []string{
+ `top/Blueprints:5:14: unrecognized property "licenses"`,
+ },
+ },
+ {
+ name: "private license",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ license_kind {
+ name: "top_notice",
+ conditions: ["notice"],
+ visibility: ["//visibility:private"],
+ }
+
+ license {
+ name: "top_allowed_as_notice",
+ license_kinds: ["top_notice"],
+ visibility: ["//visibility:private"],
+ }`),
+ "other/Blueprints": []byte(`
+ rule {
+ name: "arule",
+ licenses: ["top_allowed_as_notice"],
+ }`),
+ "yetmore/Blueprints": []byte(`
+ package {
+ default_applicable_licenses: ["top_allowed_as_notice"],
+ }`),
+ },
+ expectedErrors: []string{
+ `other/Blueprints:2:5: module "arule": depends on //top:top_allowed_as_notice `+
+ `which is not visible to this module`,
+ `yetmore/Blueprints:2:5: module "//yetmore": depends on //top:top_allowed_as_notice `+
+ `which is not visible to this module`,
+ },
+ },
+ {
+ name: "must reference license_kind module",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ rule {
+ name: "top_by_exception_only",
+ }
+
+ license {
+ name: "top_proprietary",
+ license_kinds: ["top_by_exception_only"],
+ visibility: ["//visibility:public"],
+ }`),
+ },
+ expectedErrors: []string{
+ `top/Blueprints:6:5: module "top_proprietary": license_kinds property `+
+ `"top_by_exception_only" is not a license_kind module`,
+ },
+ },
+ {
+ name: "license_kind module must exist",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ license {
+ name: "top_notice_allowed",
+ license_kinds: ["top_notice"],
+ visibility: ["//visibility:public"],
+ }`),
+ },
+ expectedErrors: []string{
+ `top/Blueprints:2:5: "top_notice_allowed" depends on undefined module "top_notice"`,
+ },
+ },
+ {
+ name: "public license",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ license_kind {
+ name: "top_by_exception_only",
+ conditions: ["by_exception_only"],
+ visibility: ["//visibility:private"],
+ }
+
+ license {
+ name: "top_proprietary",
+ license_kinds: ["top_by_exception_only"],
+ visibility: ["//visibility:public"],
+ }`),
+ "other/Blueprints": []byte(`
+ rule {
+ name: "arule",
+ licenses: ["top_proprietary"],
+ }`),
+ "yetmore/Blueprints": []byte(`
+ package {
+ default_applicable_licenses: ["top_proprietary"],
+ }`),
+ },
+ },
+ {
+ name: "multiple licenses",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ package {
+ default_applicable_licenses: ["top_proprietary"],
+ }
+
+ license_kind {
+ name: "top_notice",
+ conditions: ["notice"],
+ }
+
+ license_kind {
+ name: "top_by_exception_only",
+ conditions: ["by_exception_only"],
+ visibility: ["//visibility:public"],
+ }
+
+ license {
+ name: "top_allowed_as_notice",
+ license_kinds: ["top_notice"],
+ }
+
+ license {
+ name: "top_proprietary",
+ license_kinds: ["top_by_exception_only"],
+ visibility: ["//visibility:public"],
+ }
+ rule {
+ name: "myrule",
+ licenses: ["top_allowed_as_notice", "top_proprietary"]
+ }`),
+ "other/Blueprints": []byte(`
+ rule {
+ name: "arule",
+ licenses: ["top_proprietary"],
+ }`),
+ "yetmore/Blueprints": []byte(`
+ package {
+ default_applicable_licenses: ["top_proprietary"],
+ }`),
+ },
+ },
+}
+
+func TestLicense(t *testing.T) {
+ for _, test := range licenseTests {
+ t.Run(test.name, func(t *testing.T) {
+ _, errs := testLicense(test.fs)
+
+ expectedErrors := test.expectedErrors
+ if expectedErrors == nil {
+ FailIfErrored(t, errs)
+ } else {
+ for _, expectedError := range expectedErrors {
+ FailIfNoMatchingErrors(t, expectedError, errs)
+ }
+ if len(errs) > len(expectedErrors) {
+ t.Errorf("additional errors found, expected %d, found %d", len(expectedErrors), len(errs))
+ for i, expectedError := range expectedErrors {
+ t.Errorf("expectedErrors[%d] = %s", i, expectedError)
+ }
+ for i, err := range errs {
+ t.Errorf("errs[%d] = %s", i, err)
+ }
+ }
+ }
+ })
+ }
+}
+
+func testLicense(fs map[string][]byte) (*TestContext, []error) {
+
+ // Create a new config per test as visibility information is stored in the config.
+ env := make(map[string]string)
+ env["ANDROID_REQUIRE_LICENSES"] = "1"
+ config := TestArchConfig(buildDir, env, "", fs)
+
+ ctx := NewTestArchContext(config)
+ RegisterPackageBuildComponents(ctx)
+ registerTestPrebuiltBuildComponents(ctx)
+ RegisterLicenseKindBuildComponents(ctx)
+ RegisterLicenseBuildComponents(ctx)
+ ctx.RegisterModuleType("rule", newMockRuleModule)
+ ctx.PreArchMutators(RegisterVisibilityRuleChecker)
+ ctx.PreArchMutators(RegisterLicensesPackageMapper)
+ ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
+ ctx.PreArchMutators(RegisterLicensesPropertyGatherer)
+ ctx.PreArchMutators(RegisterVisibilityRuleGatherer)
+ ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer)
+ ctx.PostDepsMutators(RegisterLicensesDependencyChecker)
+ ctx.Register()
+
+ _, errs := ctx.ParseBlueprintsFiles(".")
+ if len(errs) > 0 {
+ return ctx, errs
+ }
+
+ _, errs = ctx.PrepareBuildActions(config)
+ return ctx, errs
+}
+
+type mockRuleModule struct {
+ ModuleBase
+ DefaultableModuleBase
+}
+
+func newMockRuleModule() Module {
+ m := &mockRuleModule{}
+ InitAndroidModule(m)
+ InitDefaultableModule(m)
+ return m
+}
+
+func (p *mockRuleModule) GenerateAndroidBuildActions(ModuleContext) {
+}
diff --git a/android/licenses.go b/android/licenses.go
new file mode 100644
index 0000000..1000429
--- /dev/null
+++ b/android/licenses.go
@@ -0,0 +1,295 @@
+// Copyright 2020 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 (
+ "reflect"
+ "sync"
+
+ "github.com/google/blueprint"
+)
+
+// Adds cross-cutting licenses dependency to propagate license metadata through the build system.
+//
+// Stage 1 - bottom-up records package-level default_applicable_licenses property mapped by package name.
+// Stage 2 - bottom-up converts licenses property or package default_applicable_licenses to dependencies.
+// Stage 3 - bottom-up type-checks every added applicable license dependency and license_kind dependency.
+// Stage 4 - GenerateBuildActions calculates properties for the union of license kinds, conditions and texts.
+
+type licensesDependencyTag struct {
+ blueprint.BaseDependencyTag
+}
+
+var (
+ licensesTag = licensesDependencyTag{}
+)
+
+// Describes the property provided by a module to reference applicable licenses.
+type applicableLicensesProperty interface {
+ // The name of the property. e.g. default_applicable_licenses or licenses
+ getName() string
+ // The values assigned to the property. (Must reference license modules.)
+ getStrings() []string
+}
+
+type applicableLicensesPropertyImpl struct {
+ name string
+ licensesProperty *[]string
+}
+
+func newApplicableLicensesProperty(name string, licensesProperty *[]string) applicableLicensesProperty {
+ return applicableLicensesPropertyImpl{
+ name: name,
+ licensesProperty: licensesProperty,
+ }
+}
+
+func (p applicableLicensesPropertyImpl) getName() string {
+ return p.name
+}
+
+func (p applicableLicensesPropertyImpl) getStrings() []string {
+ return *p.licensesProperty
+}
+
+// Set the primary applicable licenses property for a module.
+func setPrimaryLicensesProperty(module Module, name string, licensesProperty *[]string) {
+ module.base().primaryLicensesProperty = newApplicableLicensesProperty(name, licensesProperty)
+}
+
+// Storage blob for a package's default_applicable_licenses mapped by package directory.
+type licensesContainer struct {
+ licenses []string
+}
+
+func (r licensesContainer) getLicenses() []string {
+ return r.licenses
+}
+
+var packageDefaultLicensesMap = NewOnceKey("packageDefaultLicensesMap")
+
+// The map from package dir name to default applicable licenses as a licensesContainer.
+func moduleToPackageDefaultLicensesMap(config Config) *sync.Map {
+ return config.Once(packageDefaultLicensesMap, func() interface{} {
+ return &sync.Map{}
+ }).(*sync.Map)
+}
+
+// Registers the function that maps each package to its default_applicable_licenses.
+//
+// This goes before defaults expansion so the defaults can pick up the package default.
+func RegisterLicensesPackageMapper(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("licensesPackageMapper", licensesPackageMapper).Parallel()
+}
+
+// Registers the function that gathers the license dependencies for each module.
+//
+// This goes after defaults expansion so that it can pick up default licenses and before visibility enforcement.
+func RegisterLicensesPropertyGatherer(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("licensesPropertyGatherer", licensesPropertyGatherer).Parallel()
+}
+
+// Registers the function that verifies the licenses and license_kinds dependency types for each module.
+func RegisterLicensesDependencyChecker(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("licensesPropertyChecker", licensesDependencyChecker).Parallel()
+}
+
+// Maps each package to its default applicable licenses.
+func licensesPackageMapper(ctx BottomUpMutatorContext) {
+ p, ok := ctx.Module().(*packageModule)
+ if !ok {
+ return
+ }
+
+ licenses := getLicenses(ctx, p)
+
+ dir := ctx.ModuleDir()
+ c := makeLicensesContainer(licenses)
+ moduleToPackageDefaultLicensesMap(ctx.Config()).Store(dir, c)
+}
+
+// Copies the default_applicable_licenses property values for mapping by package directory.
+func makeLicensesContainer(propVals []string) licensesContainer {
+ licenses := make([]string, 0, len(propVals))
+ licenses = append(licenses, propVals...)
+
+ return licensesContainer{licenses}
+}
+
+// Gathers the applicable licenses into dependency references after defaults expansion.
+func licensesPropertyGatherer(ctx BottomUpMutatorContext) {
+ m, ok := ctx.Module().(Module)
+ if !ok {
+ return
+ }
+
+ if exemptFromRequiredApplicableLicensesProperty(m) {
+ return
+ }
+
+ licenses := getLicenses(ctx, m)
+
+ ctx.AddVariationDependencies(nil, licensesTag, licenses...)
+}
+
+// Verifies the license and license_kind dependencies are each the correct kind of module.
+func licensesDependencyChecker(ctx BottomUpMutatorContext) {
+ m, ok := ctx.Module().(Module)
+ if !ok {
+ return
+ }
+
+ // license modules have no licenses, but license_kinds must refer to license_kind modules
+ if _, ok := m.(*licenseModule); ok {
+ for _, module := range ctx.GetDirectDepsWithTag(licenseKindTag) {
+ if _, ok := module.(*licenseKindModule); !ok {
+ ctx.ModuleErrorf("license_kinds property %q is not a license_kind module", ctx.OtherModuleName(module))
+ }
+ }
+ return
+ }
+
+ if exemptFromRequiredApplicableLicensesProperty(m) {
+ return
+ }
+
+ for _, module := range ctx.GetDirectDepsWithTag(licensesTag) {
+ if _, ok := module.(*licenseModule); !ok {
+ propertyName := "licenses"
+ primaryProperty := m.base().primaryLicensesProperty
+ if primaryProperty != nil {
+ propertyName = primaryProperty.getName()
+ }
+ ctx.ModuleErrorf("%s property %q is not a license module", propertyName, ctx.OtherModuleName(module))
+ }
+ }
+}
+
+// Flattens license and license_kind dependencies into calculated properties.
+//
+// Re-validates applicable licenses properties refer only to license modules and license_kinds properties refer
+// only to license_kind modules.
+func licensesPropertyFlattener(ctx ModuleContext) {
+ m, ok := ctx.Module().(Module)
+ if !ok {
+ return
+ }
+
+ // license modules have no licenses, but license_kinds must refer to license_kind modules
+ if l, ok := m.(*licenseModule); ok {
+ mergeProps(&m.base().commonProperties.Effective_licenses, ctx.ModuleName())
+ mergeProps(&m.base().commonProperties.Effective_license_text, PathsForModuleSrc(ctx, l.properties.License_text).Strings()...)
+ for _, module := range ctx.GetDirectDepsWithTag(licenseKindTag) {
+ if lk, ok := module.(*licenseKindModule); ok {
+ mergeProps(&m.base().commonProperties.Effective_license_conditions, lk.properties.Conditions...)
+ mergeProps(&m.base().commonProperties.Effective_license_kinds, ctx.OtherModuleName(module))
+ } else {
+ ctx.ModuleErrorf("license_kinds property %q is not a license_kind module", ctx.OtherModuleName(module))
+ }
+ }
+ return
+ }
+
+ if exemptFromRequiredApplicableLicensesProperty(m) {
+ return
+ }
+
+ for _, module := range ctx.GetDirectDepsWithTag(licensesTag) {
+ if l, ok := module.(*licenseModule); ok {
+ if m.base().commonProperties.Effective_package_name == nil && l.properties.Package_name != nil {
+ m.base().commonProperties.Effective_package_name = l.properties.Package_name
+ }
+ mergeProps(&m.base().commonProperties.Effective_licenses, module.base().commonProperties.Effective_licenses...)
+ mergeProps(&m.base().commonProperties.Effective_license_text, module.base().commonProperties.Effective_license_text...)
+ mergeProps(&m.base().commonProperties.Effective_license_kinds, module.base().commonProperties.Effective_license_kinds...)
+ mergeProps(&m.base().commonProperties.Effective_license_conditions, module.base().commonProperties.Effective_license_conditions...)
+ } else {
+ propertyName := "licenses"
+ primaryProperty := m.base().primaryLicensesProperty
+ if primaryProperty != nil {
+ propertyName = primaryProperty.getName()
+ }
+ ctx.ModuleErrorf("%s property %q is not a license module", propertyName, ctx.OtherModuleName(module))
+ }
+ }
+}
+
+// Update a property string array with a distinct union of its values and a list of new values.
+func mergeProps(prop *[]string, values ...string) {
+ s := make(map[string]bool)
+ for _, v := range *prop {
+ s[v] = true
+ }
+ for _, v := range values {
+ s[v] = true
+ }
+ *prop = []string{}
+ *prop = append(*prop, SortedStringKeys(s)...)
+}
+
+// Get the licenses property falling back to the package default.
+func getLicenses(ctx BaseModuleContext, module Module) []string {
+ if exemptFromRequiredApplicableLicensesProperty(module) {
+ return nil
+ }
+
+ primaryProperty := module.base().primaryLicensesProperty
+ if primaryProperty == nil {
+ if ctx.Config().IsEnvTrue("ANDROID_REQUIRE_LICENSES") {
+ ctx.ModuleErrorf("module type %q must have an applicable licenses property", ctx.OtherModuleType(module))
+ }
+ return nil
+ }
+
+ licenses := primaryProperty.getStrings()
+ if len(licenses) > 0 {
+ s := make(map[string]bool)
+ for _, l := range licenses {
+ if _, ok := s[l]; ok {
+ ctx.ModuleErrorf("duplicate %q %s", l, primaryProperty.getName())
+ }
+ s[l] = true
+ }
+ return licenses
+ }
+
+ dir := ctx.OtherModuleDir(module)
+
+ moduleToApplicableLicenses := moduleToPackageDefaultLicensesMap(ctx.Config())
+ value, ok := moduleToApplicableLicenses.Load(dir)
+ var c licensesContainer
+ if ok {
+ c = value.(licensesContainer)
+ } else {
+ c = licensesContainer{}
+ }
+ return c.getLicenses()
+}
+
+// Returns whether a module is an allowed list of modules that do not have or need applicable licenses.
+func exemptFromRequiredApplicableLicensesProperty(module Module) bool {
+ switch reflect.TypeOf(module).String() {
+ case "*android.licenseModule": // is a license, doesn't need one
+ case "*android.licenseKindModule": // is a license, doesn't need one
+ case "*android.NamespaceModule": // just partitions things, doesn't add anything
+ case "*android.soongConfigModuleTypeModule": // creates aliases for modules with licenses
+ case "*android.soongConfigModuleTypeImport": // creates aliases for modules with licenses
+ case "*android.soongConfigStringVariableDummyModule": // used for creating aliases
+ case "*android.SoongConfigBoolVariableDummyModule": // used for creating aliases
+ default:
+ return false
+ }
+ return true
+}
diff --git a/android/licenses_test.go b/android/licenses_test.go
new file mode 100644
index 0000000..b94add7
--- /dev/null
+++ b/android/licenses_test.go
@@ -0,0 +1,863 @@
+package android
+
+import (
+ "testing"
+
+ "github.com/google/blueprint"
+)
+
+var licensesTests = []struct {
+ name string
+ fs map[string][]byte
+ expectedErrors []string
+ effectiveLicenses map[string][]string
+ effectiveInheritedLicenses map[string][]string
+ effectivePackage map[string]string
+ effectiveNotices map[string][]string
+ effectiveKinds map[string][]string
+ effectiveConditions map[string][]string
+}{
+ {
+ name: "invalid module type without licenses property",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_bad_module {
+ name: "libexample",
+ }`),
+ },
+ expectedErrors: []string{`module type "mock_bad_module" must have an applicable licenses property`},
+ },
+ {
+ name: "license must exist",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_library {
+ name: "libexample",
+ licenses: ["notice"],
+ }`),
+ },
+ expectedErrors: []string{`"libexample" depends on undefined module "notice"`},
+ },
+ {
+ name: "all good",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ license_kind {
+ name: "notice",
+ conditions: ["shownotice"],
+ }
+
+ license {
+ name: "top_Apache2",
+ license_kinds: ["notice"],
+ package_name: "topDog",
+ license_text: ["LICENSE", "NOTICE"],
+ }
+
+ mock_library {
+ name: "libexample1",
+ licenses: ["top_Apache2"],
+ }`),
+ "top/nested/Blueprints": []byte(`
+ mock_library {
+ name: "libnested",
+ licenses: ["top_Apache2"],
+ }`),
+ "other/Blueprints": []byte(`
+ mock_library {
+ name: "libother",
+ licenses: ["top_Apache2"],
+ }`),
+ },
+ effectiveLicenses: map[string][]string{
+ "libexample1": []string{"top_Apache2"},
+ "libnested": []string{"top_Apache2"},
+ "libother": []string{"top_Apache2"},
+ },
+ effectiveKinds: map[string][]string{
+ "libexample1": []string{"notice"},
+ "libnested": []string{"notice"},
+ "libother": []string{"notice"},
+ },
+ effectivePackage: map[string]string{
+ "libexample1": "topDog",
+ "libnested": "topDog",
+ "libother": "topDog",
+ },
+ effectiveConditions: map[string][]string{
+ "libexample1": []string{"shownotice"},
+ "libnested": []string{"shownotice"},
+ "libother": []string{"shownotice"},
+ },
+ effectiveNotices: map[string][]string{
+ "libexample1": []string{"top/LICENSE", "top/NOTICE"},
+ "libnested": []string{"top/LICENSE", "top/NOTICE"},
+ "libother": []string{"top/LICENSE", "top/NOTICE"},
+ },
+ },
+
+ // Defaults propagation tests
+ {
+ // Check that licenses is the union of the defaults modules.
+ name: "defaults union, basic",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ license_kind {
+ name: "top_notice",
+ conditions: ["notice"],
+ }
+
+ license {
+ name: "top_other",
+ license_kinds: ["top_notice"],
+ }
+
+ mock_defaults {
+ name: "libexample_defaults",
+ licenses: ["top_other"],
+ }
+ mock_library {
+ name: "libexample",
+ licenses: ["nested_other"],
+ defaults: ["libexample_defaults"],
+ }
+ mock_library {
+ name: "libsamepackage",
+ deps: ["libexample"],
+ }`),
+ "top/nested/Blueprints": []byte(`
+ license_kind {
+ name: "nested_notice",
+ conditions: ["notice"],
+ }
+
+ license {
+ name: "nested_other",
+ license_kinds: ["nested_notice"],
+ }
+
+ mock_library {
+ name: "libnested",
+ deps: ["libexample"],
+ }`),
+ "other/Blueprints": []byte(`
+ mock_library {
+ name: "libother",
+ deps: ["libexample"],
+ }`),
+ },
+ effectiveLicenses: map[string][]string{
+ "libexample": []string{"nested_other", "top_other"},
+ "libsamepackage": []string{},
+ "libnested": []string{},
+ "libother": []string{},
+ },
+ effectiveInheritedLicenses: map[string][]string{
+ "libexample": []string{"nested_other", "top_other"},
+ "libsamepackage": []string{"nested_other", "top_other"},
+ "libnested": []string{"nested_other", "top_other"},
+ "libother": []string{"nested_other", "top_other"},
+ },
+ effectiveKinds: map[string][]string{
+ "libexample": []string{"nested_notice", "top_notice"},
+ "libsamepackage": []string{},
+ "libnested": []string{},
+ "libother": []string{},
+ },
+ effectiveConditions: map[string][]string{
+ "libexample": []string{"notice"},
+ "libsamepackage": []string{},
+ "libnested": []string{},
+ "libother": []string{},
+ },
+ },
+ {
+ name: "defaults union, multiple defaults",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ license {
+ name: "top",
+ }
+ mock_defaults {
+ name: "libexample_defaults_1",
+ licenses: ["other"],
+ }
+ mock_defaults {
+ name: "libexample_defaults_2",
+ licenses: ["top_nested"],
+ }
+ mock_library {
+ name: "libexample",
+ defaults: ["libexample_defaults_1", "libexample_defaults_2"],
+ }
+ mock_library {
+ name: "libsamepackage",
+ deps: ["libexample"],
+ }`),
+ "top/nested/Blueprints": []byte(`
+ license {
+ name: "top_nested",
+ license_text: ["LICENSE.txt"],
+ }
+ mock_library {
+ name: "libnested",
+ deps: ["libexample"],
+ }`),
+ "other/Blueprints": []byte(`
+ license {
+ name: "other",
+ }
+ mock_library {
+ name: "libother",
+ deps: ["libexample"],
+ }`),
+ "outsider/Blueprints": []byte(`
+ mock_library {
+ name: "liboutsider",
+ deps: ["libexample"],
+ }`),
+ },
+ effectiveLicenses: map[string][]string{
+ "libexample": []string{"other", "top_nested"},
+ "libsamepackage": []string{},
+ "libnested": []string{},
+ "libother": []string{},
+ "liboutsider": []string{},
+ },
+ effectiveInheritedLicenses: map[string][]string{
+ "libexample": []string{"other", "top_nested"},
+ "libsamepackage": []string{"other", "top_nested"},
+ "libnested": []string{"other", "top_nested"},
+ "libother": []string{"other", "top_nested"},
+ "liboutsider": []string{"other", "top_nested"},
+ },
+ effectiveKinds: map[string][]string{
+ "libexample": []string{},
+ "libsamepackage": []string{},
+ "libnested": []string{},
+ "libother": []string{},
+ "liboutsider": []string{},
+ },
+ effectiveNotices: map[string][]string{
+ "libexample": []string{"top/nested/LICENSE.txt"},
+ "libsamepackage": []string{},
+ "libnested": []string{},
+ "libother": []string{},
+ "liboutsider": []string{},
+ },
+ },
+
+ // Defaults module's defaults_licenses tests
+ {
+ name: "defaults_licenses invalid",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_defaults {
+ name: "top_defaults",
+ licenses: ["notice"],
+ }`),
+ },
+ expectedErrors: []string{`"top_defaults" depends on undefined module "notice"`},
+ },
+ {
+ name: "defaults_licenses overrides package default",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ package {
+ default_applicable_licenses: ["by_exception_only"],
+ }
+ license {
+ name: "by_exception_only",
+ }
+ license {
+ name: "notice",
+ }
+ mock_defaults {
+ name: "top_defaults",
+ licenses: ["notice"],
+ }
+ mock_library {
+ name: "libexample",
+ }
+ mock_library {
+ name: "libdefaults",
+ defaults: ["top_defaults"],
+ }`),
+ },
+ effectiveLicenses: map[string][]string{
+ "libexample": []string{"by_exception_only"},
+ "libdefaults": []string{"notice"},
+ },
+ effectiveInheritedLicenses: map[string][]string{
+ "libexample": []string{"by_exception_only"},
+ "libdefaults": []string{"notice"},
+ },
+ },
+
+ // Package default_applicable_licenses tests
+ {
+ name: "package default_applicable_licenses must exist",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ package {
+ default_applicable_licenses: ["notice"],
+ }`),
+ },
+ expectedErrors: []string{`"//top" depends on undefined module "notice"`},
+ },
+ {
+ // This test relies on the default licenses being legacy_public.
+ name: "package default_applicable_licenses property used when no licenses specified",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ package {
+ default_applicable_licenses: ["top_notice"],
+ }
+
+ license {
+ name: "top_notice",
+ }
+ mock_library {
+ name: "libexample",
+ }`),
+ "outsider/Blueprints": []byte(`
+ mock_library {
+ name: "liboutsider",
+ deps: ["libexample"],
+ }`),
+ },
+ effectiveLicenses: map[string][]string{
+ "libexample": []string{"top_notice"},
+ "liboutsider": []string{},
+ },
+ effectiveInheritedLicenses: map[string][]string{
+ "libexample": []string{"top_notice"},
+ "liboutsider": []string{"top_notice"},
+ },
+ },
+ {
+ name: "package default_applicable_licenses not inherited to subpackages",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ package {
+ default_applicable_licenses: ["top_notice"],
+ }
+ license {
+ name: "top_notice",
+ }
+ mock_library {
+ name: "libexample",
+ }`),
+ "top/nested/Blueprints": []byte(`
+ package {
+ default_applicable_licenses: ["outsider"],
+ }
+
+ mock_library {
+ name: "libnested",
+ }`),
+ "top/other/Blueprints": []byte(`
+ mock_library {
+ name: "libother",
+ }`),
+ "outsider/Blueprints": []byte(`
+ license {
+ name: "outsider",
+ }
+ mock_library {
+ name: "liboutsider",
+ deps: ["libexample", "libother", "libnested"],
+ }`),
+ },
+ effectiveLicenses: map[string][]string{
+ "libexample": []string{"top_notice"},
+ "libnested": []string{"outsider"},
+ "libother": []string{},
+ "liboutsider": []string{},
+ },
+ effectiveInheritedLicenses: map[string][]string{
+ "libexample": []string{"top_notice"},
+ "libnested": []string{"outsider"},
+ "libother": []string{},
+ "liboutsider": []string{"top_notice", "outsider"},
+ },
+ },
+ {
+ name: "verify that prebuilt dependencies are included",
+ fs: map[string][]byte{
+ "prebuilts/Blueprints": []byte(`
+ license {
+ name: "prebuilt"
+ }
+ prebuilt {
+ name: "module",
+ licenses: ["prebuilt"],
+ }`),
+ "top/sources/source_file": nil,
+ "top/sources/Blueprints": []byte(`
+ license {
+ name: "top_sources"
+ }
+ source {
+ name: "module",
+ licenses: ["top_sources"],
+ }`),
+ "top/other/source_file": nil,
+ "top/other/Blueprints": []byte(`
+ source {
+ name: "other",
+ deps: [":module"],
+ }`),
+ },
+ effectiveLicenses: map[string][]string{
+ "other": []string{},
+ },
+ effectiveInheritedLicenses: map[string][]string{
+ "other": []string{"prebuilt", "top_sources"},
+ },
+ },
+ {
+ name: "verify that prebuilt dependencies are ignored for licenses reasons (preferred)",
+ fs: map[string][]byte{
+ "prebuilts/Blueprints": []byte(`
+ license {
+ name: "prebuilt"
+ }
+ prebuilt {
+ name: "module",
+ licenses: ["prebuilt"],
+ prefer: true,
+ }`),
+ "top/sources/source_file": nil,
+ "top/sources/Blueprints": []byte(`
+ license {
+ name: "top_sources"
+ }
+ source {
+ name: "module",
+ licenses: ["top_sources"],
+ }`),
+ "top/other/source_file": nil,
+ "top/other/Blueprints": []byte(`
+ source {
+ name: "other",
+ deps: [":module"],
+ }`),
+ },
+ effectiveLicenses: map[string][]string{
+ "other": []string{},
+ },
+ effectiveInheritedLicenses: map[string][]string{
+ "module": []string{"prebuilt", "top_sources"},
+ "other": []string{"prebuilt", "top_sources"},
+ },
+ },
+}
+
+func TestLicenses(t *testing.T) {
+ for _, test := range licensesTests {
+ t.Run(test.name, func(t *testing.T) {
+ ctx, errs := testLicenses(buildDir, test.fs)
+
+ CheckErrorsAgainstExpectations(t, errs, test.expectedErrors)
+
+ if test.effectiveLicenses != nil {
+ checkEffectiveLicenses(t, ctx, test.effectiveLicenses)
+ }
+
+ if test.effectivePackage != nil {
+ checkEffectivePackage(t, ctx, test.effectivePackage)
+ }
+
+ if test.effectiveNotices != nil {
+ checkEffectiveNotices(t, ctx, test.effectiveNotices)
+ }
+
+ if test.effectiveKinds != nil {
+ checkEffectiveKinds(t, ctx, test.effectiveKinds)
+ }
+
+ if test.effectiveConditions != nil {
+ checkEffectiveConditions(t, ctx, test.effectiveConditions)
+ }
+
+ if test.effectiveInheritedLicenses != nil {
+ checkEffectiveInheritedLicenses(t, ctx, test.effectiveInheritedLicenses)
+ }
+ })
+ }
+}
+
+func checkEffectiveLicenses(t *testing.T, ctx *TestContext, effectiveLicenses map[string][]string) {
+ actualLicenses := make(map[string][]string)
+ ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
+ if _, ok := m.(*licenseModule); ok {
+ return
+ }
+ if _, ok := m.(*licenseKindModule); ok {
+ return
+ }
+ if _, ok := m.(*packageModule); ok {
+ return
+ }
+ module, ok := m.(Module)
+ if !ok {
+ t.Errorf("%q not a module", m.Name())
+ return
+ }
+ base := module.base()
+ if base == nil {
+ return
+ }
+ actualLicenses[m.Name()] = base.commonProperties.Effective_licenses
+ })
+
+ for moduleName, expectedLicenses := range effectiveLicenses {
+ licenses, ok := actualLicenses[moduleName]
+ if !ok {
+ licenses = []string{}
+ }
+ if !compareUnorderedStringArrays(expectedLicenses, licenses) {
+ t.Errorf("effective licenses mismatch for module %q: expected %q, found %q", moduleName, expectedLicenses, licenses)
+ }
+ }
+}
+
+func checkEffectiveInheritedLicenses(t *testing.T, ctx *TestContext, effectiveInheritedLicenses map[string][]string) {
+ actualLicenses := make(map[string][]string)
+ ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
+ if _, ok := m.(*licenseModule); ok {
+ return
+ }
+ if _, ok := m.(*licenseKindModule); ok {
+ return
+ }
+ if _, ok := m.(*packageModule); ok {
+ return
+ }
+ module, ok := m.(Module)
+ if !ok {
+ t.Errorf("%q not a module", m.Name())
+ return
+ }
+ base := module.base()
+ if base == nil {
+ return
+ }
+ inherited := make(map[string]bool)
+ for _, l := range base.commonProperties.Effective_licenses {
+ inherited[l] = true
+ }
+ ctx.Context.Context.VisitDepsDepthFirst(m, func(c blueprint.Module) {
+ if _, ok := c.(*licenseModule); ok {
+ return
+ }
+ if _, ok := c.(*licenseKindModule); ok {
+ return
+ }
+ if _, ok := c.(*packageModule); ok {
+ return
+ }
+ cmodule, ok := c.(Module)
+ if !ok {
+ t.Errorf("%q not a module", c.Name())
+ return
+ }
+ cbase := cmodule.base()
+ if cbase == nil {
+ return
+ }
+ for _, l := range cbase.commonProperties.Effective_licenses {
+ inherited[l] = true
+ }
+ })
+ actualLicenses[m.Name()] = []string{}
+ for l := range inherited {
+ actualLicenses[m.Name()] = append(actualLicenses[m.Name()], l)
+ }
+ })
+
+ for moduleName, expectedInheritedLicenses := range effectiveInheritedLicenses {
+ licenses, ok := actualLicenses[moduleName]
+ if !ok {
+ licenses = []string{}
+ }
+ if !compareUnorderedStringArrays(expectedInheritedLicenses, licenses) {
+ t.Errorf("effective inherited licenses mismatch for module %q: expected %q, found %q", moduleName, expectedInheritedLicenses, licenses)
+ }
+ }
+}
+
+func checkEffectivePackage(t *testing.T, ctx *TestContext, effectivePackage map[string]string) {
+ actualPackage := make(map[string]string)
+ ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
+ if _, ok := m.(*licenseModule); ok {
+ return
+ }
+ if _, ok := m.(*licenseKindModule); ok {
+ return
+ }
+ if _, ok := m.(*packageModule); ok {
+ return
+ }
+ module, ok := m.(Module)
+ if !ok {
+ t.Errorf("%q not a module", m.Name())
+ return
+ }
+ base := module.base()
+ if base == nil {
+ return
+ }
+
+ if base.commonProperties.Effective_package_name == nil {
+ actualPackage[m.Name()] = ""
+ } else {
+ actualPackage[m.Name()] = *base.commonProperties.Effective_package_name
+ }
+ })
+
+ for moduleName, expectedPackage := range effectivePackage {
+ packageName, ok := actualPackage[moduleName]
+ if !ok {
+ packageName = ""
+ }
+ if expectedPackage != packageName {
+ t.Errorf("effective package mismatch for module %q: expected %q, found %q", moduleName, expectedPackage, packageName)
+ }
+ }
+}
+
+func checkEffectiveNotices(t *testing.T, ctx *TestContext, effectiveNotices map[string][]string) {
+ actualNotices := make(map[string][]string)
+ ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
+ if _, ok := m.(*licenseModule); ok {
+ return
+ }
+ if _, ok := m.(*licenseKindModule); ok {
+ return
+ }
+ if _, ok := m.(*packageModule); ok {
+ return
+ }
+ module, ok := m.(Module)
+ if !ok {
+ t.Errorf("%q not a module", m.Name())
+ return
+ }
+ base := module.base()
+ if base == nil {
+ return
+ }
+ actualNotices[m.Name()] = base.commonProperties.Effective_license_text
+ })
+
+ for moduleName, expectedNotices := range effectiveNotices {
+ notices, ok := actualNotices[moduleName]
+ if !ok {
+ notices = []string{}
+ }
+ if !compareUnorderedStringArrays(expectedNotices, notices) {
+ t.Errorf("effective notice files mismatch for module %q: expected %q, found %q", moduleName, expectedNotices, notices)
+ }
+ }
+}
+
+func checkEffectiveKinds(t *testing.T, ctx *TestContext, effectiveKinds map[string][]string) {
+ actualKinds := make(map[string][]string)
+ ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
+ if _, ok := m.(*licenseModule); ok {
+ return
+ }
+ if _, ok := m.(*licenseKindModule); ok {
+ return
+ }
+ if _, ok := m.(*packageModule); ok {
+ return
+ }
+ module, ok := m.(Module)
+ if !ok {
+ t.Errorf("%q not a module", m.Name())
+ return
+ }
+ base := module.base()
+ if base == nil {
+ return
+ }
+ actualKinds[m.Name()] = base.commonProperties.Effective_license_kinds
+ })
+
+ for moduleName, expectedKinds := range effectiveKinds {
+ kinds, ok := actualKinds[moduleName]
+ if !ok {
+ kinds = []string{}
+ }
+ if !compareUnorderedStringArrays(expectedKinds, kinds) {
+ t.Errorf("effective license kinds mismatch for module %q: expected %q, found %q", moduleName, expectedKinds, kinds)
+ }
+ }
+}
+
+func checkEffectiveConditions(t *testing.T, ctx *TestContext, effectiveConditions map[string][]string) {
+ actualConditions := make(map[string][]string)
+ ctx.Context.Context.VisitAllModules(func(m blueprint.Module) {
+ if _, ok := m.(*licenseModule); ok {
+ return
+ }
+ if _, ok := m.(*licenseKindModule); ok {
+ return
+ }
+ if _, ok := m.(*packageModule); ok {
+ return
+ }
+ module, ok := m.(Module)
+ if !ok {
+ t.Errorf("%q not a module", m.Name())
+ return
+ }
+ base := module.base()
+ if base == nil {
+ return
+ }
+ actualConditions[m.Name()] = base.commonProperties.Effective_license_conditions
+ })
+
+ for moduleName, expectedConditions := range effectiveConditions {
+ conditions, ok := actualConditions[moduleName]
+ if !ok {
+ conditions = []string{}
+ }
+ if !compareUnorderedStringArrays(expectedConditions, conditions) {
+ t.Errorf("effective license conditions mismatch for module %q: expected %q, found %q", moduleName, expectedConditions, conditions)
+ }
+ }
+}
+
+func compareUnorderedStringArrays(expected, actual []string) bool {
+ if len(expected) != len(actual) {
+ return false
+ }
+ s := make(map[string]int)
+ for _, v := range expected {
+ s[v] += 1
+ }
+ for _, v := range actual {
+ c, ok := s[v]
+ if !ok {
+ return false
+ }
+ if c < 1 {
+ return false
+ }
+ s[v] -= 1
+ }
+ return true
+}
+
+func testLicenses(buildDir string, fs map[string][]byte) (*TestContext, []error) {
+
+ // Create a new config per test as licenses information is stored in the config.
+ env := make(map[string]string)
+ env["ANDROID_REQUIRE_LICENSES"] = "1"
+ config := TestArchConfig(buildDir, env, "", fs)
+
+ ctx := NewTestArchContext(config)
+ ctx.RegisterModuleType("mock_bad_module", newMockLicensesBadModule)
+ ctx.RegisterModuleType("mock_library", newMockLicensesLibraryModule)
+ ctx.RegisterModuleType("mock_defaults", defaultsLicensesFactory)
+
+ // Order of the following method calls is significant.
+ RegisterPackageBuildComponents(ctx)
+ registerTestPrebuiltBuildComponents(ctx)
+ RegisterLicenseKindBuildComponents(ctx)
+ RegisterLicenseBuildComponents(ctx)
+ ctx.PreArchMutators(RegisterVisibilityRuleChecker)
+ ctx.PreArchMutators(RegisterLicensesPackageMapper)
+ ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
+ ctx.PreArchMutators(RegisterLicensesPropertyGatherer)
+ ctx.PreArchMutators(RegisterVisibilityRuleGatherer)
+ ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer)
+ ctx.PostDepsMutators(RegisterLicensesDependencyChecker)
+ ctx.Register()
+
+ _, errs := ctx.ParseBlueprintsFiles(".")
+ if len(errs) > 0 {
+ return ctx, errs
+ }
+
+ _, errs = ctx.PrepareBuildActions(config)
+ return ctx, errs
+}
+
+type mockLicensesBadProperties struct {
+ Visibility []string
+}
+
+type mockLicensesBadModule struct {
+ ModuleBase
+ DefaultableModuleBase
+ properties mockLicensesBadProperties
+}
+
+func newMockLicensesBadModule() Module {
+ m := &mockLicensesBadModule{}
+
+ base := m.base()
+ m.AddProperties(&base.nameProperties, &m.properties)
+
+ base.generalProperties = m.GetProperties()
+ base.customizableProperties = m.GetProperties()
+
+ // The default_visibility property needs to be checked and parsed by the visibility module during
+ // its checking and parsing phases so make it the primary visibility property.
+ setPrimaryVisibilityProperty(m, "visibility", &m.properties.Visibility)
+
+ initAndroidModuleBase(m)
+ InitDefaultableModule(m)
+
+ return m
+}
+
+func (m *mockLicensesBadModule) GenerateAndroidBuildActions(ModuleContext) {
+}
+
+type mockLicensesLibraryProperties struct {
+ Deps []string
+}
+
+type mockLicensesLibraryModule struct {
+ ModuleBase
+ DefaultableModuleBase
+ properties mockLicensesLibraryProperties
+}
+
+func newMockLicensesLibraryModule() Module {
+ m := &mockLicensesLibraryModule{}
+ m.AddProperties(&m.properties)
+ InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon)
+ InitDefaultableModule(m)
+ return m
+}
+
+type dependencyLicensesTag struct {
+ blueprint.BaseDependencyTag
+ name string
+}
+
+func (j *mockLicensesLibraryModule) DepsMutator(ctx BottomUpMutatorContext) {
+ ctx.AddVariationDependencies(nil, dependencyLicensesTag{name: "mockdeps"}, j.properties.Deps...)
+}
+
+func (p *mockLicensesLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
+}
+
+type mockLicensesDefaults struct {
+ ModuleBase
+ DefaultsModuleBase
+}
+
+func defaultsLicensesFactory() Module {
+ m := &mockLicensesDefaults{}
+ InitDefaultsModule(m)
+ return m
+}
diff --git a/android/module.go b/android/module.go
index cfb32c1..b0ad89b 100644
--- a/android/module.go
+++ b/android/module.go
@@ -619,6 +619,20 @@
// more details.
Visibility []string
+ // Describes the licenses applicable to this module. Must reference license modules.
+ Licenses []string
+
+ // Flattened from direct license dependencies. Equal to Licenses unless particular module adds more.
+ Effective_licenses []string `blueprint:"mutated"`
+ // Override of module name when reporting licenses
+ Effective_package_name *string `blueprint:"mutated"`
+ // Notice files
+ Effective_license_text []string `blueprint:"mutated"`
+ // License names
+ Effective_license_kinds []string `blueprint:"mutated"`
+ // License conditions
+ Effective_license_conditions []string `blueprint:"mutated"`
+
// control whether this module compiles for 32-bit, 64-bit, or both. Possible values
// are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both
// architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
@@ -940,6 +954,10 @@
// The default_visibility property needs to be checked and parsed by the visibility module during
// its checking and parsing phases so make it the primary visibility property.
setPrimaryVisibilityProperty(m, "visibility", &base.commonProperties.Visibility)
+
+ // The default_applicable_licenses property needs to be checked and parsed by the licenses module during
+ // its checking and parsing phases so make it the primary licenses property.
+ setPrimaryLicensesProperty(m, "licenses", &base.commonProperties.Licenses)
}
// InitAndroidArchModule initializes the Module as an Android module that is architecture-specific.
@@ -1057,6 +1075,9 @@
// The primary visibility property, may be nil, that controls access to the module.
primaryVisibilityProperty visibilityProperty
+ // The primary licenses property, may be nil, records license metadata for the module.
+ primaryLicensesProperty applicableLicensesProperty
+
noAddressSanitizer bool
installFiles InstallPaths
installFilesDepSet *installPathsDepSet
@@ -1732,6 +1753,11 @@
}
}
+ licensesPropertyFlattener(ctx)
+ if ctx.Failed() {
+ return
+ }
+
m.module.GenerateAndroidBuildActions(ctx)
if ctx.Failed() {
return
diff --git a/android/mutator.go b/android/mutator.go
index 31edea3..72c68b2 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -115,6 +115,11 @@
//
RegisterVisibilityRuleChecker,
+ // Record the default_applicable_licenses for each package.
+ //
+ // This must run before the defaults so that defaults modules can pick up the package default.
+ RegisterLicensesPackageMapper,
+
// Apply properties from defaults modules to the referencing modules.
//
// Any mutators that are added before this will not see any modules created by
@@ -141,6 +146,12 @@
// prebuilt.
RegisterPrebuiltsPreArchMutators,
+ // Gather the licenses properties for all modules for use during expansion and enforcement.
+ //
+ // This must come after the defaults mutators to ensure that any licenses supplied
+ // in a defaults module has been successfully applied before the rules are gathered.
+ RegisterLicensesPropertyGatherer,
+
// Gather the visibility rules for all modules for us during visibility enforcement.
//
// This must come after the defaults mutators to ensure that any visibility supplied
@@ -162,6 +173,7 @@
registerPathDepsMutator,
RegisterPrebuiltsPostDepsMutators,
RegisterVisibilityRuleEnforcer,
+ RegisterLicensesDependencyChecker,
RegisterNeverallowMutator,
RegisterOverridePostDepsMutators,
}
diff --git a/android/package.go b/android/package.go
index 182b3ed..7012fc7 100644
--- a/android/package.go
+++ b/android/package.go
@@ -31,6 +31,8 @@
type packageProperties struct {
// Specifies the default visibility for all modules defined in this package.
Default_visibility []string
+ // Specifies the default license terms for all modules defined in this package.
+ Default_applicable_licenses []string
}
type packageModule struct {
@@ -68,5 +70,9 @@
// its checking and parsing phases so make it the primary visibility property.
setPrimaryVisibilityProperty(module, "default_visibility", &module.properties.Default_visibility)
+ // The default_applicable_licenses property needs to be checked and parsed by the licenses module during
+ // its checking and parsing phases so make it the primary licenses property.
+ setPrimaryLicensesProperty(module, "default_applicable_licenses", &module.properties.Default_applicable_licenses)
+
return module
}
diff --git a/android/package_test.go b/android/package_test.go
index ade95d4..99be13f 100644
--- a/android/package_test.go
+++ b/android/package_test.go
@@ -17,9 +17,11 @@
package {
name: "package",
visibility: ["//visibility:private"],
+ licenses: ["license"],
}`),
},
expectedErrors: []string{
+ `top/Blueprints:5:14: unrecognized property "licenses"`,
`top/Blueprints:3:10: unrecognized property "name"`,
`top/Blueprints:4:16: unrecognized property "visibility"`,
},
@@ -44,9 +46,10 @@
"top/Blueprints": []byte(`
package {
default_visibility: ["//visibility:private"],
+ default_applicable_licenses: ["license"],
}
- package {
+ package {
}`),
},
expectedErrors: []string{
diff --git a/android/variable.go b/android/variable.go
index 1455fc2..7532797 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -181,6 +181,8 @@
DeviceCurrentApiLevelForVendorModules *string `json:",omitempty"`
DeviceSystemSdkVersions []string `json:",omitempty"`
+ RecoverySnapshotVersion *string `json:",omitempty"`
+
DeviceSecondaryArch *string `json:",omitempty"`
DeviceSecondaryArchVariant *string `json:",omitempty"`
DeviceSecondaryCpuVariant *string `json:",omitempty"`
diff --git a/apex/Android.bp b/apex/Android.bp
index 9e8c30d..e3a547c 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -7,6 +7,7 @@
"soong-android",
"soong-bpf",
"soong-cc",
+ "soong-filesystem",
"soong-java",
"soong-python",
"soong-rust",
diff --git a/apex/androidmk.go b/apex/androidmk.go
index e7f8b7f..0b114f8 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -63,6 +63,16 @@
}
}
+// Return the full module name for a dependency module, which appends the apex module name unless re-using a system lib.
+func (a *apexBundle) fullModuleName(apexBundleName string, fi *apexFile) string {
+ linkToSystemLib := a.linkToSystemLib && fi.transitiveDep && fi.availableToPlatform()
+
+ if linkToSystemLib {
+ return fi.androidMkModuleName
+ }
+ return fi.androidMkModuleName + "." + apexBundleName + a.suffix
+}
+
func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, moduleDir string,
apexAndroidMkData android.AndroidMkData) []string {
@@ -114,12 +124,7 @@
linkToSystemLib := a.linkToSystemLib && fi.transitiveDep && fi.availableToPlatform()
- var moduleName string
- if linkToSystemLib {
- moduleName = fi.androidMkModuleName
- } else {
- moduleName = fi.androidMkModuleName + "." + apexBundleName + a.suffix
- }
+ moduleName := a.fullModuleName(apexBundleName, &fi)
if !android.InList(moduleName, moduleNames) {
moduleNames = append(moduleNames, moduleName)
@@ -311,14 +316,16 @@
return moduleNames
}
-func (a *apexBundle) writeRequiredModules(w io.Writer) {
+func (a *apexBundle) writeRequiredModules(w io.Writer, apexBundleName string) {
var required []string
var targetRequired []string
var hostRequired []string
+ installMapSet := make(map[string]bool) // set of dependency module:location mappings
for _, fi := range a.filesInfo {
required = append(required, fi.requiredModuleNames...)
targetRequired = append(targetRequired, fi.targetRequiredModuleNames...)
hostRequired = append(hostRequired, fi.hostRequiredModuleNames...)
+ installMapSet[a.fullModuleName(apexBundleName, &fi)+":"+fi.installDir+"/"+fi.builtFile.Base()] = true
}
if len(required) > 0 {
@@ -330,6 +337,11 @@
if len(hostRequired) > 0 {
fmt.Fprintln(w, "LOCAL_HOST_REQUIRED_MODULES +=", strings.Join(hostRequired, " "))
}
+ if len(installMapSet) > 0 {
+ var installs []string
+ installs = append(installs, android.SortedStringKeys(installMapSet)...)
+ fmt.Fprintln(w, "LOCAL_LICENSE_INSTALL_MAP +=", strings.Join(installs, " "))
+ }
}
func (a *apexBundle) androidMkForType() android.AndroidMkData {
@@ -347,16 +359,18 @@
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
fmt.Fprintln(w, "LOCAL_MODULE :=", name+a.suffix)
+ data.Entries.WriteLicenseVariables(w)
if len(moduleNames) > 0 {
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(moduleNames, " "))
}
- a.writeRequiredModules(w)
+ a.writeRequiredModules(w, name)
fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
} else {
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
fmt.Fprintln(w, "LOCAL_MODULE :=", name+a.suffix)
+ data.Entries.WriteLicenseVariables(w)
fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC") // do we need a new class?
fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", a.outputFile.String())
fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", a.installDir.ToMakePath().String())
@@ -389,7 +403,7 @@
if len(a.requiredDeps) > 0 {
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(a.requiredDeps, " "))
}
- a.writeRequiredModules(w)
+ a.writeRequiredModules(w, name)
var postInstallCommands []string
if a.prebuiltFileToDelete != "" {
postInstallCommands = append(postInstallCommands, "rm -rf "+
diff --git a/apex/apex.go b/apex/apex.go
index 2182069..a18e34b 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -30,6 +30,7 @@
"android/soong/bpf"
"android/soong/cc"
prebuilt_etc "android/soong/etc"
+ "android/soong/filesystem"
"android/soong/java"
"android/soong/python"
"android/soong/rust"
@@ -96,6 +97,9 @@
// List of BPF programs inside this APEX bundle.
Bpfs []string
+ // List of filesystem images that are embedded inside this APEX bundle.
+ Filesystems []string
+
// Name of the apex_key module that provides the private key to sign this APEX bundle.
Key *string
@@ -530,6 +534,7 @@
bpfTag = dependencyTag{name: "bpf", payload: true}
certificateTag = dependencyTag{name: "certificate"}
executableTag = dependencyTag{name: "executable", payload: true}
+ fsTag = dependencyTag{name: "filesystem", payload: true}
javaLibTag = dependencyTag{name: "javaLib", payload: true}
jniLibTag = dependencyTag{name: "jniLib", payload: true}
keyTag = dependencyTag{name: "key"}
@@ -709,6 +714,7 @@
commonVariation := ctx.Config().AndroidCommonTarget.Variations()
ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...)
ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.properties.Bpfs...)
+ ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
// With EMMA_INSTRUMENT_FRAMEWORK=true the ART boot image includes jacoco library.
if a.artApex && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
@@ -1481,6 +1487,11 @@
return newApexFile(ctx, builtFile, builtFile.Base(), dirInApex, etc, bpfProgram)
}
+func apexFileForFilesystem(ctx android.BaseModuleContext, buildFile android.Path, fs filesystem.Filesystem) apexFile {
+ dirInApex := filepath.Join("etc", "fs")
+ return newApexFile(ctx, buildFile, buildFile.Base(), dirInApex, etc, fs)
+}
+
// WalyPayloadDeps visits dependencies that contributes to the payload of this APEX. For each of the
// visited module, the `do` callback is executed. Returning true in the callback continues the visit
// to the child modules. Returning false makes the visit to continue in the sibling or the parent
@@ -1655,6 +1666,12 @@
} else {
ctx.PropertyErrorf("bpfs", "%q is not a bpf module", depName)
}
+ case fsTag:
+ if fs, ok := child.(filesystem.Filesystem); ok {
+ filesInfo = append(filesInfo, apexFileForFilesystem(ctx, fs.OutputPath(), fs))
+ } else {
+ ctx.PropertyErrorf("filesystems", "%q is not a filesystem module", depName)
+ }
case prebuiltTag:
if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
filesInfo = append(filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 84a8356..fc74672 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -250,7 +250,7 @@
ctx.RegisterModuleType("cc_test", cc.TestFactory)
ctx.RegisterModuleType("vndk_prebuilt_shared", cc.VndkPrebuiltSharedFactory)
- ctx.RegisterModuleType("vndk_libraries_txt", cc.VndkLibrariesTxtFactory)
+ cc.RegisterVndkLibraryTxtTypes(ctx)
prebuilt_etc.RegisterPrebuiltEtcBuildComponents(ctx)
ctx.RegisterModuleType("platform_compat_config", java.PlatformCompatConfigFactory)
ctx.RegisterModuleType("sh_binary", sh.ShBinaryFactory)
@@ -3150,6 +3150,7 @@
"etc/vndkcore.libraries.VER.txt",
"etc/vndksp.libraries.VER.txt",
"etc/vndkprivate.libraries.VER.txt",
+ "etc/vndkproduct.libraries.VER.txt",
})
}
@@ -3216,15 +3217,15 @@
func vndkLibrariesTxtFiles(vers ...string) (result string) {
for _, v := range vers {
if v == "current" {
- for _, txt := range []string{"llndk", "vndkcore", "vndksp", "vndkprivate"} {
+ for _, txt := range []string{"llndk", "vndkcore", "vndksp", "vndkprivate", "vndkproduct"} {
result += `
- vndk_libraries_txt {
+ ` + txt + `_libraries_txt {
name: "` + txt + `.libraries.txt",
}
`
}
} else {
- for _, txt := range []string{"llndk", "vndkcore", "vndksp", "vndkprivate"} {
+ for _, txt := range []string{"llndk", "vndkcore", "vndksp", "vndkprivate", "vndkproduct"} {
result += `
prebuilt_etc {
name: "` + txt + `.libraries.` + v + `.txt",
diff --git a/apex/vndk_test.go b/apex/vndk_test.go
index 27d93ee..ccf4e57 100644
--- a/apex/vndk_test.go
+++ b/apex/vndk_test.go
@@ -60,6 +60,7 @@
"etc/vndkcore.libraries.VER.txt",
"etc/vndksp.libraries.VER.txt",
"etc/vndkprivate.libraries.VER.txt",
+ "etc/vndkproduct.libraries.VER.txt",
})
}
diff --git a/bpf/bpf.go b/bpf/bpf.go
index 297e13a..8142f10 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -120,6 +120,7 @@
names = append(names, objName)
fmt.Fprintln(w, "include $(CLEAR_VARS)")
fmt.Fprintln(w, "LOCAL_MODULE := ", objName)
+ data.Entries.WriteLicenseVariables(w)
fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", obj.String())
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", obj.Base())
fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC")
@@ -129,6 +130,7 @@
}
fmt.Fprintln(w, "include $(CLEAR_VARS)")
fmt.Fprintln(w, "LOCAL_MODULE := ", name)
+ data.Entries.WriteLicenseVariables(w)
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(names, " "))
fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
},
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 4ada55d..040aa0b 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -519,9 +519,7 @@
entries.SubName += ".cfi"
}
- if c.androidMkVendorSuffix {
- entries.SubName += vendorSuffix
- }
+ entries.SubName += c.androidMkSuffix
entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
c.libraryDecorator.androidMkWriteExportedFlags(entries)
@@ -548,12 +546,7 @@
func (c *snapshotBinaryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
entries.Class = "EXECUTABLES"
-
- if c.androidMkVendorSuffix {
- entries.SubName = vendorSuffix
- } else {
- entries.SubName = ""
- }
+ entries.SubName = c.androidMkSuffix
entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
entries.AddStrings("LOCAL_MODULE_SYMLINKS", c.Properties.Symlinks...)
@@ -562,12 +555,7 @@
func (c *snapshotObjectLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
entries.Class = "STATIC_LIBRARIES"
-
- if c.androidMkVendorSuffix {
- entries.SubName = vendorSuffix
- } else {
- entries.SubName = ""
- }
+ entries.SubName = c.androidMkSuffix
entries.ExtraFooters = append(entries.ExtraFooters,
func(w io.Writer, name, prefix, moduleDir string) {
diff --git a/cc/cc.go b/cc/cc.go
index ae11aa1..f45b654 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -52,6 +52,8 @@
ctx.BottomUp("sysprop_cc", SyspropMutator).Parallel()
ctx.BottomUp("vendor_snapshot", VendorSnapshotMutator).Parallel()
ctx.BottomUp("vendor_snapshot_source", VendorSnapshotSourceMutator).Parallel()
+ ctx.BottomUp("recovery_snapshot", RecoverySnapshotMutator).Parallel()
+ ctx.BottomUp("recovery_snapshot_source", RecoverySnapshotSourceMutator).Parallel()
})
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
@@ -334,10 +336,16 @@
// Normally Soong uses the directory structure to decide which modules
// should be included (framework) or excluded (non-framework) from the
- // different snapshots (vendor, recovery, etc.), but these properties
- // allow a partner to exclude a module normally thought of as a
- // framework module from a snapshot.
- Exclude_from_vendor_snapshot *bool
+ // different snapshots (vendor, recovery, etc.), but this property
+ // allows a partner to exclude a module normally thought of as a
+ // framework module from the vendor snapshot.
+ Exclude_from_vendor_snapshot *bool
+
+ // Normally Soong uses the directory structure to decide which modules
+ // should be included (framework) or excluded (non-framework) from the
+ // different snapshots (vendor, recovery, etc.), but this property
+ // allows a partner to exclude a module normally thought of as a
+ // framework module from the recovery snapshot.
Exclude_from_recovery_snapshot *bool
// List of APEXes that this module has private access to for testing purpose. The module
@@ -411,7 +419,7 @@
IsLLNDK bool `blueprint:"mutated"`
// IsLLNDKPrivate is set to true for the vendor variant of a cc_library module that has LLNDK
- // stubs and also sets llndk.vendor_available: false.
+ // stubs and also sets llndk.private: true.
IsLLNDKPrivate bool `blueprint:"mutated"`
}
@@ -1071,11 +1079,11 @@
func (c *Module) isImplementationForLLNDKPublic() bool {
library, _ := c.library.(*libraryDecorator)
return library != nil && library.hasLLNDKStubs() &&
- (Bool(library.Properties.Llndk.Vendor_available) ||
+ (!Bool(library.Properties.Llndk.Private) ||
// TODO(b/170784825): until the LLNDK properties are moved into the cc_library,
// the non-Vendor variants of the cc_library don't know if the corresponding
- // llndk_library set vendor_available: false. Since libft2 is the only
- // private LLNDK library, hardcode it during the transition.
+ // llndk_library set private: true. Since libft2 is the only private LLNDK
+ // library, hardcode it during the transition.
c.BaseModuleName() != "libft2")
}
@@ -1083,20 +1091,12 @@
func (c *Module) IsVndkPrivate() bool {
// Check if VNDK-core-private or VNDK-SP-private
if c.IsVndk() {
- if Bool(c.vndkdep.Properties.Vndk.Private) {
- return true
- }
- // TODO(b/175768895) remove this when we clean up "vendor_available: false" use cases.
- if c.VendorProperties.Vendor_available != nil && !Bool(c.VendorProperties.Vendor_available) {
- return true
- }
- return false
+ return Bool(c.vndkdep.Properties.Vndk.Private)
}
// Check if LLNDK-private
if library, ok := c.library.(*libraryDecorator); ok && c.IsLlndk() {
- // TODO(b/175768895) replace this with 'private' property.
- return !Bool(library.Properties.Llndk.Vendor_available)
+ return Bool(library.Properties.Llndk.Private)
}
return false
@@ -1634,8 +1634,9 @@
// Note: this is still non-installable
}
- // glob exported headers for snapshot, if BOARD_VNDK_VERSION is current.
- if i, ok := c.linker.(snapshotLibraryInterface); ok && ctx.DeviceConfig().VndkVersion() == "current" {
+ // glob exported headers for snapshot, if BOARD_VNDK_VERSION is current or
+ // RECOVERY_SNAPSHOT_VERSION is current.
+ if i, ok := c.linker.(snapshotLibraryInterface); ok {
if shouldCollectHeadersForSnapshot(ctx, c, apexInfo) {
i.collectHeadersForSnapshot(ctx)
}
@@ -1877,6 +1878,7 @@
vendorPublicLibraries := vendorPublicLibraries(actx.Config())
vendorSnapshotSharedLibs := vendorSnapshotSharedLibs(actx.Config())
+ recoverySnapshotSharedLibs := recoverySnapshotSharedLibs(actx.Config())
rewriteVendorLibs := func(lib string) string {
// only modules with BOARD_VNDK_VERSION uses snapshot.
@@ -1897,7 +1899,19 @@
for _, entry := range list {
// strip #version suffix out
name, _ := StubsLibNameAndVersion(entry)
- if ctx.useSdk() && inList(name, *getNDKKnownLibs(ctx.Config())) {
+ if c.InRecovery() {
+ recoverySnapshotVersion :=
+ actx.DeviceConfig().RecoverySnapshotVersion()
+ if recoverySnapshotVersion == "current" ||
+ recoverySnapshotVersion == "" {
+ nonvariantLibs = append(nonvariantLibs, name)
+ } else if snapshot, ok := recoverySnapshotSharedLibs.get(
+ name, actx.Arch().ArchType); ok {
+ nonvariantLibs = append(nonvariantLibs, snapshot)
+ } else {
+ nonvariantLibs = append(nonvariantLibs, name)
+ }
+ } else if ctx.useSdk() && inList(name, *getNDKKnownLibs(ctx.Config())) {
variantLibs = append(variantLibs, name+ndkLibrarySuffix)
} else if ctx.useVndk() {
nonvariantLibs = append(nonvariantLibs, rewriteVendorLibs(entry))
@@ -1942,14 +1956,36 @@
return lib
}
- vendorSnapshotHeaderLibs := vendorSnapshotHeaderLibs(actx.Config())
+ snapshotHeaderLibs := vendorSnapshotHeaderLibs(actx.Config())
+ snapshotStaticLibs := vendorSnapshotStaticLibs(actx.Config())
+ snapshotObjects := vendorSnapshotObjects(actx.Config())
+
+ if c.InRecovery() {
+ rewriteSnapshotLibs = func(lib string, snapshotMap *snapshotMap) string {
+ recoverySnapshotVersion :=
+ actx.DeviceConfig().RecoverySnapshotVersion()
+ if recoverySnapshotVersion == "current" ||
+ recoverySnapshotVersion == "" {
+ return lib
+ } else if snapshot, ok := snapshotMap.get(lib, actx.Arch().ArchType); ok {
+ return snapshot
+ }
+
+ return lib
+ }
+
+ snapshotHeaderLibs = recoverySnapshotHeaderLibs(actx.Config())
+ snapshotStaticLibs = recoverySnapshotStaticLibs(actx.Config())
+ snapshotObjects = recoverySnapshotObjects(actx.Config())
+ }
+
for _, lib := range deps.HeaderLibs {
depTag := libraryDependencyTag{Kind: headerLibraryDependency}
if inList(lib, deps.ReexportHeaderLibHeaders) {
depTag.reexportFlags = true
}
- lib = rewriteSnapshotLibs(lib, vendorSnapshotHeaderLibs)
+ lib = rewriteSnapshotLibs(lib, snapshotHeaderLibs)
if c.IsStubs() {
actx.AddFarVariationDependencies(append(ctx.Target().Variations(), c.ImageVariation()),
@@ -1965,7 +2001,6 @@
// map from sysprop_library to implementation library; it will be used in whole_static_libs,
// static_libs, and shared_libs.
syspropImplLibraries := syspropImplLibraries(actx.Config())
- vendorSnapshotStaticLibs := vendorSnapshotStaticLibs(actx.Config())
for _, lib := range deps.WholeStaticLibs {
depTag := libraryDependencyTag{Kind: staticLibraryDependency, wholeStatic: true, reexportFlags: true}
@@ -1973,7 +2008,7 @@
lib = impl
}
- lib = rewriteSnapshotLibs(lib, vendorSnapshotStaticLibs)
+ lib = rewriteSnapshotLibs(lib, snapshotStaticLibs)
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
@@ -1993,7 +2028,7 @@
lib = impl
}
- lib = rewriteSnapshotLibs(lib, vendorSnapshotStaticLibs)
+ lib = rewriteSnapshotLibs(lib, snapshotStaticLibs)
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
@@ -2007,14 +2042,14 @@
depTag := libraryDependencyTag{Kind: staticLibraryDependency, staticUnwinder: true}
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
- }, depTag, rewriteSnapshotLibs(staticUnwinder(actx), vendorSnapshotStaticLibs))
+ }, depTag, rewriteSnapshotLibs(staticUnwinder(actx), snapshotStaticLibs))
}
for _, lib := range deps.LateStaticLibs {
depTag := libraryDependencyTag{Kind: staticLibraryDependency, Order: lateLibraryDependency}
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
- }, depTag, rewriteSnapshotLibs(lib, vendorSnapshotStaticLibs))
+ }, depTag, rewriteSnapshotLibs(lib, snapshotStaticLibs))
}
// shared lib names without the #version suffix
@@ -2074,17 +2109,15 @@
actx.AddDependency(c, depTag, gen)
}
- vendorSnapshotObjects := vendorSnapshotObjects(actx.Config())
-
crtVariations := GetCrtVariations(ctx, c)
actx.AddVariationDependencies(crtVariations, objDepTag, deps.ObjFiles...)
if deps.CrtBegin != "" {
actx.AddVariationDependencies(crtVariations, CrtBeginDepTag,
- rewriteSnapshotLibs(deps.CrtBegin, vendorSnapshotObjects))
+ rewriteSnapshotLibs(deps.CrtBegin, snapshotObjects))
}
if deps.CrtEnd != "" {
actx.AddVariationDependencies(crtVariations, CrtEndDepTag,
- rewriteSnapshotLibs(deps.CrtEnd, vendorSnapshotObjects))
+ rewriteSnapshotLibs(deps.CrtEnd, snapshotObjects))
}
if deps.LinkerFlagsFile != "" {
actx.AddDependency(c, linkerFlagsDepTag, deps.LinkerFlagsFile)
@@ -2796,6 +2829,7 @@
func (c *Module) makeLibName(ctx android.ModuleContext, ccDep LinkableInterface, depName string) string {
vendorSuffixModules := vendorSuffixModules(ctx.Config())
+ recoverySuffixModules := recoverySuffixModules(ctx.Config())
vendorPublicLibraries := vendorPublicLibraries(ctx.Config())
libName := baseLibName(depName)
@@ -2813,8 +2847,10 @@
return baseName + ".vendor"
}
- if vendorSuffixModules[baseName] {
+ if c.inVendor() && vendorSuffixModules[baseName] {
return baseName + ".vendor"
+ } else if c.InRecovery() && recoverySuffixModules[baseName] {
+ return baseName + ".recovery"
} else {
return baseName
}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index fb85336..3502d5f 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -68,6 +68,7 @@
t.Helper()
config := TestConfig(buildDir, android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+ config.TestProductVariables.ProductVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
return testCcWithConfig(t, config)
@@ -81,6 +82,15 @@
return testCcWithConfig(t, config)
}
+func testCcNoProductVndk(t *testing.T, bp string) *android.TestContext {
+ t.Helper()
+ config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+
+ return testCcWithConfig(t, config)
+}
+
func testCcErrorWithConfig(t *testing.T, pattern string, config android.Config) {
t.Helper()
@@ -224,9 +234,6 @@
t.Helper()
mod := ctx.ModuleForTests(name, variant).Module().(*Module)
- if !mod.HasVendorVariant() {
- t.Errorf("%q must have variant %q", name, variant)
- }
// Check library properties.
lib, ok := mod.compiler.(*libraryDecorator)
@@ -408,20 +415,24 @@
},
}
- vndk_libraries_txt {
+ llndk_libraries_txt {
name: "llndk.libraries.txt",
}
- vndk_libraries_txt {
+ vndkcore_libraries_txt {
name: "vndkcore.libraries.txt",
}
- vndk_libraries_txt {
+ vndksp_libraries_txt {
name: "vndksp.libraries.txt",
}
- vndk_libraries_txt {
+ vndkprivate_libraries_txt {
name: "vndkprivate.libraries.txt",
}
- vndk_libraries_txt {
+ vndkproduct_libraries_txt {
+ name: "vndkproduct.libraries.txt",
+ }
+ vndkcorevariant_libraries_txt {
name: "vndkcorevariant.libraries.txt",
+ insert_vndk_version: false,
}
`
@@ -445,7 +456,6 @@
checkVndkModule(t, ctx, "libvndk_sp_product_private", "", true, "", productVariant)
// Check VNDK snapshot output.
-
snapshotDir := "vndk-snapshot"
snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
@@ -476,6 +486,7 @@
checkSnapshot(t, ctx, snapshotSingleton, "vndkcore.libraries.txt", "vndkcore.libraries.txt", snapshotConfigsPath, "")
checkSnapshot(t, ctx, snapshotSingleton, "vndksp.libraries.txt", "vndksp.libraries.txt", snapshotConfigsPath, "")
checkSnapshot(t, ctx, snapshotSingleton, "vndkprivate.libraries.txt", "vndkprivate.libraries.txt", snapshotConfigsPath, "")
+ checkSnapshot(t, ctx, snapshotSingleton, "vndkproduct.libraries.txt", "vndkproduct.libraries.txt", snapshotConfigsPath, "")
checkVndkOutput(t, ctx, "vndk/vndk.libraries.txt", []string{
"LLNDK: libc.so",
@@ -493,11 +504,15 @@
"VNDK-private: libvndk-private.so",
"VNDK-private: libvndk_sp_private-x.so",
"VNDK-private: libvndk_sp_product_private-x.so",
+ "VNDK-product: libc++.so",
+ "VNDK-product: libvndk_product.so",
+ "VNDK-product: libvndk_sp_product_private-x.so",
})
checkVndkLibrariesOutput(t, ctx, "llndk.libraries.txt", []string{"libc.so", "libdl.so", "libft2.so", "libm.so"})
checkVndkLibrariesOutput(t, ctx, "vndkcore.libraries.txt", []string{"libvndk-private.so", "libvndk.so", "libvndk_product.so"})
checkVndkLibrariesOutput(t, ctx, "vndksp.libraries.txt", []string{"libc++.so", "libvndk_sp-x.so", "libvndk_sp_private-x.so", "libvndk_sp_product_private-x.so"})
checkVndkLibrariesOutput(t, ctx, "vndkprivate.libraries.txt", []string{"libft2.so", "libvndk-private.so", "libvndk_sp_private-x.so", "libvndk_sp_product_private-x.so"})
+ checkVndkLibrariesOutput(t, ctx, "vndkproduct.libraries.txt", []string{"libc++.so", "libvndk_product.so", "libvndk_sp_product_private-x.so"})
checkVndkLibrariesOutput(t, ctx, "vndkcorevariant.libraries.txt", nil)
}
@@ -529,7 +544,7 @@
}
}
- vndk_libraries_txt {
+ vndkcore_libraries_txt {
name: "vndkcore.libraries.txt",
}
`)
@@ -539,8 +554,9 @@
func TestVndkLibrariesTxtAndroidMk(t *testing.T) {
bp := `
- vndk_libraries_txt {
+ llndk_libraries_txt {
name: "llndk.libraries.txt",
+ insert_vndk_version: true,
}`
config := TestConfig(buildDir, android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
@@ -586,8 +602,9 @@
nocrt: true,
}
- vndk_libraries_txt {
+ vndkcorevariant_libraries_txt {
name: "vndkcorevariant.libraries.txt",
+ insert_vndk_version: false,
}
`
@@ -711,6 +728,16 @@
},
nocrt: true,
}
+ cc_library {
+ name: "libvndk-private",
+ vendor_available: true,
+ product_available: true,
+ vndk: {
+ enabled: true,
+ private: true,
+ },
+ nocrt: true,
+ }
`)
checkVndkOutput(t, ctx, "vndk/vndk.libraries.txt", []string{
@@ -719,14 +746,19 @@
"LLNDK: libft2.so",
"LLNDK: libm.so",
"VNDK-SP: libc++.so",
+ "VNDK-core: libvndk-private.so",
"VNDK-core: libvndk.so",
"VNDK-private: libft2.so",
+ "VNDK-private: libvndk-private.so",
+ "VNDK-product: libc++.so",
+ "VNDK-product: libvndk-private.so",
+ "VNDK-product: libvndk.so",
})
}
func TestVndkModuleError(t *testing.T) {
// Check the error message for vendor_available and product_available properties.
- testCcErrorProductVndk(t, "vndk: vendor_available must be set to either true or false when `vndk: {enabled: true}`", `
+ testCcErrorProductVndk(t, "vndk: vendor_available must be set to true when `vndk: {enabled: true}`", `
cc_library {
name: "libvndk",
vndk: {
@@ -736,7 +768,7 @@
}
`)
- testCcErrorProductVndk(t, "vndk: vendor_available must be set to either true or false when `vndk: {enabled: true}`", `
+ testCcErrorProductVndk(t, "vndk: vendor_available must be set to true when `vndk: {enabled: true}`", `
cc_library {
name: "libvndk",
product_available: true,
@@ -1214,6 +1246,15 @@
t.Errorf("%q expected but not found", jsonFile)
}
}
+
+ // fake snapshot should have all outputs in the normal snapshot.
+ fakeSnapshotSingleton := ctx.SingletonForTests("vendor-fake-snapshot")
+ for _, output := range snapshotSingleton.AllOutputs() {
+ fakeOutput := strings.Replace(output, "/vendor-snapshot/", "/fake/vendor-snapshot/", 1)
+ if fakeSnapshotSingleton.MaybeOutput(fakeOutput).Rule == nil {
+ t.Errorf("%q expected but not found", fakeOutput)
+ }
+ }
}
func TestVendorSnapshotUse(t *testing.T) {
@@ -1492,6 +1533,13 @@
}
}
+func assertExcludeFromRecoverySnapshotIs(t *testing.T, c *Module, expected bool) {
+ t.Helper()
+ if c.ExcludeFromRecoverySnapshot() != expected {
+ t.Errorf("expected %q ExcludeFromRecoverySnapshot to be %t", c.String(), expected)
+ }
+}
+
func TestVendorSnapshotExclude(t *testing.T) {
// This test verifies that the exclude_from_vendor_snapshot property
@@ -1638,6 +1686,8 @@
`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
`module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
+ `module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
+ `module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
})
}
@@ -1681,6 +1731,10 @@
`module "libinclude\{.+,image:,arch:arm_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
`module "libinclude\{.+,image:vendor.+,arch:arm64_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
`module "libinclude\{.+,image:vendor.+,arch:arm_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
+ `module "libinclude\{.+,image:,arch:arm64_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
+ `module "libinclude\{.+,image:,arch:arm_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
+ `module "libinclude\{.+,image:vendor.+,arch:arm64_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
+ `module "libinclude\{.+,image:vendor.+,arch:arm_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
})
}
@@ -1739,7 +1793,7 @@
}
`
config := TestConfig(buildDir, android.Android, nil, bp, nil)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+ config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
ctx := testCcWithConfig(t, config)
@@ -1810,6 +1864,111 @@
}
}
+func TestRecoverySnapshotExclude(t *testing.T) {
+ // This test verifies that the exclude_from_recovery_snapshot property
+ // makes its way from the Android.bp source file into the module data
+ // structure. It also verifies that modules are correctly included or
+ // excluded in the recovery snapshot based on their path (framework or
+ // vendor) and the exclude_from_recovery_snapshot property.
+
+ frameworkBp := `
+ cc_library_shared {
+ name: "libinclude",
+ srcs: ["src/include.cpp"],
+ recovery_available: true,
+ }
+ cc_library_shared {
+ name: "libexclude",
+ srcs: ["src/exclude.cpp"],
+ recovery: true,
+ exclude_from_recovery_snapshot: true,
+ }
+ `
+
+ vendorProprietaryBp := `
+ cc_library_shared {
+ name: "libvendor",
+ srcs: ["vendor.cpp"],
+ recovery: true,
+ }
+ `
+
+ depsBp := GatherRequiredDepsForTest(android.Android)
+
+ mockFS := map[string][]byte{
+ "deps/Android.bp": []byte(depsBp),
+ "framework/Android.bp": []byte(frameworkBp),
+ "framework/include.cpp": nil,
+ "framework/exclude.cpp": nil,
+ "device/Android.bp": []byte(vendorProprietaryBp),
+ "device/vendor.cpp": nil,
+ }
+
+ config := TestConfig(buildDir, android.Android, nil, "", mockFS)
+ config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+ ctx := CreateTestContext(config)
+ ctx.Register()
+
+ _, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "device/Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ android.FailIfErrored(t, errs)
+
+ // Test an include and exclude framework module.
+ assertExcludeFromRecoverySnapshotIs(t, ctx.ModuleForTests("libinclude", coreVariant).Module().(*Module), false)
+ assertExcludeFromRecoverySnapshotIs(t, ctx.ModuleForTests("libinclude", recoveryVariant).Module().(*Module), false)
+ assertExcludeFromRecoverySnapshotIs(t, ctx.ModuleForTests("libexclude", recoveryVariant).Module().(*Module), true)
+
+ // A vendor module is excluded, but by its path, not the
+ // exclude_from_recovery_snapshot property.
+ assertExcludeFromRecoverySnapshotIs(t, ctx.ModuleForTests("libvendor", recoveryVariant).Module().(*Module), false)
+
+ // Verify the content of the recovery snapshot.
+
+ snapshotDir := "recovery-snapshot"
+ snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+ snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
+
+ var includeJsonFiles []string
+ var excludeJsonFiles []string
+
+ for _, arch := range [][]string{
+ []string{"arm64", "armv8-a"},
+ } {
+ archType := arch[0]
+ archVariant := arch[1]
+ archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
+
+ sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
+ sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
+
+ // Included modules
+ checkSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
+
+ // Excluded modules
+ checkSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json"))
+ checkSnapshotExclude(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libvendor.so.json"))
+ }
+
+ // Verify that each json file for an included module has a rule.
+ for _, jsonFile := range includeJsonFiles {
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
+ t.Errorf("include json file %q not found", jsonFile)
+ }
+ }
+
+ // Verify that each json file for an excluded module has no rule.
+ for _, jsonFile := range excludeJsonFiles {
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule != nil {
+ t.Errorf("exclude json file %q found", jsonFile)
+ }
+ }
+}
+
func TestDoubleLoadableDepError(t *testing.T) {
// Check whether an error is emitted when a LLNDK depends on a non-double_loadable VNDK lib.
testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
@@ -2088,7 +2247,7 @@
func TestVndkExtWithoutProductVndkVersion(t *testing.T) {
// This test checks the VNDK-Ext properties when PRODUCT_PRODUCT_VNDK_VERSION is not set.
- ctx := testCc(t, `
+ ctx := testCcNoProductVndk(t, `
cc_library {
name: "libvndk",
vendor_available: true,
@@ -2993,7 +3152,7 @@
}
llndk_library {
name: "libllndkprivate.llndk",
- vendor_available: false,
+ private: true,
symbol_file: "",
}`
@@ -3400,8 +3559,17 @@
const runtimeLibAndroidBp = `
cc_library {
+ name: "liball_available",
+ vendor_available: true,
+ product_available: true,
+ no_libcrt : true,
+ nocrt : true,
+ system_shared_libs : [],
+ }
+ cc_library {
name: "libvendor_available1",
vendor_available: true,
+ runtime_libs: ["liball_available"],
no_libcrt : true,
nocrt : true,
system_shared_libs : [],
@@ -3409,18 +3577,10 @@
cc_library {
name: "libvendor_available2",
vendor_available: true,
- runtime_libs: ["libvendor_available1"],
- no_libcrt : true,
- nocrt : true,
- system_shared_libs : [],
- }
- cc_library {
- name: "libvendor_available3",
- vendor_available: true,
- runtime_libs: ["libvendor_available1"],
+ runtime_libs: ["liball_available"],
target: {
vendor: {
- exclude_runtime_libs: ["libvendor_available1"],
+ exclude_runtime_libs: ["liball_available"],
}
},
no_libcrt : true,
@@ -3429,7 +3589,7 @@
}
cc_library {
name: "libcore",
- runtime_libs: ["libvendor_available1"],
+ runtime_libs: ["liball_available"],
no_libcrt : true,
nocrt : true,
system_shared_libs : [],
@@ -3444,7 +3604,30 @@
cc_library {
name: "libvendor2",
vendor: true,
- runtime_libs: ["libvendor_available1", "libvendor1"],
+ runtime_libs: ["liball_available", "libvendor1"],
+ no_libcrt : true,
+ nocrt : true,
+ system_shared_libs : [],
+ }
+ cc_library {
+ name: "libproduct_available1",
+ product_available: true,
+ runtime_libs: ["liball_available"],
+ no_libcrt : true,
+ nocrt : true,
+ system_shared_libs : [],
+ }
+ cc_library {
+ name: "libproduct1",
+ product_specific: true,
+ no_libcrt : true,
+ nocrt : true,
+ system_shared_libs : [],
+ }
+ cc_library {
+ name: "libproduct2",
+ product_specific: true,
+ runtime_libs: ["liball_available", "libproduct1"],
no_libcrt : true,
nocrt : true,
system_shared_libs : [],
@@ -3457,32 +3640,45 @@
// runtime_libs for core variants use the module names without suffixes.
variant := "android_arm64_armv8-a_shared"
- module := ctx.ModuleForTests("libvendor_available2", variant).Module().(*Module)
- checkRuntimeLibs(t, []string{"libvendor_available1"}, module)
+ module := ctx.ModuleForTests("libvendor_available1", variant).Module().(*Module)
+ checkRuntimeLibs(t, []string{"liball_available"}, module)
+
+ module = ctx.ModuleForTests("libproduct_available1", variant).Module().(*Module)
+ checkRuntimeLibs(t, []string{"liball_available"}, module)
module = ctx.ModuleForTests("libcore", variant).Module().(*Module)
- checkRuntimeLibs(t, []string{"libvendor_available1"}, module)
+ checkRuntimeLibs(t, []string{"liball_available"}, module)
// runtime_libs for vendor variants have '.vendor' suffixes if the modules have both core
// and vendor variants.
variant = "android_vendor.VER_arm64_armv8-a_shared"
- module = ctx.ModuleForTests("libvendor_available2", variant).Module().(*Module)
- checkRuntimeLibs(t, []string{"libvendor_available1.vendor"}, module)
+ module = ctx.ModuleForTests("libvendor_available1", variant).Module().(*Module)
+ checkRuntimeLibs(t, []string{"liball_available.vendor"}, module)
module = ctx.ModuleForTests("libvendor2", variant).Module().(*Module)
- checkRuntimeLibs(t, []string{"libvendor_available1.vendor", "libvendor1"}, module)
+ checkRuntimeLibs(t, []string{"liball_available.vendor", "libvendor1"}, module)
+
+ // runtime_libs for product variants have '.product' suffixes if the modules have both core
+ // and product variants.
+ variant = "android_product.VER_arm64_armv8-a_shared"
+
+ module = ctx.ModuleForTests("libproduct_available1", variant).Module().(*Module)
+ checkRuntimeLibs(t, []string{"liball_available.product"}, module)
+
+ module = ctx.ModuleForTests("libproduct2", variant).Module().(*Module)
+ checkRuntimeLibs(t, []string{"liball_available.product", "libproduct1"}, module)
}
func TestExcludeRuntimeLibs(t *testing.T) {
ctx := testCc(t, runtimeLibAndroidBp)
variant := "android_arm64_armv8-a_shared"
- module := ctx.ModuleForTests("libvendor_available3", variant).Module().(*Module)
- checkRuntimeLibs(t, []string{"libvendor_available1"}, module)
+ module := ctx.ModuleForTests("libvendor_available2", variant).Module().(*Module)
+ checkRuntimeLibs(t, []string{"liball_available"}, module)
variant = "android_vendor.VER_arm64_armv8-a_shared"
- module = ctx.ModuleForTests("libvendor_available3", variant).Module().(*Module)
+ module = ctx.ModuleForTests("libvendor_available2", variant).Module().(*Module)
checkRuntimeLibs(t, nil, module)
}
@@ -3493,11 +3689,14 @@
variant := "android_arm64_armv8-a_shared"
- module := ctx.ModuleForTests("libvendor_available2", variant).Module().(*Module)
- checkRuntimeLibs(t, []string{"libvendor_available1"}, module)
+ module := ctx.ModuleForTests("libvendor_available1", variant).Module().(*Module)
+ checkRuntimeLibs(t, []string{"liball_available"}, module)
module = ctx.ModuleForTests("libvendor2", variant).Module().(*Module)
- checkRuntimeLibs(t, []string{"libvendor_available1", "libvendor1"}, module)
+ checkRuntimeLibs(t, []string{"liball_available", "libvendor1"}, module)
+
+ module = ctx.ModuleForTests("libproduct2", variant).Module().(*Module)
+ checkRuntimeLibs(t, []string{"liball_available", "libproduct1"}, module)
}
func checkStaticLibs(t *testing.T, expected []string, module *Module) {
@@ -4244,3 +4443,21 @@
t.Errorf("expected %q in cflags, got %q", "-Iinclude/libbar", cFlags)
}
}
+
+func TestAidlFlagsPassedToTheAidlCompiler(t *testing.T) {
+ ctx := testCc(t, `
+ cc_library {
+ name: "libfoo",
+ srcs: ["a/Foo.aidl"],
+ aidl: { flags: ["-Werror"], },
+ }
+ `)
+
+ libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static")
+ manifest := android.RuleBuilderSboxProtoForTests(t, libfoo.Output("aidl.sbox.textproto"))
+ aidlCommand := manifest.Commands[0].GetCommand()
+ expectedAidlFlag := "-Werror"
+ if !strings.Contains(aidlCommand, expectedAidlFlag) {
+ t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
+ }
+}
diff --git a/cc/compiler.go b/cc/compiler.go
index 2c05899..eb2b566 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -123,6 +123,9 @@
// whether to generate traces (for systrace) for this interface
Generate_traces *bool
+
+ // list of flags that will be passed to the AIDL compiler
+ Flags []string
}
Renderscript struct {
@@ -521,6 +524,7 @@
}
if compiler.hasSrcExt(".aidl") {
+ flags.aidlFlags = append(flags.aidlFlags, compiler.Properties.Aidl.Flags...)
if len(compiler.Properties.Aidl.Local_include_dirs) > 0 {
localAidlIncludeDirs := android.PathsForModuleSrc(ctx, compiler.Properties.Aidl.Local_include_dirs)
flags.aidlFlags = append(flags.aidlFlags, includeDirsToFlags(localAidlIncludeDirs))
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 519a9e2..3282958 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -94,6 +94,7 @@
// `modernize-*`.
var ClangTidyDisableChecks = []string{
"misc-no-recursion",
+ "readability-function-cognitive-complexity", // http://b/175055536
}
func init() {
@@ -190,6 +191,8 @@
"-Wno-pessimizing-move", // http://b/154270751
// New warnings to be fixed after clang-r399163
"-Wno-non-c-typedef-for-linkage", // http://b/161304145
+ // New warnings to be fixed after clang-r407598
+ "-Wno-string-concatenation", // http://b/175068488
}, " "))
// Extra cflags for external third-party projects to disable warnings that
diff --git a/cc/config/global.go b/cc/config/global.go
index e5cb7ee..fa8e0fb 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -135,8 +135,8 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r399163b"
- ClangDefaultShortVersion = "11.0.5"
+ ClangDefaultVersion = "clang-r407598"
+ ClangDefaultShortVersion = "12.0.1"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
diff --git a/cc/genrule.go b/cc/genrule.go
index 9648869..1ce2169 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -75,7 +75,15 @@
}
func (g *GenruleExtraProperties) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
- return Bool(g.Recovery_available)
+ // If the build is using a snapshot, the recovery variant under AOSP directories
+ // is not needed.
+ recoverySnapshotVersion := ctx.DeviceConfig().RecoverySnapshotVersion()
+ if recoverySnapshotVersion != "current" && recoverySnapshotVersion != "" &&
+ !isRecoveryProprietaryModule(ctx) {
+ return false
+ } else {
+ return Bool(g.Recovery_available)
+ }
}
func (g *GenruleExtraProperties) ExtraImageVariations(ctx android.BaseModuleContext) []string {
diff --git a/cc/image.go b/cc/image.go
index 13d77cc..12bd65b 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -67,14 +67,15 @@
)
func (ctx *moduleContext) ProductSpecific() bool {
- //TODO(b/150902910): Replace HasNonSystemVariants() with HasProductVariant()
- return ctx.ModuleContext.ProductSpecific() ||
- (ctx.mod.HasNonSystemVariants() && ctx.mod.InProduct())
+ // Additionally check if this module is inProduct() that means it is a "product" variant of a
+ // module. As well as product specific modules, product variants must be installed to /product.
+ return ctx.ModuleContext.ProductSpecific() || ctx.mod.InProduct()
}
func (ctx *moduleContext) SocSpecific() bool {
- return ctx.ModuleContext.SocSpecific() ||
- (ctx.mod.HasVendorVariant() && ctx.mod.inVendor())
+ // Additionally check if this module is inVendor() that means it is a "vendor" variant of a
+ // module. As well as SoC specific modules, vendor variants must be installed to /vendor.
+ return ctx.ModuleContext.SocSpecific() || ctx.mod.inVendor()
}
func (ctx *moduleContextImpl) inProduct() bool {
@@ -99,18 +100,12 @@
// Returns true when this module is configured to have core and vendor variants.
func (c *Module) HasVendorVariant() bool {
- // In case of a VNDK, 'vendor_available: false' still creates a vendor variant.
- return c.IsVndk() || Bool(c.VendorProperties.Vendor_available)
+ return Bool(c.VendorProperties.Vendor_available)
}
// Returns true when this module is configured to have core and product variants.
func (c *Module) HasProductVariant() bool {
- if c.VendorProperties.Product_available == nil {
- // Without 'product_available', product variant will not be created even for VNDKs.
- return false
- }
- // However, 'product_available: false' in a VNDK still creates a product variant.
- return c.IsVndk() || Bool(c.VendorProperties.Product_available)
+ return Bool(c.VendorProperties.Product_available)
}
// Returns true when this module is configured to have core and either product or vendor variants.
@@ -187,7 +182,7 @@
// This function is used only for the VNDK modules that is available to both vendor
// and product partitions.
func (c *Module) compareVendorAndProductProps() bool {
- if !c.IsVndk() && c.VendorProperties.Product_available != nil {
+ if !c.IsVndk() && !Bool(c.VendorProperties.Product_available) {
panic(fmt.Errorf("This is only for product available VNDK libs. %q is not a VNDK library or not product available", c.Name()))
}
for _, properties := range c.GetProperties() {
@@ -203,14 +198,14 @@
vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
productSpecific := mctx.ProductSpecific()
- if m.VendorProperties.Vendor_available != nil {
+ if Bool(m.VendorProperties.Vendor_available) {
if vendorSpecific {
mctx.PropertyErrorf("vendor_available",
"doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific:true`")
}
}
- if m.VendorProperties.Product_available != nil {
+ if Bool(m.VendorProperties.Product_available) {
if productSpecific {
mctx.PropertyErrorf("product_available",
"doesn't make sense at the same time as `product_specific: true`")
@@ -227,10 +222,10 @@
if !vndkdep.isVndkExt() {
mctx.PropertyErrorf("vndk",
"must set `extends: \"...\"` to vndk extension")
- } else if m.VendorProperties.Vendor_available != nil {
+ } else if Bool(m.VendorProperties.Vendor_available) {
mctx.PropertyErrorf("vendor_available",
"must not set at the same time as `vndk: {extends: \"...\"}`")
- } else if m.VendorProperties.Product_available != nil {
+ } else if Bool(m.VendorProperties.Product_available) {
mctx.PropertyErrorf("product_available",
"must not set at the same time as `vndk: {extends: \"...\"}`")
}
@@ -240,11 +235,11 @@
"must set `vendor: true` or `product_specific: true` to set `extends: %q`",
m.getVndkExtendsModuleName())
}
- if m.VendorProperties.Vendor_available == nil {
+ if !Bool(m.VendorProperties.Vendor_available) {
mctx.PropertyErrorf("vndk",
- "vendor_available must be set to either true or false when `vndk: {enabled: true}`")
+ "vendor_available must be set to true when `vndk: {enabled: true}`")
}
- if m.VendorProperties.Product_available != nil {
+ if Bool(m.VendorProperties.Product_available) {
// If a VNDK module creates both product and vendor variants, they
// must have the same properties since they share a single VNDK
// library on runtime.
@@ -277,6 +272,9 @@
platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
boardVndkVersion := mctx.DeviceConfig().VndkVersion()
productVndkVersion := mctx.DeviceConfig().ProductVndkVersion()
+ recoverySnapshotVersion := mctx.DeviceConfig().RecoverySnapshotVersion()
+ usingRecoverySnapshot := recoverySnapshotVersion != "current" &&
+ recoverySnapshotVersion != ""
if boardVndkVersion == "current" {
boardVndkVersion = platformVndkVersion
}
@@ -315,7 +313,11 @@
if snapshot, ok := m.linker.(interface {
version() string
}); ok {
- vendorVariants = append(vendorVariants, snapshot.version())
+ if m.InstallInRecovery() {
+ recoveryVariantNeeded = true
+ } else {
+ vendorVariants = append(vendorVariants, snapshot.version())
+ }
} else {
mctx.ModuleErrorf("version is unknown for snapshot prebuilt")
}
@@ -421,6 +423,15 @@
coreVariantNeeded = false
}
+ // If using a snapshot, the recovery variant under AOSP directories is not needed,
+ // except for kernel headers, which needs all variants.
+ if _, ok := m.linker.(*kernelHeadersDecorator); !ok &&
+ !m.isSnapshotPrebuilt() &&
+ usingRecoverySnapshot &&
+ !isRecoveryProprietaryModule(mctx) {
+ recoveryVariantNeeded = false
+ }
+
for _, variant := range android.FirstUniqueStrings(vendorVariants) {
m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, VendorVariationPrefix+variant)
}
@@ -433,6 +444,14 @@
m.Properties.VendorRamdiskVariantNeeded = vendorRamdiskVariantNeeded
m.Properties.RecoveryVariantNeeded = recoveryVariantNeeded
m.Properties.CoreVariantNeeded = coreVariantNeeded
+
+ // Disable the module if no variants are needed.
+ if !ramdiskVariantNeeded &&
+ !recoveryVariantNeeded &&
+ !coreVariantNeeded &&
+ len(m.Properties.ExtraVariants) == 0 {
+ m.Disable()
+ }
}
func (c *Module) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
diff --git a/cc/library.go b/cc/library.go
index 23556b0..bc6ff69 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1738,12 +1738,9 @@
isLLNDK := false
if m, ok := mctx.Module().(*Module); ok {
- isLLNDK = m.IsLlndk()
// Don't count the vestigial llndk_library module as isLLNDK, it needs a static
// variant so that a cc_library_prebuilt can depend on it.
- if _, ok := m.linker.(*llndkStubDecorator); ok {
- isLLNDK = false
- }
+ isLLNDK = m.IsLlndk() && !isVestigialLLNDKModule(m)
}
buildStatic := library.BuildStaticVariant() && !isLLNDK
buildShared := library.BuildSharedVariant()
@@ -1855,9 +1852,8 @@
Host() bool
InRamdisk() bool
InVendorRamdisk() bool
- InRecovery() bool
}) bool {
- return !module.Host() && !module.InRamdisk() && !module.InVendorRamdisk() && !module.InRecovery()
+ return !module.Host() && !module.InRamdisk() && !module.InVendorRamdisk()
}
func CanBeVersionVariant(module interface {
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index d0fbc48..bd48501 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -55,13 +55,6 @@
// Whether the system library uses symbol versions.
Unversioned *bool
- // whether this module can be directly depended upon by libs that are installed
- // to /vendor and /product.
- // When set to false, this module can only be depended on by VNDK libraries, not
- // vendor nor product libraries. This effectively hides this module from
- // non-system modules. Default value is true.
- Vendor_available *bool
-
// list of llndk headers to re-export include directories from.
Export_llndk_headers []string `android:"arch_variant"`
@@ -100,6 +93,11 @@
return name + llndkLibrarySuffix
}
+func (stub *llndkStubDecorator) linkerProps() []interface{} {
+ props := stub.libraryDecorator.linkerProps()
+ return append(props, &stub.Properties)
+}
+
func (stub *llndkStubDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
stub.libraryDecorator.libName = stub.implementationModuleName(ctx.ModuleName())
return stub.libraryDecorator.linkerFlags(ctx, flags)
@@ -131,18 +129,11 @@
stub := &llndkStubDecorator{
libraryDecorator: library,
}
- stub.Properties.Vendor_available = BoolPtr(true)
module.compiler = stub
module.linker = stub
module.installer = nil
module.library = stub
- module.AddProperties(
- &module.Properties,
- &stub.Properties,
- &library.MutatedProperties,
- &library.flagExporter.Properties)
-
return module
}
@@ -156,8 +147,14 @@
// }
func LlndkLibraryFactory() android.Module {
module := NewLLndkStubLibrary()
- android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
- return module
+ return module.Init()
+}
+
+// isVestigialLLNDKModule returns true if m is a vestigial llndk_library module used to provide
+// properties to the LLNDK variant of a cc_library.
+func isVestigialLLNDKModule(m *Module) bool {
+ _, ok := m.linker.(*llndkStubDecorator)
+ return ok
}
type llndkHeadersDecorator struct {
diff --git a/cc/makevars.go b/cc/makevars.go
index bd8aab5..8301c6b 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -99,6 +99,7 @@
ctx.Strict("GLOBAL_CLANG_CPPFLAGS_NO_OVERRIDE", "")
ctx.Strict("BOARD_VNDK_VERSION", ctx.DeviceConfig().VndkVersion())
+ ctx.Strict("RECOVERY_SNAPSHOT_VERSION", ctx.DeviceConfig().RecoverySnapshotVersion())
// Filter vendor_public_library that are exported to make
exportedVendorPublicLibraries := []string{}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 0e2d01a..bb92a88 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -458,6 +458,22 @@
return false
}
+func toDisableUnsignedShiftBaseChange(flags []string) bool {
+ // Returns true if any flag is fsanitize*integer, and there is
+ // no explicit flag about sanitize=unsigned-shift-base.
+ for _, f := range flags {
+ if strings.Contains(f, "sanitize=unsigned-shift-base") {
+ return false
+ }
+ }
+ for _, f := range flags {
+ if strings.HasPrefix(f, "-fsanitize") && strings.Contains(f, "integer") {
+ return true
+ }
+ }
+ return false
+}
+
func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags {
minimalRuntimeLib := config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(ctx.toolchain()) + ".a"
minimalRuntimePath := "${config.ClangAsanLibDir}/" + minimalRuntimeLib
@@ -614,6 +630,10 @@
if toDisableImplicitIntegerChange(flags.Local.CFlags) {
flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize=implicit-integer-sign-change")
}
+ // http://b/171275751, Android doesn't build with this sanitizer yet.
+ if toDisableUnsignedShiftBaseChange(flags.Local.CFlags) {
+ flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize=unsigned-shift-base")
+ }
}
if len(sanitize.Properties.DiagSanitizers) > 0 {
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index 4c4e9b6..e3f3a4d 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -22,6 +22,8 @@
"sync"
"android/soong/android"
+
+ "github.com/google/blueprint/proptools"
)
// Defines the specifics of different images to which the snapshot process is applicable, e.g.,
@@ -30,6 +32,9 @@
// Used to register callbacks with the build system.
init()
+ // Returns true if a snapshot should be generated for this image.
+ shouldGenerateSnapshot(ctx android.SingletonContext) bool
+
// Function that returns true if the module is included in this image.
// Using a function return instead of a value to prevent early
// evalution of a function that may be not be defined.
@@ -55,6 +60,28 @@
// snapshot, e.g., using the exclude_from_vendor_snapshot or
// exclude_from_recovery_snapshot properties.
excludeFromSnapshot(m *Module) bool
+
+ // Returns the snapshotMap to be used for a given module and config, or nil if the
+ // module is not included in this image.
+ getSnapshotMap(m *Module, cfg android.Config) *snapshotMap
+
+ // Returns mutex used for mutual exclusion when updating the snapshot maps.
+ getMutex() *sync.Mutex
+
+ // For a given arch, a maps of which modules are included in this image.
+ suffixModules(config android.Config) map[string]bool
+
+ // Whether to add a given module to the suffix map.
+ shouldBeAddedToSuffixModules(m *Module) bool
+
+ // Returns true if the build is using a snapshot for this image.
+ isUsingSnapshot(cfg android.DeviceConfig) bool
+
+ // Whether to skip the module mutator for a module in a given context.
+ skipModuleMutator(ctx android.BottomUpMutatorContext) bool
+
+ // Whether to skip the source mutator for a given module.
+ skipSourceMutator(ctx android.BottomUpMutatorContext) bool
}
type vendorSnapshotImage struct{}
@@ -67,6 +94,13 @@
android.RegisterModuleType("vendor_snapshot_header", VendorSnapshotHeaderFactory)
android.RegisterModuleType("vendor_snapshot_binary", VendorSnapshotBinaryFactory)
android.RegisterModuleType("vendor_snapshot_object", VendorSnapshotObjectFactory)
+
+ android.RegisterSingletonType("vendor-fake-snapshot", VendorFakeSnapshotSingleton)
+}
+
+func (vendorSnapshotImage) shouldGenerateSnapshot(ctx android.SingletonContext) bool {
+ // BOARD_VNDK_VERSION must be set to 'current' in order to generate a snapshot.
+ return ctx.DeviceConfig().VndkVersion() == "current"
}
func (vendorSnapshotImage) inImage(m *Module) func() bool {
@@ -90,6 +124,75 @@
return m.ExcludeFromVendorSnapshot()
}
+func (vendorSnapshotImage) getSnapshotMap(m *Module, cfg android.Config) *snapshotMap {
+ if lib, ok := m.linker.(libraryInterface); ok {
+ if lib.static() {
+ return vendorSnapshotStaticLibs(cfg)
+ } else if lib.shared() {
+ return vendorSnapshotSharedLibs(cfg)
+ } else {
+ // header
+ return vendorSnapshotHeaderLibs(cfg)
+ }
+ } else if m.binary() {
+ return vendorSnapshotBinaries(cfg)
+ } else if m.object() {
+ return vendorSnapshotObjects(cfg)
+ } else {
+ return nil
+ }
+}
+
+func (vendorSnapshotImage) getMutex() *sync.Mutex {
+ return &vendorSnapshotsLock
+}
+
+func (vendorSnapshotImage) suffixModules(config android.Config) map[string]bool {
+ return vendorSuffixModules(config)
+}
+
+func (vendorSnapshotImage) shouldBeAddedToSuffixModules(module *Module) bool {
+ // vendor suffix should be added to snapshots if the source module isn't vendor: true.
+ if module.SocSpecific() {
+ return false
+ }
+
+ // But we can't just check SocSpecific() since we already passed the image mutator.
+ // Check ramdisk and recovery to see if we are real "vendor: true" module.
+ ramdiskAvailable := module.InRamdisk() && !module.OnlyInRamdisk()
+ vendorRamdiskAvailable := module.InVendorRamdisk() && !module.OnlyInVendorRamdisk()
+ recoveryAvailable := module.InRecovery() && !module.OnlyInRecovery()
+
+ return !ramdiskAvailable && !recoveryAvailable && !vendorRamdiskAvailable
+}
+
+func (vendorSnapshotImage) isUsingSnapshot(cfg android.DeviceConfig) bool {
+ vndkVersion := cfg.VndkVersion()
+ return vndkVersion != "current" && vndkVersion != ""
+}
+
+func (vendorSnapshotImage) skipModuleMutator(ctx android.BottomUpMutatorContext) bool {
+ vndkVersion := ctx.DeviceConfig().VndkVersion()
+ module, ok := ctx.Module().(*Module)
+ return !ok || module.VndkVersion() != vndkVersion
+}
+
+func (vendorSnapshotImage) skipSourceMutator(ctx android.BottomUpMutatorContext) bool {
+ vndkVersion := ctx.DeviceConfig().VndkVersion()
+ module, ok := ctx.Module().(*Module)
+ if !ok {
+ return true
+ }
+ if module.VndkVersion() != vndkVersion {
+ return true
+ }
+ // .. and also filter out llndk library
+ if module.IsLlndk() {
+ return true
+ }
+ return false
+}
+
func (recoverySnapshotImage) init() {
android.RegisterSingletonType("recovery-snapshot", RecoverySnapshotSingleton)
android.RegisterModuleType("recovery_snapshot_shared", RecoverySnapshotSharedFactory)
@@ -99,6 +202,12 @@
android.RegisterModuleType("recovery_snapshot_object", RecoverySnapshotObjectFactory)
}
+func (recoverySnapshotImage) shouldGenerateSnapshot(ctx android.SingletonContext) bool {
+ // RECOVERY_SNAPSHOT_VERSION must be set to 'current' in order to generate a
+ // snapshot.
+ return ctx.DeviceConfig().RecoverySnapshotVersion() == "current"
+}
+
func (recoverySnapshotImage) inImage(m *Module) func() bool {
return m.InRecovery
}
@@ -120,6 +229,52 @@
return m.ExcludeFromRecoverySnapshot()
}
+func (recoverySnapshotImage) getSnapshotMap(m *Module, cfg android.Config) *snapshotMap {
+ if lib, ok := m.linker.(libraryInterface); ok {
+ if lib.static() {
+ return recoverySnapshotStaticLibs(cfg)
+ } else if lib.shared() {
+ return recoverySnapshotSharedLibs(cfg)
+ } else {
+ // header
+ return recoverySnapshotHeaderLibs(cfg)
+ }
+ } else if m.binary() {
+ return recoverySnapshotBinaries(cfg)
+ } else if m.object() {
+ return recoverySnapshotObjects(cfg)
+ } else {
+ return nil
+ }
+}
+
+func (recoverySnapshotImage) getMutex() *sync.Mutex {
+ return &recoverySnapshotsLock
+}
+
+func (recoverySnapshotImage) suffixModules(config android.Config) map[string]bool {
+ return recoverySuffixModules(config)
+}
+
+func (recoverySnapshotImage) shouldBeAddedToSuffixModules(module *Module) bool {
+ return proptools.BoolDefault(module.Properties.Recovery_available, false)
+}
+
+func (recoverySnapshotImage) isUsingSnapshot(cfg android.DeviceConfig) bool {
+ recoverySnapshotVersion := cfg.RecoverySnapshotVersion()
+ return recoverySnapshotVersion != "current" && recoverySnapshotVersion != ""
+}
+
+func (recoverySnapshotImage) skipModuleMutator(ctx android.BottomUpMutatorContext) bool {
+ module, ok := ctx.Module().(*Module)
+ return !ok || !module.InRecovery()
+}
+
+func (recoverySnapshotImage) skipSourceMutator(ctx android.BottomUpMutatorContext) bool {
+ module, ok := ctx.Module().(*Module)
+ return !ok || !module.InRecovery()
+}
+
var vendorSnapshotImageSingleton vendorSnapshotImage
var recoverySnapshotImageSingleton recoverySnapshotImage
@@ -154,6 +309,16 @@
vendorSnapshotObjectsKey = android.NewOnceKey("vendorSnapshotObjects")
)
+var (
+ recoverySnapshotsLock sync.Mutex
+ recoverySuffixModulesKey = android.NewOnceKey("recoverySuffixModules")
+ recoverySnapshotHeaderLibsKey = android.NewOnceKey("recoverySnapshotHeaderLibs")
+ recoverySnapshotStaticLibsKey = android.NewOnceKey("recoverySnapshotStaticLibs")
+ recoverySnapshotSharedLibsKey = android.NewOnceKey("recoverySnapshotSharedLibs")
+ recoverySnapshotBinariesKey = android.NewOnceKey("recoverySnapshotBinaries")
+ recoverySnapshotObjectsKey = android.NewOnceKey("recoverySnapshotObjects")
+)
+
// vendorSuffixModules holds names of modules whose vendor variants should have the vendor suffix.
// This is determined by source modules, and then this will be used when exporting snapshot modules
// to Makefile.
@@ -200,12 +365,52 @@
}).(*snapshotMap)
}
+func recoverySuffixModules(config android.Config) map[string]bool {
+ return config.Once(recoverySuffixModulesKey, func() interface{} {
+ return make(map[string]bool)
+ }).(map[string]bool)
+}
+
+func recoverySnapshotHeaderLibs(config android.Config) *snapshotMap {
+ return config.Once(recoverySnapshotHeaderLibsKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+func recoverySnapshotSharedLibs(config android.Config) *snapshotMap {
+ return config.Once(recoverySnapshotSharedLibsKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+func recoverySnapshotStaticLibs(config android.Config) *snapshotMap {
+ return config.Once(recoverySnapshotStaticLibsKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+func recoverySnapshotBinaries(config android.Config) *snapshotMap {
+ return config.Once(recoverySnapshotBinariesKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+func recoverySnapshotObjects(config android.Config) *snapshotMap {
+ return config.Once(recoverySnapshotObjectsKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
type baseSnapshotDecoratorProperties struct {
// snapshot version.
Version string
// Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64')
Target_arch string
+
+ // Suffix to be added to the module name, e.g., vendor_shared,
+ // recovery_shared, etc.
+ Module_suffix string
}
// baseSnapshotDecorator provides common basic functions for all snapshot modules, such as snapshot
@@ -222,7 +427,6 @@
// will be seen as "libbase.vendor_static.30.arm64" by Soong.
type baseSnapshotDecorator struct {
baseProperties baseSnapshotDecoratorProperties
- moduleSuffix string
}
func (p *baseSnapshotDecorator) Name(name string) string {
@@ -235,7 +439,7 @@
versionSuffix += "." + p.arch()
}
- return p.moduleSuffix + versionSuffix
+ return p.baseProperties.Module_suffix + versionSuffix
}
func (p *baseSnapshotDecorator) version() string {
@@ -246,6 +450,10 @@
return p.baseProperties.Target_arch
}
+func (p *baseSnapshotDecorator) module_suffix() string {
+ return p.baseProperties.Module_suffix
+}
+
func (p *baseSnapshotDecorator) isSnapshotPrebuilt() bool {
return true
}
@@ -253,7 +461,7 @@
// Call this with a module suffix after creating a snapshot module, such as
// vendorSnapshotSharedSuffix, recoverySnapshotBinarySuffix, etc.
func (p *baseSnapshotDecorator) init(m *Module, suffix string) {
- p.moduleSuffix = suffix
+ p.baseProperties.Module_suffix = suffix
m.AddProperties(&p.baseProperties)
android.AddLoadHook(m, func(ctx android.LoadHookContext) {
vendorSnapshotLoadHook(ctx, p)
@@ -313,7 +521,7 @@
// Library flags for cfi variant.
Cfi snapshotLibraryProperties `android:"arch_variant"`
}
- androidMkVendorSuffix bool
+ androidMkSuffix string
}
func (p *snapshotLibraryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
@@ -337,7 +545,12 @@
// done by normal library decorator, e.g. exporting flags.
func (p *snapshotLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path {
m := ctx.Module().(*Module)
- p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
+
+ if m.inVendor() && vendorSuffixModules(ctx.Config())[m.BaseModuleName()] {
+ p.androidMkSuffix = vendorSuffix
+ } else if m.InRecovery() && recoverySuffixModules(ctx.Config())[m.BaseModuleName()] {
+ p.androidMkSuffix = recoverySuffix
+ }
if p.header() {
return p.libraryDecorator.link(ctx, flags, deps, objs)
@@ -530,8 +743,8 @@
type snapshotBinaryDecorator struct {
baseSnapshotDecorator
*binaryDecorator
- properties snapshotBinaryProperties
- androidMkVendorSuffix bool
+ properties snapshotBinaryProperties
+ androidMkSuffix string
}
func (p *snapshotBinaryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
@@ -556,7 +769,12 @@
binName := in.Base()
m := ctx.Module().(*Module)
- p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
+ if m.inVendor() && vendorSuffixModules(ctx.Config())[m.BaseModuleName()] {
+ p.androidMkSuffix = vendorSuffix
+ } else if m.InRecovery() && recoverySuffixModules(ctx.Config())[m.BaseModuleName()] {
+ p.androidMkSuffix = recoverySuffix
+
+ }
// use cpExecutable to make it executable
outputFile := android.PathForModuleOut(ctx, binName)
@@ -627,8 +845,8 @@
type snapshotObjectLinker struct {
baseSnapshotDecorator
objectLinker
- properties vendorSnapshotObjectProperties
- androidMkVendorSuffix bool
+ properties vendorSnapshotObjectProperties
+ androidMkSuffix string
}
func (p *snapshotObjectLinker) matchesWithDevice(config android.DeviceConfig) bool {
@@ -649,7 +867,12 @@
}
m := ctx.Module().(*Module)
- p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
+
+ if m.inVendor() && vendorSuffixModules(ctx.Config())[m.BaseModuleName()] {
+ p.androidMkSuffix = vendorSuffix
+ } else if m.InRecovery() && recoverySuffixModules(ctx.Config())[m.BaseModuleName()] {
+ p.androidMkSuffix = recoverySuffix
+ }
return android.PathForModuleSrc(ctx, *p.properties.Src)
}
@@ -717,17 +940,24 @@
//
// TODO(b/145966707): remove mutator and utilize android.Prebuilt to override source modules
func VendorSnapshotMutator(ctx android.BottomUpMutatorContext) {
- vndkVersion := ctx.DeviceConfig().VndkVersion()
- // don't need snapshot if current
- if vndkVersion == "current" || vndkVersion == "" {
+ snapshotMutator(ctx, vendorSnapshotImageSingleton)
+}
+
+func RecoverySnapshotMutator(ctx android.BottomUpMutatorContext) {
+ snapshotMutator(ctx, recoverySnapshotImageSingleton)
+}
+
+func snapshotMutator(ctx android.BottomUpMutatorContext, image snapshotImage) {
+ if !image.isUsingSnapshot(ctx.DeviceConfig()) {
return
}
-
module, ok := ctx.Module().(*Module)
- if !ok || !module.Enabled() || module.VndkVersion() != vndkVersion {
+ if !ok || !module.Enabled() {
return
}
-
+ if image.skipModuleMutator(ctx) {
+ return
+ }
if !module.isSnapshotPrebuilt() {
return
}
@@ -742,39 +972,31 @@
return
}
- var snapshotMap *snapshotMap
-
- if lib, ok := module.linker.(libraryInterface); ok {
- if lib.static() {
- snapshotMap = vendorSnapshotStaticLibs(ctx.Config())
- } else if lib.shared() {
- snapshotMap = vendorSnapshotSharedLibs(ctx.Config())
- } else {
- // header
- snapshotMap = vendorSnapshotHeaderLibs(ctx.Config())
- }
- } else if _, ok := module.linker.(*snapshotBinaryDecorator); ok {
- snapshotMap = vendorSnapshotBinaries(ctx.Config())
- } else if _, ok := module.linker.(*snapshotObjectLinker); ok {
- snapshotMap = vendorSnapshotObjects(ctx.Config())
- } else {
+ var snapshotMap *snapshotMap = image.getSnapshotMap(module, ctx.Config())
+ if snapshotMap == nil {
return
}
- vendorSnapshotsLock.Lock()
- defer vendorSnapshotsLock.Unlock()
+ mutex := image.getMutex()
+ mutex.Lock()
+ defer mutex.Unlock()
snapshotMap.add(module.BaseModuleName(), ctx.Arch().ArchType, ctx.ModuleName())
}
// VendorSnapshotSourceMutator disables source modules which have corresponding snapshots.
func VendorSnapshotSourceMutator(ctx android.BottomUpMutatorContext) {
+ snapshotSourceMutator(ctx, vendorSnapshotImageSingleton)
+}
+
+func RecoverySnapshotSourceMutator(ctx android.BottomUpMutatorContext) {
+ snapshotSourceMutator(ctx, recoverySnapshotImageSingleton)
+}
+
+func snapshotSourceMutator(ctx android.BottomUpMutatorContext, image snapshotImage) {
if !ctx.Device() {
return
}
-
- vndkVersion := ctx.DeviceConfig().VndkVersion()
- // don't need snapshot if current
- if vndkVersion == "current" || vndkVersion == "" {
+ if !image.isUsingSnapshot(ctx.DeviceConfig()) {
return
}
@@ -783,48 +1005,23 @@
return
}
- // vendor suffix should be added to snapshots if the source module isn't vendor: true.
- if !module.SocSpecific() {
- // But we can't just check SocSpecific() since we already passed the image mutator.
- // Check ramdisk and recovery to see if we are real "vendor: true" module.
- ramdiskAvailable := module.InRamdisk() && !module.OnlyInRamdisk()
- vendorRamdiskAvailable := module.InVendorRamdisk() && !module.OnlyInVendorRamdisk()
- recoveryAvailable := module.InRecovery() && !module.OnlyInRecovery()
+ if image.shouldBeAddedToSuffixModules(module) {
+ mutex := image.getMutex()
+ mutex.Lock()
+ defer mutex.Unlock()
- if !ramdiskAvailable && !recoveryAvailable && !vendorRamdiskAvailable {
- vendorSnapshotsLock.Lock()
- defer vendorSnapshotsLock.Unlock()
-
- vendorSuffixModules(ctx.Config())[ctx.ModuleName()] = true
- }
+ image.suffixModules(ctx.Config())[ctx.ModuleName()] = true
}
- if module.isSnapshotPrebuilt() || module.VndkVersion() != ctx.DeviceConfig().VndkVersion() {
- // only non-snapshot modules with BOARD_VNDK_VERSION
+ if module.isSnapshotPrebuilt() {
+ return
+ }
+ if image.skipSourceMutator(ctx) {
return
}
- // .. and also filter out llndk library
- if module.IsLlndk() {
- return
- }
-
- var snapshotMap *snapshotMap
-
- if lib, ok := module.linker.(libraryInterface); ok {
- if lib.static() {
- snapshotMap = vendorSnapshotStaticLibs(ctx.Config())
- } else if lib.shared() {
- snapshotMap = vendorSnapshotSharedLibs(ctx.Config())
- } else {
- // header
- snapshotMap = vendorSnapshotHeaderLibs(ctx.Config())
- }
- } else if module.binary() {
- snapshotMap = vendorSnapshotBinaries(ctx.Config())
- } else if module.object() {
- snapshotMap = vendorSnapshotObjects(ctx.Config())
- } else {
+ var snapshotMap *snapshotMap = image.getSnapshotMap(module, ctx.Config())
+ if snapshotMap == nil {
return
}
diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go
index e841a54..3e6444b 100644
--- a/cc/snapshot_utils.go
+++ b/cc/snapshot_utils.go
@@ -71,11 +71,18 @@
// shouldCollectHeadersForSnapshot determines if the module is a possible candidate for snapshot.
// If it's true, collectHeadersForSnapshot will be called in GenerateAndroidBuildActions.
func shouldCollectHeadersForSnapshot(ctx android.ModuleContext, m *Module, apexInfo android.ApexInfo) bool {
+ if ctx.DeviceConfig().VndkVersion() != "current" &&
+ ctx.DeviceConfig().RecoverySnapshotVersion() != "current" {
+ return false
+ }
if _, _, ok := isVndkSnapshotAware(ctx.DeviceConfig(), m, apexInfo); ok {
return ctx.Config().VndkSnapshotBuildArtifacts()
- } else if isVendorSnapshotAware(m, isVendorProprietaryPath(ctx.ModuleDir()), apexInfo) ||
- isRecoverySnapshotAware(m, isRecoveryProprietaryPath(ctx.ModuleDir()), apexInfo) {
- return true
+ }
+
+ for _, image := range []snapshotImage{vendorSnapshotImageSingleton, recoverySnapshotImageSingleton} {
+ if isSnapshotAware(m, image.isProprietaryPath(ctx.ModuleDir()), apexInfo, image) {
+ return true
+ }
}
return false
}
diff --git a/cc/testing.go b/cc/testing.go
index fc5b030..8d92ea2 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -299,7 +299,7 @@
llndk_library {
name: "libft2.llndk",
symbol_file: "",
- vendor_available: false,
+ private: true,
sdk_version: "current",
}
cc_library {
@@ -568,15 +568,16 @@
ctx.RegisterModuleType("vendor_public_library", vendorPublicLibraryFactory)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
- ctx.RegisterModuleType("vndk_libraries_txt", VndkLibrariesTxtFactory)
ctx.RegisterModuleType("vendor_snapshot_shared", VendorSnapshotSharedFactory)
ctx.RegisterModuleType("vendor_snapshot_static", VendorSnapshotStaticFactory)
ctx.RegisterModuleType("vendor_snapshot_binary", VendorSnapshotBinaryFactory)
+ RegisterVndkLibraryTxtTypes(ctx)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
android.RegisterPrebuiltMutators(ctx)
RegisterRequiredBuildComponentsForTest(ctx)
ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
ctx.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton)
+ ctx.RegisterSingletonType("vendor-fake-snapshot", VendorFakeSnapshotSingleton)
ctx.RegisterSingletonType("recovery-snapshot", RecoverySnapshotSingleton)
return ctx
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index d2c29d6..622ebec 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -34,6 +34,16 @@
android.OptionalPath{},
true,
vendorSnapshotImageSingleton,
+ false, /* fake */
+}
+
+var vendorFakeSnapshotSingleton = snapshotSingleton{
+ "vendor",
+ "SOONG_VENDOR_FAKE_SNAPSHOT_ZIP",
+ android.OptionalPath{},
+ true,
+ vendorSnapshotImageSingleton,
+ true, /* fake */
}
var recoverySnapshotSingleton = snapshotSingleton{
@@ -42,12 +52,17 @@
android.OptionalPath{},
false,
recoverySnapshotImageSingleton,
+ false, /* fake */
}
func VendorSnapshotSingleton() android.Singleton {
return &vendorSnapshotSingleton
}
+func VendorFakeSnapshotSingleton() android.Singleton {
+ return &vendorFakeSnapshotSingleton
+}
+
func RecoverySnapshotSingleton() android.Singleton {
return &recoverySnapshotSingleton
}
@@ -70,6 +85,11 @@
// associated with this snapshot (e.g., specific to the vendor image,
// recovery image, etc.).
image snapshotImage
+
+ // Whether this singleton is for fake snapshot or not.
+ // Fake snapshot is a snapshot whose prebuilt binaries and headers are empty.
+ // It is much faster to generate, and can be used to inspect dependencies.
+ fake bool
}
var (
@@ -85,7 +105,6 @@
// Modules under following directories are ignored. They are OEM's and vendor's
// proprietary modules(device/, kernel/, vendor/, and hardware/).
recoveryProprietaryDirs = []string{
- "bootable/recovery",
"device",
"hardware",
"kernel",
@@ -156,23 +175,26 @@
return false
}
-// Determine if a module is going to be included in vendor snapshot or not.
-//
-// Targets of vendor snapshot are "vendor: true" or "vendor_available: true" modules in
-// AOSP. They are not guaranteed to be compatible with older vendor images. (e.g. might
-// depend on newer VNDK) So they are captured as vendor snapshot To build older vendor
-// image and newer system image altogether.
-func isVendorSnapshotAware(m *Module, inVendorProprietaryPath bool, apexInfo android.ApexInfo) bool {
- return isSnapshotAware(m, inVendorProprietaryPath, apexInfo, vendorSnapshotImageSingleton)
-}
+func isRecoveryProprietaryModule(ctx android.BaseModuleContext) bool {
-// Determine if a module is going to be included in recovery snapshot or not.
-//
-// Targets of recovery snapshot are "recovery: true" or "recovery_available: true"
-// modules in AOSP. They are not guaranteed to be compatible with older recovery images.
-// So they are captured as recovery snapshot To build older recovery image.
-func isRecoverySnapshotAware(m *Module, inRecoveryProprietaryPath bool, apexInfo android.ApexInfo) bool {
- return isSnapshotAware(m, inRecoveryProprietaryPath, apexInfo, recoverySnapshotImageSingleton)
+ // Any module in a vendor proprietary path is a vendor proprietary
+ // module.
+ if isRecoveryProprietaryPath(ctx.ModuleDir()) {
+ return true
+ }
+
+ // However if the module is not in a vendor proprietary path, it may
+ // still be a vendor proprietary module. This happens for cc modules
+ // that are excluded from the vendor snapshot, and it means that the
+ // vendor has assumed control of the framework-provided module.
+
+ if c, ok := ctx.Module().(*Module); ok {
+ if c.ExcludeFromRecoverySnapshot() {
+ return true
+ }
+ }
+
+ return false
}
// Determines if the module is a candidate for snapshot.
@@ -192,7 +214,7 @@
}
// If the module would be included based on its path, check to see if
// the module is marked to be excluded. If so, skip it.
- if m.ExcludeFromVendorSnapshot() {
+ if image.excludeFromSnapshot(m) {
return false
}
if m.Target().Os.Class != android.Device {
@@ -290,8 +312,7 @@
}
func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
- // BOARD_VNDK_VERSION must be set to 'current' in order to generate a vendor snapshot.
- if ctx.DeviceConfig().VndkVersion() != "current" {
+ if !c.image.shouldGenerateSnapshot(ctx) {
return
}
@@ -331,6 +352,11 @@
*/
snapshotDir := c.name + "-snapshot"
+ if c.fake {
+ // If this is a fake snapshot singleton, place all files under fake/ subdirectory to avoid
+ // collision with real snapshot files
+ snapshotDir = filepath.Join("fake", snapshotDir)
+ }
snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
includeDir := filepath.Join(snapshotArchDir, "include")
@@ -342,6 +368,15 @@
var headers android.Paths
+ copyFile := copyFileRule
+ if c.fake {
+ // All prebuilt binaries and headers are installed by copyFile function. This makes a fake
+ // snapshot just touch prebuilts and headers, rather than installing real files.
+ copyFile = func(ctx android.SingletonContext, path android.Path, out string) android.OutputPath {
+ return writeStringToFileRule(ctx, "", out)
+ }
+ }
+
// installSnapshot function copies prebuilt file (.so, .a, or executable) and json flag file.
// For executables, init_rc and vintf_fragments files are also copied.
installSnapshot := func(m *Module) android.Paths {
@@ -380,7 +415,7 @@
out := filepath.Join(configsDir, path.Base())
if !installedConfigs[out] {
installedConfigs[out] = true
- ret = append(ret, copyFileRule(ctx, path, out))
+ ret = append(ret, copyFile(ctx, path, out))
}
}
@@ -431,7 +466,7 @@
prop.ModuleName += ".cfi"
}
snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, libType, stem)
- ret = append(ret, copyFileRule(ctx, libPath, snapshotLibOut))
+ ret = append(ret, copyFile(ctx, libPath, snapshotLibOut))
} else {
stem = ctx.ModuleName(m)
}
@@ -445,7 +480,7 @@
// install bin
binPath := m.outputFile.Path()
snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base())
- ret = append(ret, copyFileRule(ctx, binPath, snapshotBinOut))
+ ret = append(ret, copyFile(ctx, binPath, snapshotBinOut))
propOut = snapshotBinOut + ".json"
} else if m.object() {
// object files aren't installed to the device, so their names can conflict.
@@ -453,7 +488,7 @@
objPath := m.outputFile.Path()
snapshotObjOut := filepath.Join(snapshotArchDir, targetArch, "object",
ctx.ModuleName(m)+filepath.Ext(objPath.Base()))
- ret = append(ret, copyFileRule(ctx, objPath, snapshotObjOut))
+ ret = append(ret, copyFile(ctx, objPath, snapshotObjOut))
propOut = snapshotObjOut + ".json"
} else {
ctx.Errorf("unknown module %q in vendor snapshot", m.String())
@@ -480,7 +515,7 @@
inProprietaryPath := c.image.isProprietaryPath(moduleDir)
apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
- if m.ExcludeFromVendorSnapshot() {
+ if c.image.excludeFromSnapshot(m) {
if inProprietaryPath {
// Error: exclude_from_vendor_snapshot applies
// to framework-path modules only.
@@ -518,16 +553,14 @@
// skip already copied notice file
if !installedNotices[noticeOut] {
installedNotices[noticeOut] = true
- snapshotOutputs = append(snapshotOutputs, combineNoticesRule(
- ctx, m.NoticeFiles(), noticeOut))
+ snapshotOutputs = append(snapshotOutputs, combineNoticesRule(ctx, m.NoticeFiles(), noticeOut))
}
}
})
// install all headers after removing duplicates
for _, header := range android.FirstUniquePaths(headers) {
- snapshotOutputs = append(snapshotOutputs, copyFileRule(
- ctx, header, filepath.Join(includeDir, header.String())))
+ snapshotOutputs = append(snapshotOutputs, copyFile(ctx, header, filepath.Join(includeDir, header.String())))
}
// All artifacts are ready. Sort them to normalize ninja and then zip.
diff --git a/cc/vndk.go b/cc/vndk.go
index 6bc7131..c1264f7 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -35,6 +35,7 @@
vndkCoreLibrariesTxt = "vndkcore.libraries.txt"
vndkSpLibrariesTxt = "vndksp.libraries.txt"
vndkPrivateLibrariesTxt = "vndkprivate.libraries.txt"
+ vndkProductLibrariesTxt = "vndkproduct.libraries.txt"
vndkUsingCoreVariantLibrariesTxt = "vndkcorevariant.libraries.txt"
)
@@ -45,6 +46,7 @@
vndkCoreLibrariesTxt,
vndkSpLibrariesTxt,
vndkPrivateLibrariesTxt,
+ vndkProductLibrariesTxt,
}
}
// Snapshot vndks have their own *.libraries.VER.txt files.
@@ -54,6 +56,7 @@
insertVndkVersion(vndkCoreLibrariesTxt, vndkVersion),
insertVndkVersion(vndkSpLibrariesTxt, vndkVersion),
insertVndkVersion(vndkPrivateLibrariesTxt, vndkVersion),
+ insertVndkVersion(vndkProductLibrariesTxt, vndkVersion),
}
}
@@ -229,10 +232,11 @@
}
var (
- vndkCoreLibrariesKey = android.NewOnceKey("vndkCoreLibrarires")
- vndkSpLibrariesKey = android.NewOnceKey("vndkSpLibrarires")
- llndkLibrariesKey = android.NewOnceKey("llndkLibrarires")
- vndkPrivateLibrariesKey = android.NewOnceKey("vndkPrivateLibrarires")
+ vndkCoreLibrariesKey = android.NewOnceKey("vndkCoreLibraries")
+ vndkSpLibrariesKey = android.NewOnceKey("vndkSpLibraries")
+ llndkLibrariesKey = android.NewOnceKey("llndkLibraries")
+ vndkPrivateLibrariesKey = android.NewOnceKey("vndkPrivateLibraries")
+ vndkProductLibrariesKey = android.NewOnceKey("vndkProductLibraries")
vndkUsingCoreVariantLibrariesKey = android.NewOnceKey("vndkUsingCoreVariantLibraries")
vndkMustUseVendorVariantListKey = android.NewOnceKey("vndkMustUseVendorVariantListKey")
vndkLibrariesLock sync.Mutex
@@ -262,6 +266,12 @@
}).(map[string]string)
}
+func vndkProductLibraries(config android.Config) map[string]string {
+ return config.Once(vndkProductLibrariesKey, func() interface{} {
+ return make(map[string]string)
+ }).(map[string]string)
+}
+
func vndkUsingCoreVariantLibraries(config android.Config) map[string]string {
return config.Once(vndkUsingCoreVariantLibrariesKey, func() interface{} {
return make(map[string]string)
@@ -292,13 +302,19 @@
llndkLibraries(mctx.Config())[name] = filename
m.VendorProperties.IsLLNDK = true
- if !Bool(lib.Properties.Vendor_available) {
+ if Bool(lib.Properties.Private) {
vndkPrivateLibraries(mctx.Config())[name] = filename
m.VendorProperties.IsLLNDKPrivate = true
}
}
func processVndkLibrary(mctx android.BottomUpMutatorContext, m *Module) {
+ if m.InProduct() {
+ // We may skip the steps for the product variants because they
+ // are already covered by the vendor variants.
+ return
+ }
+
name := m.BaseModuleName()
filename, err := getVndkFileName(m)
if err != nil {
@@ -318,12 +334,6 @@
vndkLibrariesLock.Lock()
defer vndkLibrariesLock.Unlock()
- if m.InProduct() {
- // We may skip the other steps for the product variants because they
- // are already covered by the vendor variants.
- return
- }
-
if inList(name, vndkMustUseVendorVariantList(mctx.Config())) {
m.Properties.MustUseVendorVariant = true
}
@@ -339,6 +349,9 @@
if m.IsVndkPrivate() {
vndkPrivateLibraries(mctx.Config())[name] = filename
}
+ if Bool(m.VendorProperties.Product_available) {
+ vndkProductLibraries(mctx.Config())[name] = filename
+ }
}
// Check for modules that mustn't be VNDK
@@ -436,15 +449,32 @@
}
func init() {
- android.RegisterModuleType("vndk_libraries_txt", VndkLibrariesTxtFactory)
+ RegisterVndkLibraryTxtTypes(android.InitRegistrationContext)
android.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
}
+func RegisterVndkLibraryTxtTypes(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("llndk_libraries_txt", VndkLibrariesTxtFactory(libclangRTRemover(llndkLibraries)))
+ ctx.RegisterModuleType("vndksp_libraries_txt", VndkLibrariesTxtFactory(vndkSpLibraries))
+ ctx.RegisterModuleType("vndkcore_libraries_txt", VndkLibrariesTxtFactory(vndkCoreLibraries))
+ ctx.RegisterModuleType("vndkprivate_libraries_txt", VndkLibrariesTxtFactory(vndkPrivateLibraries))
+ ctx.RegisterModuleType("vndkproduct_libraries_txt", VndkLibrariesTxtFactory(vndkProductLibraries))
+ ctx.RegisterModuleType("vndkcorevariant_libraries_txt", VndkLibrariesTxtFactory(vndkUsingCoreVariantLibraries))
+}
+
type vndkLibrariesTxt struct {
android.ModuleBase
+
+ lister func(android.Config) map[string]string
+ properties VndkLibrariesTxtProperties
+
outputFile android.OutputPath
}
+type VndkLibrariesTxtProperties struct {
+ Insert_vndk_version *bool
+}
+
var _ etc.PrebuiltEtcModule = &vndkLibrariesTxt{}
var _ android.OutputFileProducer = &vndkLibrariesTxt{}
@@ -453,14 +483,20 @@
// - vndkcore.libraries.txt
// - vndksp.libraries.txt
// - vndkprivate.libraries.txt
+// - vndkproduct.libraries.txt
// - vndkcorevariant.libraries.txt
// A module behaves like a prebuilt_etc but its content is generated by soong.
// By being a soong module, these files can be referenced by other soong modules.
// For example, apex_vndk can depend on these files as prebuilt.
-func VndkLibrariesTxtFactory() android.Module {
- m := &vndkLibrariesTxt{}
- android.InitAndroidModule(m)
- return m
+func VndkLibrariesTxtFactory(lister func(android.Config) map[string]string) android.ModuleFactory {
+ return func() android.Module {
+ m := &vndkLibrariesTxt{
+ lister: lister,
+ }
+ m.AddProperties(&m.properties)
+ android.InitAndroidModule(m)
+ return m
+ }
}
func insertVndkVersion(filename string, vndkVersion string) string {
@@ -470,31 +506,25 @@
return filename
}
-func (txt *vndkLibrariesTxt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- var list []string
- switch txt.Name() {
- case llndkLibrariesTxt:
- for _, filename := range android.SortedStringMapValues(llndkLibraries(ctx.Config())) {
- if strings.HasPrefix(filename, "libclang_rt.hwasan-") {
+func libclangRTRemover(lister func(android.Config) map[string]string) func(android.Config) map[string]string {
+ return func(config android.Config) map[string]string {
+ libs := lister(config)
+ filteredLibs := make(map[string]string, len(libs))
+ for lib, v := range libs {
+ if strings.HasPrefix(lib, "libclang_rt.hwasan-") {
continue
}
- list = append(list, filename)
+ filteredLibs[lib] = v
}
- case vndkCoreLibrariesTxt:
- list = android.SortedStringMapValues(vndkCoreLibraries(ctx.Config()))
- case vndkSpLibrariesTxt:
- list = android.SortedStringMapValues(vndkSpLibraries(ctx.Config()))
- case vndkPrivateLibrariesTxt:
- list = android.SortedStringMapValues(vndkPrivateLibraries(ctx.Config()))
- case vndkUsingCoreVariantLibrariesTxt:
- list = android.SortedStringMapValues(vndkUsingCoreVariantLibraries(ctx.Config()))
- default:
- ctx.ModuleErrorf("name(%s) is unknown.", txt.Name())
- return
+ return filteredLibs
}
+}
+
+func (txt *vndkLibrariesTxt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ list := android.SortedStringMapValues(txt.lister(ctx.Config()))
var filename string
- if txt.Name() != vndkUsingCoreVariantLibrariesTxt {
+ if BoolDefault(txt.properties.Insert_vndk_version, true) {
filename = insertVndkVersion(txt.Name(), ctx.DeviceConfig().PlatformVndkVersion())
} else {
filename = txt.Name()
@@ -807,6 +837,7 @@
vndkcore := android.SortedStringMapValues(vndkCoreLibraries(ctx.Config()))
vndksp := android.SortedStringMapValues(vndkSpLibraries(ctx.Config()))
vndkprivate := android.SortedStringMapValues(vndkPrivateLibraries(ctx.Config()))
+ vndkproduct := android.SortedStringMapValues(vndkProductLibraries(ctx.Config()))
// Build list of vndk libs as merged & tagged & filter-out(libclang_rt):
// Since each target have different set of libclang_rt.* files,
@@ -824,6 +855,7 @@
merged = append(merged, addPrefix(vndksp, "VNDK-SP: ")...)
merged = append(merged, addPrefix(filterOutLibClangRt(vndkcore), "VNDK-core: ")...)
merged = append(merged, addPrefix(vndkprivate, "VNDK-private: ")...)
+ merged = append(merged, addPrefix(filterOutLibClangRt(vndkproduct), "VNDK-product: ")...)
c.vndkLibrariesFile = android.PathForOutput(ctx, "vndk", "vndk.libraries.txt")
android.WriteFileRule(ctx, c.vndkLibrariesFile, strings.Join(merged, "\n"))
}
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index c6181bc..2b3fbae 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -46,7 +46,10 @@
return module
}
-var dependencyTag = struct{ blueprint.BaseDependencyTag }{}
+var dependencyTag = struct {
+ blueprint.BaseDependencyTag
+ android.InstallAlwaysNeededDependencyTag
+}{}
func (f *filesystem) DepsMutator(ctx android.BottomUpMutatorContext) {
f.AddDeps(ctx, dependencyTag)
@@ -80,7 +83,7 @@
Text(">").Output(propFile).
Implicit(mkuserimg)
- f.output = android.PathForModuleOut(ctx, "filesystem.img").OutputPath
+ f.output = android.PathForModuleOut(ctx, f.installFileName()).OutputPath
builder.Command().BuiltTool("build_image").
Text(rootDir.String()). // input directory
Input(propFile).
@@ -109,3 +112,16 @@
},
}}
}
+
+// Filesystem is the public interface for the filesystem struct. Currently, it's only for the apex
+// package to have access to the output file.
+type Filesystem interface {
+ android.Module
+ OutputPath() android.Path
+}
+
+var _ Filesystem = (*filesystem)(nil)
+
+func (f *filesystem) OutputPath() android.Path {
+ return f.output
+}
diff --git a/java/app.go b/java/app.go
index 249313c..574472c 100755
--- a/java/app.go
+++ b/java/app.go
@@ -905,6 +905,8 @@
&module.appProperties,
&module.overridableAppProperties)
+ module.usesLibrary.enforce = true
+
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
android.InitOverridableModule(module, &module.appProperties.Overrides)
@@ -1175,6 +1177,9 @@
// with knowledge of their shared libraries.
type usesLibrary struct {
usesLibraryProperties UsesLibraryProperties
+
+ // Whether to enforce verify_uses_library check.
+ enforce bool
}
func (u *usesLibrary) addLib(lib string, optional bool) {
@@ -1241,7 +1246,7 @@
func (u *usesLibrary) enforceUsesLibraries() bool {
defaultEnforceUsesLibs := len(u.usesLibraryProperties.Uses_libs) > 0 ||
len(u.usesLibraryProperties.Optional_uses_libs) > 0
- return BoolDefault(u.usesLibraryProperties.Enforce_uses_libs, defaultEnforceUsesLibs)
+ return BoolDefault(u.usesLibraryProperties.Enforce_uses_libs, u.enforce || defaultEnforceUsesLibs)
}
// Freeze the value of `enforce_uses_libs` based on the current values of `uses_libs` and `optional_uses_libs`.
diff --git a/java/app_import.go b/java/app_import.go
index 2054785..df940f1 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -430,6 +430,8 @@
android.InitDefaultableModule(module)
android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk")
+ module.usesLibrary.enforce = true
+
return module
}
diff --git a/java/app_import_test.go b/java/app_import_test.go
index 3b55c81..344d23b 100644
--- a/java/app_import_test.go
+++ b/java/app_import_test.go
@@ -182,31 +182,31 @@
name: "no preferred",
aaptPreferredConfig: nil,
aaptPrebuiltDPI: []string{},
- expected: "prebuilts/apk/app.apk",
+ expected: "verify_uses_libraries/apk/app.apk",
},
{
name: "AAPTPreferredConfig matches",
aaptPreferredConfig: proptools.StringPtr("xhdpi"),
aaptPrebuiltDPI: []string{"xxhdpi", "ldpi"},
- expected: "prebuilts/apk/app_xhdpi.apk",
+ expected: "verify_uses_libraries/apk/app_xhdpi.apk",
},
{
name: "AAPTPrebuiltDPI matches",
aaptPreferredConfig: proptools.StringPtr("mdpi"),
aaptPrebuiltDPI: []string{"xxhdpi", "xhdpi"},
- expected: "prebuilts/apk/app_xxhdpi.apk",
+ expected: "verify_uses_libraries/apk/app_xxhdpi.apk",
},
{
name: "non-first AAPTPrebuiltDPI matches",
aaptPreferredConfig: proptools.StringPtr("mdpi"),
aaptPrebuiltDPI: []string{"ldpi", "xhdpi"},
- expected: "prebuilts/apk/app_xhdpi.apk",
+ expected: "verify_uses_libraries/apk/app_xhdpi.apk",
},
{
name: "no matches",
aaptPreferredConfig: proptools.StringPtr("mdpi"),
aaptPrebuiltDPI: []string{"ldpi", "xxxhdpi"},
- expected: "prebuilts/apk/app.apk",
+ expected: "verify_uses_libraries/apk/app.apk",
},
}
@@ -225,7 +225,7 @@
if len(matches) != 2 {
t.Errorf("failed to extract the src apk path from %q", jniRuleCommand)
}
- if test.expected != matches[1] {
+ if strings.HasSuffix(matches[1], test.expected) {
t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1])
}
}
@@ -302,7 +302,7 @@
},
}
`,
- expected: "prebuilts/apk/app_arm64.apk",
+ expected: "verify_uses_libraries/apk/app_arm64.apk",
},
{
name: "no matching arch",
@@ -321,7 +321,7 @@
},
}
`,
- expected: "prebuilts/apk/app.apk",
+ expected: "verify_uses_libraries/apk/app.apk",
},
{
name: "no matching arch without default",
@@ -359,7 +359,7 @@
if len(matches) != 2 {
t.Errorf("failed to extract the src apk path from %q", jniRuleCommand)
}
- if test.expected != matches[1] {
+ if strings.HasSuffix(matches[1], test.expected) {
t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1])
}
}
diff --git a/java/java.go b/java/java.go
index 18dd9bd..82b53be 100644
--- a/java/java.go
+++ b/java/java.go
@@ -304,6 +304,9 @@
// whether to generate Binder#GetTransaction name method.
Generate_get_transaction_name *bool
+
+ // list of flags that will be passed to the AIDL compiler
+ Flags []string
}
// If true, export a copy of the module as a -hostdex module for host testing.
@@ -872,6 +875,8 @@
var flags []string
var deps android.Paths
+ flags = append(flags, j.deviceProperties.Aidl.Flags...)
+
if aidlPreprocess.Valid() {
flags = append(flags, "-p"+aidlPreprocess.String())
deps = append(deps, aidlPreprocess.Path())
diff --git a/java/java_test.go b/java/java_test.go
index d1ba3db..a2466f9 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -2424,6 +2424,22 @@
}
}
+func TestAidlFlagsArePassedToTheAidlCompiler(t *testing.T) {
+ ctx, _ := testJava(t, `
+ java_library {
+ name: "foo",
+ srcs: ["aidl/foo/IFoo.aidl"],
+ aidl: { flags: ["-Werror"], },
+ }
+ `)
+
+ aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
+ expectedAidlFlag := "-Werror"
+ if !strings.Contains(aidlCommand, expectedAidlFlag) {
+ t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
+ }
+}
+
func TestDataNativeBinaries(t *testing.T) {
ctx, config := testJava(t, `
java_test_host {
diff --git a/java/system_modules.go b/java/system_modules.go
index 7394fd5..5cc546d 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -192,6 +192,7 @@
fmt.Fprintln(w, name+":", "$("+makevar+")")
fmt.Fprintln(w, ".PHONY:", name)
+ // TODO(b/151177513): Licenses: Doesn't go through base_rules. May have to generate meta_lic and meta_module here.
},
}
}
diff --git a/licenses/Android.bp b/licenses/Android.bp
new file mode 100644
index 0000000..217792f
--- /dev/null
+++ b/licenses/Android.bp
@@ -0,0 +1,1082 @@
+//
+// Copyright (C) 2020 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 {
+ default_visibility: ["//visibility:public"],
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+license {
+ name: "Android-Apache-2.0",
+ license_kinds: ["SPDX-license-identifier-Apache-2.0"],
+ copyright_notice: "Copyright (C) The Android Open Source Project",
+ license_text: ["LICENSE"],
+}
+
+license_kind {
+ name: "SPDX-license-identifier-AFL-1.1",
+ conditions: ["by_exception_only"],
+ url: "https://spdx.org/licenses/AFL-1.1.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-AFL-1.2",
+ conditions: ["by_exception_only"],
+ url: "https://spdx.org/licenses/AFL-1.2.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-AFL-2.0",
+ conditions: ["by_exception_only"],
+ url: "https://spdx.org/licenses/AFL-2.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-AFL-2.1",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/AFL-2.1.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-AFL-3.0",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/AFL-3.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-AGPL",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/AGPL.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-AGPL-1.0",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/AGPL-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-AGPL-1.0-only",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/AGPL-1.0-only.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-AGPL-1.0-or-later",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/AGPL-1.0-or-later.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-AGPL-3.0",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/AGPL-3.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-AGPL-3.0-only",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/AGPL-3.0-only.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-AGPL-3.0-or-later",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/AGPL-3.0-or-later.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-Apache",
+ conditions: ["notice"],
+}
+
+license_kind {
+ name: "SPDX-license-identifier-Apache-1.0",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/Apache-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-Apache-1.1",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/Apache-1.1.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-Apache-2.0",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/Apache-2.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-Artistic",
+ conditions: ["notice"],
+}
+
+license_kind {
+ name: "SPDX-license-identifier-Artistic-1.0",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/Artistic-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-Artistic-1.0-Perl",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/Artistic-1.0-Perl.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-Artistic-1.0-cl8",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/Artistic-1.0-cl8.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-Artistic-2.0",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/Artistic-2.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-BSD",
+ conditions: ["notice"],
+}
+
+license_kind {
+ name: "SPDX-license-identifier-BSD-1-Clause",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/BSD-1-Clause.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-BSD-2-Clause",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/BSD-2-Clause.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-BSD-2-Clause-FreeBSD",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/BSD-2-Clause-FreeBSD.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-BSD-2-Clause-NetBSD",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/BSD-2-Clause-NetBSD.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-BSD-2-Clause-Patent",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/BSD-2-Clause-Patent.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-BSD-3-Clause",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/BSD-3-Clause.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-BSD-3-Clause-Attribution",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/BSD-3-Clause-Attribution.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-BSD-3-Clause-Clear",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/BSD-3-Clause-Clear.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-BSD-3-Clause-LBNL",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/BSD-3-Clause-LBNL.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-BSD-3-Clause-No-Nuclear-License",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-BSD-3-Clause-No-Nuclear-License-2014",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License-2014.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-BSD-3-Clause-No-Nuclear-Warranty",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-Warranty.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-BSD-3-Clause-Open-MPI",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/BSD-3-Clause-Open-MPI.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-BSD-4-Clause",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/BSD-4-Clause.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-BSD-4-Clause-UC",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/BSD-4-Clause-UC.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-BSD-Protection",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/BSD-Protection.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-BSD-Source-Code",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/BSD-Source-Code.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-BSL-1.0",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/BSL-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-Beerware",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/Beerware.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY",
+ conditions: ["notice"],
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-1.0",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/CC-BY-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-2.0",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/CC-BY-2.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-2.5",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/CC-BY-2.5.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-3.0",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/CC-BY-3.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-4.0",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/CC-BY-4.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-NC",
+ conditions: ["by_exception_only", "not_allowed"],
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-NC-1.0",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/CC-BY-NC-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-NC-2.0",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/CC-BY-NC-2.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-NC-2.5",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/CC-BY-NC-2.5.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-NC-3.0",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/CC-BY-NC-3.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-NC-4.0",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/CC-BY-NC-4.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-NC-ND-1.0",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/CC-BY-NC-ND-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-NC-ND-2.0",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/CC-BY-NC-ND-2.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-NC-ND-2.5",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/CC-BY-NC-ND-2.5.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-NC-ND-3.0",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/CC-BY-NC-ND-3.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-NC-ND-4.0",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/CC-BY-NC-ND-4.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-NC-SA-1.0",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/CC-BY-NC-SA-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-NC-SA-2.0",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/CC-BY-NC-SA-2.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-NC-SA-2.5",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/CC-BY-NC-SA-2.5.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-NC-SA-3.0",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/CC-BY-NC-SA-3.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-NC-SA-4.0",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/CC-BY-NC-SA-4.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-ND",
+ conditions: ["restricted"],
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-ND-1.0",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/CC-BY-ND-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-ND-2.0",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/CC-BY-ND-2.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-ND-2.5",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/CC-BY-ND-2.5.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-ND-3.0",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/CC-BY-ND-3.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-ND-4.0",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/CC-BY-ND-4.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-SA",
+ conditions: ["restricted"],
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-SA-1.0",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/CC-BY-SA-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-SA-2.0",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/CC-BY-SA-2.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-SA-2.5",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/CC-BY-SA-2.5.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-SA-3.0",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/CC-BY-SA-3.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-SA-4.0",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/CC-BY-SA-4.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC-BY-SA-ND",
+ conditions: ["restricted"],
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CC0-1.0",
+ conditions: ["unencumbered"],
+ url: "https://spdx.org/licenses/CC0-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CPAL-1.0",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/CPAL-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CPL-1.0",
+ conditions: ["reciprocal"],
+ url: "https://spdx.org/licenses/CPL-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-EPL",
+ conditions: ["reciprocal"],
+}
+
+license_kind {
+ name: "SPDX-license-identifier-EPL-1.0",
+ conditions: ["reciprocal"],
+ url: "https://spdx.org/licenses/EPL-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-EPL-2.0",
+ conditions: ["reciprocal"],
+ url: "https://spdx.org/licenses/EPL-2.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-EUPL",
+ conditions: ["by_exception_only", "not_allowed"],
+}
+
+license_kind {
+ name: "SPDX-license-identifier-EUPL-1.0",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/EUPL-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-EUPL-1.1",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/EUPL-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-EUPL-1.2",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/EUPL-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-FTL",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/FTL.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-GPL",
+ conditions: ["restricted"],
+}
+
+license_kind {
+ name: "SPDX-license-identifier-GPL-1.0",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/GPL-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-GPL-1.0+",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/GPL-1.0+.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-GPL-1.0-only",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/GPL-1.0-only.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-GPL-1.0-or-later",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/GPL-1.0-or-later.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-GPL-2.0",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/GPL-2.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-GPL-2.0+",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/GPL-2.0+.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-GPL-2.0-only",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/GPL-2.0-only.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-GPL-2.0-or-later",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/GPL-2.0-or-later.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-GPL-2.0-with-GCC-exception",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/GPL-2.0-with-GCC-exception.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-GPL-2.0-with-autoconf-exception",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/GPL-2.0-with-autoconf-exception.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-GPL-2.0-with-bison-exception",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/GPL-2.0-with-bison-exception.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-GPL-2.0-with-classpath-exception",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/GPL-2.0-with-classpath-exception.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-GPL-2.0-with-font-exception",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/GPL-2.0-with-font-exception.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-GPL-3.0",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/GPL-3.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-GPL-3.0+",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/GPL-3.0+.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-GPL-3.0-only",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/GPL-3.0-only.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-GPL-3.0-or-later",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/GPL-3.0-or-later.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-GPL-3.0-with-GCC-exception",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/GPL-3.0-with-GCC-exception.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-GPL-3.0-with-autoconf-exception",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/GPL-3.0-with-autoconf-exception.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-GPL-with-classpath-exception",
+ conditions: ["restricted"],
+}
+
+license_kind {
+ name: "SPDX-license-identifier-HPND",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/HPND.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-ICU",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/ICU.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-ISC",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/ISC.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-JSON",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/JSON.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-LGPL",
+ conditions: ["restricted"],
+}
+
+license_kind {
+ name: "SPDX-license-identifier-LGPL-2.0",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/LGPL-2.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-LGPL-2.0+",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/LGPL-2.0+.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-LGPL-2.0-only",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/LGPL-2.0-only.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-LGPL-2.0-or-later",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/LGPL-2.0-or-later.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-LGPL-2.1",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/LGPL-2.1.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-LGPL-2.1+",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/LGPL-2.1+.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-LGPL-2.1-only",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/LGPL-2.1-only.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-LGPL-2.1-or-later",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/LGPL-2.1-or-later.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-LGPL-3.0",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/LGPL-3.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-LGPL-3.0+",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/LGPL-3.0+.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-LGPL-3.0-only",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/LGPL-3.0-only.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-LGPL-3.0-or-later",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/LGPL-3.0-or-later.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-LGPLLR",
+ conditions: ["restricted"],
+ url: "https://spdx.org/licenses/LGPLLR.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-LPL-1.02",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/LPL-1.02.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-MIT",
+ conditions: ["notice"],
+}
+
+license_kind {
+ name: "SPDX-license-identifier-MIT-0",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/MIT-0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-MIT-CMU",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/MIT-CMU.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-MIT-advertising",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/MIT-advertising.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-MIT-enna",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/MIT-enna.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-MIT-feh",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/MIT-feh.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-MITNFA",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/MITNFA.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-MPL",
+ conditions: ["reciprocal"],
+}
+
+license_kind {
+ name: "SPDX-license-identifier-MPL-1.0",
+ conditions: ["reciprocal"],
+ url: "https://spdx.org/licenses/MPL-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-MPL-1.1",
+ conditions: ["reciprocal"],
+ url: "https://spdx.org/licenses/MPL-1.1.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-MPL-2.0",
+ conditions: ["reciprocal"],
+ url: "https://spdx.org/licenses/MPL-2.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-MPL-2.0-no-copyleft-exception",
+ conditions: ["reciprocal"],
+ url: "https://spdx.org/licenses/MPL-2.0-no-copyleft-exception.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-MS-PL",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/MS-PL.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-NCSA",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/NCSA.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-OFL",
+ conditions: ["by_exception_only"],
+}
+
+license_kind {
+ name: "SPDX-license-identifier-OFL-1.0",
+ conditions: ["by_exception_only"],
+ url: "https://spdx.org/licenses/OFL-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-OFL-1.0-RFN",
+ conditions: ["by_exception_only"],
+ url: "https://spdx.org/licenses/OFL-1.0-RFN.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-OFL-1.0-no-RFN",
+ conditions: ["by_exception_only"],
+ url: "https://spdx.org/licenses/OFL-1.0-no-RFN.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-OFL-1.1",
+ conditions: ["by_exception_only"],
+ url: "https://spdx.org/licenses/OFL-1.1.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-OFL-1.1-RFN",
+ conditions: ["by_exception_only"],
+ url: "https://spdx.org/licenses/OFL-1.1-RFN.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-OFL-1.1-no-RFN",
+ conditions: ["by_exception_only"],
+ url: "https://spdx.org/licenses/OFL-1.1-no-RFN.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-OpenSSL",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/OpenSSL.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-PSF-2.0",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/PSF-2.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-SISSL",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/SISSL.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-SISSL-1.2",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/SISSL-1.2.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-SPL-1.0",
+ conditions: ["by_exception_only", "reciprocal"],
+ url: "https://spdx.org/licenses/SPL-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-SSPL",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/SSPL.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-UPL-1.0",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/UPL-1.-.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-Unicode-DFS",
+ conditions: ["notice"],
+}
+
+license_kind {
+ name: "SPDX-license-identifier-Unicode-DFS-2015",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/Unicode-DFS-2015.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-Unicode-DFS-2016",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/Unicode-DFS-2016.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-Unlicense",
+ conditions: ["unencumbered"],
+ url: "https://spdx.org/licenses/Unlicense.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-W3C",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/W3C.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-W3C-19980720",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/W3C-19980720.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-W3C-20150513",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/W3C-20150513.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-WTFPL",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/WTFPL.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-Watcom-1.0",
+ conditions: ["by_exception_only", "not_allowed"],
+ url: "https://spdx.org/licenses/Watcom-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-Xnet",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/Xnet.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-ZPL",
+ conditions: ["notice"],
+}
+
+license_kind {
+ name: "SPDX-license-identifier-ZPL-1.1",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/ZPL-1.1.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-ZPL-2.0",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/ZPL-2.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-ZPL-2.1",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/ZPL-2.1.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-Zend-2.0",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/Zend-2.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-Zlib",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/Zlib.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-libtiff",
+ conditions: ["notice"],
+ url: "https://spdx.org/licenses/libtiff.html",
+}
+
+
+// Legacy license kinds -- do not add new references -- use an spdx kind instead.
+license_kind {
+ name: "legacy_unknown",
+ conditions: ["by_exception_only"],
+}
+
+license_kind {
+ name: "legacy_unencumbered",
+ conditions: ["unencumbered"],
+}
+
+license_kind {
+ name: "legacy_notice",
+ conditions: ["notice"],
+}
+
+license_kind {
+ name: "legacy_reciprocal",
+ conditions: ["reciprocal"],
+}
+
+license_kind {
+ name: "legacy_restricted",
+ conditions: ["restricted"],
+}
+
+license_kind {
+ name: "legacy_by_exception_only",
+ conditions: ["by_exception_only"],
+}
+
+license_kind {
+ name: "legacy_not_allowed",
+ conditions: ["by_exception_only", "not_allowed"],
+}
+
+license_kind {
+ name: "legacy_proprietary",
+ conditions: ["by_exception_only", "not_allowed", "proprietary"],
+}
diff --git a/licenses/LICENSE b/licenses/LICENSE
new file mode 100644
index 0000000..dae0406
--- /dev/null
+++ b/licenses/LICENSE
@@ -0,0 +1,214 @@
+
+ Copyright (c) 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.
+
+ 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.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/phony/phony.go b/phony/phony.go
index cb60b9f..a31d402 100644
--- a/phony/phony.go
+++ b/phony/phony.go
@@ -52,6 +52,7 @@
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
fmt.Fprintln(w, "LOCAL_MODULE :=", name)
+ data.Entries.WriteLicenseVariables(w)
if p.Host() {
fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true")
}
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 35a807b..56d660e 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -31,12 +31,19 @@
// bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures.
bindgenClangVersion = "clang-r399163b"
+ _ = pctx.VariableFunc("bindgenClangVersion", func(ctx android.PackageVarContext) string {
+ if override := ctx.Config().Getenv("LLVM_BINDGEN_PREBUILTS_VERSION"); override != "" {
+ return override
+ }
+ return bindgenClangVersion
+ })
+
//TODO(b/160803703) Use a prebuilt bindgen instead of the built bindgen.
_ = pctx.HostBinToolVariable("bindgenCmd", "bindgen")
_ = pctx.SourcePathVariable("bindgenClang",
- "${cc_config.ClangBase}/${config.HostPrebuiltTag}/"+bindgenClangVersion+"/bin/clang")
+ "${cc_config.ClangBase}/${config.HostPrebuiltTag}/${bindgenClangVersion}/bin/clang")
_ = pctx.SourcePathVariable("bindgenLibClang",
- "${cc_config.ClangBase}/${config.HostPrebuiltTag}/"+bindgenClangVersion+"/lib64/")
+ "${cc_config.ClangBase}/${config.HostPrebuiltTag}/${bindgenClangVersion}/lib64/")
//TODO(ivanlozano) Switch this to RuleBuilder
bindgen = pctx.AndroidStaticRule("bindgen",
diff --git a/rust/config/global.go b/rust/config/global.go
index 22d9567..b7fff4a 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -44,6 +44,7 @@
GlobalRustFlags = []string{
"--remap-path-prefix $$(pwd)=",
"-C codegen-units=1",
+ "-C debuginfo=2",
"-C opt-level=3",
"-C relocation-model=pic",
}
diff --git a/rust/image.go b/rust/image.go
index af8c3b2..5e55e22 100644
--- a/rust/image.go
+++ b/rust/image.go
@@ -100,13 +100,13 @@
platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
// Rust does not support installing to the product image yet.
- if mod.VendorProperties.Product_available != nil {
+ if Bool(mod.VendorProperties.Product_available) {
mctx.PropertyErrorf("product_available",
"Rust modules do not yet support being available to the product image")
} else if mctx.ProductSpecific() {
mctx.PropertyErrorf("product_specific",
"Rust modules do not yet support installing to the product image.")
- } else if mod.VendorProperties.Double_loadable != nil {
+ } else if Bool(mod.VendorProperties.Double_loadable) {
mctx.PropertyErrorf("double_loadable",
"Rust modules do not yet support double loading")
}
@@ -114,7 +114,7 @@
coreVariantNeeded := true
var vendorVariants []string
- if mod.VendorProperties.Vendor_available != nil {
+ if Bool(mod.VendorProperties.Vendor_available) {
if vendorSpecific {
mctx.PropertyErrorf("vendor_available",
"doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific:true`")
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 42caff2..38306ad 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -307,6 +307,7 @@
// Actual implementation libraries are created on LoadHookMutator
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
fmt.Fprintf(w, "LOCAL_MODULE := %s\n", m.Name())
+ data.Entries.WriteLicenseVariables(w)
fmt.Fprintf(w, "LOCAL_MODULE_CLASS := FAKE\n")
fmt.Fprintf(w, "LOCAL_MODULE_TAGS := optional\n")
fmt.Fprintf(w, "include $(BUILD_SYSTEM)/base_rules.mk\n\n")
diff --git a/ui/build/config.go b/ui/build/config.go
index 1152cd7..15da1bc 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -56,6 +56,7 @@
katiSuffix string
targetDevice string
targetDeviceDir string
+ fullBuild bool
// Autodetected
totalRAM uint64
@@ -791,6 +792,14 @@
c.targetDevice = device
}
+func (c *configImpl) FullBuild() bool {
+ return c.fullBuild
+}
+
+func (c *configImpl) SetFullBuild(fullBuild bool) {
+ c.fullBuild = fullBuild
+}
+
func (c *configImpl) TargetBuildVariant() string {
if v, ok := c.environ.Get("TARGET_BUILD_VARIANT"); ok {
return v
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index fe0aca9..be6f00a 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -214,6 +214,9 @@
// So that later Kati runs can find BoardConfig.mk faster
"TARGET_DEVICE_DIR",
+ // To decide whether to skip the old installed cleanup step.
+ "FULL_BUILD",
+
// Whether --werror_overriding_commands will work
"BUILD_BROKEN_DUP_RULES",
@@ -278,6 +281,7 @@
config.SetNinjaArgs(strings.Fields(makeVars["NINJA_GOALS"]))
config.SetTargetDevice(makeVars["TARGET_DEVICE"])
config.SetTargetDeviceDir(makeVars["TARGET_DEVICE_DIR"])
+ config.SetFullBuild(makeVars["FULL_BUILD"] == "true")
config.SetBuildBrokenDupRules(makeVars["BUILD_BROKEN_DUP_RULES"] == "true")
config.SetBuildBrokenUsesNetwork(makeVars["BUILD_BROKEN_USES_NETWORK"] == "true")
diff --git a/ui/build/kati.go b/ui/build/kati.go
index 06ec646..668b20e 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -229,7 +229,11 @@
// Cleanup steps.
cleanCopyHeaders(ctx, config)
- cleanOldInstalledFiles(ctx, config)
+ // Skip the old installed file cleanup step for few non-full build goals as we don't create
+ // an installed file list for them.
+ if config.FullBuild() {
+ cleanOldInstalledFiles(ctx, config)
+ }
}
// Clean out obsolete header files on the disk that were *not copied* during the