Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

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.28 Sekunden, vorverarbeitet 2026-06-28]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik