xref: /aosp_15_r20/build/soong/java/android_manifest.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright 2018 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package java
16
17import (
18	"fmt"
19	"strconv"
20	"strings"
21
22	"github.com/google/blueprint"
23
24	"android/soong/android"
25	"android/soong/dexpreopt"
26)
27
28var manifestFixerRule = pctx.AndroidStaticRule("manifestFixer",
29	blueprint.RuleParams{
30		Command: `${config.ManifestFixerCmd} ` +
31			`$args $in $out`,
32		CommandDeps: []string{"${config.ManifestFixerCmd}"},
33	},
34	"args")
35
36var manifestMergerRule = pctx.AndroidStaticRule("manifestMerger",
37	blueprint.RuleParams{
38		Command:     `${config.ManifestMergerCmd} $args --main $in $libs --out $out`,
39		CommandDeps: []string{"${config.ManifestMergerCmd}"},
40	},
41	"args", "libs")
42
43// targetSdkVersion for manifest_fixer
44// When TARGET_BUILD_APPS is not empty, this method returns 10000 for modules targeting an unreleased SDK
45// This enables release builds (that run with TARGET_BUILD_APPS=[val...]) to target APIs that have not yet been finalized as part of an SDK
46func targetSdkVersionForManifestFixer(ctx android.ModuleContext, params ManifestFixerParams) string {
47	targetSdkVersionLevel := params.SdkContext.TargetSdkVersion(ctx)
48
49	// Check if we want to return 10000
50	// TODO(b/240294501): Determine the rules for handling test apexes
51	if shouldReturnFinalOrFutureInt(ctx, targetSdkVersionLevel, params.EnforceDefaultTargetSdkVersion) {
52		return strconv.Itoa(android.FutureApiLevel.FinalOrFutureInt())
53	}
54	targetSdkVersion, err := targetSdkVersionLevel.EffectiveVersionString(ctx)
55	if err != nil {
56		ctx.ModuleErrorf("invalid targetSdkVersion: %s", err)
57	}
58	return targetSdkVersion
59}
60
61// Return true for modules targeting "current" if either
62// 1. The module is built in unbundled mode (TARGET_BUILD_APPS not empty)
63// 2. The module is run as part of MTS, and should be testable on stable branches
64// Do not return 10000 if we are enforcing default targetSdkVersion and sdk has been finalised
65func shouldReturnFinalOrFutureInt(ctx android.ModuleContext, targetSdkVersionLevel android.ApiLevel, enforceDefaultTargetSdkVersion bool) bool {
66	// If this is a REL branch, do not return 10000
67	if ctx.Config().PlatformSdkFinal() {
68		return false
69	}
70	// If this a module targeting an unreleased SDK (MTS or unbundled builds), return 10000
71	return targetSdkVersionLevel.IsPreview() && (ctx.Config().UnbundledBuildApps() || includedInMts(ctx.Module()))
72}
73
74// Helper function that returns true if android_test, android_test_helper_app, java_test are in an MTS suite.
75func includedInMts(module android.Module) bool {
76	if test, ok := module.(androidTestApp); ok {
77		return test.includedInTestSuite("mts")
78	}
79	// java_test
80	if test, ok := module.(*Test); ok {
81		return android.PrefixInList(test.testProperties.Test_suites, "mts")
82	}
83	return false
84}
85
86type ManifestFixerParams struct {
87	SdkContext                     android.SdkContext
88	ClassLoaderContexts            dexpreopt.ClassLoaderContextMap
89	IsLibrary                      bool
90	DefaultManifestVersion         string
91	UseEmbeddedNativeLibs          bool
92	UsesNonSdkApis                 bool
93	UseEmbeddedDex                 bool
94	HasNoCode                      bool
95	TestOnly                       bool
96	LoggingParent                  string
97	EnforceDefaultTargetSdkVersion bool
98}
99
100// Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml
101func ManifestFixer(ctx android.ModuleContext, manifest android.Path,
102	params ManifestFixerParams) android.Path {
103	var args []string
104
105	if params.IsLibrary {
106		args = append(args, "--library")
107	} else if params.SdkContext != nil {
108		minSdkVersion, err := params.SdkContext.MinSdkVersion(ctx).EffectiveVersion(ctx)
109		if err != nil {
110			ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
111		}
112		if minSdkVersion.FinalOrFutureInt() >= 23 {
113			args = append(args, fmt.Sprintf("--extract-native-libs=%v", !params.UseEmbeddedNativeLibs))
114		} else if params.UseEmbeddedNativeLibs {
115			ctx.ModuleErrorf("module attempted to store uncompressed native libraries, but minSdkVersion=%s doesn't support it",
116				minSdkVersion.String())
117		}
118	}
119
120	if params.UsesNonSdkApis {
121		args = append(args, "--uses-non-sdk-api")
122	}
123
124	if params.UseEmbeddedDex {
125		args = append(args, "--use-embedded-dex")
126	}
127
128	if params.ClassLoaderContexts != nil {
129		// Libraries propagated via `uses_libs`/`optional_uses_libs` are also added (they may be
130		// propagated from dependencies).
131		requiredUsesLibs, optionalUsesLibs := params.ClassLoaderContexts.UsesLibs()
132
133		for _, usesLib := range requiredUsesLibs {
134			args = append(args, "--uses-library", usesLib)
135		}
136		for _, usesLib := range optionalUsesLibs {
137			args = append(args, "--optional-uses-library", usesLib)
138		}
139	}
140
141	if params.HasNoCode {
142		args = append(args, "--has-no-code")
143	}
144
145	if params.TestOnly {
146		args = append(args, "--test-only")
147	}
148
149	if params.LoggingParent != "" {
150		args = append(args, "--logging-parent", params.LoggingParent)
151	}
152	var deps android.Paths
153	var argsMapper = make(map[string]string)
154
155	if params.SdkContext != nil {
156		targetSdkVersion := targetSdkVersionForManifestFixer(ctx, params)
157
158		if useApiFingerprint, fingerprintTargetSdkVersion, fingerprintDeps :=
159			UseApiFingerprint(ctx); useApiFingerprint && ctx.ModuleName() != "framework-res" {
160			targetSdkVersion = fingerprintTargetSdkVersion
161			deps = append(deps, fingerprintDeps)
162		}
163
164		args = append(args, "--targetSdkVersion ", targetSdkVersion)
165
166		minSdkVersion, err := params.SdkContext.MinSdkVersion(ctx).EffectiveVersionString(ctx)
167		if err != nil {
168			ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
169		}
170
171		replaceMaxSdkVersionPlaceholder, err := params.SdkContext.ReplaceMaxSdkVersionPlaceholder(ctx).EffectiveVersion(ctx)
172		if err != nil {
173			ctx.ModuleErrorf("invalid ReplaceMaxSdkVersionPlaceholder: %s", err)
174		}
175
176		if useApiFingerprint, fingerprintMinSdkVersion, fingerprintDeps :=
177			UseApiFingerprint(ctx); useApiFingerprint && ctx.ModuleName() != "framework-res" {
178			minSdkVersion = fingerprintMinSdkVersion
179			deps = append(deps, fingerprintDeps)
180		}
181
182		if err != nil {
183			ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
184		}
185		args = append(args, "--minSdkVersion ", minSdkVersion)
186		args = append(args, "--replaceMaxSdkVersionPlaceholder ", strconv.Itoa(replaceMaxSdkVersionPlaceholder.FinalOrFutureInt()))
187		args = append(args, "--raise-min-sdk-version")
188	}
189	if params.DefaultManifestVersion != "" {
190		args = append(args, "--override-placeholder-version", params.DefaultManifestVersion)
191	}
192
193	fixedManifest := android.PathForModuleOut(ctx, "manifest_fixer", "AndroidManifest.xml")
194	argsMapper["args"] = strings.Join(args, " ")
195
196	ctx.Build(pctx, android.BuildParams{
197		Rule:        manifestFixerRule,
198		Description: "fix manifest",
199		Input:       manifest,
200		Implicits:   deps,
201		Output:      fixedManifest,
202		Args:        argsMapper,
203	})
204
205	return fixedManifest.WithoutRel()
206}
207
208type ManifestMergerParams struct {
209	staticLibManifests android.Paths
210	isLibrary          bool
211	packageName        string
212}
213
214func manifestMerger(ctx android.ModuleContext, manifest android.Path,
215	params ManifestMergerParams) android.Path {
216
217	var args []string
218	if !params.isLibrary {
219		// Follow Gradle's behavior, only pass --remove-tools-declarations when merging app manifests.
220		args = append(args, "--remove-tools-declarations")
221	}
222
223	packageName := params.packageName
224	if packageName != "" {
225		args = append(args, "--property PACKAGE="+packageName)
226	}
227
228	mergedManifest := android.PathForModuleOut(ctx, "manifest_merger", "AndroidManifest.xml")
229	ctx.Build(pctx, android.BuildParams{
230		Rule:        manifestMergerRule,
231		Description: "merge manifest",
232		Input:       manifest,
233		Implicits:   params.staticLibManifests,
234		Output:      mergedManifest,
235		Args: map[string]string{
236			"libs": android.JoinWithPrefix(params.staticLibManifests.Strings(), "--libs "),
237			"args": strings.Join(args, " "),
238		},
239	})
240
241	return mergedManifest.WithoutRel()
242}
243