hiddenapi_modular.go 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452
  1. // Copyright (C) 2021 The Android Open Source Project
  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. package java
  15. import (
  16. "fmt"
  17. "strings"
  18. "android/soong/android"
  19. "github.com/google/blueprint"
  20. )
  21. // Contains support for processing hiddenAPI in a modular fashion.
  22. // HiddenAPIScope encapsulates all the information that the hidden API processing needs about API
  23. // scopes, i.e. what is called android.SdkKind and apiScope. It does not just use those as they do
  24. // not provide the information needed by hidden API processing.
  25. type HiddenAPIScope struct {
  26. // The name of the scope, used for debug purposes.
  27. name string
  28. // The corresponding android.SdkKind, used for retrieving paths from java_sdk_library* modules.
  29. sdkKind android.SdkKind
  30. // The option needed to passed to "hiddenapi list".
  31. hiddenAPIListOption string
  32. // The name sof the source stub library modules that contain the API provided by the platform,
  33. // i.e. by modules that are not in an APEX.
  34. nonUpdatableSourceModule string
  35. // The names of the prebuilt stub library modules that contain the API provided by the platform,
  36. // i.e. by modules that are not in an APEX.
  37. nonUpdatablePrebuiltModule string
  38. }
  39. // initHiddenAPIScope initializes the scope.
  40. func initHiddenAPIScope(apiScope *HiddenAPIScope) *HiddenAPIScope {
  41. sdkKind := apiScope.sdkKind
  42. // The platform does not provide a core platform API.
  43. if sdkKind != android.SdkCorePlatform {
  44. kindAsString := sdkKind.String()
  45. var insert string
  46. if sdkKind == android.SdkPublic {
  47. insert = ""
  48. } else {
  49. insert = "." + strings.ReplaceAll(kindAsString, "-", "_")
  50. }
  51. nonUpdatableModule := "android-non-updatable"
  52. // Construct the name of the android-non-updatable source module for this scope.
  53. apiScope.nonUpdatableSourceModule = fmt.Sprintf("%s.stubs%s", nonUpdatableModule, insert)
  54. prebuiltModuleName := func(name string, kind string) string {
  55. return fmt.Sprintf("sdk_%s_current_%s", kind, name)
  56. }
  57. // Construct the name of the android-non-updatable prebuilt module for this scope.
  58. apiScope.nonUpdatablePrebuiltModule = prebuiltModuleName(nonUpdatableModule, kindAsString)
  59. }
  60. return apiScope
  61. }
  62. // android-non-updatable takes the name of a module and returns a possibly scope specific name of
  63. // the module.
  64. func (l *HiddenAPIScope) scopeSpecificStubModule(ctx android.BaseModuleContext, name string) string {
  65. // The android-non-updatable is not a java_sdk_library but there are separate stub libraries for
  66. // each scope.
  67. // TODO(b/192067200): Remove special handling of android-non-updatable.
  68. if name == "android-non-updatable" {
  69. if ctx.Config().AlwaysUsePrebuiltSdks() {
  70. return l.nonUpdatablePrebuiltModule
  71. } else {
  72. return l.nonUpdatableSourceModule
  73. }
  74. } else {
  75. // Assume that the module is either a java_sdk_library (or equivalent) and so will provide
  76. // separate stub jars for each scope or is a java_library (or equivalent) in which case it will
  77. // have the same stub jar for each scope.
  78. return name
  79. }
  80. }
  81. func (l *HiddenAPIScope) String() string {
  82. return fmt.Sprintf("HiddenAPIScope{%s}", l.name)
  83. }
  84. var (
  85. PublicHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
  86. name: "public",
  87. sdkKind: android.SdkPublic,
  88. hiddenAPIListOption: "--public-stub-classpath",
  89. })
  90. SystemHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
  91. name: "system",
  92. sdkKind: android.SdkSystem,
  93. hiddenAPIListOption: "--system-stub-classpath",
  94. })
  95. TestHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
  96. name: "test",
  97. sdkKind: android.SdkTest,
  98. hiddenAPIListOption: "--test-stub-classpath",
  99. })
  100. ModuleLibHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
  101. name: "module-lib",
  102. sdkKind: android.SdkModule,
  103. })
  104. CorePlatformHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
  105. name: "core-platform",
  106. sdkKind: android.SdkCorePlatform,
  107. hiddenAPIListOption: "--core-platform-stub-classpath",
  108. })
  109. // hiddenAPIRelevantSdkKinds lists all the android.SdkKind instances that are needed by the hidden
  110. // API processing.
  111. //
  112. // These are roughly in order from narrowest API surface to widest. Widest means the API stubs
  113. // with the biggest API surface, e.g. test is wider than system is wider than public.
  114. //
  115. // Core platform is considered wider than system/module-lib because those modules that provide
  116. // core platform APIs either do not have any system/module-lib APIs at all, or if they do it is
  117. // because the core platform API is being converted to system/module-lib APIs. In either case the
  118. // system/module-lib APIs are subsets of the core platform API.
  119. //
  120. // This is not strictly in order from narrowest to widest as the Test API is wider than system but
  121. // is neither wider or narrower than the module-lib or core platform APIs. However, this works
  122. // well enough at the moment.
  123. // TODO(b/191644675): Correctly reflect the sub/superset relationships between APIs.
  124. hiddenAPIScopes = []*HiddenAPIScope{
  125. PublicHiddenAPIScope,
  126. SystemHiddenAPIScope,
  127. TestHiddenAPIScope,
  128. ModuleLibHiddenAPIScope,
  129. CorePlatformHiddenAPIScope,
  130. }
  131. // The HiddenAPIScope instances that are supported by a java_sdk_library.
  132. //
  133. // CorePlatformHiddenAPIScope is not used as the java_sdk_library does not have special support
  134. // for core_platform API, instead it is implemented as a customized form of PublicHiddenAPIScope.
  135. hiddenAPISdkLibrarySupportedScopes = []*HiddenAPIScope{
  136. PublicHiddenAPIScope,
  137. SystemHiddenAPIScope,
  138. TestHiddenAPIScope,
  139. ModuleLibHiddenAPIScope,
  140. }
  141. // The HiddenAPIScope instances that are supported by the `hiddenapi list`.
  142. hiddenAPIFlagScopes = []*HiddenAPIScope{
  143. PublicHiddenAPIScope,
  144. SystemHiddenAPIScope,
  145. TestHiddenAPIScope,
  146. CorePlatformHiddenAPIScope,
  147. }
  148. )
  149. type hiddenAPIStubsDependencyTag struct {
  150. blueprint.BaseDependencyTag
  151. // The api scope for which this dependency was added.
  152. apiScope *HiddenAPIScope
  153. // Indicates that the dependency is not for an API provided by the current bootclasspath fragment
  154. // but is an additional API provided by a module that is not part of the current bootclasspath
  155. // fragment.
  156. fromAdditionalDependency bool
  157. }
  158. func (b hiddenAPIStubsDependencyTag) ExcludeFromApexContents() {
  159. }
  160. func (b hiddenAPIStubsDependencyTag) ReplaceSourceWithPrebuilt() bool {
  161. return false
  162. }
  163. func (b hiddenAPIStubsDependencyTag) SdkMemberType(child android.Module) android.SdkMemberType {
  164. // Do not add additional dependencies to the sdk.
  165. if b.fromAdditionalDependency {
  166. return nil
  167. }
  168. // If the module is a java_sdk_library then treat it as if it was specific in the java_sdk_libs
  169. // property, otherwise treat if it was specified in the java_header_libs property.
  170. if javaSdkLibrarySdkMemberType.IsInstance(child) {
  171. return javaSdkLibrarySdkMemberType
  172. }
  173. return javaHeaderLibsSdkMemberType
  174. }
  175. func (b hiddenAPIStubsDependencyTag) ExportMember() bool {
  176. // Export the module added via this dependency tag from the sdk.
  177. return true
  178. }
  179. // Avoid having to make stubs content explicitly visible to dependent modules.
  180. //
  181. // This is a temporary workaround to make it easier to migrate to bootclasspath_fragment modules
  182. // with proper dependencies.
  183. // TODO(b/177892522): Remove this and add needed visibility.
  184. func (b hiddenAPIStubsDependencyTag) ExcludeFromVisibilityEnforcement() {
  185. }
  186. var _ android.ExcludeFromVisibilityEnforcementTag = hiddenAPIStubsDependencyTag{}
  187. var _ android.ReplaceSourceWithPrebuilt = hiddenAPIStubsDependencyTag{}
  188. var _ android.ExcludeFromApexContentsTag = hiddenAPIStubsDependencyTag{}
  189. var _ android.SdkMemberDependencyTag = hiddenAPIStubsDependencyTag{}
  190. // hiddenAPIComputeMonolithicStubLibModules computes the set of module names that provide stubs
  191. // needed to produce the hidden API monolithic stub flags file.
  192. func hiddenAPIComputeMonolithicStubLibModules(config android.Config) map[*HiddenAPIScope][]string {
  193. var publicStubModules []string
  194. var systemStubModules []string
  195. var testStubModules []string
  196. var corePlatformStubModules []string
  197. if config.AlwaysUsePrebuiltSdks() {
  198. // Build configuration mandates using prebuilt stub modules
  199. publicStubModules = append(publicStubModules, "sdk_public_current_android")
  200. systemStubModules = append(systemStubModules, "sdk_system_current_android")
  201. testStubModules = append(testStubModules, "sdk_test_current_android")
  202. } else {
  203. // Use stub modules built from source
  204. publicStubModules = append(publicStubModules, android.SdkPublic.JavaLibraryName(config))
  205. systemStubModules = append(systemStubModules, android.SdkSystem.JavaLibraryName(config))
  206. testStubModules = append(testStubModules, android.SdkTest.JavaLibraryName(config))
  207. }
  208. // We do not have prebuilts of the core platform api yet
  209. corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs")
  210. // Allow products to define their own stubs for custom product jars that apps can use.
  211. publicStubModules = append(publicStubModules, config.ProductHiddenAPIStubs()...)
  212. systemStubModules = append(systemStubModules, config.ProductHiddenAPIStubsSystem()...)
  213. testStubModules = append(testStubModules, config.ProductHiddenAPIStubsTest()...)
  214. if config.IsEnvTrue("EMMA_INSTRUMENT") {
  215. // Add jacoco-stubs to public, system and test. It doesn't make any real difference as public
  216. // allows everyone access but it is needed to ensure consistent flags between the
  217. // bootclasspath fragment generated flags and the platform_bootclasspath generated flags.
  218. publicStubModules = append(publicStubModules, "jacoco-stubs")
  219. systemStubModules = append(systemStubModules, "jacoco-stubs")
  220. testStubModules = append(testStubModules, "jacoco-stubs")
  221. }
  222. m := map[*HiddenAPIScope][]string{}
  223. m[PublicHiddenAPIScope] = publicStubModules
  224. m[SystemHiddenAPIScope] = systemStubModules
  225. m[TestHiddenAPIScope] = testStubModules
  226. m[CorePlatformHiddenAPIScope] = corePlatformStubModules
  227. return m
  228. }
  229. // hiddenAPIAddStubLibDependencies adds dependencies onto the modules specified in
  230. // apiScopeToStubLibModules. It adds them in a well known order and uses a HiddenAPIScope specific
  231. // tag to identify the source of the dependency.
  232. func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, apiScopeToStubLibModules map[*HiddenAPIScope][]string) {
  233. module := ctx.Module()
  234. for _, apiScope := range hiddenAPIScopes {
  235. modules := apiScopeToStubLibModules[apiScope]
  236. ctx.AddDependency(module, hiddenAPIStubsDependencyTag{apiScope: apiScope}, modules...)
  237. }
  238. }
  239. // hiddenAPIRetrieveDexJarBuildPath retrieves the DexJarBuildPath from the specified module, if
  240. // available, or reports an error.
  241. func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module, kind android.SdkKind) android.Path {
  242. var dexJar OptionalDexJarPath
  243. if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
  244. dexJar = sdkLibrary.SdkApiStubDexJar(ctx, kind)
  245. } else if j, ok := module.(UsesLibraryDependency); ok {
  246. dexJar = j.DexJarBuildPath()
  247. } else {
  248. ctx.ModuleErrorf("dependency %s of module type %s does not support providing a dex jar", module, ctx.OtherModuleType(module))
  249. return nil
  250. }
  251. if !dexJar.Valid() {
  252. ctx.ModuleErrorf("dependency %s does not provide a dex jar: %s", module, dexJar.InvalidReason())
  253. return nil
  254. }
  255. return dexJar.Path()
  256. }
  257. // HIDDENAPI_STUB_FLAGS_IMPL_FLAGS is the set of flags that identify implementation only signatures,
  258. // i.e. those signatures that are not part of any API (including the hidden API).
  259. var HIDDENAPI_STUB_FLAGS_IMPL_FLAGS = []string{}
  260. var HIDDENAPI_FLAGS_CSV_IMPL_FLAGS = []string{"blocked"}
  261. // buildRuleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
  262. //
  263. // The rule is initialized but not built so that the caller can modify it and select an appropriate
  264. // name.
  265. func buildRuleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, name, desc string, outputPath android.WritablePath, bootDexJars android.Paths, input HiddenAPIFlagInput, stubFlagSubsets SignatureCsvSubsets) {
  266. // Singleton rule which applies hiddenapi on all boot class path dex files.
  267. rule := android.NewRuleBuilder(pctx, ctx)
  268. tempPath := tempPathForRestat(ctx, outputPath)
  269. // Find the widest API stubs provided by the fragments on which this depends, if any.
  270. dependencyStubDexJars := input.DependencyStubDexJarsByScope.StubDexJarsForWidestAPIScope()
  271. // Add widest API stubs from the additional dependencies of this, if any.
  272. dependencyStubDexJars = append(dependencyStubDexJars, input.AdditionalStubDexJarsByScope.StubDexJarsForWidestAPIScope()...)
  273. command := rule.Command().
  274. Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")).
  275. Text("list").
  276. FlagForEachInput("--dependency-stub-dex=", dependencyStubDexJars).
  277. FlagForEachInput("--boot-dex=", bootDexJars)
  278. // If no module stub flags paths are provided then this must be being called for a
  279. // bootclasspath_fragment and not the whole platform_bootclasspath.
  280. if stubFlagSubsets == nil {
  281. // This is being run on a fragment of the bootclasspath.
  282. command.Flag("--fragment")
  283. }
  284. // Iterate over the api scopes in a fixed order.
  285. for _, apiScope := range hiddenAPIFlagScopes {
  286. // Merge in the stub dex jar paths for this api scope from the fragments on which it depends.
  287. // They will be needed to resolve dependencies from this fragment's stubs to classes in the
  288. // other fragment's APIs.
  289. var paths android.Paths
  290. paths = append(paths, input.DependencyStubDexJarsByScope.StubDexJarsForScope(apiScope)...)
  291. paths = append(paths, input.AdditionalStubDexJarsByScope.StubDexJarsForScope(apiScope)...)
  292. paths = append(paths, input.StubDexJarsByScope.StubDexJarsForScope(apiScope)...)
  293. if len(paths) > 0 {
  294. option := apiScope.hiddenAPIListOption
  295. command.FlagWithInputList(option+"=", paths, ":")
  296. }
  297. }
  298. // Add the output path.
  299. command.FlagWithOutput("--out-api-flags=", tempPath)
  300. // If there are stub flag files that have been generated by fragments on which this depends then
  301. // use them to validate the stub flag file generated by the rules created by this method.
  302. if len(stubFlagSubsets) > 0 {
  303. validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, stubFlagSubsets,
  304. HIDDENAPI_STUB_FLAGS_IMPL_FLAGS)
  305. // Add the file that indicates that the file generated by this is valid.
  306. //
  307. // This will cause the validation rule above to be run any time that the output of this rule
  308. // changes but the validation will run in parallel with other rules that depend on this file.
  309. command.Validation(validFile)
  310. }
  311. commitChangeForRestat(rule, tempPath, outputPath)
  312. rule.Build(name, desc)
  313. }
  314. // HiddenAPIFlagFileProperties contains paths to the flag files that can be used to augment the
  315. // information obtained from annotations within the source code in order to create the complete set
  316. // of flags that should be applied to the dex implementation jars on the bootclasspath.
  317. //
  318. // Each property contains a list of paths. With the exception of the Unsupported_packages the paths
  319. // of each property reference a plain text file that contains a java signature per line. The flags
  320. // for each of those signatures will be updated in a property specific way.
  321. //
  322. // The Unsupported_packages property contains a list of paths, each of which is a plain text file
  323. // with one Java package per line. All members of all classes within that package (but not nested
  324. // packages) will be updated in a property specific way.
  325. type HiddenAPIFlagFileProperties struct {
  326. Hidden_api struct {
  327. // Marks each signature in the referenced files as being unsupported.
  328. Unsupported []string `android:"path"`
  329. // Marks each signature in the referenced files as being unsupported because it has been
  330. // removed. Any conflicts with other flags are ignored.
  331. Removed []string `android:"path"`
  332. // Marks each signature in the referenced files as being supported only for
  333. // targetSdkVersion <= R and low priority.
  334. Max_target_r_low_priority []string `android:"path"`
  335. // Marks each signature in the referenced files as being supported only for
  336. // targetSdkVersion <= Q.
  337. Max_target_q []string `android:"path"`
  338. // Marks each signature in the referenced files as being supported only for
  339. // targetSdkVersion <= P.
  340. Max_target_p []string `android:"path"`
  341. // Marks each signature in the referenced files as being supported only for
  342. // targetSdkVersion <= O
  343. // and low priority. Any conflicts with other flags are ignored.
  344. Max_target_o_low_priority []string `android:"path"`
  345. // Marks each signature in the referenced files as being blocked.
  346. Blocked []string `android:"path"`
  347. // Marks each signature in every package in the referenced files as being unsupported.
  348. Unsupported_packages []string `android:"path"`
  349. }
  350. }
  351. type hiddenAPIFlagFileCategory struct {
  352. // PropertyName is the name of the property for this category.
  353. PropertyName string
  354. // propertyValueReader retrieves the value of the property for this category from the set of
  355. // properties.
  356. propertyValueReader func(properties *HiddenAPIFlagFileProperties) []string
  357. // commandMutator adds the appropriate command line options for this category to the supplied
  358. // command
  359. commandMutator func(command *android.RuleBuilderCommand, path android.Path)
  360. }
  361. // The flag file category for removed members of the API.
  362. //
  363. // This is extracted from HiddenAPIFlagFileCategories as it is needed to add the dex signatures
  364. // list of removed API members that are generated automatically from the removed.txt files provided
  365. // by API stubs.
  366. var hiddenAPIRemovedFlagFileCategory = &hiddenAPIFlagFileCategory{
  367. // See HiddenAPIFlagFileProperties.Removed
  368. PropertyName: "removed",
  369. propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
  370. return properties.Hidden_api.Removed
  371. },
  372. commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
  373. command.FlagWithInput("--unsupported ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "removed")
  374. },
  375. }
  376. type hiddenAPIFlagFileCategories []*hiddenAPIFlagFileCategory
  377. func (c hiddenAPIFlagFileCategories) byProperty(name string) *hiddenAPIFlagFileCategory {
  378. for _, category := range c {
  379. if category.PropertyName == name {
  380. return category
  381. }
  382. }
  383. panic(fmt.Errorf("no category exists with property name %q in %v", name, c))
  384. }
  385. var HiddenAPIFlagFileCategories = hiddenAPIFlagFileCategories{
  386. // See HiddenAPIFlagFileProperties.Unsupported
  387. {
  388. PropertyName: "unsupported",
  389. propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
  390. return properties.Hidden_api.Unsupported
  391. },
  392. commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
  393. command.FlagWithInput("--unsupported ", path)
  394. },
  395. },
  396. hiddenAPIRemovedFlagFileCategory,
  397. // See HiddenAPIFlagFileProperties.Max_target_r_low_priority
  398. {
  399. PropertyName: "max_target_r_low_priority",
  400. propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
  401. return properties.Hidden_api.Max_target_r_low_priority
  402. },
  403. commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
  404. command.FlagWithInput("--max-target-r ", path).FlagWithArg("--tag ", "lo-prio")
  405. },
  406. },
  407. // See HiddenAPIFlagFileProperties.Max_target_q
  408. {
  409. PropertyName: "max_target_q",
  410. propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
  411. return properties.Hidden_api.Max_target_q
  412. },
  413. commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
  414. command.FlagWithInput("--max-target-q ", path)
  415. },
  416. },
  417. // See HiddenAPIFlagFileProperties.Max_target_p
  418. {
  419. PropertyName: "max_target_p",
  420. propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
  421. return properties.Hidden_api.Max_target_p
  422. },
  423. commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
  424. command.FlagWithInput("--max-target-p ", path)
  425. },
  426. },
  427. // See HiddenAPIFlagFileProperties.Max_target_o_low_priority
  428. {
  429. PropertyName: "max_target_o_low_priority",
  430. propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
  431. return properties.Hidden_api.Max_target_o_low_priority
  432. },
  433. commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
  434. command.FlagWithInput("--max-target-o ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "lo-prio")
  435. },
  436. },
  437. // See HiddenAPIFlagFileProperties.Blocked
  438. {
  439. PropertyName: "blocked",
  440. propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
  441. return properties.Hidden_api.Blocked
  442. },
  443. commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
  444. command.FlagWithInput("--blocked ", path)
  445. },
  446. },
  447. // See HiddenAPIFlagFileProperties.Unsupported_packages
  448. {
  449. PropertyName: "unsupported_packages",
  450. propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
  451. return properties.Hidden_api.Unsupported_packages
  452. },
  453. commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
  454. command.FlagWithInput("--unsupported ", path).Flag("--packages ")
  455. },
  456. },
  457. }
  458. // FlagFilesByCategory maps a hiddenAPIFlagFileCategory to the paths to the files in that category.
  459. type FlagFilesByCategory map[*hiddenAPIFlagFileCategory]android.Paths
  460. // append the supplied flags files to the corresponding category in this map.
  461. func (s FlagFilesByCategory) append(other FlagFilesByCategory) {
  462. for _, category := range HiddenAPIFlagFileCategories {
  463. s[category] = append(s[category], other[category]...)
  464. }
  465. }
  466. // sort the paths for each category in this map.
  467. func (s FlagFilesByCategory) sort() {
  468. for category, value := range s {
  469. s[category] = android.SortedUniquePaths(value)
  470. }
  471. }
  472. // HiddenAPIInfo contains information provided by the hidden API processing.
  473. //
  474. // That includes paths resolved from HiddenAPIFlagFileProperties and also generated by hidden API
  475. // processing.
  476. type HiddenAPIInfo struct {
  477. // FlagFilesByCategory maps from the flag file category to the paths containing information for
  478. // that category.
  479. FlagFilesByCategory FlagFilesByCategory
  480. // The paths to the stub dex jars for each of the *HiddenAPIScope in hiddenAPIScopes provided by
  481. // this fragment and the fragments on which this depends.
  482. TransitiveStubDexJarsByScope StubDexJarsByModule
  483. // The output from the hidden API processing needs to be made available to other modules.
  484. HiddenAPIFlagOutput
  485. }
  486. func newHiddenAPIInfo() *HiddenAPIInfo {
  487. info := HiddenAPIInfo{
  488. FlagFilesByCategory: FlagFilesByCategory{},
  489. TransitiveStubDexJarsByScope: StubDexJarsByModule{},
  490. }
  491. return &info
  492. }
  493. func (i *HiddenAPIInfo) mergeFromFragmentDeps(ctx android.ModuleContext, fragments []android.Module) {
  494. // Merge all the information from the fragments. The fragments form a DAG so it is possible that
  495. // this will introduce duplicates so they will be resolved after processing all the fragments.
  496. for _, fragment := range fragments {
  497. if ctx.OtherModuleHasProvider(fragment, HiddenAPIInfoProvider) {
  498. info := ctx.OtherModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
  499. i.TransitiveStubDexJarsByScope.addStubDexJarsByModule(info.TransitiveStubDexJarsByScope)
  500. }
  501. }
  502. }
  503. // StubFlagSubset returns a SignatureCsvSubset that contains a path to a filtered-stub-flags.csv
  504. // file and a path to a signature-patterns.csv file that defines a subset of the monolithic stub
  505. // flags file, i.e. out/soong/hiddenapi/hiddenapi-stub-flags.txt, against which it will be compared.
  506. func (i *HiddenAPIInfo) StubFlagSubset() SignatureCsvSubset {
  507. return SignatureCsvSubset{i.FilteredStubFlagsPath, i.SignaturePatternsPath}
  508. }
  509. // FlagSubset returns a SignatureCsvSubset that contains a path to a filtered-flags.csv file and a
  510. // path to a signature-patterns.csv file that defines a subset of the monolithic flags file, i.e.
  511. // out/soong/hiddenapi/hiddenapi-flags.csv, against which it will be compared.
  512. func (i *HiddenAPIInfo) FlagSubset() SignatureCsvSubset {
  513. return SignatureCsvSubset{i.FilteredFlagsPath, i.SignaturePatternsPath}
  514. }
  515. var HiddenAPIInfoProvider = blueprint.NewProvider(HiddenAPIInfo{})
  516. // HiddenAPIInfoForSdk contains information provided by the hidden API processing for use
  517. // by the sdk snapshot.
  518. //
  519. // That includes paths resolved from HiddenAPIFlagFileProperties and also generated by hidden API
  520. // processing.
  521. type HiddenAPIInfoForSdk struct {
  522. // FlagFilesByCategory maps from the flag file category to the paths containing information for
  523. // that category.
  524. FlagFilesByCategory FlagFilesByCategory
  525. // The output from the hidden API processing needs to be made available to other modules.
  526. HiddenAPIFlagOutput
  527. }
  528. // Provides hidden API info for the sdk snapshot.
  529. var HiddenAPIInfoForSdkProvider = blueprint.NewProvider(HiddenAPIInfoForSdk{})
  530. // ModuleStubDexJars contains the stub dex jars provided by a single module.
  531. //
  532. // It maps a *HiddenAPIScope to the path to stub dex jars appropriate for that scope. See
  533. // hiddenAPIScopes for a list of the acceptable *HiddenAPIScope values.
  534. type ModuleStubDexJars map[*HiddenAPIScope]android.Path
  535. // stubDexJarForWidestAPIScope returns the stub dex jars for the widest API scope provided by this
  536. // map.
  537. //
  538. // The relative width of APIs is determined by their order in hiddenAPIScopes.
  539. func (s ModuleStubDexJars) stubDexJarForWidestAPIScope() android.Path {
  540. for i := len(hiddenAPIScopes) - 1; i >= 0; i-- {
  541. apiScope := hiddenAPIScopes[i]
  542. if stubsForAPIScope, ok := s[apiScope]; ok {
  543. return stubsForAPIScope
  544. }
  545. }
  546. return nil
  547. }
  548. // StubDexJarsByModule contains the stub dex jars provided by a set of modules.
  549. //
  550. // It maps a module name to the path to the stub dex jars provided by that module.
  551. type StubDexJarsByModule map[string]ModuleStubDexJars
  552. // addStubDexJar adds a stub dex jar path provided by the specified module for the specified scope.
  553. func (s StubDexJarsByModule) addStubDexJar(ctx android.ModuleContext, module android.Module, scope *HiddenAPIScope, stubDexJar android.Path) {
  554. name := android.RemoveOptionalPrebuiltPrefix(module.Name())
  555. // Each named module provides one dex jar for each scope. However, in some cases different API
  556. // versions of a single classes are provided by separate modules. e.g. the core platform
  557. // version of java.lang.Object is provided by the legacy.art.module.platform.api module but the
  558. // public version is provided by the art.module.public.api module. In those cases it is necessary
  559. // to treat all those modules as they were the same name, otherwise it will result in multiple
  560. // definitions of a single class being passed to hidden API processing which will cause an error.
  561. if name == scope.nonUpdatablePrebuiltModule || name == scope.nonUpdatableSourceModule {
  562. // Treat all *android-non-updatable* modules as if they were part of an android-non-updatable
  563. // java_sdk_library.
  564. // TODO(b/192067200): Remove once android-non-updatable is a java_sdk_library or equivalent.
  565. name = "android-non-updatable"
  566. } else if name == "legacy.art.module.platform.api" {
  567. // Treat legacy.art.module.platform.api as if it was an API scope provided by the
  568. // art.module.public.api java_sdk_library which will be the case once the former has been
  569. // migrated to a module_lib API.
  570. name = "art.module.public.api"
  571. } else if name == "legacy.i18n.module.platform.api" {
  572. // Treat legacy.i18n.module.platform.api as if it was an API scope provided by the
  573. // i18n.module.public.api java_sdk_library which will be the case once the former has been
  574. // migrated to a module_lib API.
  575. name = "i18n.module.public.api"
  576. } else if name == "conscrypt.module.platform.api" {
  577. // Treat conscrypt.module.platform.api as if it was an API scope provided by the
  578. // conscrypt.module.public.api java_sdk_library which will be the case once the former has been
  579. // migrated to a module_lib API.
  580. name = "conscrypt.module.public.api"
  581. } else if d, ok := module.(SdkLibraryComponentDependency); ok {
  582. sdkLibraryName := d.SdkLibraryName()
  583. if sdkLibraryName != nil {
  584. // The module is a component of a java_sdk_library so use the name of the java_sdk_library.
  585. // e.g. if this module is `foo.system.stubs` and is part of the `foo` java_sdk_library then
  586. // use `foo` as the name.
  587. name = *sdkLibraryName
  588. }
  589. }
  590. stubDexJarsByScope := s[name]
  591. if stubDexJarsByScope == nil {
  592. stubDexJarsByScope = ModuleStubDexJars{}
  593. s[name] = stubDexJarsByScope
  594. }
  595. stubDexJarsByScope[scope] = stubDexJar
  596. }
  597. // addStubDexJarsByModule adds the stub dex jars in the supplied StubDexJarsByModule to this map.
  598. func (s StubDexJarsByModule) addStubDexJarsByModule(other StubDexJarsByModule) {
  599. for module, stubDexJarsByScope := range other {
  600. s[module] = stubDexJarsByScope
  601. }
  602. }
  603. // StubDexJarsForWidestAPIScope returns a list of stub dex jars containing the widest API scope
  604. // provided by each module.
  605. //
  606. // The relative width of APIs is determined by their order in hiddenAPIScopes.
  607. func (s StubDexJarsByModule) StubDexJarsForWidestAPIScope() android.Paths {
  608. stubDexJars := android.Paths{}
  609. modules := android.SortedKeys(s)
  610. for _, module := range modules {
  611. stubDexJarsByScope := s[module]
  612. stubDexJars = append(stubDexJars, stubDexJarsByScope.stubDexJarForWidestAPIScope())
  613. }
  614. return stubDexJars
  615. }
  616. // StubDexJarsForScope returns a list of stub dex jars containing the stub dex jars provided by each
  617. // module for the specified scope.
  618. //
  619. // If a module does not provide a stub dex jar for the supplied scope then it does not contribute to
  620. // the returned list.
  621. func (s StubDexJarsByModule) StubDexJarsForScope(scope *HiddenAPIScope) android.Paths {
  622. stubDexJars := android.Paths{}
  623. modules := android.SortedKeys(s)
  624. for _, module := range modules {
  625. stubDexJarsByScope := s[module]
  626. // Not every module will have the same set of
  627. if jars, ok := stubDexJarsByScope[scope]; ok {
  628. stubDexJars = append(stubDexJars, jars)
  629. }
  630. }
  631. return stubDexJars
  632. }
  633. type HiddenAPIPropertyInfo struct {
  634. // FlagFilesByCategory contains the flag files that override the initial flags that are derived
  635. // from the stub dex files.
  636. FlagFilesByCategory FlagFilesByCategory
  637. // See HiddenAPIFlagFileProperties.Package_prefixes
  638. PackagePrefixes []string
  639. // See HiddenAPIFlagFileProperties.Single_packages
  640. SinglePackages []string
  641. // See HiddenAPIFlagFileProperties.Split_packages
  642. SplitPackages []string
  643. }
  644. var hiddenAPIPropertyInfoProvider = blueprint.NewProvider(HiddenAPIPropertyInfo{})
  645. // newHiddenAPIPropertyInfo creates a new initialized HiddenAPIPropertyInfo struct.
  646. func newHiddenAPIPropertyInfo() HiddenAPIPropertyInfo {
  647. return HiddenAPIPropertyInfo{
  648. FlagFilesByCategory: FlagFilesByCategory{},
  649. }
  650. }
  651. // extractFlagFilesFromProperties extracts the paths to flag files that are specified in the
  652. // supplied properties and stores them in this struct.
  653. func (i *HiddenAPIPropertyInfo) extractFlagFilesFromProperties(ctx android.ModuleContext, p *HiddenAPIFlagFileProperties) {
  654. for _, category := range HiddenAPIFlagFileCategories {
  655. paths := android.PathsForModuleSrc(ctx, category.propertyValueReader(p))
  656. i.FlagFilesByCategory[category] = paths
  657. }
  658. }
  659. // extractPackageRulesFromProperties extracts the package rules that are specified in the supplied
  660. // properties and stores them in this struct.
  661. func (i *HiddenAPIPropertyInfo) extractPackageRulesFromProperties(p *HiddenAPIPackageProperties) {
  662. i.PackagePrefixes = p.Hidden_api.Package_prefixes
  663. i.SinglePackages = p.Hidden_api.Single_packages
  664. i.SplitPackages = p.Hidden_api.Split_packages
  665. }
  666. func (i *HiddenAPIPropertyInfo) gatherPropertyInfo(ctx android.ModuleContext, contents []android.Module) {
  667. for _, module := range contents {
  668. if ctx.OtherModuleHasProvider(module, hiddenAPIPropertyInfoProvider) {
  669. info := ctx.OtherModuleProvider(module, hiddenAPIPropertyInfoProvider).(HiddenAPIPropertyInfo)
  670. i.FlagFilesByCategory.append(info.FlagFilesByCategory)
  671. i.PackagePrefixes = append(i.PackagePrefixes, info.PackagePrefixes...)
  672. i.SinglePackages = append(i.SinglePackages, info.SinglePackages...)
  673. i.SplitPackages = append(i.SplitPackages, info.SplitPackages...)
  674. }
  675. }
  676. // Dedup and sort the information to ensure consistent builds.
  677. i.FlagFilesByCategory.sort()
  678. i.PackagePrefixes = android.SortedUniqueStrings(i.PackagePrefixes)
  679. i.SinglePackages = android.SortedUniqueStrings(i.SinglePackages)
  680. i.SplitPackages = android.SortedUniqueStrings(i.SplitPackages)
  681. }
  682. // HiddenAPIFlagInput encapsulates information obtained from a module and its dependencies that are
  683. // needed for hidden API flag generation.
  684. type HiddenAPIFlagInput struct {
  685. HiddenAPIPropertyInfo
  686. // StubDexJarsByScope contains the stub dex jars for different *HiddenAPIScope and which determine
  687. // the initial flags for each dex member.
  688. StubDexJarsByScope StubDexJarsByModule
  689. // DependencyStubDexJarsByScope contains the stub dex jars provided by the fragments on which this
  690. // depends. It is the result of merging HiddenAPIInfo.TransitiveStubDexJarsByScope from each
  691. // fragment on which this depends.
  692. DependencyStubDexJarsByScope StubDexJarsByModule
  693. // AdditionalStubDexJarsByScope contains stub dex jars provided by other modules in addition to
  694. // the ones that are obtained from fragments on which this depends.
  695. //
  696. // These are kept separate from stub dex jars in HiddenAPIFlagInput.DependencyStubDexJarsByScope
  697. // as there are not propagated transitively to other fragments that depend on this.
  698. AdditionalStubDexJarsByScope StubDexJarsByModule
  699. // RemovedTxtFiles is the list of removed.txt files provided by java_sdk_library modules that are
  700. // specified in the bootclasspath_fragment's stub_libs and contents properties.
  701. RemovedTxtFiles android.Paths
  702. }
  703. // newHiddenAPIFlagInput creates a new initialized HiddenAPIFlagInput struct.
  704. func newHiddenAPIFlagInput() HiddenAPIFlagInput {
  705. input := HiddenAPIFlagInput{
  706. HiddenAPIPropertyInfo: newHiddenAPIPropertyInfo(),
  707. StubDexJarsByScope: StubDexJarsByModule{},
  708. DependencyStubDexJarsByScope: StubDexJarsByModule{},
  709. AdditionalStubDexJarsByScope: StubDexJarsByModule{},
  710. }
  711. return input
  712. }
  713. // gatherStubLibInfo gathers information from the stub libs needed by hidden API processing from the
  714. // dependencies added in hiddenAPIAddStubLibDependencies.
  715. //
  716. // That includes paths to the stub dex jars as well as paths to the *removed.txt files.
  717. func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, contents []android.Module) {
  718. addFromModule := func(ctx android.ModuleContext, module android.Module, apiScope *HiddenAPIScope) {
  719. sdkKind := apiScope.sdkKind
  720. dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, sdkKind)
  721. if dexJar != nil {
  722. i.StubDexJarsByScope.addStubDexJar(ctx, module, apiScope, dexJar)
  723. }
  724. if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
  725. removedTxtFile := sdkLibrary.SdkRemovedTxtFile(ctx, sdkKind)
  726. i.RemovedTxtFiles = append(i.RemovedTxtFiles, removedTxtFile.AsPaths()...)
  727. }
  728. }
  729. // If the contents includes any java_sdk_library modules then add them to the stubs.
  730. for _, module := range contents {
  731. if _, ok := module.(SdkLibraryDependency); ok {
  732. // Add information for every possible API scope needed by hidden API.
  733. for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
  734. addFromModule(ctx, module, apiScope)
  735. }
  736. }
  737. }
  738. ctx.VisitDirectDeps(func(module android.Module) {
  739. tag := ctx.OtherModuleDependencyTag(module)
  740. if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
  741. apiScope := hiddenAPIStubsTag.apiScope
  742. if hiddenAPIStubsTag.fromAdditionalDependency {
  743. dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, apiScope.sdkKind)
  744. if dexJar != nil {
  745. i.AdditionalStubDexJarsByScope.addStubDexJar(ctx, module, apiScope, dexJar)
  746. }
  747. } else {
  748. addFromModule(ctx, module, apiScope)
  749. }
  750. }
  751. })
  752. // Normalize the paths, i.e. remove duplicates and sort.
  753. i.RemovedTxtFiles = android.SortedUniquePaths(i.RemovedTxtFiles)
  754. }
  755. func (i *HiddenAPIFlagInput) transitiveStubDexJarsByScope() StubDexJarsByModule {
  756. transitive := i.DependencyStubDexJarsByScope
  757. transitive.addStubDexJarsByModule(i.StubDexJarsByScope)
  758. return transitive
  759. }
  760. // HiddenAPIFlagOutput contains paths to output files from the hidden API flag generation for a
  761. // bootclasspath_fragment module.
  762. type HiddenAPIFlagOutput struct {
  763. // The path to the generated annotation-flags.csv file.
  764. AnnotationFlagsPath android.Path
  765. // The path to the generated metadata.csv file.
  766. MetadataPath android.Path
  767. // The path to the generated index.csv file.
  768. IndexPath android.Path
  769. // The path to the generated stub-flags.csv file.
  770. StubFlagsPath android.Path
  771. // The path to the generated all-flags.csv file.
  772. AllFlagsPath android.Path
  773. // The path to the generated signature-patterns.txt file which defines the subset of the
  774. // monolithic hidden API files provided in this.
  775. SignaturePatternsPath android.Path
  776. // The path to the generated filtered-stub-flags.csv file.
  777. FilteredStubFlagsPath android.Path
  778. // The path to the generated filtered-flags.csv file.
  779. FilteredFlagsPath android.Path
  780. }
  781. // bootDexJarByModule is a map from base module name (without prebuilt_ prefix) to the boot dex
  782. // path.
  783. type bootDexJarByModule map[string]android.Path
  784. // addPath adds the path for a module to the map.
  785. func (b bootDexJarByModule) addPath(module android.Module, path android.Path) {
  786. b[android.RemoveOptionalPrebuiltPrefix(module.Name())] = path
  787. }
  788. // bootDexJars returns the boot dex jar paths sorted by their keys.
  789. func (b bootDexJarByModule) bootDexJars() android.Paths {
  790. paths := android.Paths{}
  791. for _, k := range android.SortedKeys(b) {
  792. paths = append(paths, b[k])
  793. }
  794. return paths
  795. }
  796. // bootDexJarsWithoutCoverage returns the boot dex jar paths sorted by their keys without coverage
  797. // libraries if present.
  798. func (b bootDexJarByModule) bootDexJarsWithoutCoverage() android.Paths {
  799. paths := android.Paths{}
  800. for _, k := range android.SortedKeys(b) {
  801. if k == "jacocoagent" {
  802. continue
  803. }
  804. paths = append(paths, b[k])
  805. }
  806. return paths
  807. }
  808. // HiddenAPIOutput encapsulates the output from the hidden API processing.
  809. type HiddenAPIOutput struct {
  810. HiddenAPIFlagOutput
  811. // The map from base module name to the path to the encoded boot dex file.
  812. EncodedBootDexFilesByModule bootDexJarByModule
  813. }
  814. // pathForValidation creates a path of the same type as the supplied type but with a name of
  815. // <path>.valid.
  816. //
  817. // e.g. If path is an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv then this will return
  818. // an OutputPath for out/soong/hiddenapi/hiddenapi-flags.csv.valid
  819. func pathForValidation(ctx android.PathContext, path android.WritablePath) android.WritablePath {
  820. extWithoutLeadingDot := strings.TrimPrefix(path.Ext(), ".")
  821. return path.ReplaceExtension(ctx, extWithoutLeadingDot+".valid")
  822. }
  823. // buildRuleToGenerateHiddenApiFlags creates a rule to create the monolithic hidden API flags from
  824. // the flags from all the modules, the stub flags, augmented with some additional configuration
  825. // files.
  826. //
  827. // baseFlagsPath is the path to the flags file containing all the information from the stubs plus
  828. // an entry for every single member in the dex implementation jars of the individual modules. Every
  829. // signature in any of the other files MUST be included in this file.
  830. //
  831. // annotationFlags is the path to the annotation flags file generated from annotation information
  832. // in each module.
  833. //
  834. // hiddenAPIInfo is a struct containing paths to files that augment the information provided by
  835. // the annotationFlags.
  836. func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc string,
  837. outputPath android.WritablePath, baseFlagsPath android.Path, annotationFlagPaths android.Paths,
  838. flagFilesByCategory FlagFilesByCategory, flagSubsets SignatureCsvSubsets, generatedRemovedDexSignatures android.OptionalPath) {
  839. // Create the rule that will generate the flag files.
  840. tempPath := tempPathForRestat(ctx, outputPath)
  841. rule := android.NewRuleBuilder(pctx, ctx)
  842. command := rule.Command().
  843. BuiltTool("generate_hiddenapi_lists").
  844. FlagWithInput("--csv ", baseFlagsPath).
  845. Inputs(annotationFlagPaths).
  846. FlagWithOutput("--output ", tempPath)
  847. // Add the options for the different categories of flag files.
  848. for _, category := range HiddenAPIFlagFileCategories {
  849. paths := flagFilesByCategory[category]
  850. for _, path := range paths {
  851. category.commandMutator(command, path)
  852. }
  853. }
  854. // If available then pass the automatically generated file containing dex signatures of removed
  855. // API members to the rule so they can be marked as removed.
  856. if generatedRemovedDexSignatures.Valid() {
  857. hiddenAPIRemovedFlagFileCategory.commandMutator(command, generatedRemovedDexSignatures.Path())
  858. }
  859. commitChangeForRestat(rule, tempPath, outputPath)
  860. // If there are flag files that have been generated by fragments on which this depends then use
  861. // them to validate the flag file generated by the rules created by this method.
  862. if len(flagSubsets) > 0 {
  863. validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, flagSubsets,
  864. HIDDENAPI_FLAGS_CSV_IMPL_FLAGS)
  865. // Add the file that indicates that the file generated by this is valid.
  866. //
  867. // This will cause the validation rule above to be run any time that the output of this rule
  868. // changes but the validation will run in parallel with other rules that depend on this file.
  869. command.Validation(validFile)
  870. }
  871. rule.Build(name, desc)
  872. }
  873. // SignatureCsvSubset describes a subset of a monolithic flags file, i.e. either
  874. // out/soong/hiddenapi/hiddenapi-stub-flags.txt or out/soong/hiddenapi/hiddenapi-flags.csv
  875. type SignatureCsvSubset struct {
  876. // The path to the CSV file containing hidden API flags.
  877. //
  878. // It has the dex member signature as the first column, with flags, one per column, in the
  879. // subsequent columns.
  880. CsvFile android.Path
  881. // The path to the CSV file containing the signature patterns.
  882. //
  883. // It is a single column CSV file with the column containing a signature pattern.
  884. SignaturePatternsFile android.Path
  885. }
  886. type SignatureCsvSubsets []SignatureCsvSubset
  887. func (s SignatureCsvSubsets) RelativeToTop() []string {
  888. result := []string{}
  889. for _, subset := range s {
  890. result = append(result, fmt.Sprintf("%s:%s", subset.CsvFile.RelativeToTop(), subset.SignaturePatternsFile.RelativeToTop()))
  891. }
  892. return result
  893. }
  894. // buildRuleSignaturePatternsFile creates a rule to generate a file containing the set of signature
  895. // patterns that will select a subset of the monolithic flags.
  896. func buildRuleSignaturePatternsFile(
  897. ctx android.ModuleContext, flagsPath android.Path,
  898. splitPackages []string, packagePrefixes []string, singlePackages []string,
  899. suffix string) android.Path {
  900. hiddenApiSubDir := "modular-hiddenapi" + suffix
  901. patternsFile := android.PathForModuleOut(ctx, hiddenApiSubDir, "signature-patterns.csv")
  902. // Create a rule to validate the output from the following rule.
  903. rule := android.NewRuleBuilder(pctx, ctx)
  904. // Quote any * in the packages to avoid them being expanded by the shell.
  905. quotedSplitPackages := []string{}
  906. for _, pkg := range splitPackages {
  907. quotedSplitPackages = append(quotedSplitPackages, strings.ReplaceAll(pkg, "*", "\\*"))
  908. }
  909. rule.Command().
  910. BuiltTool("signature_patterns").
  911. FlagWithInput("--flags ", flagsPath).
  912. FlagForEachArg("--split-package ", quotedSplitPackages).
  913. FlagForEachArg("--package-prefix ", packagePrefixes).
  914. FlagForEachArg("--single-package ", singlePackages).
  915. FlagWithOutput("--output ", patternsFile)
  916. rule.Build("hiddenAPISignaturePatterns"+suffix, "hidden API signature patterns"+suffix)
  917. return patternsFile
  918. }
  919. // buildRuleRemoveSignaturesWithImplementationFlags creates a rule that will remove signatures from
  920. // the input flags file which have only the implementation flags, i.e. are not part of an API.
  921. //
  922. // The implementationFlags specifies the set of default flags that identifies the signature of a
  923. // private, implementation only, member. Signatures that match those flags are removed from the
  924. // flags as they are implementation only.
  925. //
  926. // This is used to remove implementation only signatures from the signature files that are persisted
  927. // in the sdk snapshot as the sdk snapshots should not include implementation details. The
  928. // signatures generated by this method will be compared by the buildRuleValidateOverlappingCsvFiles
  929. // method which treats any missing signatures as if they were implementation only signatures.
  930. func buildRuleRemoveSignaturesWithImplementationFlags(ctx android.BuilderContext,
  931. name string, desc string, inputPath android.Path, filteredPath android.WritablePath,
  932. implementationFlags []string) {
  933. rule := android.NewRuleBuilder(pctx, ctx)
  934. implementationFlagPattern := ""
  935. for _, implementationFlag := range implementationFlags {
  936. implementationFlagPattern = implementationFlagPattern + "," + implementationFlag
  937. }
  938. rule.Command().
  939. Text(`grep -vE "^[^,]+` + implementationFlagPattern + `$"`).Input(inputPath).
  940. Text(">").Output(filteredPath).
  941. // Grep's exit code depends on whether it finds anything. It is 0 (build success) when it finds
  942. // something and 1 (build failure) when it does not and 2 (when it encounters an error).
  943. // However, while it is unlikely it is not an error if this does not find any matches. The
  944. // following will only run if the grep does not find something and in that case it will treat
  945. // an exit code of 1 as success and anything else as failure.
  946. Text("|| test $? -eq 1")
  947. rule.Build(name, desc)
  948. }
  949. // buildRuleValidateOverlappingCsvFiles checks that the modular CSV files, i.e. the files generated
  950. // by the individual bootclasspath_fragment modules are subsets of the monolithic CSV file.
  951. //
  952. // The implementationFlags specifies the set of default flags that identifies the signature of a
  953. // private, implementation only, member. A signature which is present in a monolithic flags subset
  954. // defined by SignatureCsvSubset but which is not present in the flags file from the corresponding
  955. // module is assumed to be an implementation only member and so must have these flags.
  956. func buildRuleValidateOverlappingCsvFiles(ctx android.BuilderContext, name string, desc string,
  957. monolithicFilePath android.WritablePath, csvSubsets SignatureCsvSubsets,
  958. implementationFlags []string) android.WritablePath {
  959. // The file which is used to record that the flags file is valid.
  960. validFile := pathForValidation(ctx, monolithicFilePath)
  961. // Create a rule to validate the output from the following rule.
  962. rule := android.NewRuleBuilder(pctx, ctx)
  963. command := rule.Command().
  964. BuiltTool("verify_overlaps").
  965. FlagWithInput("--monolithic-flags ", monolithicFilePath)
  966. for _, subset := range csvSubsets {
  967. command.
  968. Flag("--module-flags ").
  969. Textf("%s:%s", subset.CsvFile, subset.SignaturePatternsFile).
  970. Implicit(subset.CsvFile).Implicit(subset.SignaturePatternsFile)
  971. }
  972. for _, implementationFlag := range implementationFlags {
  973. command.FlagWithArg("--implementation-flag ", implementationFlag)
  974. }
  975. // If validation passes then update the file that records that.
  976. command.Text("&& touch").Output(validFile)
  977. rule.Build(name+"Validation", desc+" validation")
  978. return validFile
  979. }
  980. // hiddenAPIFlagRulesForBootclasspathFragment will generate all the flags for a fragment of the
  981. // bootclasspath.
  982. //
  983. // It takes:
  984. // * Map from android.SdkKind to stub dex jar paths defining the API for that sdk kind.
  985. // * The list of modules that are the contents of the fragment.
  986. // * The additional manually curated flag files to use.
  987. //
  988. // It generates:
  989. // * stub-flags.csv
  990. // * annotation-flags.csv
  991. // * metadata.csv
  992. // * index.csv
  993. // * all-flags.csv
  994. func hiddenAPIFlagRulesForBootclasspathFragment(ctx android.ModuleContext, bootDexInfoByModule bootDexInfoByModule, contents []android.Module, input HiddenAPIFlagInput, suffix string) HiddenAPIFlagOutput {
  995. hiddenApiSubDir := "modular-hiddenapi" + suffix
  996. // Generate the stub-flags.csv.
  997. stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
  998. buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "modularHiddenAPIStubFlagsFile"+suffix, "modular hiddenapi stub flags", stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input, nil)
  999. // Extract the classes jars from the contents.
  1000. classesJars := extractClassesJarsFromModules(contents)
  1001. // Generate the set of flags from the annotations in the source code.
  1002. annotationFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "annotation-flags.csv")
  1003. buildRuleToGenerateAnnotationFlags(ctx, "modular hiddenapi annotation flags"+suffix, classesJars, stubFlagsCSV, annotationFlagsCSV)
  1004. // Generate the metadata from the annotations in the source code.
  1005. metadataCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "metadata.csv")
  1006. buildRuleToGenerateMetadata(ctx, "modular hiddenapi metadata"+suffix, classesJars, stubFlagsCSV, metadataCSV)
  1007. // Generate the index file from the CSV files in the classes jars.
  1008. indexCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "index.csv")
  1009. buildRuleToGenerateIndex(ctx, "modular hiddenapi index"+suffix, classesJars, indexCSV)
  1010. // Removed APIs need to be marked and in order to do that the hiddenAPIInfo needs to specify files
  1011. // containing dex signatures of all the removed APIs. In the monolithic files that is done by
  1012. // manually combining all the removed.txt files for each API and then converting them to dex
  1013. // signatures, see the combined-removed-dex module. This does that automatically by using the
  1014. // *removed.txt files retrieved from the java_sdk_library modules that are specified in the
  1015. // stub_libs and contents properties of a bootclasspath_fragment.
  1016. removedDexSignatures := buildRuleToGenerateRemovedDexSignatures(ctx, suffix, input.RemovedTxtFiles)
  1017. // Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex
  1018. // files.
  1019. allFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv")
  1020. buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags"+suffix, "modular hiddenapi all flags"+suffix, allFlagsCSV, stubFlagsCSV, android.Paths{annotationFlagsCSV}, input.FlagFilesByCategory, nil, removedDexSignatures)
  1021. // Generate the filtered-stub-flags.csv file which contains the filtered stub flags that will be
  1022. // compared against the monolithic stub flags.
  1023. filteredStubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "filtered-stub-flags.csv")
  1024. buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredStubFlags"+suffix,
  1025. "modular hiddenapi filtered stub flags"+suffix, stubFlagsCSV, filteredStubFlagsCSV,
  1026. HIDDENAPI_STUB_FLAGS_IMPL_FLAGS)
  1027. // Generate the filtered-flags.csv file which contains the filtered flags that will be compared
  1028. // against the monolithic flags.
  1029. filteredFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "filtered-flags.csv")
  1030. buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredFlags"+suffix,
  1031. "modular hiddenapi filtered flags"+suffix, allFlagsCSV, filteredFlagsCSV,
  1032. HIDDENAPI_FLAGS_CSV_IMPL_FLAGS)
  1033. // Store the paths in the info for use by other modules and sdk snapshot generation.
  1034. return HiddenAPIFlagOutput{
  1035. AnnotationFlagsPath: annotationFlagsCSV,
  1036. MetadataPath: metadataCSV,
  1037. IndexPath: indexCSV,
  1038. StubFlagsPath: stubFlagsCSV,
  1039. AllFlagsPath: allFlagsCSV,
  1040. FilteredStubFlagsPath: filteredStubFlagsCSV,
  1041. FilteredFlagsPath: filteredFlagsCSV,
  1042. }
  1043. }
  1044. // hiddenAPIEncodeRulesForBootclasspathFragment generates rules to encode hidden API flags into the
  1045. // dex jars in bootDexInfoByModule.
  1046. func hiddenAPIEncodeRulesForBootclasspathFragment(ctx android.ModuleContext, bootDexInfoByModule bootDexInfoByModule, allFlagsCSV android.Path) bootDexJarByModule {
  1047. // Encode the flags into the boot dex files.
  1048. encodedBootDexJarsByModule := bootDexJarByModule{}
  1049. outputDir := android.PathForModuleOut(ctx, "hiddenapi-modular/encoded").OutputPath
  1050. for _, name := range android.SortedKeys(bootDexInfoByModule) {
  1051. bootDexInfo := bootDexInfoByModule[name]
  1052. unencodedDex := bootDexInfo.path
  1053. encodedDex := hiddenAPIEncodeDex(ctx, unencodedDex, allFlagsCSV, bootDexInfo.uncompressDex, bootDexInfo.minSdkVersion, outputDir)
  1054. encodedBootDexJarsByModule[name] = encodedDex
  1055. }
  1056. return encodedBootDexJarsByModule
  1057. }
  1058. func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, suffix string, removedTxtFiles android.Paths) android.OptionalPath {
  1059. if len(removedTxtFiles) == 0 {
  1060. return android.OptionalPath{}
  1061. }
  1062. output := android.PathForModuleOut(ctx, "module-hiddenapi"+suffix, "removed-dex-signatures.txt")
  1063. rule := android.NewRuleBuilder(pctx, ctx)
  1064. rule.Command().
  1065. BuiltTool("metalava").
  1066. Flag("--no-banner").
  1067. Inputs(removedTxtFiles).
  1068. FlagWithOutput("--dex-api ", output)
  1069. rule.Build("modular-hiddenapi-removed-dex-signatures"+suffix, "modular hiddenapi removed dex signatures"+suffix)
  1070. return android.OptionalPathForPath(output)
  1071. }
  1072. // extractBootDexJarsFromModules extracts the boot dex jars from the supplied modules.
  1073. func extractBootDexJarsFromModules(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule {
  1074. bootDexJars := bootDexJarByModule{}
  1075. for _, module := range contents {
  1076. hiddenAPIModule := hiddenAPIModuleFromModule(ctx, module)
  1077. if hiddenAPIModule == nil {
  1078. continue
  1079. }
  1080. bootDexJar := retrieveBootDexJarFromHiddenAPIModule(ctx, hiddenAPIModule)
  1081. bootDexJars.addPath(module, bootDexJar)
  1082. }
  1083. return bootDexJars
  1084. }
  1085. func hiddenAPIModuleFromModule(ctx android.BaseModuleContext, module android.Module) hiddenAPIModule {
  1086. if hiddenAPIModule, ok := module.(hiddenAPIModule); ok {
  1087. return hiddenAPIModule
  1088. } else if _, ok := module.(*DexImport); ok {
  1089. // Ignore this for the purposes of hidden API processing
  1090. } else {
  1091. ctx.ModuleErrorf("module %s does not implement hiddenAPIModule", module)
  1092. }
  1093. return nil
  1094. }
  1095. // bootDexInfo encapsulates both the path and uncompressDex status retrieved from a hiddenAPIModule.
  1096. type bootDexInfo struct {
  1097. // The path to the dex jar that has not had hidden API flags encoded into it.
  1098. path android.Path
  1099. // Indicates whether the dex jar needs uncompressing before encoding.
  1100. uncompressDex bool
  1101. // The minimum sdk version that the dex jar will be used on.
  1102. minSdkVersion android.ApiLevel
  1103. }
  1104. // bootDexInfoByModule is a map from module name (as returned by module.Name()) to the boot dex
  1105. // path (as returned by hiddenAPIModule.bootDexJar()) and the uncompressDex flag.
  1106. type bootDexInfoByModule map[string]bootDexInfo
  1107. // bootDexJars returns the boot dex jar paths sorted by their keys.
  1108. func (b bootDexInfoByModule) bootDexJars() android.Paths {
  1109. paths := android.Paths{}
  1110. for _, m := range android.SortedKeys(b) {
  1111. paths = append(paths, b[m].path)
  1112. }
  1113. return paths
  1114. }
  1115. // extractBootDexInfoFromModules extracts the boot dex jar and uncompress dex state from
  1116. // each of the supplied modules which must implement hiddenAPIModule.
  1117. func extractBootDexInfoFromModules(ctx android.ModuleContext, contents []android.Module) bootDexInfoByModule {
  1118. bootDexJarsByModule := bootDexInfoByModule{}
  1119. for _, module := range contents {
  1120. hiddenAPIModule := module.(hiddenAPIModule)
  1121. bootDexJar := retrieveBootDexJarFromHiddenAPIModule(ctx, hiddenAPIModule)
  1122. bootDexJarsByModule[module.Name()] = bootDexInfo{
  1123. path: bootDexJar,
  1124. uncompressDex: *hiddenAPIModule.uncompressDex(),
  1125. minSdkVersion: hiddenAPIModule.MinSdkVersion(ctx),
  1126. }
  1127. }
  1128. return bootDexJarsByModule
  1129. }
  1130. // retrieveBootDexJarFromHiddenAPIModule retrieves the boot dex jar from the hiddenAPIModule.
  1131. //
  1132. // If the module does not provide a boot dex jar, i.e. the returned boot dex jar is unset or
  1133. // invalid, then create a fake path and either report an error immediately or defer reporting of the
  1134. // error until the path is actually used.
  1135. func retrieveBootDexJarFromHiddenAPIModule(ctx android.ModuleContext, module hiddenAPIModule) android.Path {
  1136. bootDexJar := module.bootDexJar()
  1137. if !bootDexJar.Valid() {
  1138. fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/boot-dex/%s.jar", module.Name()))
  1139. handleMissingDexBootFile(ctx, module, fake, bootDexJar.InvalidReason())
  1140. return fake
  1141. }
  1142. return bootDexJar.Path()
  1143. }
  1144. // extractClassesJarsFromModules extracts the class jars from the supplied modules.
  1145. func extractClassesJarsFromModules(contents []android.Module) android.Paths {
  1146. classesJars := android.Paths{}
  1147. for _, module := range contents {
  1148. classesJars = append(classesJars, retrieveClassesJarsFromModule(module)...)
  1149. }
  1150. return classesJars
  1151. }
  1152. // retrieveClassesJarsFromModule retrieves the classes jars from the supplied module.
  1153. func retrieveClassesJarsFromModule(module android.Module) android.Paths {
  1154. if hiddenAPIModule, ok := module.(hiddenAPIModule); ok {
  1155. return hiddenAPIModule.classesJars()
  1156. }
  1157. return nil
  1158. }
  1159. // deferReportingMissingBootDexJar returns true if a missing boot dex jar should not be reported by
  1160. // Soong but should instead only be reported in ninja if the file is actually built.
  1161. func deferReportingMissingBootDexJar(ctx android.ModuleContext, module android.Module) bool {
  1162. // Any missing dependency should be allowed.
  1163. if ctx.Config().AllowMissingDependencies() {
  1164. return true
  1165. }
  1166. // This is called for both platform_bootclasspath and bootclasspath_fragment modules.
  1167. //
  1168. // A bootclasspath_fragment module should only use the APEX variant of source or prebuilt modules.
  1169. // Ideally, a bootclasspath_fragment module should never have a platform variant created for it
  1170. // but unfortunately, due to b/187910671 it does.
  1171. //
  1172. // That causes issues when obtaining a boot dex jar for a prebuilt module as a prebuilt module
  1173. // used by a bootclasspath_fragment can only provide a boot dex jar when it is part of APEX, i.e.
  1174. // has an APEX variant not a platform variant.
  1175. //
  1176. // There are some other situations when a prebuilt module used by a bootclasspath_fragment cannot
  1177. // provide a boot dex jar:
  1178. // 1. If the bootclasspath_fragment is not exported by the prebuilt_apex/apex_set module then it
  1179. // does not have an APEX variant and only has a platform variant and neither do its content
  1180. // modules.
  1181. // 2. Some build configurations, e.g. setting TARGET_BUILD_USE_PREBUILT_SDKS causes all
  1182. // java_sdk_library_import modules to be treated as preferred and as many of them are not part
  1183. // of an apex they cannot provide a boot dex jar.
  1184. //
  1185. // The first case causes problems when the affected prebuilt modules are preferred but that is an
  1186. // invalid configuration and it is ok for it to fail as the work to enable that is not yet
  1187. // complete. The second case is used for building targets that do not use boot dex jars and so
  1188. // deferring error reporting to ninja is fine as the affected ninja targets should never be built.
  1189. // That is handled above.
  1190. //
  1191. // A platform_bootclasspath module can use libraries from both platform and APEX variants. Unlike
  1192. // the bootclasspath_fragment it supports dex_import modules which provides the dex file. So, it
  1193. // can obtain a boot dex jar from a prebuilt that is not part of an APEX. However, it is assumed
  1194. // that if the library can be part of an APEX then it is the APEX variant that is used.
  1195. //
  1196. // This check handles the slightly different requirements of the bootclasspath_fragment and
  1197. // platform_bootclasspath modules by only deferring error reporting for the platform variant of
  1198. // a prebuilt modules that has other variants which are part of an APEX.
  1199. //
  1200. // TODO(b/187910671): Remove this once platform variants are no longer created unnecessarily.
  1201. if android.IsModulePrebuilt(module) {
  1202. // An inactive source module can still contribute to the APEX but an inactive prebuilt module
  1203. // should not contribute to anything. So, rather than have a missing dex jar cause a Soong
  1204. // failure defer the error reporting to Ninja. Unless the prebuilt build target is explicitly
  1205. // built Ninja should never use the dex jar file.
  1206. if !isActiveModule(module) {
  1207. return true
  1208. }
  1209. if am, ok := module.(android.ApexModule); ok && am.InAnyApex() {
  1210. apexInfo := ctx.OtherModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
  1211. if apexInfo.IsForPlatform() {
  1212. return true
  1213. }
  1214. }
  1215. }
  1216. return false
  1217. }
  1218. // handleMissingDexBootFile will either log a warning or create an error rule to create the fake
  1219. // file depending on the value returned from deferReportingMissingBootDexJar.
  1220. func handleMissingDexBootFile(ctx android.ModuleContext, module android.Module, fake android.WritablePath, reason string) {
  1221. if deferReportingMissingBootDexJar(ctx, module) {
  1222. // Create an error rule that pretends to create the output file but will actually fail if it
  1223. // is run.
  1224. ctx.Build(pctx, android.BuildParams{
  1225. Rule: android.ErrorRule,
  1226. Output: fake,
  1227. Args: map[string]string{
  1228. "error": fmt.Sprintf("missing boot dex jar dependency for %s: %s", module, reason),
  1229. },
  1230. })
  1231. } else {
  1232. ctx.ModuleErrorf("module %s does not provide a dex jar: %s", module, reason)
  1233. }
  1234. }
  1235. // retrieveEncodedBootDexJarFromModule returns a path to the boot dex jar from the supplied module's
  1236. // DexJarBuildPath() method.
  1237. //
  1238. // The returned path will usually be to a dex jar file that has been encoded with hidden API flags.
  1239. // However, under certain conditions, e.g. errors, or special build configurations it will return
  1240. // a path to a fake file.
  1241. func retrieveEncodedBootDexJarFromModule(ctx android.ModuleContext, module android.Module) android.Path {
  1242. bootDexJar := module.(interface{ DexJarBuildPath() OptionalDexJarPath }).DexJarBuildPath()
  1243. if !bootDexJar.Valid() {
  1244. fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/encoded-dex/%s.jar", module.Name()))
  1245. handleMissingDexBootFile(ctx, module, fake, bootDexJar.InvalidReason())
  1246. return fake
  1247. }
  1248. return bootDexJar.Path()
  1249. }
  1250. // extractEncodedDexJarsFromModules extracts the encoded dex jars from the supplied modules.
  1251. func extractEncodedDexJarsFromModules(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule {
  1252. encodedDexJarsByModuleName := bootDexJarByModule{}
  1253. for _, module := range contents {
  1254. path := retrieveEncodedBootDexJarFromModule(ctx, module)
  1255. encodedDexJarsByModuleName.addPath(module, path)
  1256. }
  1257. return encodedDexJarsByModuleName
  1258. }