blob: de1bcf5060a4e7d9973971c634f54ed4b3a4d520 [file] [log] [blame]
Colin Crossf24a22a2019-01-31 14:12:44 -08001// Copyright 2019 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 "android/soong/android"
19)
20
21func init() {
22 android.RegisterSingletonType("hiddenapi", hiddenAPISingletonFactory)
23}
24
25type hiddenAPISingletonPathsStruct struct {
26 stubFlags android.OutputPath
27 flags android.OutputPath
28 metadata android.OutputPath
29}
30
31var hiddenAPISingletonPathsKey = android.NewOnceKey("hiddenAPISingletonPathsKey")
32
33// hiddenAPISingletonPaths creates all the paths for singleton files the first time it is called, which may be
34// from a ModuleContext that needs to reference a file that will be created by a singleton rule that hasn't
35// yet been created.
36func hiddenAPISingletonPaths(ctx android.PathContext) hiddenAPISingletonPathsStruct {
37 return ctx.Config().Once(hiddenAPISingletonPathsKey, func() interface{} {
38 return hiddenAPISingletonPathsStruct{
39 stubFlags: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-stub-flags.txt"),
40 flags: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-flags.csv"),
41 metadata: android.PathForOutput(ctx, "hiddenapi", "hiddenapi-greylist.csv"),
42 }
43 }).(hiddenAPISingletonPathsStruct)
44}
45
Colin Crossf24a22a2019-01-31 14:12:44 -080046func hiddenAPISingletonFactory() android.Singleton {
47 return hiddenAPISingleton{}
48}
49
50type hiddenAPISingleton struct{}
51
52// hiddenAPI singleton rules
53func (hiddenAPISingleton) GenerateBuildActions(ctx android.SingletonContext) {
54 // Don't run any hiddenapi rules if UNSAFE_DISABLE_HIDDENAPI_FLAGS=true
55 if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
56 return
57 }
58
59 stubFlagsRule(ctx)
60
61 // These rules depend on files located in frameworks/base, skip them if running in a tree that doesn't have them.
62 if ctx.Config().FrameworksBaseDirExists(ctx) {
63 flagsRule(ctx)
64 metadataRule(ctx)
65 } else {
66 emptyFlagsRule(ctx)
67 }
68}
69
70// stubFlagsRule creates the rule to build hiddenapi-stub-flags.txt out of dex jars from stub modules and boot image
71// modules.
72func stubFlagsRule(ctx android.SingletonContext) {
73 // Public API stubs
74 publicStubModules := []string{
75 "android_stubs_current",
76 "android.test.base.stubs",
77 }
78
79 // System API stubs
80 systemStubModules := []string{
81 "android_system_stubs_current",
82 }
83
84 // Test API stubs
85 testStubModules := []string{
86 "android_test_stubs_current",
87 }
88
89 // Core Platform API stubs
90 corePlatformStubModules := []string{
91 "core.platform.api.stubs",
92 }
93
94 // Allow products to define their own stubs for custom product jars that apps can use.
95 publicStubModules = append(publicStubModules, ctx.Config().ProductHiddenAPIStubs()...)
96 systemStubModules = append(systemStubModules, ctx.Config().ProductHiddenAPIStubsSystem()...)
97 testStubModules = append(testStubModules, ctx.Config().ProductHiddenAPIStubsTest()...)
98
99 publicStubPaths := make(android.Paths, len(publicStubModules))
100 systemStubPaths := make(android.Paths, len(systemStubModules))
101 testStubPaths := make(android.Paths, len(testStubModules))
102 corePlatformStubPaths := make(android.Paths, len(corePlatformStubModules))
103
104 moduleListToPathList := map[*[]string]android.Paths{
105 &publicStubModules: publicStubPaths,
106 &systemStubModules: systemStubPaths,
107 &testStubModules: testStubPaths,
108 &corePlatformStubModules: corePlatformStubPaths,
109 }
110
111 var bootDexJars android.Paths
112
113 ctx.VisitAllModules(func(module android.Module) {
114 // Collect dex jar paths for the modules listed above.
115 if j, ok := module.(Dependency); ok {
116 name := ctx.ModuleName(module)
117 for moduleList, pathList := range moduleListToPathList {
118 if i := android.IndexList(name, *moduleList); i != -1 {
119 pathList[i] = j.DexJar()
120 }
121 }
122 }
123
124 // Collect dex jar paths for modules that had hiddenapi encode called on them.
125 if h, ok := module.(hiddenAPIIntf); ok {
126 if jar := h.bootDexJar(); jar != nil {
127 bootDexJars = append(bootDexJars, jar)
128 }
129 }
130 })
131
132 var missingDeps []string
133 // Ensure all modules were converted to paths
134 for moduleList, pathList := range moduleListToPathList {
135 for i := range pathList {
136 if pathList[i] == nil {
137 if ctx.Config().AllowMissingDependencies() {
138 missingDeps = append(missingDeps, (*moduleList)[i])
139 pathList[i] = android.PathForOutput(ctx, "missing")
140 } else {
141 ctx.Errorf("failed to find dex jar path for module %q",
142 (*moduleList)[i])
143 }
144 }
145 }
146 }
147
148 // Singleton rule which applies hiddenapi on all boot class path dex files.
149 rule := android.NewRuleBuilder()
150
151 outputPath := hiddenAPISingletonPaths(ctx).stubFlags
152 tempPath := android.PathForOutput(ctx, outputPath.Rel()+".tmp")
153
154 rule.MissingDeps(missingDeps)
155
156 rule.Command().
157 Tool(pctx.HostBinToolPath(ctx, "hiddenapi").String()).
158 Text("list").
159 FlagForEachInput("--boot-dex=", bootDexJars.Strings()).
160 FlagWithInputList("--public-stub-classpath=", publicStubPaths.Strings(), ":").
161 FlagWithInputList("--public-stub-classpath=", systemStubPaths.Strings(), ":").
162 FlagWithInputList("--public-stub-classpath=", testStubPaths.Strings(), ":").
163 FlagWithInputList("--core-platform-stub-classpath=", corePlatformStubPaths.Strings(), ":").
164 FlagWithOutput("--out-api-flags=", tempPath.String())
165
166 commitChangeForRestat(rule, tempPath, outputPath)
167
168 rule.Build(pctx, ctx, "hiddenAPIStubFlagsFile", "hiddenapi stub flags")
169}
170
171// flagsRule creates a rule to build hiddenapi-flags.csv out of flags.csv files generated for boot image modules and
172// the greylists.
173func flagsRule(ctx android.SingletonContext) {
174 var flagsCSV android.Paths
175
176 var greylistIgnoreConflicts android.Path
177
178 ctx.VisitAllModules(func(module android.Module) {
179 if h, ok := module.(hiddenAPIIntf); ok {
180 if csv := h.flagsCSV(); csv != nil {
181 flagsCSV = append(flagsCSV, csv)
182 }
183 } else if ds, ok := module.(*Droidstubs); ok && ctx.ModuleName(module) == "hiddenapi-lists-docs" {
184 greylistIgnoreConflicts = ds.removedDexApiFile
185 }
186 })
187
188 if greylistIgnoreConflicts == nil {
189 ctx.Errorf("failed to find removed_dex_api_filename from hiddenapi-lists-docs module")
190 return
191 }
192
193 rule := android.NewRuleBuilder()
194
195 outputPath := hiddenAPISingletonPaths(ctx).flags
196 tempPath := android.PathForOutput(ctx, outputPath.Rel()+".tmp")
197
198 stubFlags := hiddenAPISingletonPaths(ctx).stubFlags
199
200 rule.Command().
201 Tool(android.PathForSource(ctx, "frameworks/base/tools/hiddenapi/generate_hiddenapi_lists.py").String()).
202 FlagWithInput("--csv ", stubFlags.String()).
203 Inputs(flagsCSV.Strings()).
204 FlagWithInput("--greylist ",
205 android.PathForSource(ctx, "frameworks/base/config/hiddenapi-greylist.txt").String()).
206 FlagWithInput("--greylist-ignore-conflicts ",
207 greylistIgnoreConflicts.String()).
208 FlagWithInput("--greylist-max-p ",
209 android.PathForSource(ctx, "frameworks/base/config/hiddenapi-greylist-max-p.txt").String()).
210 FlagWithInput("--greylist-max-o-ignore-conflicts ",
211 android.PathForSource(ctx, "frameworks/base/config/hiddenapi-greylist-max-o.txt").String()).
212 FlagWithInput("--blacklist ",
213 android.PathForSource(ctx, "frameworks/base/config/hiddenapi-force-blacklist.txt").String()).
214 FlagWithOutput("--output ", tempPath.String())
215
216 commitChangeForRestat(rule, tempPath, outputPath)
217
218 rule.Build(pctx, ctx, "hiddenAPIFlagsFile", "hiddenapi flags")
219}
220
221// emptyFlagsRule creates a rule to build an empty hiddenapi-flags.csv, which is needed by master-art-host builds that
222// have a partial manifest without frameworks/base but still need to build a boot image.
223func emptyFlagsRule(ctx android.SingletonContext) {
224 rule := android.NewRuleBuilder()
225
226 outputPath := hiddenAPISingletonPaths(ctx).flags
227
228 rule.Command().Text("rm").Flag("-f").Output(outputPath.String())
229 rule.Command().Text("touch").Output(outputPath.String())
230
231 rule.Build(pctx, ctx, "emptyHiddenAPIFlagsFile", "empty hiddenapi flags")
232}
233
234// metadataRule creates a rule to build hiddenapi-greylist.csv out of the metadata.csv files generated for boot image
235// modules.
236func metadataRule(ctx android.SingletonContext) {
237 var metadataCSV android.Paths
238
239 ctx.VisitAllModules(func(module android.Module) {
240 if h, ok := module.(hiddenAPIIntf); ok {
241 if csv := h.metadataCSV(); csv != nil {
242 metadataCSV = append(metadataCSV, csv)
243 }
244 }
245 })
246
247 rule := android.NewRuleBuilder()
248
249 outputPath := hiddenAPISingletonPaths(ctx).metadata
250
251 rule.Command().
252 Tool(android.PathForSource(ctx, "frameworks/base/tools/hiddenapi/merge_csv.py").String()).
253 Inputs(metadataCSV.Strings()).
254 Text(">").
255 Output(outputPath.String())
256
257 rule.Build(pctx, ctx, "hiddenAPIGreylistMetadataFile", "hiddenapi greylist metadata")
258}
259
260// commitChangeForRestat adds a command to a rule that updates outputPath from tempPath if they are different. It
261// also marks the rule as restat and marks the tempPath as a temporary file that should not be considered an output of
262// the rule.
263func commitChangeForRestat(rule *android.RuleBuilder, tempPath, outputPath android.WritablePath) {
264 rule.Restat()
265 rule.Temporary(tempPath.String())
266 rule.Command().
267 Text("(").
268 Text("if").
269 Text("cmp -s").Input(tempPath.String()).Output(outputPath.String()).Text(";").
270 Text("then").
271 Text("rm").Input(tempPath.String()).Text(";").
272 Text("else").
273 Text("mv").Input(tempPath.String()).Output(outputPath.String()).Text(";").
274 Text("fi").
275 Text(")")
276}
277
278func init() {
279 android.RegisterMakeVarsProvider(pctx, hiddenAPIMakeVars)
280}
281
282// Export paths to Make. INTERNAL_PLATFORM_HIDDENAPI_FLAGS is used by Make rules in art/ and cts/.
283// Both paths are used to call dist-for-goals.
284func hiddenAPIMakeVars(ctx android.MakeVarsContext) {
285 if !ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
Colin Cross697412f2019-02-07 14:27:35 -0800286 singletonPaths := hiddenAPISingletonPaths(ctx)
Colin Crossf24a22a2019-01-31 14:12:44 -0800287 ctx.Strict("INTERNAL_PLATFORM_HIDDENAPI_FLAGS", singletonPaths.flags.String())
288 ctx.Strict("INTERNAL_PLATFORM_HIDDENAPI_GREYLIST_METADATA", singletonPaths.metadata.String())
289 }
290}