diff options
| -rw-r--r-- | android/mutator.go | 2 | ||||
| -rw-r--r-- | android/neverallow.go | 18 | ||||
| -rw-r--r-- | android/neverallow_test.go | 4 | ||||
| -rw-r--r-- | cc/androidmk.go | 4 | ||||
| -rw-r--r-- | cc/cc.go | 9 | ||||
| -rw-r--r-- | cc/config/arm64_device.go | 2 | ||||
| -rw-r--r-- | cc/config/clang.go | 2 | ||||
| -rw-r--r-- | cc/installer.go | 4 | ||||
| -rw-r--r-- | cc/library.go | 12 | ||||
| -rw-r--r-- | cc/prebuilt.go | 5 | ||||
| -rwxr-xr-x | java/app.go | 18 | ||||
| -rw-r--r-- | java/app_test.go | 102 | ||||
| -rw-r--r-- | java/java.go | 26 | ||||
| -rw-r--r-- | java/sdk.go | 21 |
14 files changed, 200 insertions, 29 deletions
diff --git a/android/mutator.go b/android/mutator.go index a46d4beb1..10a815ae4 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -103,7 +103,7 @@ var postDeps = []RegisterMutatorFunc{ registerPathDepsMutator, RegisterPrebuiltsPostDepsMutators, RegisterVisibilityRuleEnforcer, - registerNeverallowMutator, + RegisterNeverallowMutator, RegisterOverridePostDepsMutators, } diff --git a/android/neverallow.go b/android/neverallow.go index 04ec27d20..cf09792e0 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -42,7 +42,7 @@ import ( // counts as a match // - it has none of the "Without" properties matched (same rules as above) -func registerNeverallowMutator(ctx RegisterMutatorsContext) { +func RegisterNeverallowMutator(ctx RegisterMutatorsContext) { ctx.BottomUp("neverallow", neverallowMutator).Parallel() } @@ -247,7 +247,7 @@ func neverallowMutator(ctx BottomUpMutatorContext) { } type ValueMatcher interface { - test(string) bool + Test(string) bool String() string } @@ -255,7 +255,7 @@ type equalMatcher struct { expected string } -func (m *equalMatcher) test(value string) bool { +func (m *equalMatcher) Test(value string) bool { return m.expected == value } @@ -266,7 +266,7 @@ func (m *equalMatcher) String() string { type anyMatcher struct { } -func (m *anyMatcher) test(value string) bool { +func (m *anyMatcher) Test(value string) bool { return true } @@ -280,7 +280,7 @@ type startsWithMatcher struct { prefix string } -func (m *startsWithMatcher) test(value string) bool { +func (m *startsWithMatcher) Test(value string) bool { return strings.HasPrefix(value, m.prefix) } @@ -292,7 +292,7 @@ type regexMatcher struct { re *regexp.Regexp } -func (m *regexMatcher) test(value string) bool { +func (m *regexMatcher) Test(value string) bool { return m.re.MatchString(value) } @@ -302,7 +302,7 @@ func (m *regexMatcher) String() string { type isSetMatcher struct{} -func (m *isSetMatcher) test(value string) bool { +func (m *isSetMatcher) Test(value string) bool { return value != "" } @@ -573,7 +573,7 @@ func hasProperty(properties []interface{}, prop ruleProperty) bool { } check := func(value string) bool { - return prop.matcher.test(value) + return prop.matcher.Test(value) } if matchValue(propertiesValue, check) { @@ -630,6 +630,6 @@ func neverallowRules(config Config) []Rule { // Overrides the default neverallow rules for the supplied config. // // For testing only. -func setTestNeverallowRules(config Config, testRules []Rule) { +func SetTestNeverallowRules(config Config, testRules []Rule) { config.Once(neverallowRulesKey, func() interface{} { return testRules }) } diff --git a/android/neverallow_test.go b/android/neverallow_test.go index 0373b7923..2fc42e31f 100644 --- a/android/neverallow_test.go +++ b/android/neverallow_test.go @@ -313,7 +313,7 @@ func TestNeverallow(t *testing.T) { t.Run(test.name, func(t *testing.T) { // If the test has its own rules then use them instead of the default ones. if test.rules != nil { - setTestNeverallowRules(config, test.rules) + SetTestNeverallowRules(config, test.rules) } _, errs := testNeverallow(config) CheckErrorsAgainstExpectations(t, errs, test.expectedErrors) @@ -327,7 +327,7 @@ func testNeverallow(config Config) (*TestContext, []error) { ctx.RegisterModuleType("java_library", newMockJavaLibraryModule) ctx.RegisterModuleType("java_library_host", newMockJavaLibraryModule) ctx.RegisterModuleType("java_device_for_host", newMockJavaLibraryModule) - ctx.PostDepsMutators(registerNeverallowMutator) + ctx.PostDepsMutators(RegisterNeverallowMutator) ctx.Register(config) _, errs := ctx.ParseBlueprintsFiles("Android.bp") diff --git a/cc/androidmk.go b/cc/androidmk.go index 19c71826f..5438b149d 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -271,6 +271,10 @@ func (library *libraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries entries.SubName = "." + library.stubsVersion() } entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) { + // Note library.skipInstall() has a special case to get here for static + // libraries that otherwise would have skipped installation and hence not + // have executed AndroidMkEntries at all. The reason is to ensure they get + // a NOTICE file make target which other libraries might depend on. entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true) if library.buildStubs() { entries.SetBool("LOCAL_NO_NOTICE_FILE", true) @@ -404,6 +404,7 @@ type installer interface { inSanitizerDir() bool hostToolPath() android.OptionalPath relativeInstallPath() string + skipInstall(mod *Module) } type xref interface { @@ -2639,6 +2640,14 @@ func (c *Module) InstallInRecovery() bool { return c.InRecovery() } +func (c *Module) SkipInstall() { + if c.installer == nil { + c.ModuleBase.SkipInstall() + return + } + c.installer.skipInstall(c) +} + func (c *Module) HostToolPath() android.OptionalPath { if c.installer == nil { return android.OptionalPath{} diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go index 19aedd99d..5575baaab 100644 --- a/cc/config/arm64_device.go +++ b/cc/config/arm64_device.go @@ -37,10 +37,8 @@ var ( } arm64Ldflags = []string{ - "-Wl,-m,aarch64_elf64_le_vec", "-Wl,--hash-style=gnu", "-Wl,-z,separate-code", - "-fuse-ld=gold", "-Wl,--icf=safe", } diff --git a/cc/config/clang.go b/cc/config/clang.go index 274ccd5d5..bdd9030f4 100644 --- a/cc/config/clang.go +++ b/cc/config/clang.go @@ -80,10 +80,8 @@ var ClangUnknownCflags = sorted([]string{ // Ldflags that should be filtered out when linking with clang lld var ClangUnknownLldflags = sorted([]string{ - "-fuse-ld=gold", "-Wl,--fix-cortex-a8", "-Wl,--no-fix-cortex-a8", - "-Wl,-m,aarch64_elf64_le_vec", }) var ClangLibToolingUnknownCflags = sorted([]string{}) diff --git a/cc/installer.go b/cc/installer.go index 200d59e9f..0b4a68cc8 100644 --- a/cc/installer.go +++ b/cc/installer.go @@ -106,3 +106,7 @@ func (installer *baseInstaller) hostToolPath() android.OptionalPath { func (installer *baseInstaller) relativeInstallPath() string { return String(installer.Properties.Relative_install_path) } + +func (installer *baseInstaller) skipInstall(mod *Module) { + mod.ModuleBase.SkipInstall() +} diff --git a/cc/library.go b/cc/library.go index 140f87a0a..94fffb951 100644 --- a/cc/library.go +++ b/cc/library.go @@ -1329,6 +1329,18 @@ func (library *libraryDecorator) availableFor(what string) bool { return android.CheckAvailableForApex(what, list) } +func (library *libraryDecorator) skipInstall(mod *Module) { + if library.static() && library.buildStatic() && !library.buildStubs() { + // If we're asked to skip installation of a static library (in particular + // when it's not //apex_available:platform) we still want an AndroidMk entry + // for it to ensure we get the relevant NOTICE file targets (cf. + // notice_files.mk) that other libraries might depend on. AndroidMkEntries + // always sets LOCAL_UNINSTALLABLE_MODULE for these entries. + return + } + mod.ModuleBase.SkipInstall() +} + var versioningMacroNamesListKey = android.NewOnceKey("versioningMacroNamesList") func versioningMacroNamesList(config android.Config) *map[string]string { diff --git a/cc/prebuilt.go b/cc/prebuilt.go index fc9cc17d3..2ef31950e 100644 --- a/cc/prebuilt.go +++ b/cc/prebuilt.go @@ -155,6 +155,10 @@ func (p *prebuiltLibraryLinker) disablePrebuilt() { p.properties.Srcs = nil } +func (p *prebuiltLibraryLinker) skipInstall(mod *Module) { + mod.ModuleBase.SkipInstall() +} + func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) { module, library := NewLibrary(hod) module.compiler = nil @@ -163,6 +167,7 @@ func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDec libraryDecorator: library, } module.linker = prebuilt + module.installer = prebuilt module.AddProperties(&prebuilt.properties) diff --git a/java/app.go b/java/app.go index ae9cd5f11..ac5121a3d 100755 --- a/java/app.go +++ b/java/app.go @@ -110,6 +110,10 @@ type appProperties struct { PreventInstall bool `blueprint:"mutated"` HideFromMake bool `blueprint:"mutated"` IsCoverageVariant bool `blueprint:"mutated"` + + // Whether this app is considered mainline updatable or not. When set to true, this will enforce + // additional rules for making sure that the APK is truly updatable. Default is false. + Updatable *bool } // android_app properties that can be overridden by override_android_app @@ -249,11 +253,21 @@ func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleCon } func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) { - a.checkPlatformAPI(ctx) - a.checkSdkVersion(ctx) + a.checkAppSdkVersions(ctx) a.generateAndroidBuildActions(ctx) } +func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) { + if Bool(a.appProperties.Updatable) { + if !a.sdkVersion().stable() { + ctx.PropertyErrorf("sdk_version", "Updatable apps must use stable SDKs, found %v", a.sdkVersion()) + } + } + + a.checkPlatformAPI(ctx) + a.checkSdkVersions(ctx) +} + // Returns true if the native libraries should be stored in the APK uncompressed and the // extractNativeLibs application flag should be set to false in the manifest. func (a *AndroidApp) useEmbeddedNativeLibs(ctx android.ModuleContext) bool { diff --git a/java/app_test.go b/java/app_test.go index 43696dbb8..7b04e4629 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -264,6 +264,108 @@ func TestAndroidAppLinkType(t *testing.T) { `) } +func TestUpdatableApps(t *testing.T) { + testCases := []struct { + name string + bp string + expectedError string + }{ + { + name: "Stable public SDK", + bp: `android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "29", + updatable: true, + }`, + }, + { + name: "Stable system SDK", + bp: `android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "system_29", + updatable: true, + }`, + }, + { + name: "Current public SDK", + bp: `android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "current", + updatable: true, + }`, + }, + { + name: "Current system SDK", + bp: `android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "system_current", + updatable: true, + }`, + }, + { + name: "Current module SDK", + bp: `android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "module_current", + updatable: true, + }`, + }, + { + name: "Current core SDK", + bp: `android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "core_current", + updatable: true, + }`, + }, + { + name: "No Platform APIs", + bp: `android_app { + name: "foo", + srcs: ["a.java"], + platform_apis: true, + updatable: true, + }`, + expectedError: "Updatable apps must use stable SDKs", + }, + { + name: "No Core Platform APIs", + bp: `android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "core_platform", + updatable: true, + }`, + expectedError: "Updatable apps must use stable SDKs", + }, + { + name: "No unspecified APIs", + bp: `android_app { + name: "foo", + srcs: ["a.java"], + updatable: true, + }`, + expectedError: "Updatable apps must use stable SDK", + }, + } + + for _, test := range testCases { + t.Run(test.name, func(t *testing.T) { + if test.expectedError == "" { + testJava(t, test.bp) + } else { + testJavaError(t, test.expectedError, test.bp) + } + }) + } +} + func TestResourceDirs(t *testing.T) { testCases := []struct { name string diff --git a/java/java.go b/java/java.go index a8ca3ffef..61974f5af 100644 --- a/java/java.go +++ b/java/java.go @@ -86,7 +86,7 @@ func RegisterJavaBuildComponents(ctx android.RegistrationContext) { ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory) } -func (j *Module) checkSdkVersion(ctx android.ModuleContext) { +func (j *Module) checkSdkVersions(ctx android.ModuleContext) { if j.SocSpecific() || j.DeviceSpecific() || (j.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) { if sc, ok := ctx.Module().(sdkContext); ok { @@ -96,6 +96,18 @@ func (j *Module) checkSdkVersion(ctx android.ModuleContext) { } } } + + ctx.VisitDirectDeps(func(module android.Module) { + tag := ctx.OtherModuleDependencyTag(module) + switch module.(type) { + // TODO(satayev): cover other types as well, e.g. imports + case *Library, *AndroidLibrary: + switch tag { + case bootClasspathTag, libTag, staticLibTag, java9LibTag: + checkLinkType(ctx, j, module.(linkTypeContext), tag.(dependencyTag)) + } + } + }) } func (j *Module) checkPlatformAPI(ctx android.ModuleContext) { @@ -898,15 +910,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { // Handled by AndroidApp.collectAppDeps return } - switch module.(type) { - case *Library, *AndroidLibrary: - if to, ok := module.(linkTypeContext); ok { - switch tag { - case bootClasspathTag, libTag, staticLibTag: - checkLinkType(ctx, j, to, tag.(dependencyTag)) - } - } - } + switch dep := module.(type) { case SdkLibraryDependency: switch tag { @@ -1818,7 +1822,7 @@ func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bo } func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { - j.checkSdkVersion(ctx) + j.checkSdkVersions(ctx) j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar") j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &j.dexpreopter) diff --git a/java/sdk.go b/java/sdk.go index 0e132d399..92076f4b5 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -147,6 +147,10 @@ type sdkSpec struct { raw string } +func (s sdkSpec) String() string { + return fmt.Sprintf("%s_%s", s.kind, s.version) +} + // valid checks if this sdkSpec is well-formed. Note however that true doesn't mean that the // specified SDK actually exists. func (s sdkSpec) valid() bool { @@ -158,6 +162,23 @@ func (s sdkSpec) specified() bool { return s.valid() && s.kind != sdkPrivate } +// whether the API surface is managed and versioned, i.e. has .txt file that +// get frozen on SDK freeze and changes get reviewed by API council. +func (s sdkSpec) stable() bool { + if !s.specified() { + return false + } + switch s.kind { + case sdkCore, sdkPublic, sdkSystem, sdkModule, sdkSystemServer: + return true + case sdkNone, sdkCorePlatform, sdkTest, sdkPrivate: + return false + default: + panic(fmt.Errorf("unknown sdkKind=%v", s.kind)) + } + return false +} + // prebuiltSdkAvailableForUnbundledBuilt tells whether this sdkSpec can have a prebuilt SDK // that can be used for unbundled builds. func (s sdkSpec) prebuiltSdkAvailableForUnbundledBuild() bool { |