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 casts android.Module to java.androidTestApp 75// If this type conversion is possible, it queries whether the test app is included in an MTS suite 76func includedInMts(module android.Module) bool { 77 if test, ok := module.(androidTestApp); ok { 78 return test.includedInTestSuite("mts") 79 } 80 return false 81} 82 83type ManifestFixerParams struct { 84 SdkContext android.SdkContext 85 ClassLoaderContexts dexpreopt.ClassLoaderContextMap 86 IsLibrary bool 87 DefaultManifestVersion string 88 UseEmbeddedNativeLibs bool 89 UsesNonSdkApis bool 90 UseEmbeddedDex bool 91 HasNoCode bool 92 TestOnly bool 93 LoggingParent string 94 EnforceDefaultTargetSdkVersion bool 95} 96 97// Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml 98func ManifestFixer(ctx android.ModuleContext, manifest android.Path, 99 params ManifestFixerParams) android.Path { 100 var args []string 101 102 if params.IsLibrary { 103 args = append(args, "--library") 104 } else if params.SdkContext != nil { 105 minSdkVersion, err := params.SdkContext.MinSdkVersion(ctx).EffectiveVersion(ctx) 106 if err != nil { 107 ctx.ModuleErrorf("invalid minSdkVersion: %s", err) 108 } 109 if minSdkVersion.FinalOrFutureInt() >= 23 { 110 args = append(args, fmt.Sprintf("--extract-native-libs=%v", !params.UseEmbeddedNativeLibs)) 111 } else if params.UseEmbeddedNativeLibs { 112 ctx.ModuleErrorf("module attempted to store uncompressed native libraries, but minSdkVersion=%s doesn't support it", 113 minSdkVersion.String()) 114 } 115 } 116 117 if params.UsesNonSdkApis { 118 args = append(args, "--uses-non-sdk-api") 119 } 120 121 if params.UseEmbeddedDex { 122 args = append(args, "--use-embedded-dex") 123 } 124 125 if params.ClassLoaderContexts != nil { 126 // Libraries propagated via `uses_libs`/`optional_uses_libs` are also added (they may be 127 // propagated from dependencies). 128 requiredUsesLibs, optionalUsesLibs := params.ClassLoaderContexts.UsesLibs() 129 130 for _, usesLib := range requiredUsesLibs { 131 args = append(args, "--uses-library", usesLib) 132 } 133 for _, usesLib := range optionalUsesLibs { 134 args = append(args, "--optional-uses-library", usesLib) 135 } 136 } 137 138 if params.HasNoCode { 139 args = append(args, "--has-no-code") 140 } 141 142 if params.TestOnly { 143 args = append(args, "--test-only") 144 } 145 146 if params.LoggingParent != "" { 147 args = append(args, "--logging-parent", params.LoggingParent) 148 } 149 var deps android.Paths 150 var argsMapper = make(map[string]string) 151 152 if params.SdkContext != nil { 153 targetSdkVersion := targetSdkVersionForManifestFixer(ctx, params) 154 155 if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" { 156 targetSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String()) 157 deps = append(deps, ApiFingerprintPath(ctx)) 158 } 159 160 args = append(args, "--targetSdkVersion ", targetSdkVersion) 161 162 minSdkVersion, err := params.SdkContext.MinSdkVersion(ctx).EffectiveVersionString(ctx) 163 if err != nil { 164 ctx.ModuleErrorf("invalid minSdkVersion: %s", err) 165 } 166 167 replaceMaxSdkVersionPlaceholder, err := params.SdkContext.ReplaceMaxSdkVersionPlaceholder(ctx).EffectiveVersion(ctx) 168 if err != nil { 169 ctx.ModuleErrorf("invalid ReplaceMaxSdkVersionPlaceholder: %s", err) 170 } 171 172 if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" { 173 minSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String()) 174 deps = append(deps, ApiFingerprintPath(ctx)) 175 } 176 177 if err != nil { 178 ctx.ModuleErrorf("invalid minSdkVersion: %s", err) 179 } 180 args = append(args, "--minSdkVersion ", minSdkVersion) 181 args = append(args, "--replaceMaxSdkVersionPlaceholder ", strconv.Itoa(replaceMaxSdkVersionPlaceholder.FinalOrFutureInt())) 182 args = append(args, "--raise-min-sdk-version") 183 } 184 if params.DefaultManifestVersion != "" { 185 args = append(args, "--override-placeholder-version", params.DefaultManifestVersion) 186 } 187 188 fixedManifest := android.PathForModuleOut(ctx, "manifest_fixer", "AndroidManifest.xml") 189 argsMapper["args"] = strings.Join(args, " ") 190 191 ctx.Build(pctx, android.BuildParams{ 192 Rule: manifestFixerRule, 193 Description: "fix manifest", 194 Input: manifest, 195 Implicits: deps, 196 Output: fixedManifest, 197 Args: argsMapper, 198 }) 199 200 return fixedManifest.WithoutRel() 201} 202 203func manifestMerger(ctx android.ModuleContext, manifest android.Path, staticLibManifests android.Paths, 204 isLibrary bool) android.Path { 205 206 var args string 207 if !isLibrary { 208 // Follow Gradle's behavior, only pass --remove-tools-declarations when merging app manifests. 209 args = "--remove-tools-declarations" 210 } 211 212 mergedManifest := android.PathForModuleOut(ctx, "manifest_merger", "AndroidManifest.xml") 213 ctx.Build(pctx, android.BuildParams{ 214 Rule: manifestMergerRule, 215 Description: "merge manifest", 216 Input: manifest, 217 Implicits: staticLibManifests, 218 Output: mergedManifest, 219 Args: map[string]string{ 220 "libs": android.JoinWithPrefix(staticLibManifests.Strings(), "--libs "), 221 "args": args, 222 }, 223 }) 224 225 return mergedManifest.WithoutRel() 226} 227