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 "strings" 20 21 "github.com/google/blueprint" 22 23 "android/soong/android" 24) 25 26var manifestFixerRule = pctx.AndroidStaticRule("manifestFixer", 27 blueprint.RuleParams{ 28 Command: `${config.ManifestFixerCmd} ` + 29 `--minSdkVersion ${minSdkVersion} ` + 30 `--targetSdkVersion ${targetSdkVersion} ` + 31 `--raise-min-sdk-version ` + 32 `$args $in $out`, 33 CommandDeps: []string{"${config.ManifestFixerCmd}"}, 34 }, 35 "minSdkVersion", "targetSdkVersion", "args") 36 37var manifestMergerRule = pctx.AndroidStaticRule("manifestMerger", 38 blueprint.RuleParams{ 39 Command: `${config.ManifestMergerCmd} $args --main $in $libs --out $out`, 40 CommandDeps: []string{"${config.ManifestMergerCmd}"}, 41 }, 42 "args", "libs") 43 44// These two libs are added as optional dependencies (<uses-library> with 45// android:required set to false). This is because they haven't existed in pre-P 46// devices, but classes in them were in bootclasspath jars, etc. So making them 47// hard dependencies (android:required=true) would prevent apps from being 48// installed to such legacy devices. 49var optionalUsesLibs = []string{ 50 "android.test.base", 51 "android.test.mock", 52} 53 54// Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml 55func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext, sdkLibraries []string, 56 isLibrary, useEmbeddedNativeLibs, usesNonSdkApis, useEmbeddedDex, hasNoCode bool, loggingParent string) android.Path { 57 58 var args []string 59 if isLibrary { 60 args = append(args, "--library") 61 } else { 62 minSdkVersion, err := sdkContext.minSdkVersion().effectiveVersion(ctx) 63 if err != nil { 64 ctx.ModuleErrorf("invalid minSdkVersion: %s", err) 65 } 66 if minSdkVersion >= 23 { 67 args = append(args, fmt.Sprintf("--extract-native-libs=%v", !useEmbeddedNativeLibs)) 68 } else if useEmbeddedNativeLibs { 69 ctx.ModuleErrorf("module attempted to store uncompressed native libraries, but minSdkVersion=%d doesn't support it", 70 minSdkVersion) 71 } 72 } 73 74 if usesNonSdkApis { 75 args = append(args, "--uses-non-sdk-api") 76 } 77 78 if useEmbeddedDex { 79 args = append(args, "--use-embedded-dex") 80 } 81 82 for _, usesLib := range sdkLibraries { 83 if inList(usesLib, optionalUsesLibs) { 84 args = append(args, "--optional-uses-library", usesLib) 85 } else { 86 args = append(args, "--uses-library", usesLib) 87 } 88 } 89 90 if hasNoCode { 91 args = append(args, "--has-no-code") 92 } 93 94 if loggingParent != "" { 95 args = append(args, "--logging-parent", loggingParent) 96 } 97 var deps android.Paths 98 targetSdkVersion, err := sdkContext.targetSdkVersion().effectiveVersionString(ctx) 99 if err != nil { 100 ctx.ModuleErrorf("invalid targetSdkVersion: %s", err) 101 } 102 if UseApiFingerprint(ctx) { 103 targetSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String()) 104 deps = append(deps, ApiFingerprintPath(ctx)) 105 } 106 107 minSdkVersion, err := sdkContext.minSdkVersion().effectiveVersionString(ctx) 108 if err != nil { 109 ctx.ModuleErrorf("invalid minSdkVersion: %s", err) 110 } 111 if UseApiFingerprint(ctx) { 112 minSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String()) 113 deps = append(deps, ApiFingerprintPath(ctx)) 114 } 115 116 fixedManifest := android.PathForModuleOut(ctx, "manifest_fixer", "AndroidManifest.xml") 117 if err != nil { 118 ctx.ModuleErrorf("invalid minSdkVersion: %s", err) 119 } 120 ctx.Build(pctx, android.BuildParams{ 121 Rule: manifestFixerRule, 122 Description: "fix manifest", 123 Input: manifest, 124 Implicits: deps, 125 Output: fixedManifest, 126 Args: map[string]string{ 127 "minSdkVersion": minSdkVersion, 128 "targetSdkVersion": targetSdkVersion, 129 "args": strings.Join(args, " "), 130 }, 131 }) 132 133 return fixedManifest.WithoutRel() 134} 135 136func manifestMerger(ctx android.ModuleContext, manifest android.Path, staticLibManifests android.Paths, 137 isLibrary bool) android.Path { 138 139 var args string 140 if !isLibrary { 141 // Follow Gradle's behavior, only pass --remove-tools-declarations when merging app manifests. 142 args = "--remove-tools-declarations" 143 } 144 145 mergedManifest := android.PathForModuleOut(ctx, "manifest_merger", "AndroidManifest.xml") 146 ctx.Build(pctx, android.BuildParams{ 147 Rule: manifestMergerRule, 148 Description: "merge manifest", 149 Input: manifest, 150 Implicits: staticLibManifests, 151 Output: mergedManifest, 152 Args: map[string]string{ 153 "libs": android.JoinWithPrefix(staticLibManifests.Strings(), "--libs "), 154 "args": args, 155 }, 156 }) 157 158 return mergedManifest.WithoutRel() 159} 160