diff --git a/java/Android.bp b/java/Android.bp index a17140ce1..623a6c577 100644 --- a/java/Android.bp +++ b/java/Android.bp @@ -65,6 +65,7 @@ bootstrap_go_package { "sdk_library_external.go", "support_libraries.go", "system_modules.go", + "systemserver_classpath_fragment.go", "testing.go", "tradefed.go", ], @@ -91,6 +92,7 @@ bootstrap_go_package { "rro_test.go", "sdk_test.go", "system_modules_test.go", + "systemserver_classpath_fragment_test.go", ], pluginFor: ["soong_build"], } diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go index 460cc3ef4..00e95913b 100644 --- a/java/classpath_fragment.go +++ b/java/classpath_fragment.go @@ -58,6 +58,8 @@ type classpathFragment interface { type ClasspathFragmentBase struct { properties classpathFragmentProperties + classpathType classpathType + outputFilepath android.OutputPath installDirPath android.InstallPath } @@ -67,8 +69,9 @@ func (c *ClasspathFragmentBase) classpathFragmentBase() *ClasspathFragmentBase { } // Initializes ClasspathFragmentBase struct. Must be called by all modules that include ClasspathFragmentBase. -func initClasspathFragment(c classpathFragment) { +func initClasspathFragment(c classpathFragment, classpathType classpathType) { base := c.classpathFragmentBase() + base.classpathType = classpathType c.AddProperties(&base.properties) } @@ -87,9 +90,17 @@ func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.M c.installDirPath = android.PathForModuleInstall(ctx, "etc", "classpaths") var jars []classpathJar - jars = appendClasspathJar(jars, BOOTCLASSPATH, defaultBootclasspath(ctx)...) - jars = appendClasspathJar(jars, DEX2OATBOOTCLASSPATH, defaultBootImageConfig(ctx).getAnyAndroidVariant().dexLocationsDeps...) - jars = appendClasspathJar(jars, SYSTEMSERVERCLASSPATH, systemServerClasspath(ctx)...) + switch c.classpathType { + case BOOTCLASSPATH: + jars = appendClasspathJar(jars, BOOTCLASSPATH, defaultBootclasspath(ctx)...) + jars = appendClasspathJar(jars, DEX2OATBOOTCLASSPATH, defaultBootImageConfig(ctx).getAnyAndroidVariant().dexLocationsDeps...) + case SYSTEMSERVERCLASSPATH: + jars = appendClasspathJar(jars, SYSTEMSERVERCLASSPATH, systemServerClasspath(ctx)...) + default: + // Only supported classpath fragments are BOOTCLASSPATH and SYSTEMSERVERCLASSPATH. + // DEX2OATBOOTCLASSPATH is a special case of BOOTCLASSPATH and is auto-generated. + panic(fmt.Errorf("found %v, expected either BOOTCLASSPATH or SYSTEMSERVERCLASSPATH", c.classpathType)) + } generatedJson := android.PathForModuleOut(ctx, outputFilename+".json") writeClasspathsJson(ctx, generatedJson, jars) diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index 1acb9f4f5..1f2494296 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -72,8 +72,8 @@ type platformBootclasspathProperties struct { func platformBootclasspathFactory() android.SingletonModule { m := &platformBootclasspathModule{} m.AddProperties(&m.properties) - // TODO(satayev): split systemserver and apex jars into separate configs. - initClasspathFragment(m) + // TODO(satayev): split apex jars into separate configs. + initClasspathFragment(m, BOOTCLASSPATH) android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) return m } diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go new file mode 100644 index 000000000..3f8a0836f --- /dev/null +++ b/java/systemserver_classpath_fragment.go @@ -0,0 +1,50 @@ +// Copyright 2021 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 java + +import ( + "android/soong/android" +) + +func init() { + registerSystemserverClasspathBuildComponents(android.InitRegistrationContext) +} + +func registerSystemserverClasspathBuildComponents(ctx android.RegistrationContext) { + // TODO(satayev): add systemserver_classpath_fragment module + ctx.RegisterModuleType("platform_systemserverclasspath", platformSystemServerClasspathFactory) +} + +type platformSystemServerClasspathModule struct { + android.ModuleBase + + ClasspathFragmentBase +} + +func platformSystemServerClasspathFactory() android.Module { + m := &platformSystemServerClasspathModule{} + initClasspathFragment(m, SYSTEMSERVERCLASSPATH) + android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) + return m +} + +func (b *platformSystemServerClasspathModule) AndroidMkEntries() (entries []android.AndroidMkEntries) { + return b.classpathFragmentBase().androidMkEntries() +} + +func (b *platformSystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { + // TODO(satayev): split apex jars into separate configs. + b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx) +} diff --git a/java/systemserver_classpath_fragment_test.go b/java/systemserver_classpath_fragment_test.go new file mode 100644 index 000000000..6126d5eb1 --- /dev/null +++ b/java/systemserver_classpath_fragment_test.go @@ -0,0 +1,97 @@ +// Copyright (C) 2021 The Android Open Source Project +// +// 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 java + +import ( + "testing" + + "android/soong/android" +) + +var prepareForTestWithSystemserverClasspath = android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, +) + +func TestSystemserverClasspathVariant(t *testing.T) { + result := android.GroupFixturePreparers( + prepareForTestWithSystemserverClasspath, + android.FixtureWithRootAndroidBp(` + platform_systemserverclasspath { + name: "platform-systemserverclasspath", + } + `), + ).RunTest(t) + + variants := result.ModuleVariantsForTests("platform-systemserverclasspath") + android.AssertIntEquals(t, "expect 1 variant", 1, len(variants)) +} + +func TestSystemserverClasspath_ClasspathFragmentPaths(t *testing.T) { + result := android.GroupFixturePreparers( + prepareForTestWithSystemserverClasspath, + android.FixtureWithRootAndroidBp(` + platform_systemserverclasspath { + name: "platform-systemserverclasspath", + } + `), + ).RunTest(t) + + p := result.Module("platform-systemserverclasspath", "android_common").(*platformSystemServerClasspathModule) + android.AssertStringEquals(t, "output filepath", p.Name()+".pb", p.ClasspathFragmentBase.outputFilepath.Base()) + android.AssertPathRelativeToTopEquals(t, "install filepath", "out/soong/target/product/test_device/system/etc/classpaths", p.ClasspathFragmentBase.installDirPath) +} + +func TestSystemserverClasspathModule_AndroidMkEntries(t *testing.T) { + preparer := android.GroupFixturePreparers( + prepareForTestWithSystemserverClasspath, + android.FixtureWithRootAndroidBp(` + platform_systemserverclasspath { + name: "platform-systemserverclasspath", + } + `), + ) + + t.Run("AndroidMkEntries", func(t *testing.T) { + result := preparer.RunTest(t) + + p := result.Module("platform-systemserverclasspath", "android_common").(*platformSystemServerClasspathModule) + + entries := android.AndroidMkEntriesForTest(t, result.TestContext, p) + android.AssertIntEquals(t, "AndroidMkEntries count", 1, len(entries)) + }) + + t.Run("classpath-fragment-entry", func(t *testing.T) { + result := preparer.RunTest(t) + + want := map[string][]string{ + "LOCAL_MODULE": {"platform-systemserverclasspath"}, + "LOCAL_MODULE_CLASS": {"ETC"}, + "LOCAL_INSTALLED_MODULE_STEM": {"platform-systemserverclasspath.pb"}, + // Output and Install paths are tested separately in TestSystemserverClasspath_ClasspathFragmentPaths + } + + p := result.Module("platform-systemserverclasspath", "android_common").(*platformSystemServerClasspathModule) + + entries := android.AndroidMkEntriesForTest(t, result.TestContext, p) + got := entries[0] + for k, expectedValue := range want { + if value, ok := got.EntryMap[k]; ok { + android.AssertDeepEquals(t, k, expectedValue, value) + } else { + t.Errorf("No %s defined, saw %q", k, got.EntryMap) + } + } + }) +} diff --git a/java/testing.go b/java/testing.go index 649d27bf5..37e63f5f9 100644 --- a/java/testing.go +++ b/java/testing.go @@ -244,6 +244,7 @@ func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) { RegisterSdkLibraryBuildComponents(ctx) RegisterStubsBuildComponents(ctx) RegisterSystemModulesBuildComponents(ctx) + registerSystemserverClasspathBuildComponents(ctx) } // gatherRequiredDepsForTest gathers the module definitions used by