• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, sdkContext android.SdkContext) string {
47	targetSdkVersionSpec := sdkContext.TargetSdkVersion(ctx)
48	if ctx.Config().UnbundledBuildApps() && targetSdkVersionSpec.ApiLevel.IsPreview() {
49		return strconv.Itoa(android.FutureApiLevel.FinalOrFutureInt())
50	}
51	targetSdkVersion, err := targetSdkVersionSpec.EffectiveVersionString(ctx)
52	if err != nil {
53		ctx.ModuleErrorf("invalid targetSdkVersion: %s", err)
54	}
55	return targetSdkVersion
56}
57
58type ManifestFixerParams struct {
59	SdkContext            android.SdkContext
60	ClassLoaderContexts   dexpreopt.ClassLoaderContextMap
61	IsLibrary             bool
62	UseEmbeddedNativeLibs bool
63	UsesNonSdkApis        bool
64	UseEmbeddedDex        bool
65	HasNoCode             bool
66	TestOnly              bool
67	LoggingParent         string
68}
69
70// Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml
71func ManifestFixer(ctx android.ModuleContext, manifest android.Path,
72	params ManifestFixerParams) android.Path {
73	var args []string
74
75	if params.IsLibrary {
76		args = append(args, "--library")
77	} else if params.SdkContext != nil {
78		minSdkVersion, err := params.SdkContext.MinSdkVersion(ctx).EffectiveVersion(ctx)
79		if err != nil {
80			ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
81		}
82		if minSdkVersion.FinalOrFutureInt() >= 23 {
83			args = append(args, fmt.Sprintf("--extract-native-libs=%v", !params.UseEmbeddedNativeLibs))
84		} else if params.UseEmbeddedNativeLibs {
85			ctx.ModuleErrorf("module attempted to store uncompressed native libraries, but minSdkVersion=%d doesn't support it",
86				minSdkVersion)
87		}
88	}
89
90	if params.UsesNonSdkApis {
91		args = append(args, "--uses-non-sdk-api")
92	}
93
94	if params.UseEmbeddedDex {
95		args = append(args, "--use-embedded-dex")
96	}
97
98	if params.ClassLoaderContexts != nil {
99		// manifest_fixer should add only the implicit SDK libraries inferred by Soong, not those added
100		// explicitly via `uses_libs`/`optional_uses_libs`.
101		requiredUsesLibs, optionalUsesLibs := params.ClassLoaderContexts.ImplicitUsesLibs()
102
103		for _, usesLib := range requiredUsesLibs {
104			args = append(args, "--uses-library", usesLib)
105		}
106		for _, usesLib := range optionalUsesLibs {
107			args = append(args, "--optional-uses-library", usesLib)
108		}
109	}
110
111	if params.HasNoCode {
112		args = append(args, "--has-no-code")
113	}
114
115	if params.TestOnly {
116		args = append(args, "--test-only")
117	}
118
119	if params.LoggingParent != "" {
120		args = append(args, "--logging-parent", params.LoggingParent)
121	}
122	var deps android.Paths
123	var argsMapper = make(map[string]string)
124
125	if params.SdkContext != nil {
126		targetSdkVersion := targetSdkVersionForManifestFixer(ctx, params.SdkContext)
127		args = append(args, "--targetSdkVersion ", targetSdkVersion)
128
129		if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" {
130			targetSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
131			deps = append(deps, ApiFingerprintPath(ctx))
132		}
133
134		minSdkVersion, err := params.SdkContext.MinSdkVersion(ctx).EffectiveVersionString(ctx)
135		if err != nil {
136			ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
137		}
138
139		if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" {
140			minSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
141			deps = append(deps, ApiFingerprintPath(ctx))
142		}
143
144		if err != nil {
145			ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
146		}
147		args = append(args, "--minSdkVersion ", minSdkVersion)
148		args = append(args, "--raise-min-sdk-version")
149	}
150
151	fixedManifest := android.PathForModuleOut(ctx, "manifest_fixer", "AndroidManifest.xml")
152	argsMapper["args"] = strings.Join(args, " ")
153
154	ctx.Build(pctx, android.BuildParams{
155		Rule:        manifestFixerRule,
156		Description: "fix manifest",
157		Input:       manifest,
158		Implicits:   deps,
159		Output:      fixedManifest,
160		Args:        argsMapper,
161	})
162
163	return fixedManifest.WithoutRel()
164}
165
166func manifestMerger(ctx android.ModuleContext, manifest android.Path, staticLibManifests android.Paths,
167	isLibrary bool) android.Path {
168
169	var args string
170	if !isLibrary {
171		// Follow Gradle's behavior, only pass --remove-tools-declarations when merging app manifests.
172		args = "--remove-tools-declarations"
173	}
174
175	mergedManifest := android.PathForModuleOut(ctx, "manifest_merger", "AndroidManifest.xml")
176	ctx.Build(pctx, android.BuildParams{
177		Rule:        manifestMergerRule,
178		Description: "merge manifest",
179		Input:       manifest,
180		Implicits:   staticLibManifests,
181		Output:      mergedManifest,
182		Args: map[string]string{
183			"libs": android.JoinWithPrefix(staticLibManifests.Strings(), "--libs "),
184			"args": args,
185		},
186	})
187
188	return mergedManifest.WithoutRel()
189}
190