Check updatable APKs compile against managed SDKs.
As a follow up, this property will be set to APKs participating in mainline program.
Bug: 153333044
Test: m
Change-Id: I6ea2f3c1d26992259e4e9e6a6d8cecf091d39c43
Merged-In: I6ea2f3c1d26992259e4e9e6a6d8cecf091d39c43
(cherry picked from commit 2db1c3f1c4
)
Exempt-From-Owner-Approval: clean cherry-pick
This commit is contained in:
parent
ee42b2079d
commit
e5ac15a1b7
4 changed files with 154 additions and 13 deletions
18
java/app.go
18
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
|
||||
|
@ -242,11 +246,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 {
|
||||
|
|
102
java/app_test.go
102
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
|
||||
|
|
26
java/java.go
26
java/java.go
|
@ -80,7 +80,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 {
|
||||
|
@ -90,6 +90,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) {
|
||||
|
@ -892,15 +904,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 {
|
||||
|
@ -1817,7 +1821,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)
|
||||
|
|
21
java/sdk.go
21
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 {
|
||||
|
|
Loading…
Reference in a new issue