Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f86fe9a8 authored by Jihoon Kang's avatar Jihoon Kang
Browse files

Implement InstallableModule for Java modules

This change enables the container information to be collected for Java
modules.

Test: m nothing --no-skip-soong-tests
Bug: 338660802
Change-Id: I01bf99fa274275a608601ad6248d577ae8f6dffc
parent c3d4e115
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ bootstrap_go_package {
        "apex_test.go",
        "bootclasspath_fragment_test.go",
        "classpath_element_test.go",
        "container_test.go",
        "dexpreopt_bootjars_test.go",
        "platform_bootclasspath_test.go",
        "systemserver_classpath_fragment_test.go",

apex/container_test.go

0 → 100644
+329 −0
Original line number Diff line number Diff line
// Copyright 2024 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 apex

import (
	"android/soong/android"
	"android/soong/java"
	"fmt"
	"testing"
)

var checkContainerMatch = func(t *testing.T, name string, container string, expected bool, actual bool) {
	errorMessage := fmt.Sprintf("module %s container %s value differ", name, container)
	android.AssertBoolEquals(t, errorMessage, expected, actual)
}

func TestApexDepsContainers(t *testing.T) {
	result := android.GroupFixturePreparers(
		prepareForApexTest,
		java.PrepareForTestWithJavaSdkLibraryFiles,
		java.FixtureWithLastReleaseApis("mybootclasspathlib"),
	).RunTestWithBp(t, `
		apex {
			name: "myapex",
			key: "myapex.key",
			bootclasspath_fragments: [
				"mybootclasspathfragment",
			],
			updatable: true,
			min_sdk_version: "30",
		}
		apex_key {
			name: "myapex.key",
			public_key: "testkey.avbpubkey",
			private_key: "testkey.pem",
		}
		bootclasspath_fragment {
			name: "mybootclasspathfragment",
			contents: [
				"mybootclasspathlib",
			],
			apex_available: [
				"myapex",
			],
			hidden_api: {
				split_packages: ["*"],
			},
		}
		java_sdk_library {
			name: "mybootclasspathlib",
			srcs: [
				"mybootclasspathlib.java",
			],
			apex_available: [
				"myapex",
			],
			compile_dex: true,
			static_libs: [
				"foo",
				"baz",
			],
			libs: [
				"bar",
			],
			min_sdk_version: "30",
		}
		java_library {
			name: "foo",
			srcs:[
				"A.java",
			],
			apex_available: [
				"myapex",
			],
			min_sdk_version: "30",
		}
		java_library {
			name: "bar",
			srcs:[
				"A.java",
			],
			min_sdk_version: "30",
		}
		java_library {
			name: "baz",
			srcs:[
				"A.java",
			],
			apex_available: [
				"//apex_available:platform",
				"myapex",
			],
			min_sdk_version: "30",
		}
	`)
	testcases := []struct {
		moduleName        string
		variant           string
		isSystemContainer bool
		isApexContainer   bool
	}{
		{
			moduleName:        "mybootclasspathlib",
			variant:           "android_common_myapex",
			isSystemContainer: true,
			isApexContainer:   true,
		},
		{
			moduleName:        "mybootclasspathlib.impl",
			variant:           "android_common_apex30",
			isSystemContainer: true,
			isApexContainer:   true,
		},
		{
			moduleName:        "mybootclasspathlib.stubs",
			variant:           "android_common",
			isSystemContainer: true,
			isApexContainer:   false,
		},
		{
			moduleName:        "foo",
			variant:           "android_common_apex30",
			isSystemContainer: true,
			isApexContainer:   true,
		},
		{
			moduleName:        "bar",
			variant:           "android_common",
			isSystemContainer: true,
			isApexContainer:   false,
		},
		{
			moduleName:        "baz",
			variant:           "android_common_apex30",
			isSystemContainer: true,
			isApexContainer:   true,
		},
	}

	for _, c := range testcases {
		m := result.ModuleForTests(c.moduleName, c.variant)
		containers, _ := android.OtherModuleProvider(result.TestContext.OtherModuleProviderAdaptor(), m.Module(), android.ContainersInfoProvider)
		belongingContainers := containers.BelongingContainers()
		checkContainerMatch(t, c.moduleName, "system", c.isSystemContainer, android.InList(android.SystemContainer, belongingContainers))
		checkContainerMatch(t, c.moduleName, "apex", c.isApexContainer, android.InList(android.ApexContainer, belongingContainers))
	}
}

func TestNonUpdatableApexDepsContainers(t *testing.T) {
	result := android.GroupFixturePreparers(
		prepareForApexTest,
		java.PrepareForTestWithJavaSdkLibraryFiles,
		java.FixtureWithLastReleaseApis("mybootclasspathlib"),
	).RunTestWithBp(t, `
		apex {
			name: "myapex",
			key: "myapex.key",
			bootclasspath_fragments: [
				"mybootclasspathfragment",
			],
			updatable: false,
		}
		apex_key {
			name: "myapex.key",
			public_key: "testkey.avbpubkey",
			private_key: "testkey.pem",
		}
		bootclasspath_fragment {
			name: "mybootclasspathfragment",
			contents: [
				"mybootclasspathlib",
			],
			apex_available: [
				"myapex",
			],
			hidden_api: {
				split_packages: ["*"],
			},
		}
		java_sdk_library {
			name: "mybootclasspathlib",
			srcs: [
				"mybootclasspathlib.java",
			],
			apex_available: [
				"myapex",
			],
			compile_dex: true,
			static_libs: [
				"foo",
			],
			libs: [
				"bar",
			],
		}
		java_library {
			name: "foo",
			srcs:[
				"A.java",
			],
			apex_available: [
				"myapex",
			],
		}
		java_library {
			name: "bar",
			srcs:[
				"A.java",
			],
		}
	`)
	testcases := []struct {
		moduleName        string
		variant           string
		isSystemContainer bool
		isApexContainer   bool
	}{
		{
			moduleName:        "mybootclasspathlib",
			variant:           "android_common_myapex",
			isSystemContainer: true,
			isApexContainer:   true,
		},
		{
			moduleName:        "mybootclasspathlib.impl",
			variant:           "android_common_apex10000",
			isSystemContainer: true,
			isApexContainer:   true,
		},
		{
			moduleName:        "mybootclasspathlib.stubs",
			variant:           "android_common",
			isSystemContainer: true,
			isApexContainer:   false,
		},
		{
			moduleName:        "foo",
			variant:           "android_common_apex10000",
			isSystemContainer: true,
			isApexContainer:   true,
		},
		{
			moduleName:        "bar",
			variant:           "android_common",
			isSystemContainer: true,
			isApexContainer:   false,
		},
	}

	for _, c := range testcases {
		m := result.ModuleForTests(c.moduleName, c.variant)
		containers, _ := android.OtherModuleProvider(result.TestContext.OtherModuleProviderAdaptor(), m.Module(), android.ContainersInfoProvider)
		belongingContainers := containers.BelongingContainers()
		checkContainerMatch(t, c.moduleName, "system", c.isSystemContainer, android.InList(android.SystemContainer, belongingContainers))
		checkContainerMatch(t, c.moduleName, "apex", c.isApexContainer, android.InList(android.ApexContainer, belongingContainers))
	}
}

func TestUpdatableAndNonUpdatableApexesIdenticalMinSdkVersion(t *testing.T) {
	result := android.GroupFixturePreparers(
		prepareForApexTest,
		java.PrepareForTestWithJavaSdkLibraryFiles,
		android.FixtureMergeMockFs(android.MockFS{
			"system/sepolicy/apex/myapex_non_updatable-file_contexts": nil,
			"system/sepolicy/apex/myapex_updatable-file_contexts":     nil,
		}),
	).RunTestWithBp(t, `
		apex {
			name: "myapex_non_updatable",
			key: "myapex_non_updatable.key",
			java_libs: [
				"foo",
			],
			updatable: false,
			min_sdk_version: "30",
		}
		apex_key {
			name: "myapex_non_updatable.key",
			public_key: "testkey.avbpubkey",
			private_key: "testkey.pem",
		}

		apex {
			name: "myapex_updatable",
			key: "myapex_updatable.key",
			java_libs: [
				"foo",
			],
			updatable: true,
			min_sdk_version: "30",
		}
		apex_key {
			name: "myapex_updatable.key",
			public_key: "testkey.avbpubkey",
			private_key: "testkey.pem",
		}

		java_library {
			name: "foo",
			srcs:[
				"A.java",
			],
			apex_available: [
				"myapex_non_updatable",
				"myapex_updatable",
			],
			min_sdk_version: "30",
			sdk_version: "current",
		}
	`)

	fooApexVariant := result.ModuleForTests("foo", "android_common_apex30")
	containers, _ := android.OtherModuleProvider(result.TestContext.OtherModuleProviderAdaptor(), fooApexVariant.Module(), android.ContainersInfoProvider)
	belongingContainers := containers.BelongingContainers()
	checkContainerMatch(t, "foo", "system", true, android.InList(android.SystemContainer, belongingContainers))
	checkContainerMatch(t, "foo", "apex", true, android.InList(android.ApexContainer, belongingContainers))
}
+1 −0
Original line number Diff line number Diff line
@@ -87,6 +87,7 @@ bootstrap_go_package {
        "app_set_test.go",
        "app_test.go",
        "code_metadata_test.go",
        "container_test.go",
        "bootclasspath_fragment_test.go",
        "device_host_converter_test.go",
        "dex_test.go",
+12 −0
Original line number Diff line number Diff line
@@ -552,6 +552,18 @@ type Module struct {
	aconfigCacheFiles android.Paths
}

var _ android.InstallableModule = (*Module)(nil)

// To satisfy the InstallableModule interface
func (j *Module) EnforceApiContainerChecks() bool {
	return true
}

// Overrides android.ModuleBase.InstallInProduct()
func (j *Module) InstallInProduct() bool {
	return j.ProductSpecific()
}

func (j *Module) CheckStableSdkVersion(ctx android.BaseModuleContext) error {
	sdkVersion := j.SdkVersion(ctx)
	if sdkVersion.Stable() {

java/container_test.go

0 → 100644
+129 −0
Original line number Diff line number Diff line
// Copyright 2024 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"
	"fmt"
	"testing"
)

var checkContainerMatch = func(t *testing.T, name string, container string, expected bool, actual bool) {
	errorMessage := fmt.Sprintf("module %s container %s value differ", name, container)
	android.AssertBoolEquals(t, errorMessage, expected, actual)
}

func TestJavaContainersModuleProperties(t *testing.T) {
	result := android.GroupFixturePreparers(
		prepareForJavaTest,
	).RunTestWithBp(t, `
		java_library {
			name: "foo",
			srcs: ["A.java"],
		}
		java_library {
			name: "foo_vendor",
			srcs: ["A.java"],
			vendor: true,
			sdk_version: "current",
		}
		java_library {
			name: "foo_soc_specific",
			srcs: ["A.java"],
			soc_specific: true,
			sdk_version: "current",
		}
		java_library {
			name: "foo_product_specific",
			srcs: ["A.java"],
			product_specific: true,
			sdk_version: "current",
		}
		java_test {
			name: "foo_cts_test",
			srcs: ["A.java"],
			test_suites: [
				"cts",
			],
		}
		java_test {
			name: "foo_non_cts_test",
			srcs: ["A.java"],
			test_suites: [
				"general-tests",
			],
		}
	`)

	testcases := []struct {
		moduleName         string
		isSystemContainer  bool
		isVendorContainer  bool
		isProductContainer bool
		isCts              bool
	}{
		{
			moduleName:         "foo",
			isSystemContainer:  true,
			isVendorContainer:  false,
			isProductContainer: false,
			isCts:              false,
		},
		{
			moduleName:         "foo_vendor",
			isSystemContainer:  false,
			isVendorContainer:  true,
			isProductContainer: false,
			isCts:              false,
		},
		{
			moduleName:         "foo_soc_specific",
			isSystemContainer:  false,
			isVendorContainer:  true,
			isProductContainer: false,
			isCts:              false,
		},
		{
			moduleName:         "foo_product_specific",
			isSystemContainer:  false,
			isVendorContainer:  false,
			isProductContainer: true,
			isCts:              false,
		},
		{
			moduleName:         "foo_cts_test",
			isSystemContainer:  false,
			isVendorContainer:  false,
			isProductContainer: false,
			isCts:              true,
		},
		{
			moduleName:         "foo_non_cts_test",
			isSystemContainer:  false,
			isVendorContainer:  false,
			isProductContainer: false,
			isCts:              false,
		},
	}

	for _, c := range testcases {
		m := result.ModuleForTests(c.moduleName, "android_common")
		containers, _ := android.OtherModuleProvider(result.TestContext.OtherModuleProviderAdaptor(), m.Module(), android.ContainersInfoProvider)
		belongingContainers := containers.BelongingContainers()
		checkContainerMatch(t, c.moduleName, "system", c.isSystemContainer, android.InList(android.SystemContainer, belongingContainers))
		checkContainerMatch(t, c.moduleName, "vendor", c.isVendorContainer, android.InList(android.VendorContainer, belongingContainers))
		checkContainerMatch(t, c.moduleName, "product", c.isProductContainer, android.InList(android.ProductContainer, belongingContainers))
	}
}