From 6fa44c197335a8bea4f96cce3296f5c92d8dd7e7 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Tue, 27 Sep 2022 12:41:52 +0100 Subject: [PATCH 01/82] java_sdk_library_import: Copy all prebuilt properties to child modules Previously, only the prefer property was copied from the java_sdk_library_import module to its child modules which meant that if the use_source_config_var property was used to control the prefer property that the child modules would never be used. That can cause build breakages when building against prebuilts as some parts of the build will use prebuilt files from java_sdk_library_import and some will use source files from the corresponding java_sdk_library. This change copies the use_source_config_var property too. It also adds tests to verify that dependencies on child modules of a java_sdk_library use the prebuilt child modules of the corresponding java_sdk_library_import. That revealed a bug with the handling of stub sources where the prefer property was set after creating the module which has also been fixed. Bug: 249192297 Test: m nothing # Cherry pick into branch broken by previous behavior and make # sure that it fixes it. Change-Id: I5719c257f8457bcb2238bc7965215512a20f1095 (cherry picked from commit on android-review.googlesource.com host: bf4de041de611de4b3ec24c5f261c4293522961a) Merged-In: I5719c257f8457bcb2238bc7965215512a20f1095 (cherry picked from commit 8ab8056a4f9de6cec1fdedc7d49502439ea7aef6) --- android/prebuilt.go | 14 +++++++- java/sdk_library.go | 17 ++++++---- java/sdk_library_test.go | 70 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 91 insertions(+), 10 deletions(-) diff --git a/android/prebuilt.go b/android/prebuilt.go index 584348767..e7f221b6d 100644 --- a/android/prebuilt.go +++ b/android/prebuilt.go @@ -56,7 +56,9 @@ func (t prebuiltDependencyTag) ExcludeFromApexContents() {} var _ ExcludeFromVisibilityEnforcementTag = PrebuiltDepTag var _ ExcludeFromApexContentsTag = PrebuiltDepTag -type PrebuiltProperties struct { +// UserSuppliedPrebuiltProperties contains the prebuilt properties that can be specified in an +// Android.bp file. +type UserSuppliedPrebuiltProperties struct { // When prefer is set to true the prebuilt will be used instead of any source module with // a matching name. Prefer *bool `android:"arch_variant"` @@ -70,6 +72,16 @@ type PrebuiltProperties struct { // If specified then the prefer property is ignored in favor of the value of the Soong config // variable. Use_source_config_var *ConfigVarProperties +} + +// CopyUserSuppliedPropertiesFromPrebuilt copies the user supplied prebuilt properties from the +// prebuilt properties. +func (u *UserSuppliedPrebuiltProperties) CopyUserSuppliedPropertiesFromPrebuilt(p *Prebuilt) { + *u = p.properties.UserSuppliedPrebuiltProperties +} + +type PrebuiltProperties struct { + UserSuppliedPrebuiltProperties SourceExists bool `blueprint:"mutated"` UsePrebuilt bool `blueprint:"mutated"` diff --git a/java/sdk_library.go b/java/sdk_library.go index 47ffc6afc..cb4805823 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -2119,8 +2119,9 @@ func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.Defaultabl Sdk_version *string Libs []string Jars []string - Prefer *bool Compile_dex *bool + + android.UserSuppliedPrebuiltProperties }{} props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope)) props.Sdk_version = scopeProperties.Sdk_version @@ -2130,7 +2131,7 @@ func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.Defaultabl props.Jars = scopeProperties.Jars // The imports are preferred if the java_sdk_library_import is preferred. - props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer()) + props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt) // The imports need to be compiled to dex if the java_sdk_library_import requests it. compileDex := module.properties.Compile_dex @@ -2144,16 +2145,18 @@ func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.Defaultabl func (module *SdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) { props := struct { - Name *string - Srcs []string - Prefer *bool + Name *string + Srcs []string + + android.UserSuppliedPrebuiltProperties }{} props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope)) props.Srcs = scopeProperties.Stub_srcs - mctx.CreateModule(PrebuiltStubsSourcesFactory, &props) // The stubs source is preferred if the java_sdk_library_import is preferred. - props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer()) + props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt) + + mctx.CreateModule(PrebuiltStubsSourcesFactory, &props) } // Add the dependencies on the child module in the component deps mutator so that it diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go index 3500c84d2..ec971a8fe 100644 --- a/java/sdk_library_test.go +++ b/java/sdk_library_test.go @@ -867,11 +867,12 @@ func TestJavaSdkLibraryImport_WithSource(t *testing.T) { }) } -func TestJavaSdkLibraryImport_Preferred(t *testing.T) { +func testJavaSdkLibraryImport_Preferred(t *testing.T, prefer string, preparer android.FixturePreparer) { result := android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, FixtureWithLastReleaseApis("sdklib"), + preparer, ).RunTestWithBp(t, ` java_sdk_library { name: "sdklib", @@ -885,11 +886,37 @@ func TestJavaSdkLibraryImport_Preferred(t *testing.T) { java_sdk_library_import { name: "sdklib", - prefer: true, + `+prefer+` public: { jars: ["a.jar"], + stub_srcs: ["a.java"], + current_api: "current.txt", + removed_api: "removed.txt", + annotations: "annotations.zip", }, } + + java_library { + name: "combined", + static_libs: [ + "sdklib.stubs", + ], + java_resources: [ + ":sdklib.stubs.source", + ":sdklib{.public.api.txt}", + ":sdklib{.public.removed-api.txt}", + ":sdklib{.public.annotations.zip}", + ], + sdk_version: "none", + system_modules: "none", + } + + java_library { + name: "public", + srcs: ["a.java"], + libs: ["sdklib"], + sdk_version: "current", + } `) CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{ @@ -903,9 +930,48 @@ func TestJavaSdkLibraryImport_Preferred(t *testing.T) { CheckModuleDependencies(t, result.TestContext, "prebuilt_sdklib", "android_common", []string{ `dex2oatd`, `prebuilt_sdklib.stubs`, + `prebuilt_sdklib.stubs.source`, `sdklib.impl`, `sdklib.xml`, }) + + // Make sure that dependencies on child modules use the prebuilt when preferred. + CheckModuleDependencies(t, result.TestContext, "combined", "android_common", []string{ + // Each use of :sdklib{...} adds a dependency onto prebuilt_sdklib. + `prebuilt_sdklib`, + `prebuilt_sdklib`, + `prebuilt_sdklib`, + `prebuilt_sdklib.stubs`, + `prebuilt_sdklib.stubs.source`, + }) + + // Make sure that dependencies on sdklib that resolve to one of the child libraries use the + // prebuilt library. + public := result.ModuleForTests("public", "android_common") + rule := public.Output("javac/public.jar") + inputs := rule.Implicits.Strings() + expected := "out/soong/.intermediates/prebuilt_sdklib.stubs/android_common/combined/sdklib.stubs.jar" + if !android.InList(expected, inputs) { + t.Errorf("expected %q to contain %q", inputs, expected) + } +} + +func TestJavaSdkLibraryImport_Preferred(t *testing.T) { + t.Run("prefer", func(t *testing.T) { + testJavaSdkLibraryImport_Preferred(t, "prefer: true,", android.NullFixturePreparer) + }) + + t.Run("use_source_config_var", func(t *testing.T) { + testJavaSdkLibraryImport_Preferred(t, + "use_source_config_var: {config_namespace: \"acme\", var_name: \"use_source\"},", + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + variables.VendorVars = map[string]map[string]string{ + "acme": { + "use_source": "false", + }, + } + })) + }) } func TestJavaSdkLibraryEnforce(t *testing.T) { From 521fdf5b647bbbb6523d26a93723b4c3136b902d Mon Sep 17 00:00:00 2001 From: Cole Faust Date: Fri, 1 Sep 2023 16:11:47 -0700 Subject: [PATCH 02/82] Add install_symlink soong module type This can be used to install symlinks to arbitrary locations/targets on the device. Used to replace a make-built symlink. Bug: 205632228 Test: built and ran the emulator observed the /system/bin/hwservicemanager symlink is still there (cherry picked from https://android-review.googlesource.com/q/commit:dff9c14148de93502b3880d9f9943054c2eeb392) Merged-In: I6df922c8d919e6d56fa79702815a89c98f4d65ed Change-Id: I6df922c8d919e6d56fa79702815a89c98f4d65ed --- etc/Android.bp | 2 + etc/install_symlink.go | 92 ++++++++++++++++++++++++ etc/install_symlink_test.go | 135 ++++++++++++++++++++++++++++++++++++ etc/prebuilt_etc_test.go | 2 +- 4 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 etc/install_symlink.go create mode 100644 etc/install_symlink_test.go diff --git a/etc/Android.bp b/etc/Android.bp index c67023679..cefd717aa 100644 --- a/etc/Android.bp +++ b/etc/Android.bp @@ -14,10 +14,12 @@ bootstrap_go_package { srcs: [ "prebuilt_etc.go", "snapshot_etc.go", + "install_symlink.go", ], testSrcs: [ "prebuilt_etc_test.go", "snapshot_etc_test.go", + "install_symlink_test.go", ], pluginFor: ["soong_build"], } diff --git a/etc/install_symlink.go b/etc/install_symlink.go new file mode 100644 index 000000000..2182b8669 --- /dev/null +++ b/etc/install_symlink.go @@ -0,0 +1,92 @@ +// Copyright 2023 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 etc + +import ( + "android/soong/android" + "path/filepath" + "strings" +) + +func init() { + RegisterInstallSymlinkBuildComponents(android.InitRegistrationContext) +} + +func RegisterInstallSymlinkBuildComponents(ctx android.RegistrationContext) { + ctx.RegisterModuleType("install_symlink", InstallSymlinkFactory) +} + +// install_symlink can be used to install an symlink with an arbitrary target to an arbitrary path +// on the device. +func InstallSymlinkFactory() android.Module { + module := &InstallSymlink{} + module.AddProperties(&module.properties) + android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) + return module +} + +type InstallSymlinkProperties struct { + // Where to install this symlink, relative to the partition it's installed on. + // Which partition it's installed on can be controlled by the vendor, system_ext, ramdisk, etc. + // properties. + Installed_location string + // The target of the symlink, aka where the symlink points. + Symlink_target string +} + +type InstallSymlink struct { + android.ModuleBase + properties InstallSymlinkProperties + + output android.Path + installedPath android.InstallPath +} + +func (m *InstallSymlink) GenerateAndroidBuildActions(ctx android.ModuleContext) { + if filepath.Clean(m.properties.Symlink_target) != m.properties.Symlink_target { + ctx.PropertyErrorf("symlink_target", "Should be a clean filepath") + return + } + if filepath.Clean(m.properties.Installed_location) != m.properties.Installed_location { + ctx.PropertyErrorf("installed_location", "Should be a clean filepath") + return + } + if strings.HasPrefix(m.properties.Installed_location, "../") || strings.HasPrefix(m.properties.Installed_location, "/") { + ctx.PropertyErrorf("installed_location", "Should not start with / or ../") + return + } + + out := android.PathForModuleOut(ctx, "out.txt") + android.WriteFileRuleVerbatim(ctx, out, "") + m.output = out + + name := filepath.Base(m.properties.Installed_location) + installDir := android.PathForModuleInstall(ctx, filepath.Dir(m.properties.Installed_location)) + m.installedPath = ctx.InstallAbsoluteSymlink(installDir, name, m.properties.Symlink_target) +} + +func (m *InstallSymlink) AndroidMkEntries() []android.AndroidMkEntries { + return []android.AndroidMkEntries{{ + Class: "FAKE", + // Need at least one output file in order for this to take effect. + OutputFile: android.OptionalPathForPath(m.output), + Include: "$(BUILD_PHONY_PACKAGE)", + ExtraEntries: []android.AndroidMkExtraEntriesFunc{ + func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { + entries.AddStrings("LOCAL_SOONG_INSTALL_SYMLINKS", m.installedPath.String()) + }, + }, + }} +} diff --git a/etc/install_symlink_test.go b/etc/install_symlink_test.go new file mode 100644 index 000000000..d7165e5de --- /dev/null +++ b/etc/install_symlink_test.go @@ -0,0 +1,135 @@ +// Copyright 2023 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 etc + +import ( + "android/soong/android" + "strings" + "testing" +) + +var prepareForInstallSymlinkTest = android.GroupFixturePreparers( + android.PrepareForTestWithArchMutator, + android.FixtureRegisterWithContext(RegisterInstallSymlinkBuildComponents), +) + +func TestInstallSymlinkBasic(t *testing.T) { + result := prepareForInstallSymlinkTest.RunTestWithBp(t, ` + install_symlink { + name: "foo", + installed_location: "bin/foo", + symlink_target: "/system/system_ext/bin/foo", + } + `) + + foo_variants := result.ModuleVariantsForTests("foo") + if len(foo_variants) != 1 { + t.Fatalf("expected 1 variant, got %#v", foo_variants) + } + + foo := result.ModuleForTests("foo", "android_common").Module() + androidMkEntries := android.AndroidMkEntriesForTest(t, result.TestContext, foo) + if len(androidMkEntries) != 1 { + t.Fatalf("expected 1 androidmkentry, got %d", len(androidMkEntries)) + } + + symlinks := androidMkEntries[0].EntryMap["LOCAL_SOONG_INSTALL_SYMLINKS"] + if len(symlinks) != 1 { + t.Fatalf("Expected 1 symlink, got %d", len(symlinks)) + } + + if !strings.HasSuffix(symlinks[0], "system/bin/foo") { + t.Fatalf("Expected symlink install path to end in system/bin/foo, got: %s", symlinks[0]) + } +} + +func TestInstallSymlinkToRecovery(t *testing.T) { + result := prepareForInstallSymlinkTest.RunTestWithBp(t, ` + install_symlink { + name: "foo", + installed_location: "bin/foo", + symlink_target: "/system/system_ext/bin/foo", + recovery: true, + } + `) + + foo_variants := result.ModuleVariantsForTests("foo") + if len(foo_variants) != 1 { + t.Fatalf("expected 1 variant, got %#v", foo_variants) + } + + foo := result.ModuleForTests("foo", "android_common").Module() + androidMkEntries := android.AndroidMkEntriesForTest(t, result.TestContext, foo) + if len(androidMkEntries) != 1 { + t.Fatalf("expected 1 androidmkentry, got %d", len(androidMkEntries)) + } + + symlinks := androidMkEntries[0].EntryMap["LOCAL_SOONG_INSTALL_SYMLINKS"] + if len(symlinks) != 1 { + t.Fatalf("Expected 1 symlink, got %d", len(symlinks)) + } + + if !strings.HasSuffix(symlinks[0], "recovery/root/system/bin/foo") { + t.Fatalf("Expected symlink install path to end in recovery/root/system/bin/foo, got: %s", symlinks[0]) + } +} + +func TestErrorOnNonCleanTarget(t *testing.T) { + prepareForInstallSymlinkTest. + ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("Should be a clean filepath")). + RunTestWithBp(t, ` + install_symlink { + name: "foo", + installed_location: "bin/foo", + symlink_target: "/system/system_ext/../bin/foo", + } + `) +} + +func TestErrorOnNonCleanInstalledLocation(t *testing.T) { + prepareForInstallSymlinkTest. + ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("Should be a clean filepath")). + RunTestWithBp(t, ` + install_symlink { + name: "foo", + installed_location: "bin/../foo", + symlink_target: "/system/system_ext/bin/foo", + } + `) +} + +func TestErrorOnInstalledPathStartingWithDotDot(t *testing.T) { + prepareForInstallSymlinkTest. + ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("Should not start with / or \\.\\./")). + RunTestWithBp(t, ` + install_symlink { + name: "foo", + installed_location: "../bin/foo", + symlink_target: "/system/system_ext/bin/foo", + } + `) +} + +func TestErrorOnInstalledPathStartingWithSlash(t *testing.T) { + prepareForInstallSymlinkTest. + ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("Should not start with / or \\.\\./")). + RunTestWithBp(t, ` + install_symlink { + name: "foo", + installed_location: "/bin/foo", + symlink_target: "/system/system_ext/bin/foo", + } + `) +} diff --git a/etc/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go index 0d44c31ef..df117097e 100644 --- a/etc/prebuilt_etc_test.go +++ b/etc/prebuilt_etc_test.go @@ -82,7 +82,7 @@ func TestPrebuiltEtcVariants(t *testing.T) { baz_variants := result.ModuleVariantsForTests("baz.conf") if len(baz_variants) != 1 { - t.Errorf("expected 1, got %#v", bar_variants) + t.Errorf("expected 1, got %#v", baz_variants) } } From be0dee88122a6c5d09d2cc20448a3083920a7f9b Mon Sep 17 00:00:00 2001 From: Dan Shi Date: Fri, 26 May 2023 04:21:44 +0000 Subject: [PATCH 03/82] Support test runnner option in auto generated test configs Bug: 284179405 Bug: 236980335 Test: unittest Change-Id: Ifae3d556ff79153ca6c3067347fc259b665fb2e1 Merged-In: Ifae3d556ff79153ca6c3067347fc259b665fb2e1 --- cc/test.go | 5 +++++ java/java.go | 5 +++++ java/java_test.go | 24 ++++++++++++++++++++++++ tradefed/autogen.go | 37 +++++++++++++++++++++++++------------ 4 files changed, 59 insertions(+), 12 deletions(-) diff --git a/cc/test.go b/cc/test.go index 27de06b07..3f5f71007 100644 --- a/cc/test.go +++ b/cc/test.go @@ -70,6 +70,10 @@ type TestOptions struct { // Add MinApiLevelModuleController with ro.vndk.version property. If ro.vndk.version has an // integer value and the value is less than the min_vndk_version, skip this module. Min_vndk_version *int64 + + // Extra