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

Commit aa3408a5 authored by LaMont Jones's avatar LaMont Jones Committed by Gerrit Code Review
Browse files

Merge "Add multitree apex metadata"

parents 074c8c3b 11d2d09a
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ bootstrap_go_package {
        "bp2build.go",
        "deapexer.go",
        "key.go",
        "metadata.go",
        "prebuilt.go",
        "testing.go",
        "vndk.go",
@@ -37,6 +38,7 @@ bootstrap_go_package {
        "apex_test.go",
        "bootclasspath_fragment_test.go",
        "classpath_element_test.go",
        "metadata_test.go",
        "platform_bootclasspath_test.go",
        "systemserver_classpath_fragment_test.go",
        "vndk_test.go",

apex/metadata.go

0 → 100644
+99 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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 apex

import (
	"encoding/json"

	"github.com/google/blueprint"

	"android/soong/android"
)

var (
	mtctx = android.NewPackageContext("android/soong/multitree_apex")
)

func init() {
	RegisterModulesSingleton(android.InitRegistrationContext)
}

func RegisterModulesSingleton(ctx android.RegistrationContext) {
	ctx.RegisterSingletonType("apex_multitree_singleton", multitreeAnalysisSingletonFactory)
}

var PrepareForTestWithApexMultitreeSingleton = android.FixtureRegisterWithContext(RegisterModulesSingleton)

func multitreeAnalysisSingletonFactory() android.Singleton {
	return &multitreeAnalysisSingleton{}
}

type multitreeAnalysisSingleton struct {
	multitreeApexMetadataPath android.OutputPath
}

type ApexMultitreeMetadataEntry struct {
	// The name of the apex.
	Name string

	// TODO: Add other properties as needed.
}

type ApexMultitreeMetadata struct {
	// Information about the installable apexes.
	Apexes map[string]ApexMultitreeMetadataEntry
}

func (p *multitreeAnalysisSingleton) GenerateBuildActions(context android.SingletonContext) {
	data := ApexMultitreeMetadata{
		Apexes: make(map[string]ApexMultitreeMetadataEntry, 0),
	}
	context.VisitAllModules(func(module android.Module) {
		// If this module is not being installed, ignore it.
		if !module.Enabled() || module.IsSkipInstall() {
			return
		}
		// Actual apexes provide ApexBundleInfoProvider.
		if _, ok := context.ModuleProvider(module, ApexBundleInfoProvider).(ApexBundleInfo); !ok {
			return
		}
		bundle, ok := module.(*apexBundle)
		if ok && !bundle.testApex && !bundle.vndkApex && bundle.primaryApexType {
			name := module.Name()
			entry := ApexMultitreeMetadataEntry{
				Name: name,
			}
			data.Apexes[name] = entry
		}
	})
	p.multitreeApexMetadataPath = android.PathForOutput(context, "multitree_apex_metadata.json")

	jsonStr, err := json.Marshal(data)
	if err != nil {
		context.Errorf(err.Error())
	}
	android.WriteFileRule(context, p.multitreeApexMetadataPath, string(jsonStr))
	// This seems cleaner, but doesn't emit the phony rule in testing.
	// context.Phony("multitree_apex_metadata", p.multitreeApexMetadataPath)

	context.Build(mtctx, android.BuildParams{
		Rule:        blueprint.Phony,
		Description: "phony rule for multitree_apex_metadata",
		Inputs:      []android.Path{p.multitreeApexMetadataPath},
		Output:      android.PathForPhony(context, "multitree_apex_metadata"),
	})
}

apex/metadata_test.go

0 → 100644
+103 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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 apex

import (
	"strings"
	"testing"

	"android/soong/android"
	"android/soong/java"
)

func TestModulesSingleton(t *testing.T) {
	result := android.GroupFixturePreparers(
		PrepareForTestWithApexMultitreeSingleton,
		java.PrepareForTestWithDexpreopt,
		PrepareForTestWithApexBuildComponents,
		java.FixtureConfigureApexBootJars("myapex:foo"),
		java.PrepareForTestWithJavaSdkLibraryFiles,
	).RunTestWithBp(t, `
		prebuilt_apex {
			name: "myapex",
			src: "myapex.apex",
			exported_bootclasspath_fragments: ["mybootclasspath-fragment"],
		}

		// A prebuilt java_sdk_library_import that is not preferred by default but will be preferred
		// because AlwaysUsePrebuiltSdks() is true.
		java_sdk_library_import {
			name: "foo",
			prefer: false,
			shared_library: false,
			permitted_packages: ["foo"],
			public: {
				jars: ["sdk_library/public/foo-stubs.jar"],
				stub_srcs: ["sdk_library/public/foo_stub_sources"],
				current_api: "sdk_library/public/foo.txt",
				removed_api: "sdk_library/public/foo-removed.txt",
				sdk_version: "current",
			},
			apex_available: ["myapex"],
		}

		prebuilt_bootclasspath_fragment {
			name: "mybootclasspath-fragment",
			apex_available: [
				"myapex",
			],
			contents: [
				"foo",
			],
			hidden_api: {
				stub_flags: "prebuilt-stub-flags.csv",
				annotation_flags: "prebuilt-annotation-flags.csv",
				metadata: "prebuilt-metadata.csv",
				index: "prebuilt-index.csv",
				all_flags: "prebuilt-all-flags.csv",
			},
		}

		platform_bootclasspath {
			name: "myplatform-bootclasspath",
			fragments: [
				{
					apex: "myapex",
					module:"mybootclasspath-fragment",
				},
			],
		}
`,
	)

	outputs := result.SingletonForTests("apex_multitree_singleton").AllOutputs()
	for _, output := range outputs {
		testingBuildParam := result.SingletonForTests("apex_multitree_singleton").Output(output)
		switch {
		case strings.Contains(output, "soong/multitree_apex_metadata.json"):
			android.AssertStringEquals(t, "Invalid build rule", "android/soong/android.writeFile", testingBuildParam.Rule.String())
			android.AssertIntEquals(t, "Invalid input", len(testingBuildParam.Inputs), 0)
			android.AssertStringDoesContain(t, "Invalid output path", output, "soong/multitree_apex_metadata.json")

		case strings.HasSuffix(output, "multitree_apex_metadata"):
			android.AssertStringEquals(t, "Invalid build rule", "<builtin>:phony", testingBuildParam.Rule.String())
			android.AssertStringEquals(t, "Invalid input", testingBuildParam.Inputs[0].String(), "out/soong/multitree_apex_metadata.json")
			android.AssertStringEquals(t, "Invalid output path", output, "multitree_apex_metadata")
			android.AssertIntEquals(t, "Invalid args", len(testingBuildParam.Args), 0)
		}
	}
}