Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/build/build/soong/java/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 45 kB image not shown  

Quelle  sdk_library_internal.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

// Copyright 2024 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package java

import (
 "fmt"
 "path"
 "strings"

 "android/soong/android"
 "android/soong/dexpreopt"
 "android/soong/etc"
 "android/soong/java/config"

 "github.com/google/blueprint/proptools"
)

// ---------------------------------------------------------------------------------------------
// Naming scheme of the submodules generated by java_sdk_library and java_sdk_library_import
// ---------------------------------------------------------------------------------------------

const (
 sdkXmlFileSuffix = ".xml"
 implLibSuffix    = ".impl"
)

func implLibraryModuleName(sdkLibName string) string {
 return sdkLibName + implLibSuffix
}

// Module name of the runtime implementation library
func (c *commonToSdkLibraryAndImport) implLibraryModuleName() string {
 return implLibraryModuleName(c.module.RootLibraryName())
}

// Module name of the XML file for the lib
func (c *commonToSdkLibraryAndImport) xmlPermissionsModuleName() string {
 return c.module.RootLibraryName() + sdkXmlFileSuffix
}

// Name of the java_library module that compiles the stubs source.
func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope) string {
 baseName := c.module.RootLibraryName()
 return apiScope.stubsLibraryModuleName(baseName)
}

// Name of the java_library module that compiles the exportable stubs source.
func (c *commonToSdkLibraryAndImport) exportableStubsLibraryModuleName(apiScope *apiScope) string {
 baseName := c.module.RootLibraryName()
 return apiScope.exportableStubsLibraryModuleName(baseName)
}

// Name of the droidstubs module that generates the stubs source and may also
// generate/check the API.
func (c *commonToSdkLibraryAndImport) droidstubsModuleName(apiScope *apiScope) string {
 baseName := c.module.RootLibraryName()
 return apiScope.stubsSourceModuleName(baseName)
}

// Name of the java_api_library module that generates the from-text stubs source
// and compiles to a jar file.
func (c *commonToSdkLibraryAndImport) fromTextStubsLibraryModuleName(apiScope *apiScope) string {
 baseName := c.module.RootLibraryName()
 return apiScope.apiLibraryModuleName(baseName)
}

// Name of the java_library module that compiles the stubs
// generated from source Java files.
func (c *commonToSdkLibraryAndImport) fromSourceStubsLibraryModuleName(apiScope *apiScope) string {
 baseName := c.module.RootLibraryName()
 return apiScope.sourceStubsLibraryModuleName(baseName)
}

// Name of the java_library module that compiles the exportable stubs
// generated from source Java files.
func (c *commonToSdkLibraryAndImport) exportableFromSourceStubsLibraryModuleName(apiScope *apiScope) string {
 baseName := c.module.RootLibraryName()
 return apiScope.exportableSourceStubsLibraryModuleName(baseName)
}

// ---------------------------------------------------------------------------------------------
// Build rules of the submodules generated by java_sdk_library.
// java_sdk_library "framework-foo" generates the following submodules:
//
// - "framework-foo.impl" (type: [Library]): the implementation library, which generates the
//  compilation outputs that include the implementation details and the private apis
//  (i.e. class/methods that are annotated @hide).
//
// - "framework-foo.stubs.source.<[apiScope.name]>" (type: [Droidstubs]): droidstubs module that
//  generates the stubs and the api files for the given api scope.
//
// - "framework-foo.stubs.<[apiScope.name]>" (type: [Library]): stub library module that
//  provides the compilation output of the stubs to the reverse dependencies. The module
//  itself does not perform any compilation actions; the module statically depends on one of
//  the from-source stub module or the from-text stub configuration based on the build
//   configuration.
//
// - "framework-foo.stubs.<[apiScope.name]>.from-source" (type: [Library]): stub library module
//  that compiles the stubs generated by the droidstubs submodule. This module is a static
//  dependency of the stub library module when
//  [android/soong/android/config.BuildFromTextStub()] is false.
//
// - "framework-foo.stubs.<[apiScope.name]>.from-text" (type: [ApiLibrary]): api library module
//  that generates and compiles the stubs from the api files checked in the tree instead of
//  the source Java files (e.g. *-current.txt files). This module is a static dependency of
//  the stub library module when [android/soong/android/config.BuildFromTextStub()] is true.
//
// - "framework-foo.stubs.exportable.<[apiScope.name]>" (type: [Library]): stub library module
//  that provides the "exportable" stubs. "exportable" stubs are the stubs that do not
//  include in-development flagged apis. This module is only used for SDK builds to generate
//  the SDK artifacts, and not purposed for consumption for other modules.
//
// - "framework-foo.stubs.exportable.<[apiScope.name]>.from-source" (type: [Library]): stub
//  library module that compiles the "exportable" stubs generated by the droidstubs
//  submodule. This module is always a static dependency of the "exportable" stub library
//  module given that from-text stubs cannot be used for SDK builds as it does not contain
//  documentations.
//
// - "framework-foo.xml" (type: [sdkLibraryXml]): xml library that generates the permission xml
//  file, which allows [SdkLibrary] to be used with <uses-permission> tag in the
//  AndroidManifest.xml files.
// ---------------------------------------------------------------------------------------------

// Creates the implementation [Library] with ".impl" suffix.
func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) {
 visibility := childModuleVisibility(module.sdkLibraryProperties.Impl_library_visibility)

 libs := module.properties.Libs.Clone()
 libs.AppendSimpleValue(module.sdkLibraryProperties.Impl_only_libs)
 staticLibs := module.properties.Static_libs.Clone()
 staticLibs.AppendSimpleValue(module.sdkLibraryProperties.Impl_only_static_libs)
 props := struct {
  Name           *string
  Enabled        proptools.Configurable[bool]
  Visibility     []string
  Libs           proptools.Configurable[[]string]
  Static_libs    proptools.Configurable[[]string]
  Apex_available []string
  Stem           *string
 }{
  Name:       proptools.StringPtr(module.implLibraryModuleName()),
  Enabled:    module.EnabledProperty(),
  Visibility: visibility,

  Libs: libs,

  Static_libs: staticLibs,
  // Pass the apex_available settings down so that the impl library can be statically
  // embedded within a library that is added to an APEX. Needed for updatable-media.
  Apex_available: module.ApexAvailable(),

  Stem: proptools.StringPtr(module.Name()),
 }

 properties := []interface{}{
  &module.properties,
  &module.protoProperties,
  &module.deviceProperties,
  &module.dexProperties,
  &module.dexpreoptProperties,
  &module.linter.properties,
  &module.overridableProperties,
  &module.usesLibrary.usesLibraryProperties,
  &props,
  module.sdkComponentPropertiesForChildLibrary(),
 }
 mctx.CreateModule(LibraryFactory, properties...)
}

// getApiSurfaceForScope returns the api surface name to use for the apiScope. If one is specified
// in the corresponding ApiScopeProperties.Api_surface property that is used, otherwise the name of
// the apiScope is used.
func (module *SdkLibrary) getApiSurfaceForScope(apiScope *apiScope) *string {
 scopeProperties := module.scopeToProperties[apiScope]

 apiSurface := scopeProperties.Api_surface
 if apiSurface == nil {
  apiSurface = &apiScope.name
 }

 return apiSurface
}

// Creates the [Droidstubs] module with ".stubs.source.<[apiScope.name]>" that creates stubs
// source files from the given full source files and also updates and checks the API
// specification files (i.e. "*-current.txt", "*-removed.txt" files).
func (module *SdkLibrary) createDroidstubs(mctx android.DefaultableHookContext, apiScope *apiScope, name string, scopeSpecificDroidstubsArgs []string) {
 props := struct {
  Name                             *string
  Enabled                          proptools.Configurable[bool]
  Visibility                       []string
  Srcs                             proptools.Configurable[[]string]
  Installable                      *bool
  Sdk_version                      *string
  Api_surface                      *string
  System_modules                   *string
  Libs                             proptools.Configurable[[]string]
  Output_javadoc_comments          *bool
  Arg_files                        []string
  Args                             *string
  Java_version                     *string
  Annotations_enabled              *bool
  Merge_annotations_dirs           []string
  Merge_inclusion_annotations_dirs []string
  Generate_stubs                   *bool
  Previous_api                     *string
  Aconfig_declarations             []string
  Check_api                        struct {
   Current       ApiToCheck
   Last_released ApiToCheck

   Api_lint struct {
    Enabled       *bool
    New_since     *string
    Baseline_file *string
   }
  }
  Aidl struct {
   Include_dirs       []string
   Local_include_dirs []string
  }
  Dists []android.Dist
 }{}

 // The stubs source processing uses the same compile time classpath when extracting the
 // API from the implementation library as it does when compiling it. i.e. the same
 // * sdk version
 // * system_modules
 // * libs (static_libs/libs)

 props.Name = proptools.StringPtr(name)
 props.Enabled = module.EnabledProperty()
 props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_source_visibility)
 props.Srcs = module.properties.Srcs.Clone()
 props.Srcs.AppendSimpleValue(module.sdkLibraryProperties.Api_srcs)
 props.Sdk_version = module.deviceProperties.Sdk_version
 props.Api_surface = module.getApiSurfaceForScope(apiScope)
 props.System_modules = module.deviceProperties.System_modules
 props.Installable = proptools.BoolPtr(false)
 // A droiddoc module has only one Libs property and doesn't distinguish between
 // shared libs and static libs. So we need to add both of these libs to Libs property.
 props.Libs = proptools.NewConfigurable[[]string](nil, nil)
 props.Libs.Append(module.properties.Libs)
 props.Libs.Append(module.properties.Static_libs)
 props.Libs.AppendSimpleValue(module.sdkLibraryProperties.Stub_only_libs)
 props.Libs.AppendSimpleValue(module.scopeToProperties[apiScope].Libs)
 props.Aidl.Include_dirs = module.deviceProperties.Aidl.Include_dirs
 props.Aidl.Local_include_dirs = module.deviceProperties.Aidl.Local_include_dirs
 props.Java_version = module.properties.Java_version

 props.Annotations_enabled = module.sdkLibraryProperties.Annotations_enabled
 props.Merge_annotations_dirs = module.sdkLibraryProperties.Merge_annotations_dirs
 props.Merge_inclusion_annotations_dirs = module.sdkLibraryProperties.Merge_inclusion_annotations_dirs
 props.Aconfig_declarations = module.sdkLibraryProperties.Aconfig_declarations

 droidstubsArgs := []string{}
 if len(module.sdkLibraryProperties.Api_packages) != 0 {
  droidstubsArgs = append(droidstubsArgs, "--stub-packages "+strings.Join(module.sdkLibraryProperties.Api_packages, ":"))
 }
 droidstubsArgs = append(droidstubsArgs, module.sdkLibraryProperties.Droiddoc_options...)
 disabledWarnings := []string{"HiddenSuperclass"}
 if proptools.BoolDefault(module.sdkLibraryProperties.Api_lint.Legacy_errors_allowed, true) {
  disabledWarnings = append(disabledWarnings,
   "BroadcastBehavior",
   "DeprecationMismatch",
   "MissingPermission",
   "SdkConstant",
   "Todo",
  )
 }
 droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide "))

 // Output Javadoc comments for public scope.
 if apiScope == apiScopePublic {
  props.Output_javadoc_comments = proptools.BoolPtr(true)
 }

 // Add in scope specific arguments.
 droidstubsArgs = append(droidstubsArgs, scopeSpecificDroidstubsArgs...)
 props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files
 props.Args = proptools.StringPtr(strings.Join(droidstubsArgs, " "))

 // List of APIs identified from the provided source files are created. They are later
 // compared against to the not-yet-released (a.k.a current) list of APIs and to the
 // last-released (a.k.a numbered) list of API.
 currentApiFileName := apiScope.apiFilePrefix + "current.txt"
 removedApiFileName := apiScope.apiFilePrefix + "removed.txt"
 apiDir := module.getApiDir()
 currentApiFileName = path.Join(apiDir, currentApiFileName)
 removedApiFileName = path.Join(apiDir, removedApiFileName)

 // check against the not-yet-release API
 props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName)
 props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName)
 if !module.ModuleBuildFromTextStubs() {
  props.Check_api.Current.Default_in_droid = proptools.BoolPtr(true)
 }

 // Although a latest API is always provided it may not be a suitable one for
 // comparing against, e.g. because the API surface does not require backwards
 // compatibility or the latest API is a fake that is added simply to satisfy
 // Metalava's requirement to provide one when working with flagged APIs.
 compareAgainstLatestApi := module.compareAgainstLatestApi(apiScope)

 // check against the latest released API
 latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope))
 props.Previous_api = latestApiFilegroupName

 // Only perform compatibility checks if latest API is suitable.
 props.Check_api.Last_released.Enabled = proptools.BoolPtr(compareAgainstLatestApi)

 props.Check_api.Last_released.Api_file = latestApiFilegroupName
 props.Check_api.Last_released.Removed_api_file = proptools.StringPtr(
  module.latestRemovedApiFilegroupName(apiScope))
 props.Check_api.Last_released.Baseline_file = proptools.StringPtr(
  module.latestIncompatibilitiesFilegroupName(apiScope))

 // Only perform the API lint check if the latest API is suitable.
 if proptools.Bool(module.sdkLibraryProperties.Api_lint.Enabled) && compareAgainstLatestApi {
  // Enable api lint.
  props.Check_api.Api_lint.Enabled = proptools.BoolPtr(true)
  props.Check_api.Api_lint.New_since = latestApiFilegroupName

  // If it exists then pass a lint-baseline.txt through to droidstubs.
  baselinePath := path.Join(apiDir, apiScope.apiFilePrefix+"lint-baseline.txt")
  baselinePathRelativeToRoot := path.Join(mctx.ModuleDir(), baselinePath)
  paths, err := mctx.GlobWithDeps(baselinePathRelativeToRoot, nil)
  if err != nil {
   mctx.ModuleErrorf("error checking for presence of %s: %s", baselinePathRelativeToRoot, err)
  }
  if len(paths) == 1 {
   props.Check_api.Api_lint.Baseline_file = proptools.StringPtr(baselinePath)
  } else if len(paths) != 0 {
   mctx.ModuleErrorf("error checking for presence of %s: expected one path, found: %v", baselinePathRelativeToRoot, paths)
  }
 }

 if !Bool(module.sdkLibraryProperties.No_dist) {
  // Dist the api txt and removed api txt artifacts for sdk builds.
  distDir := proptools.StringPtr(path.Join(module.apiDistPath(apiScope), "api"))
  stubsTypeTagPrefix := ""
  if mctx.Config().ReleaseHiddenApiExportableStubs() {
   stubsTypeTagPrefix = ".exportable"
  }
  for _, p := range []struct {
   tag     string
   pattern string
  }{
   // "exportable" api files are copied to the dist directory instead of the
   // "everything" api files when "RELEASE_HIDDEN_API_EXPORTABLE_STUBS" build flag
   // is set. Otherwise, the "everything" api files are copied to the dist directory.
   {tag: "%s.api.txt", pattern: "%s.txt"},
   {tag: "%s.removed-api.txt", pattern: "%s-removed.txt"},
  } {
   props.Dists = append(props.Dists, android.Dist{
    Targets: []string{"sdk", "win_sdk"},
    Dir:     distDir,
    Dest:    proptools.StringPtr(fmt.Sprintf(p.pattern, module.distStem())),
    Tag:     proptools.StringPtr(fmt.Sprintf(p.tag, stubsTypeTagPrefix)),
   })
  }
 }

 mctx.CreateModule(DroidstubsFactory, &props, module.sdkComponentPropertiesForChildLibrary()).(*Droidstubs).CallHookIfAvailable(mctx)
}

type libraryProperties struct {
 Name           *string
 Enabled        proptools.Configurable[bool]
 Visibility     []string
 Srcs           []string
 Installable    *bool
 Sdk_version    *string
 System_modules *string
 Patch_module   *string
 Libs           []string
 Static_libs    []string
 Compile_dex    *bool
 Java_version   *string
 Openjdk9       struct {
  Srcs       []string
  Javacflags []string
 }
 Dist struct {
  Targets []string
  Dest    *string
  Dir     *string
  Tag     *string
 }
 Is_stubs_module       *bool
 Stub_contributing_api *string
}

func (module *SdkLibrary) stubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope) libraryProperties {
 props := libraryProperties{}
 props.Enabled = module.EnabledProperty()
 props.Visibility = []string{"//visibility:override", "//visibility:private"}
 // sources are generated from the droiddoc
 sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
 props.Sdk_version = proptools.StringPtr(sdkVersion)
 props.System_modules = module.deviceProperties.System_modules
 props.Patch_module = module.properties.Patch_module
 props.Installable = proptools.BoolPtr(false)
 props.Libs = module.sdkLibraryProperties.Stub_only_libs
 props.Libs = append(props.Libs, module.scopeToProperties[apiScope].Libs...)
 props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs
 // The stub-annotations library contains special versions of the annotations
 // with CLASS retention policy, so that they're kept.
 if proptools.Bool(module.sdkLibraryProperties.Annotations_enabled) {
  props.Libs = append(props.Libs, "stub-annotations")
 }
 props.Openjdk9.Srcs = module.properties.Openjdk9.Srcs
 props.Openjdk9.Javacflags = module.properties.Openjdk9.Javacflags
 // We compile the stubs for 1.8 in line with the main android.jar stubs, and potential
 // interop with older developer tools that don't support 1.9.
 props.Java_version = proptools.StringPtr("1.8")
 props.Is_stubs_module = proptools.BoolPtr(true)
 props.Stub_contributing_api = proptools.StringPtr(apiScope.kind.String())

 return props
}

// Creates the from-source stub [Library] with ".stubs.<[apiScope.name]>.from-source" suffix.
func (module *SdkLibrary) createFromSourceStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {

 props := module.stubsLibraryProps(mctx, apiScope)
 props.Name = proptools.StringPtr(module.fromSourceStubsLibraryModuleName(apiScope))
 props.Srcs = []string{":" + module.droidstubsModuleName(apiScope)}

 mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}

// Creates the "exportable" from-source stub [Library] with
// ".stubs.exportable.<[apiScope.name]>" suffix.
func (module *SdkLibrary) createExportableFromSourceStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
 props := module.stubsLibraryProps(mctx, apiScope)
 props.Name = proptools.StringPtr(module.exportableFromSourceStubsLibraryModuleName(apiScope))
 props.Srcs = []string{":" + module.droidstubsModuleName(apiScope) + "{.exportable}"}

 mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}

// Creates the from-text stub [ApiLibrary] with ".stubs.<[apiScope.name]>.from-text" suffix.
func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
 props := struct {
  Name              *string
  Enabled           proptools.Configurable[bool]
  Visibility        []string
  Api_contributions []string
  Libs              proptools.Configurable[[]string]
  Static_libs       []string
  System_modules    *string
  Enable_validation *bool
  Stubs_type        *string
  Sdk_version       *string
  Previous_api      *string
 }{}

 props.Name = proptools.StringPtr(module.fromTextStubsLibraryModuleName(apiScope))
 props.Enabled = module.EnabledProperty()
 props.Visibility = []string{"//visibility:override", "//visibility:private"}

 apiContributions := []string{}

 // Api surfaces are not independent of each other, but have subset relationships,
 // and so does the api files. To generate from-text stubs for api surfaces other than public,
 // all subset api domains' api_contributions must be added as well.
 scope := apiScope
 for scope != nil {
  apiContributions = append(apiContributions, module.droidstubsModuleName(scope)+".api.contribution")
  scope = scope.extends
 }
 if apiScope == apiScopePublic {
  additionalApiContribution := module.apiLibraryAdditionalApiContribution()
  if additionalApiContribution != "" {
   apiContributions = append(apiContributions, additionalApiContribution)
  }
 }

 props.Api_contributions = apiContributions

 // Ensure that stub-annotations is added to the classpath before any other libs
 props.Libs = proptools.NewConfigurable[[]string](nil, nil)
 props.Libs.AppendSimpleValue([]string{"stub-annotations"})
 props.Libs.Append(module.properties.Libs)
 props.Libs.Append(module.properties.Static_libs)
 props.Libs.AppendSimpleValue(module.sdkLibraryProperties.Stub_only_libs)
 props.Libs.AppendSimpleValue(module.scopeToProperties[apiScope].Libs)
 props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs

 props.System_modules = module.deviceProperties.System_modules
 props.Enable_validation = proptools.BoolPtr(true)
 props.Stubs_type = proptools.StringPtr("everything")

 if module.deviceProperties.Sdk_version != nil {
  props.Sdk_version = module.deviceProperties.Sdk_version
 }

 // check against the latest released API
 latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope))
 props.Previous_api = latestApiFilegroupName

 mctx.CreateModule(ApiLibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}

func (module *SdkLibrary) topLevelStubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope, doDist bool) libraryProperties {
 props := libraryProperties{}

 props.Enabled = module.EnabledProperty()
 props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility)
 sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
 props.Sdk_version = proptools.StringPtr(sdkVersion)

 props.System_modules = module.deviceProperties.System_modules

 // The imports need to be compiled to dex if the java_sdk_library requests it.
 compileDex := module.dexProperties.Compile_dex
 if module.stubLibrariesCompiledForDex() {
  compileDex = proptools.BoolPtr(true)
 }
 props.Compile_dex = compileDex

 props.Stub_contributing_api = proptools.StringPtr(apiScope.kind.String())

 if !Bool(module.sdkLibraryProperties.No_dist) && doDist {
  props.Dist.Targets = []string{"sdk", "win_sdk"}
  props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.distStem()))
  props.Dist.Dir = proptools.StringPtr(module.apiDistPath(apiScope))
  props.Dist.Tag = proptools.StringPtr(".jar")
 }
 props.Is_stubs_module = proptools.BoolPtr(true)

 return props
}

// Creates the stub [Library] with ".stubs.<[apiScope.name]>" suffix.
func (module *SdkLibrary) createTopLevelStubsLibrary(
 mctx android.DefaultableHookContext, apiScope *apiScope) {

 // Dist the "everything" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is false
 doDist := !mctx.Config().ReleaseHiddenApiExportableStubs()
 props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist)
 props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))

 // Add the stub compiling java_library/java_api_library as static lib based on build config
 staticLib := module.fromSourceStubsLibraryModuleName(apiScope)
 if mctx.Config().BuildFromTextStub() && module.ModuleBuildFromTextStubs() {
  staticLib = module.fromTextStubsLibraryModuleName(apiScope)
 }
 props.Static_libs = append(props.Static_libs, staticLib)

 mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}

// Creates the "exportable" stub [Library] with ".stubs.exportable.<[apiScope.name]>" suffix.
func (module *SdkLibrary) createTopLevelExportableStubsLibrary(
 mctx android.DefaultableHookContext, apiScope *apiScope) {

 // Dist the "exportable" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is true
 doDist := mctx.Config().ReleaseHiddenApiExportableStubs()
 props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist)
 props.Name = proptools.StringPtr(module.exportableStubsLibraryModuleName(apiScope))

 staticLib := module.exportableFromSourceStubsLibraryModuleName(apiScope)
 props.Static_libs = append(props.Static_libs, staticLib)

 mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}

type removeListFromListPostProcessor struct {
 toRemove []string
}

func (p removeListFromListPostProcessor) PostProcess(list []string) []string {
 return android.RemoveListFromList(list, p.toRemove)
}

// Creates the [sdkLibraryXml] with ".xml" suffix.
func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) {
 moduleMinApiLevel := module.Library.MinSdkVersion(mctx)
 var moduleMinApiLevelStr = moduleMinApiLevel.String()
 if moduleMinApiLevel == android.NoneApiLevel {
  moduleMinApiLevelStr = "current"
 }
 libs := module.properties.Libs.Clone()
 libs.AddPostProcessor(removeListFromListPostProcessor{config.FrameworkLibraries})

 props := struct {
  Name                      *string
  Enabled                   proptools.Configurable[bool]
  Lib_name                  *string
  Apex_available            []string
  On_bootclasspath_since    *string
  On_bootclasspath_before   *string
  Min_device_sdk            *string
  Max_device_sdk            *string
  Sdk_library_min_api_level *string
  Uses_libs                 proptools.Configurable[[]string]
  Libs                      proptools.Configurable[[]string]
  Impl_only_libs            []string
 }{
  Name:                      proptools.StringPtr(module.xmlPermissionsModuleName()),
  Enabled:                   module.EnabledProperty(),
  Lib_name:                  proptools.StringPtr(module.BaseModuleName()),
  Apex_available:            module.ApexProperties.Apex_available,
  On_bootclasspath_since:    module.commonSdkLibraryProperties.On_bootclasspath_since,
  On_bootclasspath_before:   module.commonSdkLibraryProperties.On_bootclasspath_before,
  Min_device_sdk:            module.commonSdkLibraryProperties.Min_device_sdk,
  Max_device_sdk:            module.commonSdkLibraryProperties.Max_device_sdk,
  Sdk_library_min_api_level: &moduleMinApiLevelStr,
  Uses_libs:                 module.usesLibraryProperties.Uses_libs.Clone(),
  Libs:                      libs,
  Impl_only_libs:            module.sdkLibraryProperties.Impl_only_libs,
 }

 mctx.CreateModule(sdkLibraryXmlFactory, &props)
}

// ---------------------------------------------------------------------------------------------
// Build rules of the submodules generated by java_sdk_library_import.
// Note that the java_sdk_library_import module does not generate the implementation library.
// Instead, it will create a dependency to the source implemenetation library if one exists.
// java_sdk_library_import "framework-foo" generates the following submodules:
//
// - "framework-foo.stubs.<[apiScope.name]>" (type: [Import]): prebuilt stub library module that
//  provides the stub jar file checked in the tree.
//
// - "framework-foo.stubs.source.<[apiScope.name]>" (type: [PrebuiltStubsSources]): prebuilt
//  droidstubs module that provides the stub source jar file checked in the tree.
//
// - "framework-foo.stubs.source.<[apiScope.name]>.api.contribution"
//  (type [JavaApiContributionImport]): prebuilt java_api_contribution module that provides
//  the prebuilt api file for previously released from-text stub generation.
// ---------------------------------------------------------------------------------------------

// Creates the prebuilt stub [Import] with ".stubs.<[apiScope.name]>" suffix.
func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
 // Creates a java import for the jar with ".stubs" suffix
 props := struct {
  Name                             *string
  Source_module_name               *string
  Created_by_java_sdk_library_name *string
  Sdk_version                      *string
  Libs                             []string
  Jars                             []string
  Compile_dex                      *bool
  Is_stubs_module                  *bool

  android.UserSuppliedPrebuiltProperties
 }{}
 props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
 props.Source_module_name = proptools.StringPtr(apiScope.stubsLibraryModuleName(module.BaseModuleName()))
 props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
 props.Sdk_version = scopeProperties.Sdk_version
 // Prepend any of the libs from the legacy public properties to the libs for each of the
 // scopes to avoid having to duplicate them in each scope.
 props.Libs = append(module.properties.Libs, scopeProperties.Libs...)
 props.Jars = scopeProperties.Jars

 // The imports are preferred if the java_sdk_library_import is preferred.
 props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt)

 // The imports need to be compiled to dex if the java_sdk_library_import requests it.
 compileDex := module.properties.Compile_dex
 if module.stubLibrariesCompiledForDex() {
  compileDex = proptools.BoolPtr(true)
 }
 props.Compile_dex = compileDex
 props.Is_stubs_module = proptools.BoolPtr(true)

 mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}

func (module *SdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
 props := struct {
  Name                             *string
  Source_module_name               *string
  Created_by_java_sdk_library_name *string
  Srcs                             []string

  android.UserSuppliedPrebuiltProperties
 }{}
 props.Name = proptools.StringPtr(module.droidstubsModuleName(apiScope))
 props.Source_module_name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName()))
 props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
 props.Srcs = scopeProperties.Stub_srcs

 // The stubs source is preferred if the java_sdk_library_import is preferred.
 props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt)

 mctx.CreateModule(PrebuiltStubsSourcesFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}

// Creates the prebuilt api contribution [JavaApiContributionImport] with
// ".stubs.source.<[apiScope.name]>.api.contribution" suffix.
func (module *SdkLibraryImport) createPrebuiltApiContribution(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
 api_file := scopeProperties.Current_api
 api_surface := &apiScope.name

 props := struct {
  Name                             *string
  Source_module_name               *string
  Created_by_java_sdk_library_name *string
  Api_surface                      *string
  Api_file                         *string
  Visibility                       []string
 }{}

 props.Name = proptools.StringPtr(module.droidstubsModuleName(apiScope) + ".api.contribution")
 props.Source_module_name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName()) + ".api.contribution")
 props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
 props.Api_surface = api_surface
 props.Api_file = api_file
 props.Visibility = []string{"//visibility:override", "//visibility:public"}

 mctx.CreateModule(ApiContributionImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}

// ---------------------------------------------------------------------------------------------
// End of the build rules of the submodules generated by java_sdk_library_import.
// ---------------------------------------------------------------------------------------------

// Definition of the [sdkLibraryXml] module. The module generates the permissions xml file,
// so that the apps can specify the java_sdk_library using <uses-permission> tag in the
// AndroidManifest.xml file.
type sdkLibraryXml struct {
 android.ModuleBase
 android.DefaultableModuleBase
 android.ApexModuleBase

 properties sdkLibraryXmlProperties

 outputFilePath android.OutputPath
 installDirPath android.InstallPath

 usesLibrary
}

type sdkLibraryXmlProperties struct {
 // canonical name of the lib
 Lib_name *string

 // Signals that this shared library is part of the bootclasspath starting
 // on the version indicated in this attribute.
 //
 // This will make platforms at this level and above to ignore
 // <uses-library> tags with this library name because the library is already
 // available
 On_bootclasspath_since *string

 // Signals that this shared library was part of the bootclasspath before
 // (but not including) the version indicated in this attribute.
 //
 // The system will automatically add a <uses-library> tag with this library to
 // apps that target any SDK less than the version indicated in this attribute.
 On_bootclasspath_before *string

 // Indicates that PackageManager should ignore this shared library if the
 // platform is below the version indicated in this attribute.
 //
 // This means that the device won't recognise this library as installed.
 Min_device_sdk *string

 // Indicates that PackageManager should ignore this shared library if the
 // platform is above the version indicated in this attribute.
 //
 // This means that the device won't recognise this library as installed.
 Max_device_sdk *string

 // The SdkLibrary's min api level as a string
 //
 // This value comes from the ApiLevel of the MinSdkVersion property.
 Sdk_library_min_api_level *string

 // List of java libraries that will be in the classpath.
 Libs proptools.Configurable[[]string] `android:"arch_variant"`

 // List of Java libraries that will be in the classpath when building the implementation lib.
 Impl_only_libs []string `android:"arch_variant"`
}

// java_sdk_library_xml builds the permission xml file for a java_sdk_library.
// Not to be used directly by users. java_sdk_library internally uses this.
func sdkLibraryXmlFactory() android.Module {
 module := &sdkLibraryXml{}

 module.AddProperties(&module.properties, &module.usesLibrary.usesLibraryProperties)

 android.InitApexModule(module)
 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)

 return module
}

func (module *sdkLibraryXml) UniqueApexVariations() bool {
 // sdkLibraryXml needs a unique variation per APEX because the generated XML file contains the path to the
 // mounted APEX, which contains the name of the APEX.
 return true
}

// from android.PrebuiltEtcModule
func (module *sdkLibraryXml) BaseDir() string {
 return "etc"
}

// from android.PrebuiltEtcModule
func (module *sdkLibraryXml) SubDir() string {
 return "permissions"
}

var _ etc.PrebuiltEtcModule = (*sdkLibraryXml)(nil)

// from android.ApexModule
func (module *sdkLibraryXml) AvailableFor(what string) bool {
 return android.CheckAvailableForApex(what, module.ApexAvailableFor())
}

func (module *sdkLibraryXml) ApexAvailableFor() []string {
 return []string{android.AvailableToPlatform, android.AvailableToAnyApex}
}

func (module *sdkLibraryXml) DepsMutator(ctx android.BottomUpMutatorContext) {
 module.usesLibrary.deps(ctx, false)
 libDeps := ctx.AddVariationDependencies(nil, usesLibStagingTag, module.properties.Libs.GetOrDefault(ctx, nil)...)
 libDeps = append(libDeps, ctx.AddVariationDependencies(nil, usesLibStagingTag, module.properties.Impl_only_libs...)...)
 module.usesLibrary.depsFromLibs(ctx, libDeps)
}

var _ android.ApexModule = (*sdkLibraryXml)(nil)

// Implements android.ApexModule
func (m *sdkLibraryXml) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel {
 return android.MinApiLevel
}

// File path to the runtime implementation library
func (module *sdkLibraryXml) implPath(ctx android.ModuleContext) string {
 implName := proptools.String(module.properties.Lib_name)
 if apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider); !apexInfo.IsForPlatform() {
  // TODO(b/146468504): ApexVariationName() is only a soong module name, not apex name.
  // In most cases, this works fine. But when apex_name is set or override_apex is used
  // this can be wrong.
  return fmt.Sprintf("/apex/%s/javalib/%s.jar", apexInfo.BaseApexName, implName)
 }
 partition := "system"
 if module.SocSpecific() {
  partition = "vendor"
 } else if module.DeviceSpecific() {
  partition = "odm"
 } else if module.ProductSpecific() {
  partition = "product"
 } else if module.SystemExtSpecific() {
  partition = "system_ext"
 }
 return "/" + partition + "/framework/" + implName + ".jar"
}

func formattedOptionalSdkLevelAttribute(ctx android.ModuleContext, attrName string, value *string) string {
 if value == nil {
  return ""
 }
 apiLevel, err := android.ApiLevelFromUser(ctx, *value)
 if err != nil {
  // attributes in bp files have underscores but in the xml have dashes.
  ctx.PropertyErrorf(strings.ReplaceAll(attrName, "-", "_"), err.Error())
  return ""
 }
 if apiLevel.IsCurrent() {
  // passing "current" would always mean a future release, never the current (or the current in
  // progress) which means some conditions would never be triggered.
  ctx.PropertyErrorf(strings.ReplaceAll(attrName, "-", "_"),
   `"current" is not an allowed value for this attribute`)
  return ""
 }
 // "safeValue" is safe because it translates finalized codenames to a string
 // with their SDK int.
 safeValue := apiLevel.String()
 return formattedOptionalAttribute(attrName, &safeValue)
}

// formats an attribute for the xml permissions file if the value is not null
// returns empty string otherwise
func formattedOptionalAttribute(attrName string, value *string) string {
 if value == nil {
  return ""
 }
 return fmt.Sprintf("        %s=\"%s\"\n", attrName, *value)
}

func (module *sdkLibraryXml) formattedDependenciesAttribute(ctx android.ModuleContext) string {
 classLoaderContexts := module.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
 dependencies := make([]string, 0, len(classLoaderContexts[dexpreopt.AnySdkVersion]))
 for _, dep := range classLoaderContexts[dexpreopt.AnySdkVersion] {
  dependencies = append(dependencies, dep.Name)
 }
 if len(dependencies) == 0 {
  return ""
 }
 return fmt.Sprintf("        dependency=\"%s\"\n", strings.Join(dependencies, ":"))
}

func (module *sdkLibraryXml) permissionsContents(ctx android.ModuleContext) string {
 libName := proptools.String(module.properties.Lib_name)
 libNameAttr := formattedOptionalAttribute("name", &libName)
 filePath := module.implPath(ctx)
 filePathAttr := formattedOptionalAttribute("file", &filePath)
 implicitFromAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-since", module.properties.On_bootclasspath_since)
 implicitUntilAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-before", module.properties.On_bootclasspath_before)
 minSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "min-device-sdk", module.properties.Min_device_sdk)
 maxSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "max-device-sdk", module.properties.Max_device_sdk)
 dependenciesAttr := module.formattedDependenciesAttribute(ctx)
 // <library> is understood in all android versions whereas <apex-library> is only understood from API T (and ignored before that).
 // similarly, min_device_sdk is only understood from T. So if a library is using that, we need to use the apex-library to make sure this library is not loaded before T
 var libraryTag string
 if module.properties.Min_device_sdk != nil {
  libraryTag = "    <apex-library\n"
 } else {
  libraryTag = "    <library\n"
 }

 return strings.Join([]string{
  "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n",
  "<!-- Copyright (C) 2018 The Android Open Source Project\n",
  "\n",
  "    Licensed under the Apache License, Version 2.0 (the \"License\");\n",
  "    you may not use this file except in compliance with the License.\n",
  "    You may obtain a copy of the License at\n",
  "\n",
  "        http://www.apache.org/licenses/LICENSE-2.0\n",
  "\n",
  "    Unless required by applicable law or agreed to in writing, software\n",
  "    distributed under the License is distributed on an \"AS IS\" BASIS,\n",
  "    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
  "    See the License for the specific language governing permissions and\n",
  "    limitations under the License.\n",
  "-->\n",
  "<permissions>\n",
  libraryTag,
  libNameAttr,
  filePathAttr,
  implicitFromAttr,
  implicitUntilAttr,
  minSdkAttr,
  maxSdkAttr,
  dependenciesAttr,
  "    />\n",
  "</permissions>\n",
 }, "")
}

func (module *sdkLibraryXml) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
 if !apexInfo.IsForPlatform() {
  module.HideFromMake()
 }

 libName := proptools.String(module.properties.Lib_name)
 module.selfValidate(ctx)
 xmlContent := module.permissionsContents(ctx)

 module.outputFilePath = android.PathForModuleOut(ctx, libName+".xml").OutputPath
 android.WriteFileRuleVerbatim(ctx, module.outputFilePath, xmlContent)

 module.installDirPath = android.PathForModuleInstall(ctx, "etc", module.SubDir())
 ctx.PackageFile(module.installDirPath, libName+".xml", module.outputFilePath)

 ctx.SetOutputFiles(android.OutputPaths{module.outputFilePath}.Paths(), "")

 etc.SetCommonPrebuiltEtcInfo(ctx, module)
}

func (module *sdkLibraryXml) PrepareAndroidMKProviderInfo(config android.Config) *android.AndroidMkProviderInfo {
 info := &android.AndroidMkProviderInfo{}
 info.PrimaryInfo = android.AndroidMkInfo{
  Class:      "ETC",
  OutputFile: android.OptionalPathForPath(module.outputFilePath),
 }
 info.PrimaryInfo.SetString("LOCAL_MODULE_TAGS", "optional")
 info.PrimaryInfo.SetString("LOCAL_MODULE_PATH", module.installDirPath.String())
 info.PrimaryInfo.SetString("LOCAL_INSTALLED_MODULE_STEM", module.outputFilePath.Base())

 return info
}

func (module *sdkLibraryXml) selfValidate(ctx android.ModuleContext) {
 module.validateAtLeastTAttributes(ctx)
 module.validateMinAndMaxDeviceSdk(ctx)
 module.validateMinMaxDeviceSdkAndModuleMinSdk(ctx)
 module.validateOnBootclasspathBeforeRequirements(ctx)
}

func (module *sdkLibraryXml) validateAtLeastTAttributes(ctx android.ModuleContext) {
 t := android.ApiLevelOrPanic(ctx, "Tiramisu")
 module.attrAtLeastT(ctx, t, module.properties.Min_device_sdk, "min_device_sdk")
 module.attrAtLeastT(ctx, t, module.properties.Max_device_sdk, "max_device_sdk")
 module.attrAtLeastT(ctx, t, module.properties.On_bootclasspath_before, "on_bootclasspath_before")
 module.attrAtLeastT(ctx, t, module.properties.On_bootclasspath_since, "on_bootclasspath_since")
}

func (module *sdkLibraryXml) attrAtLeastT(ctx android.ModuleContext, t android.ApiLevel, attr *string, attrName string) {
 if attr != nil {
  if level, err := android.ApiLevelFromUser(ctx, *attr); err == nil {
   // we will inform the user of invalid inputs when we try to write the
   // permissions xml file so we don't need to do it here
   if t.GreaterThan(level) {
    ctx.PropertyErrorf(attrName, "Attribute value needs to be at least T")
   }
  }
 }
}

func (module *sdkLibraryXml) validateMinAndMaxDeviceSdk(ctx android.ModuleContext) {
 if module.properties.Min_device_sdk != nil && module.properties.Max_device_sdk != nil {
  min, minErr := android.ApiLevelFromUser(ctx, *module.properties.Min_device_sdk)
  max, maxErr := android.ApiLevelFromUser(ctx, *module.properties.Max_device_sdk)
  if minErr == nil && maxErr == nil {
   // we will inform the user of invalid inputs when we try to write the
   // permissions xml file so we don't need to do it here
   if min.GreaterThan(max) {
    ctx.ModuleErrorf("min_device_sdk can't be greater than max_device_sdk")
   }
  }
 }
}

func (module *sdkLibraryXml) validateMinMaxDeviceSdkAndModuleMinSdk(ctx android.ModuleContext) {
 moduleMinApi := android.ApiLevelOrPanic(ctx, *module.properties.Sdk_library_min_api_level)
 if module.properties.Min_device_sdk != nil {
  api, err := android.ApiLevelFromUser(ctx, *module.properties.Min_device_sdk)
  if err == nil {
   if moduleMinApi.GreaterThan(api) {
    ctx.PropertyErrorf("min_device_sdk", "Can't be less than module's min sdk (%s)", moduleMinApi)
   }
  }
 }
 if module.properties.Max_device_sdk != nil {
  api, err := android.ApiLevelFromUser(ctx, *module.properties.Max_device_sdk)
  if err == nil {
   if moduleMinApi.GreaterThan(api) {
    ctx.PropertyErrorf("max_device_sdk", "Can't be less than module's min sdk (%s)", moduleMinApi)
   }
  }
 }
}

func (module *sdkLibraryXml) validateOnBootclasspathBeforeRequirements(ctx android.ModuleContext) {
 moduleMinApi := android.ApiLevelOrPanic(ctx, *module.properties.Sdk_library_min_api_level)
 if module.properties.On_bootclasspath_before != nil {
  t := android.ApiLevelOrPanic(ctx, "Tiramisu")
  // if we use the attribute, then we need to do this validation
  if moduleMinApi.LessThan(t) {
   // if minAPi is < T, then we need to have min_device_sdk (which only accepts T+)
   if module.properties.Min_device_sdk == nil {
    ctx.PropertyErrorf("on_bootclasspath_before", "Using this property requires that the module's min_sdk_version or the shared library's min_device_sdk is at least T")
   }
  }
 }
}

[Dauer der Verarbeitung: 0.23 Sekunden, vorverarbeitet 2026-06-28]