Merge "Unify handling of compat and normal libs in class loader contexts."
This commit is contained in:
@@ -100,20 +100,30 @@ type GlobalSoongConfig struct {
|
|||||||
ConstructContext android.Path
|
ConstructContext android.Path
|
||||||
}
|
}
|
||||||
|
|
||||||
// These libs are added as optional dependencies (<uses-library> with android:required set to false).
|
// These libs are added as <uses-library> dependencies for apps if the targetSdkVersion in the
|
||||||
// This is because they haven't existed prior to certain SDK version, but classes in them were in
|
// app manifest is less than the specified version. This is needed because these libraries haven't
|
||||||
// bootclasspath jars, etc. So making them hard dependencies (android:required=true) would prevent
|
// existed prior to certain SDK version, but classes in them were in bootclasspath jars, etc.
|
||||||
// apps from being installed to such legacy devices.
|
// Some of the compatibility libraries are optional (their <uses-library> tag has "required=false"),
|
||||||
var OptionalCompatUsesLibs = []string{
|
// so that if this library is missing this in not a build or run-time error.
|
||||||
"org.apache.http.legacy",
|
var OrgApacheHttpLegacy = "org.apache.http.legacy"
|
||||||
"android.test.base",
|
var AndroidTestBase = "android.test.base"
|
||||||
"android.test.mock",
|
var AndroidTestMock = "android.test.mock"
|
||||||
}
|
var AndroidHidlBase = "android.hidl.base-V1.0-java"
|
||||||
|
var AndroidHidlManager = "android.hidl.manager-V1.0-java"
|
||||||
|
|
||||||
var CompatUsesLibs = []string{
|
var OptionalCompatUsesLibs28 = []string{
|
||||||
"android.hidl.base-V1.0-java",
|
OrgApacheHttpLegacy,
|
||||||
"android.hidl.manager-V1.0-java",
|
|
||||||
}
|
}
|
||||||
|
var OptionalCompatUsesLibs30 = []string{
|
||||||
|
AndroidTestBase,
|
||||||
|
AndroidTestMock,
|
||||||
|
}
|
||||||
|
var CompatUsesLibs29 = []string{
|
||||||
|
AndroidHidlBase,
|
||||||
|
AndroidHidlManager,
|
||||||
|
}
|
||||||
|
var OptionalCompatUsesLibs = append(android.CopyOf(OptionalCompatUsesLibs28), OptionalCompatUsesLibs30...)
|
||||||
|
var CompatUsesLibs = android.CopyOf(CompatUsesLibs29)
|
||||||
|
|
||||||
const UnknownInstallLibraryPath = "error"
|
const UnknownInstallLibraryPath = "error"
|
||||||
|
|
||||||
|
@@ -195,6 +195,9 @@ func bootProfileCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig,
|
|||||||
}
|
}
|
||||||
|
|
||||||
type classLoaderContext struct {
|
type classLoaderContext struct {
|
||||||
|
// Library names
|
||||||
|
Names []string
|
||||||
|
|
||||||
// The class loader context using paths in the build.
|
// The class loader context using paths in the build.
|
||||||
Host android.Paths
|
Host android.Paths
|
||||||
|
|
||||||
@@ -209,7 +212,7 @@ type classLoaderContext struct {
|
|||||||
// targetSdkVersion in the manifest or APK is less than that API version.
|
// targetSdkVersion in the manifest or APK is less than that API version.
|
||||||
type classLoaderContextMap map[int]*classLoaderContext
|
type classLoaderContextMap map[int]*classLoaderContext
|
||||||
|
|
||||||
const anySdkVersion int = 9999 // should go last in class loader context
|
const AnySdkVersion int = 9999 // should go last in class loader context
|
||||||
|
|
||||||
func (m classLoaderContextMap) getValue(sdkVer int) *classLoaderContext {
|
func (m classLoaderContextMap) getValue(sdkVer int) *classLoaderContext {
|
||||||
if _, ok := m[sdkVer]; !ok {
|
if _, ok := m[sdkVer]; !ok {
|
||||||
@@ -218,14 +221,19 @@ func (m classLoaderContextMap) getValue(sdkVer int) *classLoaderContext {
|
|||||||
return m[sdkVer]
|
return m[sdkVer]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (clc *classLoaderContext) addLib(lib string, hostPath android.Path, targetPath string) {
|
||||||
|
clc.Names = append(clc.Names, lib)
|
||||||
|
clc.Host = append(clc.Host, hostPath)
|
||||||
|
clc.Target = append(clc.Target, targetPath)
|
||||||
|
}
|
||||||
|
|
||||||
func (m classLoaderContextMap) addLibs(ctx android.PathContext, sdkVer int, module *ModuleConfig, libs ...string) bool {
|
func (m classLoaderContextMap) addLibs(ctx android.PathContext, sdkVer int, module *ModuleConfig, libs ...string) bool {
|
||||||
clc := m.getValue(sdkVer)
|
clc := m.getValue(sdkVer)
|
||||||
for _, lib := range libs {
|
for _, lib := range libs {
|
||||||
if p, ok := module.LibraryPaths[lib]; ok && p.Host != nil && p.Device != UnknownInstallLibraryPath {
|
if p, ok := module.LibraryPaths[lib]; ok && p.Host != nil && p.Device != UnknownInstallLibraryPath {
|
||||||
clc.Host = append(clc.Host, p.Host)
|
clc.addLib(lib, p.Host, p.Device)
|
||||||
clc.Target = append(clc.Target, p.Device)
|
|
||||||
} else {
|
} else {
|
||||||
if sdkVer == anySdkVersion {
|
if sdkVer == AnySdkVersion {
|
||||||
// Fail the build if dexpreopt doesn't know paths to one of the <uses-library>
|
// Fail the build if dexpreopt doesn't know paths to one of the <uses-library>
|
||||||
// dependencies. In the future we may need to relax this and just disable dexpreopt.
|
// dependencies. In the future we may need to relax this and just disable dexpreopt.
|
||||||
android.ReportPathErrorf(ctx, "dexpreopt cannot find path for <uses-library> '%s'", lib)
|
android.ReportPathErrorf(ctx, "dexpreopt cannot find path for <uses-library> '%s'", lib)
|
||||||
@@ -239,11 +247,17 @@ func (m classLoaderContextMap) addLibs(ctx android.PathContext, sdkVer int, modu
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m classLoaderContextMap) usesLibs() []string {
|
||||||
|
if clc, ok := m[AnySdkVersion]; ok {
|
||||||
|
return clc.Names
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (m classLoaderContextMap) addSystemServerLibs(sdkVer int, ctx android.PathContext, module *ModuleConfig, libs ...string) {
|
func (m classLoaderContextMap) addSystemServerLibs(sdkVer int, ctx android.PathContext, module *ModuleConfig, libs ...string) {
|
||||||
clc := m.getValue(sdkVer)
|
clc := m.getValue(sdkVer)
|
||||||
for _, lib := range libs {
|
for _, lib := range libs {
|
||||||
clc.Host = append(clc.Host, SystemServerDexJarHostPath(ctx, lib))
|
clc.addLib(lib, SystemServerDexJarHostPath(ctx, lib), filepath.Join("/system/framework", lib+".jar"))
|
||||||
clc.Target = append(clc.Target, filepath.Join("/system/framework", lib+".jar"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,7 +275,7 @@ func (m classLoaderContextMap) addSystemServerLibs(sdkVer int, ctx android.PathC
|
|||||||
// as the runtime classpath won't match and the dexpreopted code will be discarded. Therefore in
|
// as the runtime classpath won't match and the dexpreopted code will be discarded. Therefore in
|
||||||
// such cases the function returns nil, which disables dexpreopt.
|
// such cases the function returns nil, which disables dexpreopt.
|
||||||
//
|
//
|
||||||
// 2. All other library jars or APKs for which the exact <uses-library> list is unknown. They use
|
// 3. All other library jars or APKs for which the exact <uses-library> list is unknown. They use
|
||||||
// the unsafe &-classpath workaround that means empty class loader context and absence of runtime
|
// the unsafe &-classpath workaround that means empty class loader context and absence of runtime
|
||||||
// check that the class loader context provided by the PackageManager agrees with the stored
|
// check that the class loader context provided by the PackageManager agrees with the stored
|
||||||
// class loader context recorded in the .odex file.
|
// class loader context recorded in the .odex file.
|
||||||
@@ -273,21 +287,19 @@ func genClassLoaderContext(ctx android.PathContext, global *GlobalConfig, module
|
|||||||
if jarIndex := android.IndexList(module.Name, systemServerJars); jarIndex >= 0 {
|
if jarIndex := android.IndexList(module.Name, systemServerJars); jarIndex >= 0 {
|
||||||
// System server jars should be dexpreopted together: class loader context of each jar
|
// System server jars should be dexpreopted together: class loader context of each jar
|
||||||
// should include all preceding jars on the system server classpath.
|
// should include all preceding jars on the system server classpath.
|
||||||
classLoaderContexts.addSystemServerLibs(anySdkVersion, ctx, module, systemServerJars[:jarIndex]...)
|
classLoaderContexts.addSystemServerLibs(AnySdkVersion, ctx, module, systemServerJars[:jarIndex]...)
|
||||||
|
|
||||||
} else if module.EnforceUsesLibraries {
|
} else if module.EnforceUsesLibraries {
|
||||||
// Unconditional class loader context.
|
// Unconditional class loader context.
|
||||||
usesLibs := append(copyOf(module.UsesLibraries), module.OptionalUsesLibraries...)
|
usesLibs := append(copyOf(module.UsesLibraries), module.OptionalUsesLibraries...)
|
||||||
if !classLoaderContexts.addLibs(ctx, anySdkVersion, module, usesLibs...) {
|
if !classLoaderContexts.addLibs(ctx, AnySdkVersion, module, usesLibs...) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conditional class loader context for API version < 28.
|
// Conditional class loader context for API version < 28.
|
||||||
const httpLegacy = "org.apache.http.legacy"
|
const httpLegacy = "org.apache.http.legacy"
|
||||||
if !contains(usesLibs, httpLegacy) {
|
if !classLoaderContexts.addLibs(ctx, 28, module, httpLegacy) {
|
||||||
if !classLoaderContexts.addLibs(ctx, 28, module, httpLegacy) {
|
return nil
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conditional class loader context for API version < 29.
|
// Conditional class loader context for API version < 29.
|
||||||
@@ -301,10 +313,8 @@ func genClassLoaderContext(ctx android.PathContext, global *GlobalConfig, module
|
|||||||
|
|
||||||
// Conditional class loader context for API version < 30.
|
// Conditional class loader context for API version < 30.
|
||||||
const testBase = "android.test.base"
|
const testBase = "android.test.base"
|
||||||
if !contains(usesLibs, testBase) {
|
if !classLoaderContexts.addLibs(ctx, 30, module, testBase) {
|
||||||
if !classLoaderContexts.addLibs(ctx, 30, module, testBase) {
|
return nil
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -314,9 +324,32 @@ func genClassLoaderContext(ctx android.PathContext, global *GlobalConfig, module
|
|||||||
// to the &.
|
// to the &.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fixConditionalClassLoaderContext(classLoaderContexts)
|
||||||
|
|
||||||
return &classLoaderContexts
|
return &classLoaderContexts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now that the full unconditional context is known, reconstruct conditional context.
|
||||||
|
// Apply filters for individual libraries, mirroring what the PackageManager does when it
|
||||||
|
// constructs class loader context on device.
|
||||||
|
func fixConditionalClassLoaderContext(clcMap classLoaderContextMap) {
|
||||||
|
usesLibs := clcMap.usesLibs()
|
||||||
|
|
||||||
|
for sdkVer, clc := range clcMap {
|
||||||
|
if sdkVer == AnySdkVersion {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
clcMap[sdkVer] = &classLoaderContext{}
|
||||||
|
for i, lib := range clc.Names {
|
||||||
|
if android.InList(lib, usesLibs) {
|
||||||
|
// skip compatibility libraries that are already included in unconditional context
|
||||||
|
} else {
|
||||||
|
clcMap[sdkVer].addLib(lib, clc.Host[i], clc.Target[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, global *GlobalConfig,
|
func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, global *GlobalConfig,
|
||||||
module *ModuleConfig, rule *android.RuleBuilder, archIdx int, classLoaderContexts classLoaderContextMap,
|
module *ModuleConfig, rule *android.RuleBuilder, archIdx int, classLoaderContexts classLoaderContextMap,
|
||||||
profile android.WritablePath, appImage bool, generateDM bool) {
|
profile android.WritablePath, appImage bool, generateDM bool) {
|
||||||
@@ -363,7 +396,7 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
|
|||||||
|
|
||||||
checkSystemServerOrder(ctx, jarIndex)
|
checkSystemServerOrder(ctx, jarIndex)
|
||||||
|
|
||||||
clc := classLoaderContexts[anySdkVersion]
|
clc := classLoaderContexts[AnySdkVersion]
|
||||||
rule.Command().
|
rule.Command().
|
||||||
Text("class_loader_context_arg=--class-loader-context=PCL[" + strings.Join(clc.Host.Strings(), ":") + "]").
|
Text("class_loader_context_arg=--class-loader-context=PCL[" + strings.Join(clc.Host.Strings(), ":") + "]").
|
||||||
Implicits(clc.Host).
|
Implicits(clc.Host).
|
||||||
@@ -391,14 +424,15 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
|
|||||||
Text(`eval "$(`).Tool(globalSoong.ConstructContext).
|
Text(`eval "$(`).Tool(globalSoong.ConstructContext).
|
||||||
Text(` --target-sdk-version ${target_sdk_version}`)
|
Text(` --target-sdk-version ${target_sdk_version}`)
|
||||||
for _, ver := range android.SortedIntKeys(classLoaderContexts) {
|
for _, ver := range android.SortedIntKeys(classLoaderContexts) {
|
||||||
clc := classLoaderContexts.getValue(ver)
|
if clc := classLoaderContexts.getValue(ver); len(clc.Host) > 0 {
|
||||||
verString := fmt.Sprintf("%d", ver)
|
verString := fmt.Sprintf("%d", ver)
|
||||||
if ver == anySdkVersion {
|
if ver == AnySdkVersion {
|
||||||
verString = "any" // a special keyword that means any SDK version
|
verString = "any" // a special keyword that means any SDK version
|
||||||
|
}
|
||||||
|
cmd.Textf(`--host-classpath-for-sdk %s %s`, verString, strings.Join(clc.Host.Strings(), ":")).
|
||||||
|
Implicits(clc.Host).
|
||||||
|
Textf(`--target-classpath-for-sdk %s %s`, verString, strings.Join(clc.Target, ":"))
|
||||||
}
|
}
|
||||||
cmd.Textf(`--host-classpath-for-sdk %s %s`, verString, strings.Join(clc.Host.Strings(), ":")).
|
|
||||||
Implicits(clc.Host).
|
|
||||||
Textf(`--target-classpath-for-sdk %s %s`, verString, strings.Join(clc.Target, ":"))
|
|
||||||
}
|
}
|
||||||
cmd.Text(`)"`)
|
cmd.Text(`)"`)
|
||||||
} else {
|
} else {
|
||||||
|
@@ -2766,7 +2766,7 @@ func TestUsesLibraries(t *testing.T) {
|
|||||||
name: "prebuilt",
|
name: "prebuilt",
|
||||||
apk: "prebuilts/apk/app.apk",
|
apk: "prebuilts/apk/app.apk",
|
||||||
certificate: "platform",
|
certificate: "platform",
|
||||||
uses_libs: ["foo"],
|
uses_libs: ["foo", "android.test.runner"],
|
||||||
optional_uses_libs: [
|
optional_uses_libs: [
|
||||||
"bar",
|
"bar",
|
||||||
"baz",
|
"baz",
|
||||||
@@ -2804,7 +2804,7 @@ func TestUsesLibraries(t *testing.T) {
|
|||||||
|
|
||||||
cmd = prebuilt.Rule("verify_uses_libraries").RuleParams.Command
|
cmd = prebuilt.Rule("verify_uses_libraries").RuleParams.Command
|
||||||
|
|
||||||
if w := `uses_library_names="foo"`; !strings.Contains(cmd, w) {
|
if w := `uses_library_names="foo android.test.runner"`; !strings.Contains(cmd, w) {
|
||||||
t.Errorf("wanted %q in %q", w, cmd)
|
t.Errorf("wanted %q in %q", w, cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2812,20 +2812,48 @@ func TestUsesLibraries(t *testing.T) {
|
|||||||
t.Errorf("wanted %q in %q", w, cmd)
|
t.Errorf("wanted %q in %q", w, cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that all present libraries are preopted, including implicit SDK dependencies, possibly stubs
|
// Test that all present libraries are preopted, including implicit SDK dependencies, possibly stubs.
|
||||||
cmd = app.Rule("dexpreopt").RuleParams.Command
|
cmd = app.Rule("dexpreopt").RuleParams.Command
|
||||||
w := `--target-classpath-for-sdk any` +
|
w := `--target-classpath-for-sdk any` +
|
||||||
` /system/framework/foo.jar` +
|
` /system/framework/foo.jar` +
|
||||||
`:/system/framework/quuz.jar` +
|
`:/system/framework/quuz.jar` +
|
||||||
`:/system/framework/qux.jar` +
|
`:/system/framework/qux.jar` +
|
||||||
`:/system/framework/runtime-library.jar` +
|
`:/system/framework/runtime-library.jar` +
|
||||||
`:/system/framework/bar.jar`
|
`:/system/framework/bar.jar `
|
||||||
if !strings.Contains(cmd, w) {
|
if !strings.Contains(cmd, w) {
|
||||||
t.Errorf("wanted %q in %q", w, cmd)
|
t.Errorf("wanted %q in %q", w, cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test conditional context for target SDK version 28.
|
||||||
|
if w := `--target-classpath-for-sdk 28` +
|
||||||
|
` /system/framework/org.apache.http.legacy.jar `; !strings.Contains(cmd, w) {
|
||||||
|
t.Errorf("wanted %q in %q", w, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test conditional context for target SDK version 29.
|
||||||
|
if w := `--target-classpath-for-sdk 29` +
|
||||||
|
` /system/framework/android.hidl.base-V1.0-java.jar` +
|
||||||
|
`:/system/framework/android.hidl.manager-V1.0-java.jar `; !strings.Contains(cmd, w) {
|
||||||
|
t.Errorf("wanted %q in %q", w, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test conditional context for target SDK version 30.
|
||||||
|
if w := `--target-classpath-for-sdk 30` +
|
||||||
|
` /system/framework/android.test.base.jar `; !strings.Contains(cmd, w) {
|
||||||
|
t.Errorf("wanted %q in %q", w, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
cmd = prebuilt.Rule("dexpreopt").RuleParams.Command
|
cmd = prebuilt.Rule("dexpreopt").RuleParams.Command
|
||||||
if w := `--target-classpath-for-sdk any /system/framework/foo.jar:/system/framework/bar.jar`; !strings.Contains(cmd, w) {
|
if w := `--target-classpath-for-sdk any` +
|
||||||
|
` /system/framework/foo.jar` +
|
||||||
|
`:/system/framework/android.test.runner.jar` +
|
||||||
|
`:/system/framework/bar.jar `; !strings.Contains(cmd, w) {
|
||||||
|
t.Errorf("wanted %q in %q", w, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test conditional context for target SDK version 30.
|
||||||
|
if w := `--target-classpath-for-sdk 30` +
|
||||||
|
` /system/framework/android.test.base.jar `; !strings.Contains(cmd, w) {
|
||||||
t.Errorf("wanted %q in %q", w, cmd)
|
t.Errorf("wanted %q in %q", w, cmd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -22,6 +22,7 @@ import (
|
|||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
"android/soong/cc"
|
"android/soong/cc"
|
||||||
|
"android/soong/dexpreopt"
|
||||||
"android/soong/python"
|
"android/soong/python"
|
||||||
|
|
||||||
"github.com/google/blueprint"
|
"github.com/google/blueprint"
|
||||||
@@ -152,6 +153,24 @@ func GatherRequiredDepsForTest() string {
|
|||||||
`, extra)
|
`, extra)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For class loader context and <uses-library> tests.
|
||||||
|
dexpreoptModules := []string{"android.test.runner"}
|
||||||
|
dexpreoptModules = append(dexpreoptModules, dexpreopt.CompatUsesLibs...)
|
||||||
|
dexpreoptModules = append(dexpreoptModules, dexpreopt.OptionalCompatUsesLibs...)
|
||||||
|
|
||||||
|
for _, extra := range dexpreoptModules {
|
||||||
|
bp += fmt.Sprintf(`
|
||||||
|
java_library {
|
||||||
|
name: "%s",
|
||||||
|
srcs: ["a.java"],
|
||||||
|
sdk_version: "none",
|
||||||
|
system_modules: "stable-core-platform-api-stubs-system-modules",
|
||||||
|
compile_dex: true,
|
||||||
|
installable: true,
|
||||||
|
}
|
||||||
|
`, extra)
|
||||||
|
}
|
||||||
|
|
||||||
bp += `
|
bp += `
|
||||||
java_library {
|
java_library {
|
||||||
name: "framework",
|
name: "framework",
|
||||||
@@ -166,48 +185,7 @@ func GatherRequiredDepsForTest() string {
|
|||||||
android_app {
|
android_app {
|
||||||
name: "framework-res",
|
name: "framework-res",
|
||||||
sdk_version: "core_platform",
|
sdk_version: "core_platform",
|
||||||
}
|
}`
|
||||||
|
|
||||||
java_library {
|
|
||||||
name: "android.hidl.base-V1.0-java",
|
|
||||||
srcs: ["a.java"],
|
|
||||||
sdk_version: "none",
|
|
||||||
system_modules: "stable-core-platform-api-stubs-system-modules",
|
|
||||||
installable: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
java_library {
|
|
||||||
name: "android.hidl.manager-V1.0-java",
|
|
||||||
srcs: ["a.java"],
|
|
||||||
sdk_version: "none",
|
|
||||||
system_modules: "stable-core-platform-api-stubs-system-modules",
|
|
||||||
installable: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
java_library {
|
|
||||||
name: "org.apache.http.legacy",
|
|
||||||
srcs: ["a.java"],
|
|
||||||
sdk_version: "none",
|
|
||||||
system_modules: "stable-core-platform-api-stubs-system-modules",
|
|
||||||
installable: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
java_library {
|
|
||||||
name: "android.test.base",
|
|
||||||
srcs: ["a.java"],
|
|
||||||
sdk_version: "none",
|
|
||||||
system_modules: "stable-core-platform-api-stubs-system-modules",
|
|
||||||
installable: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
java_library {
|
|
||||||
name: "android.test.mock",
|
|
||||||
srcs: ["a.java"],
|
|
||||||
sdk_version: "none",
|
|
||||||
system_modules: "stable-core-platform-api-stubs-system-modules",
|
|
||||||
installable: true,
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
systemModules := []string{
|
systemModules := []string{
|
||||||
"core-current-stubs-system-modules",
|
"core-current-stubs-system-modules",
|
||||||
|
Reference in New Issue
Block a user