From 7ae2b0f2b60675394a57ee83e4c7baca65e125bd Mon Sep 17 00:00:00 2001 From: Cole Faust Date: Fri, 1 Sep 2023 16:11:47 -0700 Subject: [PATCH 1/5] 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 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 cab7389b6e..97788e4887 100644 --- a/etc/Android.bp +++ b/etc/Android.bp @@ -12,9 +12,11 @@ bootstrap_go_package { ], srcs: [ "prebuilt_etc.go", + "install_symlink.go", ], testSrcs: [ "prebuilt_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 0000000000..2182b8669d --- /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 0000000000..d7165e5de0 --- /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 354f6bb6ea..662184c226 100644 --- a/etc/prebuilt_etc_test.go +++ b/etc/prebuilt_etc_test.go @@ -66,7 +66,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) } } -- GitLab From 108bd003ab283ad2893cd35ba0bfa0ccfddaa9ff Mon Sep 17 00:00:00 2001 From: althafvly Date: Thu, 27 Feb 2025 19:28:24 +0530 Subject: [PATCH 2/5] add dummy Preprocessed soong variable --- java/app_import.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/java/app_import.go b/java/app_import.go index 3371e8e1fe..3ff1e4371a 100644 --- a/java/app_import.go +++ b/java/app_import.go @@ -99,6 +99,9 @@ type AndroidAppImportProperties struct { // If set, create package-export.apk, which other packages can // use to get PRODUCT-agnostic resource data like IDs and type definitions. Export_package_resources *bool + + // Whether the prebuilt apk can be installed without additional processing. Default is false. + Preprocessed *bool } func (a *AndroidAppImport) IsInstallable() bool { -- GitLab From 2e353768855dce6d9b219e11a6bc5eb90a724f07 Mon Sep 17 00:00:00 2001 From: althafvly Date: Thu, 27 Feb 2025 21:41:04 +0530 Subject: [PATCH 3/5] Fix install_symlink --- android/fixture.go | 12 ++++++++++++ etc/install_symlink.go | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/android/fixture.go b/android/fixture.go index fd051a7a4e..376a36a149 100644 --- a/android/fixture.go +++ b/android/fixture.go @@ -586,6 +586,18 @@ func FixtureExpectsAllErrorsToMatchAPattern(patterns []string) FixtureErrorHandl }) } +// FixtureExpectsOneErrorPattern returns an error handler that will cause the test to fail +// if there is more than one error or the error does not match the pattern. +// +// If the test fails this handler will call `result.FailNow()` which will exit the goroutine within +// which the test is being run which means that the RunTest() method will not return. +func FixtureExpectsOneErrorPattern(pattern string) FixtureErrorHandler { + return FixtureCustomErrorHandler(func(t *testing.T, result *TestResult) { + t.Helper() + CheckErrorsAgainstExpectations(t, result.Errs, []string{pattern}) + }) +} + // FixtureCustomErrorHandler creates a custom error handler func FixtureCustomErrorHandler(function func(t *testing.T, result *TestResult)) FixtureErrorHandler { return simpleErrorHandler{ diff --git a/etc/install_symlink.go b/etc/install_symlink.go index 2182b8669d..8c19668729 100644 --- a/etc/install_symlink.go +++ b/etc/install_symlink.go @@ -69,7 +69,7 @@ func (m *InstallSymlink) GenerateAndroidBuildActions(ctx android.ModuleContext) } out := android.PathForModuleOut(ctx, "out.txt") - android.WriteFileRuleVerbatim(ctx, out, "") + android.WriteFileRule(ctx, out, "") m.output = out name := filepath.Base(m.properties.Installed_location) -- GitLab From c1319b0ca62ece53a9b46bb9e8b7b567b2d2736c Mon Sep 17 00:00:00 2001 From: althafvly Date: Wed, 26 Feb 2025 19:02:06 +0530 Subject: [PATCH 4/5] Browser: Sign with user-keys if its available --- java/app.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/java/app.go b/java/app.go index 18389d39e3..b3273bb8be 100755 --- a/java/app.go +++ b/java/app.go @@ -576,9 +576,21 @@ func processMainCert(m android.ModuleBase, certPropValue string, certificates [] var mainCert Certificate if certPropValue != "" { defaultDir := ctx.Config().DefaultAppCertificateDir(ctx) - mainCert = Certificate{ - Pem: defaultDir.Join(ctx, certPropValue+".x509.pem"), - Key: defaultDir.Join(ctx, certPropValue+".pk8"), + + userKeyBasePath := "user-keys/" + certPropValue + userPemPath := android.ExistentPathForSource(ctx, userKeyBasePath+".x509.pem") + userKeyPath := android.ExistentPathForSource(ctx, userKeyBasePath+".pk8") + + if certPropValue == "platform" && userPemPath.Valid() && userKeyPath.Valid() { + mainCert = Certificate{ + Pem: userPemPath.Path(), + Key: userKeyPath.Path(), + } + } else { + mainCert = Certificate{ + Pem: defaultDir.Join(ctx, certPropValue+".x509.pem"), + Key: defaultDir.Join(ctx, certPropValue+".pk8"), + } } } else { pem, key := ctx.Config().DefaultAppCertificate(ctx) -- GitLab From ccbcb9e43885162391935a2b4f0b51bc751b2666 Mon Sep 17 00:00:00 2001 From: Jiakai Zhang Date: Thu, 1 Jun 2023 15:16:58 +0100 Subject: [PATCH 5/5] Drop INTERNAL_PLATFORM_MISSING_USES_LIBRARIES. Bug: 282877248 Test: Presubmit build tests. Change-Id: Idd69433f308f5f47973ff0d5340a2399a27cb32c --- android/config.go | 4 ---- android/variable.go | 2 -- java/app.go | 12 +++++++++--- java/app_test.go | 3 --- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/android/config.go b/android/config.go index 48700fb21c..7e4d22c12e 100644 --- a/android/config.go +++ b/android/config.go @@ -1359,10 +1359,6 @@ func (c *config) ProductPrivateSepolicyDirs() []string { return c.productVariables.ProductPrivateSepolicyDirs } -func (c *config) MissingUsesLibraries() []string { - return c.productVariables.MissingUsesLibraries -} - func (c *deviceConfig) DeviceArch() string { return String(c.config.productVariables.DeviceArch) } diff --git a/android/variable.go b/android/variable.go index f84ba82b31..19d305a6da 100644 --- a/android/variable.go +++ b/android/variable.go @@ -374,8 +374,6 @@ type productVariables struct { TargetFSConfigGen []string `json:",omitempty"` - MissingUsesLibraries []string `json:",omitempty"` - EnforceProductPartitionInterface *bool `json:",omitempty"` EnforceInterPartitionJavaSdkLibrary *bool `json:",omitempty"` diff --git a/java/app.go b/java/app.go index b3273bb8be..32be5b518a 100755 --- a/java/app.go +++ b/java/app.go @@ -18,6 +18,7 @@ package java // related module types, including their override variants. import ( + "fmt" "path/filepath" "sort" "strings" @@ -1247,10 +1248,15 @@ func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, hasFrameworkLibs } } -// presentOptionalUsesLibs returns optional_uses_libs after filtering out MissingUsesLibraries, which don't exist in the -// build. +// presentOptionalUsesLibs returns optional_uses_libs after filtering out libraries that don't exist in the source tree. func (u *usesLibrary) presentOptionalUsesLibs(ctx android.BaseModuleContext) []string { - optionalUsesLibs, _ := android.FilterList(u.usesLibraryProperties.Optional_uses_libs, ctx.Config().MissingUsesLibraries()) + optionalUsesLibs := android.FilterListPred(u.usesLibraryProperties.Optional_uses_libs, func(s string) bool { + exists := ctx.OtherModuleExists(s) + if !exists { + fmt.Printf("Warning: Module '%s' depends on non-existing optional_uses_libs '%s'\n", ctx.ModuleName(), s) + } + return exists + }) return optionalUsesLibs } diff --git a/java/app_test.go b/java/app_test.go index 372266ef8f..4d7bd7af07 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -2342,9 +2342,6 @@ func TestUsesLibraries(t *testing.T) { prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, FixtureWithLastReleaseApis("runtime-library", "foo", "quuz", "qux", "bar", "fred"), - android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { - variables.MissingUsesLibraries = []string{"baz"} - }), ).RunTestWithBp(t, bp) app := result.ModuleForTests("app", "android_common") -- GitLab