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