Eine aufbereitete Darstellung der Quelle

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

Benutzer

Quellcode-Bibliothek base.go   Sprache: unbekannt

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

// Copyright 2021 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"
 "maps"
 "path/filepath"
 "reflect"
 "slices"
 "strconv"
 "strings"

 "github.com/google/blueprint"
 "github.com/google/blueprint/depset"
 "github.com/google/blueprint/pathtools"
 "github.com/google/blueprint/proptools"

 "android/soong/android"
 "android/soong/dexpreopt"
 "android/soong/java/config"
)

//go:generate go run ../../blueprint/gobtools/codegen

// This file contains the definition and the implementation of the base module that most
// source-based Java module structs embed.

// TODO:
// Autogenerated files:
//  Renderscript
// Post-jar passes:
//  Proguard
// Rmtypedefs
// DroidDoc
// Findbugs

// Properties that are common to most Java modules, i.e. whether it's a host or device module.
type CommonProperties struct {
 // list of source files used to compile the Java module.  May be .java, .kt, .logtags, .proto,
 // or .aidl files.
 Srcs proptools.Configurable[[]string] `android:"path,arch_variant"`

 // list Kotlin of source files containing Kotlin code that should be treated as common code in
 // a codebase that supports Kotlin multiplatform.  See
 // https://kotlinlang.org/docs/reference/multiplatform.html.  May be only be .kt files.
 Common_srcs []string `android:"path,arch_variant"`

 // list of source files that should not be used to build the Java module.
 // This is most useful in the arch/multilib variants to remove non-common files
 Exclude_srcs proptools.Configurable[[]string] `android:"path,arch_variant"`

 // list of Kotlin source files that should excluded from the list of common_srcs.
 Exclude_common_srcs []string `android:"path,arch_variant"`

 // list of directories containing Java resources
 Java_resource_dirs []string `android:"arch_variant"`

 // list of directories that should be excluded from java_resource_dirs
 Exclude_java_resource_dirs []string `android:"arch_variant"`

 // list of files to use as Java resources
 Java_resources proptools.Configurable[[]string] `android:"path,arch_variant"`

 // list of files that should be excluded from java_resources and java_resource_dirs
 Exclude_java_resources []string `android:"path,arch_variant"`

 // Same as java_resources, but modules added here will use the device variant. Can be useful
 // for making a host test that tests the contents of a device built app.
 Device_common_java_resources proptools.Configurable[[]string] `android:"path_device_common"`

 // Same as java_resources, but modules added here will use the device's os variant and the
 // device's first architecture variant. Can be useful for making a host test that tests the
 // contents of a native device built app.
 Device_first_java_resources proptools.Configurable[[]string] `android:"path_device_first"`

 // list of module-specific flags that will be used for javac compiles
 Javacflags []string `android:"arch_variant"`

 // list of module-specific flags that will be used for kotlinc compiles
 Kotlincflags []string `android:"arch_variant"`

 // Kotlin language version to target. Currently only 1.9 and 2 are supported.
 // See kotlinc's `-language-version` flag.
 Kotlin_lang_version *string

 // Whether this target supports compilation with the kotlin-incremental-client.
 Kotlin_incremental *bool

 // Which annotation processor to use when working with kotlin: kapt or ksp. Defaults to false.
 Enable_ksp *bool

 // List of annotation processor options to pass in.
 Annotation_processor_flags []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 compiled into the resulting jar
 Static_libs proptools.Configurable[[]string] `android:"arch_variant"`

 // List of Kotlin libraries whose `internal` members are accessible to this library
 Associates []string `android:"arch_variant"`

 // manifest file to be included in resulting jar
 Manifest proptools.Configurable[string] `android:"path,replace_instead_of_append"`

 // if not blank, run jarjar using the specified rules file
 Jarjar_rules *string `android:"path,arch_variant"`

 // java class names to rename with jarjar when a reverse dependency has a jarjar_prefix
 // property.
 Jarjar_rename []string

 // if not blank, used as prefix to generate repackage rule
 Jarjar_prefix *string

 // Number of shards for jarjar. It needs to be an integer represented as a string.
 // TODO(b/383559945) change it to int, once Configurable supports the type.
 Jarjar_shards proptools.Configurable[string]

 // If not blank, set the java version passed to javac as -source and -target
 Java_version *string

 // If set to "warn" or "error", enables strict dependency checking for this module.
 // This ensures that the module only references classes that are provided by its direct
 // dependencies, preventing accidental usage of transitive dependencies.
 Strict_deps *string // "off", "warn", "error" (default: "off")

 // If set to true, allow this module to be dexed and installed on devices.  Has no
 // effect on host modules, which are always considered installable.
 Installable *bool

 // If set to true, include sources used to compile the module in to the final jar
 Include_srcs *bool

 // If not empty, classes are restricted to the specified packages and their sub-packages.
 // This restriction is checked after applying jarjar rules and including static libs.
 Permitted_packages []string

 // List of modules to use as annotation processors
 Plugins []string

 // List of modules to use as kotlin plugin
 Kotlin_plugins []string

 // List of modules to export to libraries that directly depend on this library as annotation
 // processors.  Note that if the plugins set generates_api: true this will disable the turbine
 // optimization on modules that depend on this module, which will reduce parallelism and cause
 // more recompilation.
 Exported_plugins []string

 // The number of Java source entries each Javac instance can process
 Javac_shard_size *int64

 // The number of shards to be used for processing srcJars
 Javac_srcjar_shards *int64

 // Add host jdk tools.jar to bootclasspath
 Use_tools_jar *bool

 Openjdk9 struct {
  // List of source files that should only be used when passing -source 1.9 or higher
  Srcs []string `android:"path"`

  // List of javac flags that should only be used when passing -source 1.9 or higher
  Javacflags []string
 }

 // When compiling language level 9+ .java code in packages that are part of
 // a system module, patch_module names the module that your sources and
 // dependencies should be patched into. The Android runtime currently
 // doesn't implement the JEP 261 module system so this option is only
 // supported at compile time. It should only be needed to compile tests in
 // packages that exist in libcore and which are inconvenient to move
 // elsewhere.
 Patch_module *string

 Jacoco struct {
  // List of classes to include for instrumentation with jacoco to collect coverage
  // information at runtime when building with coverage enabled.  If unset defaults to all
  // classes.
  // Supports '*' as the last character of an entry in the list as a wildcard match.
  // If preceded by '.' it matches all classes in the package and subpackages, otherwise
  // it matches classes in the package that have the class name as a prefix.
  Include_filter []string

  // List of classes to exclude from instrumentation with jacoco to collect coverage
  // information at runtime when building with coverage enabled.  Overrides classes selected
  // by the include_filter property.
  // Supports '*' as the last character of an entry in the list as a wildcard match.
  // If preceded by '.' it matches all classes in the package and subpackages, otherwise
  // it matches classes in the package that have the class name as a prefix.
  Exclude_filter []string
 }

 Errorprone struct {
  // List of javac flags that should only be used when running errorprone.
  Javacflags []string

  // List of java_plugin modules that provide extra errorprone checks.
  Extra_check_modules []string

  // This property can be in 3 states. When set to true, errorprone will
  // be run during the regular build. When set to false, errorprone will
  // never be run. When unset, errorprone will be run when the RUN_ERROR_PRONE
  // environment variable is true. Setting this to false will improve build
  // performance more than adding -XepDisableAllChecks in javacflags.
  Enabled *bool
 }

 Proto struct {
  // List of extra options that will be passed to the proto generator.
  Output_params []string
 }

 // If true, then jacocoagent is automatically added as a libs dependency so that
 // r8 will not strip instrumentation classes out of dexed libraries.
 Instrument bool `blueprint:"mutated"`
 // If true, then the module supports statically including the jacocoagent
 // into the library.
 Supports_static_instrumentation bool `blueprint:"mutated"`

 // List of files to include in the META-INF/services folder of the resulting jar.
 Services []string `android:"path,arch_variant"`

 // If true, package the kotlin stdlib into the jar.  Defaults to true.
 Static_kotlin_stdlib *bool `android:"arch_variant"`

 // A list of java_library instances that provide additional hiddenapi annotations for the library.
 Hiddenapi_additional_annotations []string

 // Additional srcJars tacked in by GeneratedJavaLibraryModule
 Generated_srcjars []android.Path `android:"mutated"`

 // intermediate aconfig cache file tacked in by GeneratedJavaLibraryModule
 Aconfig_Cache_files []android.Path `android:"mutated"`

 // If true, then only the headers are built and not the implementation jar.
 Headers_only *bool

 // If specified, this is used for this library's header jar, rather than generating it. This
 // should only be used if the library adds nothing new to the header jars vs the provided path.
 // For example, this could be used if the module only adds implementation code.
 Header_jar_override string `android:"path,arch_variant"`

 // A list of files or dependencies to make available to the build sandbox. This is
 // useful if source files are symlinks, the targets of the symlinks must be listed here.
 // Note that currently not all actions implemented by android_apps are sandboxed, so you
 // may only see this being necessary in lint builds.
 Compile_data []string `android:"path"`

 // Property signifying whether the module compiles stubs or not.
 // Should be set to true when srcs of this module are stub files.
 // This property does not need to be set to true when the module depends on
 // the stubs via libs, but should be set to true when the module depends on
 // the stubs via static libs.
 Is_stubs_module *bool

 Ravenizer struct {
  // If true, enable the "Ravenizer" tool on the output jar.
  // "Ravenizer" is a tool for Ravenwood tests, but it can also be enabled on other kinds
  // of java targets.
  Enabled *bool

  // If true, the "Ravenizer" tool will remove all Mockito and DexMaker
  // classes from the output jar.
  Strip_mockito *bool

  // Extra arguments passed to Ravenizer
  Flags []string
 }

 // Contributing api surface of the stub module. Is not visible to bp modules, and should
 // only be set for stub submodules generated by the java_sdk_library
 Stub_contributing_api *string `blueprint:"mutated"`

 // If true, enable the "ApiMapper" tool on the output jar. "ApiMapper" is a tool to inject
 // bytecode to log API calls.
 ApiMapper bool `blueprint:"mutated"`
}

// Properties that are specific to device modules. Host module factories should not add these when
// constructing a new module.
type DeviceProperties struct {
 // If not blank, set to the version of the sdk to compile against.
 // Defaults to an empty string, which compiles the module against the private platform APIs.
 // Values are of one of the following forms:
 // 1) numerical API level, "current", "none", or "core_platform"
 // 2) An SDK kind with an API level: "<sdk kind>_<API level>"
 // See build/soong/android/sdk_version.go for the complete and up to date list of SDK kinds.
 // If the SDK kind is empty, it will be set to public.
 Sdk_version *string

 // if not blank, set the maximum version of the sdk that the compiled artifacts will run against.
 // Defaults to empty string "". See sdk_version for possible values.
 Max_sdk_version *string

 // if not blank, set the maxSdkVersion properties of permission and uses-permission tags.
 // Defaults to empty string "". See sdk_version for possible values.
 Replace_max_sdk_version_placeholder *string

 // if not blank, set the targetSdkVersion in the AndroidManifest.xml.
 // Defaults to sdk_version if not set. See sdk_version for possible values.
 Target_sdk_version *string

 // Whether to compile against the platform APIs instead of an SDK.
 // If true, then sdk_version must be empty. The value of this field
 // is ignored when module's type isn't android_app, android_test, or android_test_helper_app.
 Platform_apis *bool

 Aidl struct {
  // Top level directories to pass to aidl tool
  Include_dirs []string

  // Directories rooted at the Android.bp file to pass to aidl tool
  Local_include_dirs []string

  // directories that should be added as include directories for any aidl sources of modules
  // that depend on this module, as well as to aidl for this module.
  Export_include_dirs []string

  // whether to generate traces (for systrace) for this interface
  Generate_traces *bool

  // whether to generate Binder#GetTransaction name method.
  Generate_get_transaction_name *bool

  // whether all interfaces should be annotated with required permissions.
  Enforce_permissions *bool

  // allowlist for interfaces that (temporarily) do not require annotation for permissions.
  Enforce_permissions_exceptions []string `android:"path"`

  // list of flags that will be passed to the AIDL compiler
  Flags []string
 }

 // If true, export a copy of the module as a -hostdex module for host testing.
 Hostdex *bool

 Target struct {
  Hostdex struct {
   // Additional required dependencies to add to -hostdex modules.
   Required []string
  }
 }

 // When targeting 1.9 and above, override the modules to use with --system,
 // otherwise provides defaults libraries to add to the bootclasspath.
 System_modules *string

 IsSDKLibrary bool `blueprint:"mutated"`

 // If true, generate the signature file of APK Signing Scheme V4, along side the signed APK file.
 // Defaults to false.
 V4_signature *bool

 // Only for libraries created by a sysprop_library module, SyspropPublicStub is the name of the
 // public stubs library.
 SyspropPublicStub string `blueprint:"mutated"`

 HiddenAPIPackageProperties
 HiddenAPIFlagFileProperties
}

// Properties that can be overridden by overriding module (e.g. override_android_app)
type OverridableProperties struct {
 // set the name of the output. If not set, `name` is used.
 // To override a module with this property set, overriding module might need to set this as well.
 // Otherwise, both the overridden and the overriding modules will have the same output name, which
 // can cause the duplicate output error.
 Stem *string

 // if not blank, set the minimum version of the sdk that the compiled artifacts will run against.
 // Defaults to sdk_version if not set. See sdk_version for possible values.
 Min_sdk_version proptools.Configurable[string] `android:"replace_instead_of_append"`
}

// Functionality common to Module and Import
//
// It is embedded in Module so its functionality can be used by methods in Module
// but it is currently only initialized by Import and Library.
type embeddableInModuleAndImport struct {

 // Functionality related to this being used as a component of a java_sdk_library.
 EmbeddableSdkLibraryComponent
}

func (e *embeddableInModuleAndImport) initModuleAndImport(module android.Module) {
 e.initSdkLibraryComponent(module)
}

// Module/Import's OutgoingDepIsInSameApex(...) delegates to this method.
//
// This cannot implement OutgoingDepIsInSameApex(...) directly as that leads to ambiguity with
// the one provided by ApexModuleBase.
func depIsInSameApex(tag blueprint.DependencyTag) bool {
 // dependencies other than the static linkage are all considered crossing APEX boundary
 if tag == staticLibTag {
  return true
 }
 return false
}

// OptionalDexJarPath can be either unset, hold a valid path to a dex jar file,
// or an invalid path describing the reason it is invalid.
//
// It is unset if a dex jar isn't applicable, i.e. no build rule has been
// requested to create one.
//
// If a dex jar has been requested to be built then it is set, and it may be
// either a valid android.Path, or invalid with a reason message. The latter
// happens if the source that should produce the dex file isn't able to.
//
// E.g. it is invalid with a reason message if there is a prebuilt APEX that
// could produce the dex jar through a deapexer module, but the APEX isn't
// installable so doing so wouldn't be safe.
// @auto-generate: gob
type OptionalDexJarPath struct {
 isSet bool
 path  android.OptionalPath
}

// IsSet returns true if a path has been set, either invalid or valid.
func (o OptionalDexJarPath) IsSet() bool {
 return o.isSet
}

// Valid returns true if there is a path that is valid.
func (o OptionalDexJarPath) Valid() bool {
 return o.isSet && o.path.Valid()
}

// Path returns the valid path, or panics if it's either not set or is invalid.
func (o OptionalDexJarPath) Path() android.Path {
 if !o.isSet {
  panic("path isn't set")
 }
 return o.path.Path()
}

// PathOrNil returns the path if it's set and valid, or else nil.
func (o OptionalDexJarPath) PathOrNil() android.Path {
 if o.Valid() {
  return o.Path()
 }
 return nil
}

// InvalidReason returns the reason for an invalid path, which is never "". It
// returns "" for an unset or valid path.
func (o OptionalDexJarPath) InvalidReason() string {
 if !o.isSet {
  return ""
 }
 return o.path.InvalidReason()
}

func (o OptionalDexJarPath) String() string {
 if !o.isSet {
  return "<unset>"
 }
 return o.path.String()
}

// makeUnsetDexJarPath returns an unset OptionalDexJarPath.
func makeUnsetDexJarPath() OptionalDexJarPath {
 return OptionalDexJarPath{isSet: false}
}

// makeDexJarPathFromOptionalPath returns an OptionalDexJarPath that is set with
// the given OptionalPath, which may be valid or invalid.
func makeDexJarPathFromOptionalPath(path android.OptionalPath) OptionalDexJarPath {
 return OptionalDexJarPath{isSet: true, path: path}
}

// makeDexJarPathFromPath returns an OptionalDexJarPath that is set with the
// valid given path. It returns an unset OptionalDexJarPath if the given path is
// nil.
func makeDexJarPathFromPath(path android.Path) OptionalDexJarPath {
 if path == nil {
  return makeUnsetDexJarPath()
 }
 return makeDexJarPathFromOptionalPath(android.OptionalPathForPath(path))
}

// Module contains the properties and members used by all java module types
type Module struct {
 android.ModuleBase
 android.DefaultableModuleBase
 android.ApexModuleBase
 // TODO(b/461815001): remove this and replace usage of WalkDepsProxy with
 //  VisitDirectDepsProxy and DepSets.
 blueprint.ModuleUsesIncrementalWalkDeps

 // Functionality common to Module and Import.
 embeddableInModuleAndImport

 properties       CommonProperties
 protoProperties  android.ProtoProperties
 deviceProperties DeviceProperties

 overridableProperties OverridableProperties
 sourceProperties      android.SourceProperties

 // jar file containing header classes including static library dependencies, suitable for
 // inserting into the bootclasspath/classpath of another compile
 headerJarFile android.Path

 // jar file containing implementation classes including static library dependencies but no
 // resources
 implementationJarFile android.Path

 // args and dependencies to package source files into a srcjar
 srcJarArgs []string
 srcJarDeps android.Paths

 // directClasspath contains just the direct dependencies for strict deps verification.
 directClasspath classpath

 kSnapshotFiles     map[string]android.Path
 skipKSnapshotFiles map[string]bool

 // the source files of this module and all its static dependencies
 transitiveSrcFiles depset.DepSet[android.Path]

 // jar file containing implementation classes and resources including static library
 // dependencies
 implementationAndResourcesJar android.Path

 // output file containing classes.dex and resources
 dexJarFile OptionalDexJarPath

 // output file containing uninstrumented classes that will be instrumented by jacoco
 jacocoInfo JacocoInfo

 // output file of the module, which may be a classes jar or a dex jar
 outputFile          android.Path
 installedOutputFile android.Path
 extraOutputFiles    android.Paths

 exportAidlIncludeDirs     android.Paths
 ignoredAidlPermissionList android.Paths

 logtagsSrcs android.Paths

 // installed file for binary dependency
 installFile android.Path

 // installed file for hostdex copy
 hostdexInstallFile android.InstallPath

 // list of unique .java and .kt source files
 uniqueSrcFiles android.Paths

 // list of .aidl source files
 aidlSrcs android.Paths

 // list of .proto source files
 protoSrcs android.Paths

 // list of srcjars that was passed to javac
 compiledSrcJars android.Paths

 // manifest file to use instead of properties.Manifest
 overrideManifest android.OptionalPath

 // list of plugins that this java module is exporting
 exportedPluginJars android.Paths

 // list of plugins that this java module is exporting
 exportedPluginClasses []string

 // if true, the exported plugins generate API and require disabling turbine.
 exportedDisableTurbine bool

 // list of source files, collected from srcFiles with unique java and all kt files,
 // will be used by android.IDEInfo struct
 expandIDEInfoCompiledSrcs []string

 // expanded Jarjar_rules
 expandJarjarRules android.Path

 // jarjar rule for inherited jarjar rules
 repackageJarjarRules android.Path

 // Extra files generated by the module type to be added as java resources.
 extraResources android.Paths

 // Extra src or jars for compile()
 extraSrcJars         android.Paths
 extraClasspathJars   android.Paths
 extraCombinedJars    android.Paths
 extraDepCombinedJars android.Paths

 hiddenAPI
 dexer
 dexpreopter
 usesLibrary
 linter

 // list of the xref extraction files
 kytheFiles       android.Paths
 kytheKotlinFiles android.Paths

 sdkVersion    android.SdkSpec
 minSdkVersion android.ApiLevel
 maxSdkVersion android.ApiLevel

 sourceExtensions []string

 annoSrcJars android.Paths

 // output file name based on Stem property.
 // This should be set in every ModuleWithStem's GenerateAndroidBuildActions
 // or the module should override Stem().
 stem string

 // Values that will be set in the JarJarProvider data for jarjar repackaging,
 // and merged with our dependencies' rules.
 jarjarRenameRules map[string]string

 stubsLinkType StubsLinkType

 // Paths to the aconfig intermediate cache files that are provided by the
 // java_aconfig_library or java_library modules that are statically linked
 // to this module. Does not contain cache files from all transitive dependencies.
 aconfigCacheFiles android.Paths

 // List of soong module dependencies required to compile the current module.
 // This information is printed out to `Dependencies` field in module_bp_java_deps.json
 compileDepNames []string

 ravenizer struct {
  enabled bool
 }
}

var _ android.InstallableModule = (*Module)(nil)

// To satisfy the InstallableModule interface
func (j *Module) StaticDependencyTags() []blueprint.DependencyTag {
 return []blueprint.DependencyTag{staticLibTag}
}

// To satisfy the InstallableModule interface
func (j *Module) DynamicDependencyTags() []blueprint.DependencyTag {
 return []blueprint.DependencyTag{libTag, sdkLibTag, bootClasspathTag, systemModulesTag,
  instrumentationForTag, java9LibTag}
}

// Overrides android.ModuleBase.InstallInProduct()
func (j *Module) InstallInProduct() bool {
 return j.ProductSpecific()
}

var _ android.StubsAvailableModule = (*Module)(nil)

// To safisfy the StubsAvailableModule interface
func (j *Module) IsStubsModule() bool {
 return proptools.Bool(j.properties.Is_stubs_module)
}

func CheckStableSdkVersion(ctx android.BaseModuleContext, module android.ModuleProxy) error {
 if info, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
  if info.SdkVersion.Stable() {
   return nil
  }
  if info.SdkVersion.Kind == android.SdkCorePlatform {
   if useLegacyCorePlatformApi(ctx, android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).BaseModuleName) {
    return fmt.Errorf("non stable SDK %v - uses legacy core platform", info.SdkVersion)
   } else {
    // Treat stable core platform as stable.
    return nil
   }
  } else {
   return fmt.Errorf("non stable SDK %v", info.SdkVersion)
  }
 }

 return nil
}

// checkSdkVersions enforces restrictions around SDK dependencies.
func (j *Module) checkSdkVersions(ctx android.ModuleContext) {
 if j.RequiresStableAPIs(ctx) {
  if sc, ok := ctx.Module().(android.SdkContext); ok {
   if !sc.SdkVersion(ctx).Specified() {
    ctx.PropertyErrorf("sdk_version",
     "sdk_version must have a value when the module is located at vendor or product(only if PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE is set).")
   }
  }
 }

 // Make sure this module doesn't statically link to modules with lower-ranked SDK link type.
 // See rank() for details.
 ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
  tag := ctx.OtherModuleDependencyTag(module)
  libInfo, isJavaLibrary := android.OtherModuleProvider(ctx, module, JavaLibraryInfoProvider)
  _, isAndroidLibrary := android.OtherModuleProvider(ctx, module, AndroidLibraryInfoProvider)
  _, isJavaAconfigLibrary := android.OtherModuleProvider(ctx, module, android.CodegenInfoProvider)
  // Exclude java_aconfig_library modules to maintain consistency with existing behavior.
  if (isJavaLibrary && !libInfo.Prebuilt && !isJavaAconfigLibrary) || isAndroidLibrary {
   // TODO(satayev): cover other types as well, e.g. imports
   switch tag {
   case bootClasspathTag, sdkLibTag, libTag, staticLibTag, java9LibTag:
    j.checkSdkLinkType(ctx, module)
   }
  }
 })
}

func (j *Module) checkPlatformAPI(ctx android.ModuleContext) {
 if sc, ok := ctx.Module().(android.SdkContext); ok {
  usePlatformAPI := proptools.Bool(j.deviceProperties.Platform_apis)
  sdkVersionSpecified := sc.SdkVersion(ctx).Specified()
  if usePlatformAPI && sdkVersionSpecified {
   ctx.PropertyErrorf("platform_apis", "This module has conflicting settings. sdk_version is not empty, which means this module cannot use platform APIs. However platform_apis is set to true.")
  } else if !usePlatformAPI && !sdkVersionSpecified {
   ctx.PropertyErrorf("platform_apis", "This module has conflicting settings. sdk_version is empty, which means that this module is build against platform APIs. However platform_apis is not set to true")
  }

 }
}

func (j *Module) checkHeadersOnly(ctx android.ModuleContext) {
 if _, ok := ctx.Module().(android.SdkContext); ok {
  headersOnly := proptools.Bool(j.properties.Headers_only)
  installable := proptools.Bool(j.properties.Installable)

  if headersOnly && installable {
   ctx.PropertyErrorf("headers_only", "This module has conflicting settings. headers_only is true which, which means this module doesn't generate an implementation jar. However installable is set to true.")
  }
 }
}

func (j *Module) addHostProperties() {
 j.AddProperties(
  &j.properties,
  &j.overridableProperties,
  &j.protoProperties,
  &j.usesLibraryProperties,
 )
}

func (j *Module) addHostAndDeviceProperties() {
 j.addHostProperties()
 j.AddProperties(
  &j.deviceProperties,
  &j.dexer.dexProperties,
  &j.dexpreoptProperties,
  &j.linter.properties,
 )
}

// provideHiddenAPIPropertyInfo populates a HiddenAPIPropertyInfo from hidden API properties and
// makes it available through the hiddenAPIPropertyInfoProvider.
func (j *Module) provideHiddenAPIPropertyInfo(ctx android.ModuleContext) {
 hiddenAPIInfo := newHiddenAPIPropertyInfo()

 // Populate with flag file paths from the properties.
 hiddenAPIInfo.extractFlagFilesFromProperties(ctx, &j.deviceProperties.HiddenAPIFlagFileProperties)

 // Populate with package rules from the properties.
 hiddenAPIInfo.extractPackageRulesFromProperties(ctx, &j.deviceProperties.HiddenAPIPackageProperties)

 android.SetProvider(ctx, hiddenAPIPropertyInfoProvider, hiddenAPIInfo)
}

// helper method for java modules to set OutputFilesProvider
func setOutputFiles(ctx android.ModuleContext, m *Module) {
 ctx.SetOutputFiles(append(android.PathsIfNonNil(m.outputFile), m.extraOutputFiles...), "")
 ctx.SetOutputFiles(android.PathsIfNonNil(m.outputFile), android.DefaultDistTag)
 ctx.SetOutputFiles(android.PathsIfNonNil(m.implementationAndResourcesJar), ".jar")
 ctx.SetOutputFiles(android.PathsIfNonNil(m.headerJarFile), ".hjar")
 if m.dexer.proguardDictionary.Valid() {
  ctx.SetOutputFiles(android.Paths{m.dexer.proguardDictionary.Path()}, ".proguard_map")
 }
 if m.dexpreopter.outputProfilePathOnHost != nil {
  ctx.SetOutputFiles(android.Paths{m.dexpreopter.outputProfilePathOnHost}, ".dexpreopt_prof")
 }
 ctx.SetOutputFiles(m.properties.Generated_srcjars, ".generated_srcjars")
}

func InitJavaModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
 initJavaModule(module, hod, false)
}

func InitJavaModuleMultiTargets(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
 initJavaModule(module, hod, true)
}

func initJavaModule(module android.DefaultableModule, hod android.HostOrDeviceSupported, multiTargets bool) {
 multilib := android.MultilibCommon
 if multiTargets {
  android.InitAndroidMultiTargetsArchModule(module, hod, multilib)
 } else {
  android.InitAndroidArchModule(module, hod, multilib)
 }
 android.InitDefaultableModule(module)
}

func (j *Module) shouldInstrument(ctx android.BaseModuleContext) bool {
 return j.properties.Instrument &&
  ctx.Config().IsEnvTrue("EMMA_INSTRUMENT") &&
  ctx.DeviceConfig().JavaCoverageEnabledForPath(ctx.ModuleDir())
}

func (j *Module) shouldApiMapper() bool {
 return j.properties.ApiMapper
}

func (j *Module) shouldInstrumentStatic(ctx android.BaseModuleContext) bool {
 return j.properties.Supports_static_instrumentation &&
  j.shouldInstrument(ctx) &&
  (ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_STATIC") ||
   ctx.Config().UnbundledBuild())
}

func (j *Module) shouldInstrumentInApex(ctx android.BaseModuleContext) bool {
 // Force enable the instrumentation for java code that is built for APEXes ...
 // except for the jacocoagent itself (because instrumenting jacocoagent using jacocoagent
 // doesn't make sense) or framework libraries (e.g. libraries found in the InstrumentFrameworkModules list) unless EMMA_INSTRUMENT_FRAMEWORK is true.
 apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
 isJacocoAgent := ctx.ModuleName() == "jacocoagent"

 compileDex := Bool(j.dexProperties.Compile_dex) || Bool(j.properties.Installable)
 if compileDex && !isJacocoAgent && !apexInfo.IsForPlatform() {
  if !inList(ctx.ModuleName(), config.InstrumentFrameworkModules) {
   return true
  } else if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
   return true
  }
 }
 return false
}

func (j *Module) setInstrument(value bool) {
 j.properties.Instrument = value
}

func (j *Module) setApiMapper(value bool) {
 j.properties.ApiMapper = value
}

func (j *Module) SdkVersion(ctx android.ConfigContext) android.SdkSpec {
 return android.SdkSpecFrom(ctx, String(j.deviceProperties.Sdk_version))
}

func (j *Module) SystemModules() string {
 return proptools.String(j.deviceProperties.System_modules)
}

func (j *Module) MinSdkVersion(ctx android.MinSdkVersionFromValueContext) android.ApiLevel {
 minSdkVersion := j.overridableProperties.Min_sdk_version.Get(j.ConfigurableEvaluator(ctx))
 if minSdkVersion.IsPresent() {
  return android.ApiLevelFrom(ctx, minSdkVersion.Get())
 }
 return j.SdkVersion(ctx).ApiLevel
}

func (j *Module) GetDeviceProperties() *DeviceProperties {
 return &j.deviceProperties
}

func (j *Module) MaxSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
 if j.deviceProperties.Max_sdk_version != nil {
  return android.ApiLevelFrom(ctx, *j.deviceProperties.Max_sdk_version)
 }
 // Default is PrivateApiLevel
 return android.SdkSpecPrivate.ApiLevel
}

func (j *Module) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel {
 if j.deviceProperties.Replace_max_sdk_version_placeholder != nil {
  return android.ApiLevelFrom(ctx, *j.deviceProperties.Replace_max_sdk_version_placeholder)
 }
 // Default is PrivateApiLevel
 return android.SdkSpecPrivate.ApiLevel
}

func (j *Module) MinSdkVersionString() string {
 return j.minSdkVersion.String()
}

func (j *Module) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
 if j.deviceProperties.Target_sdk_version != nil {
  return android.ApiLevelFrom(ctx, *j.deviceProperties.Target_sdk_version)
 }
 return j.SdkVersion(ctx).ApiLevel
}

func (j *Module) AvailableFor(what string) bool {
 return android.CheckAvailableForApex(what, j.ApexAvailableFor())
}

func (j *Module) ApexAvailableFor() []string {
 list := j.ApexModuleBase.ApexAvailable()
 if Bool(j.deviceProperties.Hostdex) {
  // Exception: for hostdex: true libraries, the platform variant is created
  // even if it's not marked as available to platform. In that case, the platform
  // variant is used only for the hostdex and not installed to the device.
  list = append(list, android.AvailableToPlatform)
 }
 return android.FirstUniqueStrings(list)
}

func (j *Module) libs(ctx android.BaseModuleContext) []string {
 return j.properties.Libs.GetOrDefault(ctx, nil)
}

func (j *Module) staticLibs(ctx android.BaseModuleContext) []string {
 return j.properties.Static_libs.GetOrDefault(ctx, nil)
}

func (j *Module) incrementalKotlin(config android.Config) bool {
 incremental := proptools.BoolDefault(
  j.properties.Kotlin_incremental, config.PartialCompileFlags().Enable_inc_kotlin)
 nonIncrementalFlags := []string{"-Xmulti-platform", "-Xexpect-actual-classes"}
 for _, flag := range nonIncrementalFlags {
  incremental = incremental && !slices.Contains(j.properties.Kotlincflags, flag)
 }

 return incremental
}

func (j *Module) useKsp() bool {
 return proptools.BoolDefault(j.properties.Enable_ksp, false)
}

func (j *Module) deps(ctx android.BottomUpMutatorContext) {
 j.dexpreopter.DepsMutator(ctx)
 j.setOptimizeForceDisabled(proptools.Bool(j.properties.Is_stubs_module))
 if ctx.Device() {
  j.linter.deps(ctx)

  compileDex := proptools.Bool(j.properties.Installable) || proptools.Bool(j.dexProperties.Compile_dex)
  addR8DexDeps := compileDex && !j.dexer.isOptimizeForceDisabled(ctx)
  sdkDeps(ctx, android.SdkContext(j), addR8DexDeps)

  if j.deviceProperties.SyspropPublicStub != "" {
   // This is a sysprop implementation library that has a corresponding sysprop public
   // stubs library, and a dependency on it so that dependencies on the implementation can
   // be forwarded to the public stubs library when necessary.
   ctx.AddVariationDependencies(nil, syspropPublicStubDepTag, j.deviceProperties.SyspropPublicStub)
  }
 }

 libDeps := ctx.AddVariationDependencies(nil, libTag, j.libs(ctx)...)

 ctx.AddVariationDependencies(nil, staticLibTag, j.staticLibs(ctx)...)

 // Add dependency on libraries that provide additional hidden api annotations.
 ctx.AddVariationDependencies(nil, hiddenApiAnnotationsTag, j.properties.Hiddenapi_additional_annotations...)

 // Add dependency on (soft) downstream libs from which to trace references during optimization.
 traceRefs := j.dexProperties.Optimize.Trace_references_from.GetOrDefault(ctx, []string{})
 ctx.AddVariationDependencies(nil, traceReferencesTag, traceRefs...)

 j.usesLibrary.depsFromLibs(ctx, libDeps)

 ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), pluginTag, j.properties.Plugins...)
 ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), kotlinPluginTag, j.properties.Kotlin_plugins...)
 ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), exportedPluginTag, j.properties.Exported_plugins...)

 if j.properties.Strict_deps != nil && (*j.properties.Strict_deps == "warn" || *j.properties.Strict_deps == "error") {
  ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), javaStrictDepsPluginTag, "soong_java_strict_deps_plugin")
  ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), kotlinStrictDepsPluginTag, "soong_kotlin_strict_deps_plugin")
 }

 epEnabled := j.properties.Errorprone.Enabled
 if (ctx.Config().RunErrorProne() && epEnabled == nil) || Bool(epEnabled) {
  ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), errorpronePluginTag, "error_prone_plugin")
  ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), errorpronePluginTag, j.properties.Errorprone.Extra_check_modules...)
 }

 android.ProtoDeps(ctx, &j.protoProperties)
 if j.hasSrcExt(ctx, ".proto") {
  protoDeps(ctx, &j.protoProperties)
 }

 if j.hasSrcExt(ctx, ".kt") {
  // TODO(ccross): move this to a mutator pass that can tell if generated sources contain
  // Kotlin files
  tag := staticLibTag
  if !BoolDefault(j.properties.Static_kotlin_stdlib, true) {
   tag = libTag
  }
  ctx.AddVariationDependencies(nil, tag,
   "kotlin-stdlib", "kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8", "kotlin-annotations")
 }

 // Framework libraries need special handling in static coverage builds: they should not have
 // static dependency on jacoco, otherwise there would be multiple conflicting definitions of
 // the same jacoco classes coming from different bootclasspath jars.
 if inList(ctx.ModuleName(), config.InstrumentFrameworkModules) {
  if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
   j.properties.Instrument = true
  }
 } else if j.shouldInstrumentStatic(ctx) {
  ctx.AddVariationDependencies(nil, staticLibTag, "jacocoagent")
 }

 incremental := j.incrementalKotlin(ctx.Config())
 if j.useCompose(ctx) {
  if incremental {
   ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), composeEmbeddablePluginTag,
    "kotlin-compose-compiler-embeddable-plugin")
  }
  ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), composePluginTag,
   "kotlin-compose-compiler-plugin")
 }

 j.EmbeddableSdkLibraryComponent.setComponentDependencyInfoProvider(ctx)

 ctx.AddHostToolDependencies("cp_if_changed")
}

func hasSrcExt(srcs []string, ext string) bool {
 for _, src := range srcs {
  if filepath.Ext(src) == ext {
   return true
  }
 }

 return false
}

func (j *Module) hasSrcExt(ctx android.ConfigurableEvaluatorContext, ext string) bool {
 return hasSrcExt(j.properties.Srcs.GetOrDefault(j.ConfigurableEvaluator(ctx), nil), ext)
}

func (j *Module) individualAidlFlags(ctx android.ModuleContext, aidlFile android.Path) string {
 var flags string

 if Bool(j.deviceProperties.Aidl.Enforce_permissions) {
  if !android.InList(aidlFile.String(), j.ignoredAidlPermissionList.Strings()) {
   flags = "-Wmissing-permission-annotation -Werror"
  }
 }
 return flags
}

func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.OptionalPath,
 aidlIncludeDirs android.Paths, aidlSrcs android.Paths) (string, android.Paths) {

 aidlIncludes := android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Local_include_dirs)
 aidlIncludes = append(aidlIncludes,
  android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)...)
 aidlIncludes = append(aidlIncludes,
  android.PathsForSource(ctx, j.deviceProperties.Aidl.Include_dirs)...)

 var flags []string
 var deps android.Paths
 var includeDirs android.Paths

 flags = append(flags, j.deviceProperties.Aidl.Flags...)

 if aidlPreprocess.Valid() {
  flags = append(flags, "-p"+aidlPreprocess.String())
  deps = append(deps, aidlPreprocess.Path())
 } else if len(aidlIncludeDirs) > 0 {
  includeDirs = append(includeDirs, aidlIncludeDirs...)
 }

 if len(j.exportAidlIncludeDirs) > 0 {
  includeDirs = append(includeDirs, j.exportAidlIncludeDirs...)
 }

 if len(aidlIncludes) > 0 {
  includeDirs = append(includeDirs, aidlIncludes...)
 }

 includeDirs = append(includeDirs, android.PathForModuleSrc(ctx))
 if src := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "src"); src.Valid() {
  includeDirs = append(includeDirs, src.Path())
 }
 flags = append(flags, android.JoinWithPrefix(includeDirs.Strings(), "-I"))
 // add flags for dirs containing AIDL srcs that haven't been specified yet
 flags = append(flags, genAidlIncludeFlags(ctx, aidlSrcs, includeDirs))

 sdkVersion := (j.SdkVersion(ctx)).Kind
 defaultTrace := ((sdkVersion == android.SdkSystemServer) || (sdkVersion == android.SdkCore) || (sdkVersion == android.SdkCorePlatform) || (sdkVersion == android.SdkModule) || (sdkVersion == android.SdkSystem))
 if proptools.BoolDefault(j.deviceProperties.Aidl.Generate_traces, defaultTrace) {
  flags = append(flags, "-t")
 }

 if Bool(j.deviceProperties.Aidl.Generate_get_transaction_name) {
  flags = append(flags, "--transaction_names")
 }

 if Bool(j.deviceProperties.Aidl.Enforce_permissions) {
  exceptions := j.deviceProperties.Aidl.Enforce_permissions_exceptions
  j.ignoredAidlPermissionList = android.PathsForModuleSrcExcludes(ctx, exceptions, nil)
 }

 aidlMinSdkVersion := j.MinSdkVersion(ctx)

 // Cap the API level for vendor modules to 34.
 if j.InstallInVendor() {
  vendorCap := android.ApiLevelFrom(ctx, "34")
  if vendorCap.LessThan(aidlMinSdkVersion) {
   aidlMinSdkVersion = vendorCap
  }
 }

 flags = append(flags, "--min_sdk_version="+aidlMinSdkVersion.String())

 return strings.Join(flags, " "), deps
}

func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaBuilderFlags {

 var flags javaBuilderFlags

 // javaVersion flag.
 flags.javaVersion = getJavaVersion(ctx, String(j.properties.Java_version), android.SdkContext(j))

 epEnabled := j.properties.Errorprone.Enabled
 if (ctx.Config().RunErrorProne() && epEnabled == nil) || Bool(epEnabled) {
  if config.ErrorProneFlags == nil && !ctx.Config().RunningInsideUnitTest() {
   ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?")
  }

  errorProneFlags := []string{
   "-Xplugin:ErrorProne",
   "${config.ErrorProneChecks}",
  }
  errorProneFlags = append(errorProneFlags, j.properties.Errorprone.Javacflags...)

  flags.errorProneExtraJavacFlags = "${config.ErrorProneHeapFlags} ${config.ErrorProneFlags} " +
   "'" + strings.Join(errorProneFlags, " ") + "'"
 }

 if j.properties.Strict_deps != nil && (*j.properties.Strict_deps == "warn" || *j.properties.Strict_deps == "error") {
  flags.strictDepsLevel = *j.properties.Strict_deps
 }

 // classpath
 flags.bootClasspath = append(flags.bootClasspath, deps.bootClasspath...)
 flags.classpath = append(flags.classpath, deps.classpath...)
 flags.directClasspath = append(flags.directClasspath, deps.directClasspath...)
 flags.javaStrictDepsPluginJars = append(flags.javaStrictDepsPluginJars, deps.javaStrictDepsPluginJars...)
 flags.kotlinStrictDepsPluginJars = append(flags.kotlinStrictDepsPluginJars, deps.kotlinStrictDepsPluginJars...)
 flags.dexClasspath = append(flags.dexClasspath, deps.dexClasspath...)
 flags.java9Classpath = append(flags.java9Classpath, deps.java9Classpath...)
 flags.processorPath = append(flags.processorPath, deps.processorPath...)
 flags.errorProneProcessorPath = append(flags.errorProneProcessorPath, deps.errorProneProcessorPath...)

 flags.processors = append(flags.processors, deps.processorClasses...)
 flags.processors = android.FirstUniqueStrings(flags.processors)

 if len(flags.bootClasspath) == 0 && ctx.Host() && !flags.javaVersion.usesJavaModules() &&
  decodeSdkDep(ctx, android.SdkContext(j)).hasStandardLibs() {
  // Give host-side tools a version of OpenJDK's standard libraries
  // close to what they're targeting. As of Dec 2017, AOSP is only
  // bundling OpenJDK 8 and 9, so nothing < 8 is available.
  //
  // When building with OpenJDK 8, the following should have no
  // effect since those jars would be available by default.
  //
  // When building with OpenJDK 9 but targeting a version < 1.8,
  // putting them on the bootclasspath means that:
  // a) code can't (accidentally) refer to OpenJDK 9 specific APIs
  // b) references to existing APIs are not reinterpreted in an
  //    OpenJDK 9-specific way, eg. calls to subclasses of
  //    java.nio.Buffer as in http://b/70862583
  java8Home := ctx.Config().Getenv("ANDROID_JAVA8_HOME")
  flags.bootClasspath = append(flags.bootClasspath,
   android.PathForSource(ctx, java8Home, "jre/lib/jce.jar"),
   android.PathForSource(ctx, java8Home, "jre/lib/rt.jar"))
  if Bool(j.properties.Use_tools_jar) {
   flags.bootClasspath = append(flags.bootClasspath,
    android.PathForSource(ctx, java8Home, "lib/tools.jar"))
  }
 }

 // systemModules
 flags.systemModules = deps.systemModules

 flags.kSnapshotFiles = deps.kSnapshotFiles

 return flags
}

func (j *Module) collectJavacFlags(
 ctx android.ModuleContext, flags javaBuilderFlags, srcFiles android.Paths) javaBuilderFlags {
 // javac flags.
 javacFlags := j.properties.Javacflags
 var needsDebugInfo bool

 needsDebugInfo = false
 for _, flag := range javacFlags {
  if strings.HasPrefix(flag, "-g") {
   needsDebugInfo = true
  }
 }

 if ctx.Config().MinimizeJavaDebugInfo() && !ctx.Host() && !needsDebugInfo {
  // For non-host binaries, override the -g flag passed globally to remove
  // local variable debug info to reduce disk and memory usage.
  javacFlags = append(javacFlags, "-g:source,lines")
 }
 javacFlags = append(javacFlags, "-Xlint:-dep-ann")

 if flags.javaVersion.usesJavaModules() {
  javacFlags = append(javacFlags, j.properties.Openjdk9.Javacflags...)
 } else if len(j.properties.Openjdk9.Javacflags) > 0 {
  // java version defaults higher than openjdk 9, these conditionals should no longer be necessary
  ctx.PropertyErrorf("openjdk9.javacflags", "JDK version defaults to higher than 9")
 }

 if flags.javaVersion.usesJavaModules() {
  if j.properties.Patch_module != nil {
   // Manually specify build directory in case it is not under the repo root.
   // (javac doesn't seem to expand into symbolic links when searching for patch-module targets, so
   // just adding a symlink under the root doesn't help.)
   patchPathDirs := []string{android.PathForModuleOut(ctx).String()}
   for _, srcFile := range srcFiles {
    srcDir := filepath.Dir(srcFile.String())
    if !slices.Contains(patchPathDirs, srcDir) {
     patchPathDirs = append(patchPathDirs, srcDir)
    }
   }
   patchPathDirs = append(patchPathDirs, flags.classpath.Strings()...)
   patchPathFlag := "--patch-module=" + String(j.properties.Patch_module) + "=" + strings.Join(patchPathDirs, ":")
   patchPathFlagFile := android.PathForModuleOut(ctx, "javac", "patch_module_paths")
   android.WriteFileRule(ctx, patchPathFlagFile, patchPathFlag)
   javacFlags = append(javacFlags, "@"+patchPathFlagFile.String())
   flags.javacFlagsDeps = append(flags.javacFlagsDeps, patchPathFlagFile)
  }
 }

 if !srcFiles.HasExt(".kt") || !j.useKsp() {
  for _, apFlag := range j.properties.Annotation_processor_flags {
   javacFlags = append(javacFlags, "-A"+apFlag)
  }
 }

 if len(javacFlags) > 0 {
  // optimization.
  ctx.Variable(pctx, "javacFlags", strings.Join(javacFlags, " "))
  flags.javacFlags = "$javacFlags"
 }

 return flags
}

func (j *Module) addGeneratedSrcJars(path android.Path) {
 j.properties.Generated_srcjars = append(j.properties.Generated_srcjars, path)
}

func (j *Module) compile(ctx android.ModuleContext) *JavaInfo {

 manifest := j.overrideManifest
 manifestFromProp := j.properties.Manifest.GetOrDefault(ctx, "")
 if !manifest.Valid() && manifestFromProp != "" {
  manifest = android.OptionalPathForPath(android.PathForModuleSrc(ctx, manifestFromProp))
 }

 // Auto-propagating jarjar rules
 jarjarProviderData := j.collectJarJarRules(ctx)
 if jarjarProviderData != nil {
  android.SetProvider(ctx, JarJarProvider, *jarjarProviderData)
  text := getJarJarRuleText(jarjarProviderData)
  if text != "" {
   ruleTextFile := android.PathForModuleOut(ctx, "repackaged-jarjar", "repackaging.txt")
   android.WriteFileRule(ctx, ruleTextFile, text)
   j.repackageJarjarRules = ruleTextFile
  }
 }

 j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)

 // Only override the original value if explicitly set
 if j.properties.Ravenizer.Enabled != nil {
  j.ravenizer.enabled = *j.properties.Ravenizer.Enabled
 }

 deps := j.collectDeps(ctx)
 j.directClasspath = deps.directClasspath
 j.kSnapshotFiles = deps.kSnapshotFiles
 j.skipKSnapshotFiles = make(map[string]bool)
 if j.extraClasspathJars != nil {
  for _, jar := range j.extraClasspathJars {
   j.addKSnapshot(ctx, jar)
  }
 }
 if j.extraCombinedJars != nil {
  for _, jar := range j.extraCombinedJars {
   j.addKSnapshot(ctx, jar)
  }
 }
 flags := j.collectBuilderFlags(ctx, deps)

 if flags.javaVersion.usesJavaModules() {
  j.properties.Srcs.AppendSimpleValue(j.properties.Openjdk9.Srcs)
 } else if len(j.properties.Openjdk9.Javacflags) > 0 {
  // java version defaults higher than openjdk 9, these conditionals should no longer be necessary
  ctx.PropertyErrorf("openjdk9.srcs", "JDK version defaults to higher than 9")
 }

 srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs.GetOrDefault(ctx, nil),
  j.properties.Exclude_srcs.GetOrDefault(ctx, nil))
 j.sourceExtensions = []string{}
 for _, ext := range []string{".kt", ".proto", ".aidl", ".java", ".logtags"} {
  if hasSrcExt(srcFiles.Strings(), ext) {
   j.sourceExtensions = append(j.sourceExtensions, ext)
  }
 }
 if hasSrcExt(srcFiles.Strings(), ".proto") {
  flags = protoFlags(ctx, &j.properties, &j.protoProperties, flags)
  j.protoSrcs = srcFiles.FilterByExt(".proto")
 }

 kotlinCommonSrcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Common_srcs, j.properties.Exclude_common_srcs)
 if len(kotlinCommonSrcFiles.FilterOutByExt(".kt")) > 0 {
  ctx.PropertyErrorf("common_srcs", "common_srcs must be .kt files")
 }

 aidlSrcs := srcFiles.FilterByExt(".aidl")
 j.aidlSrcs = aidlSrcs
 flags.aidlFlags, flags.aidlDeps = j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs, aidlSrcs)

 nonGeneratedSrcJars := srcFiles.FilterByExt(".srcjar")
 srcFiles = j.genSources(ctx, srcFiles, flags)

 // Collect javac flags only after computing the full set of srcFiles to
 // ensure that the --patch-module lookup paths are complete.
 flags = j.collectJavacFlags(ctx, flags, srcFiles)

 srcJars := srcFiles.FilterByExt(".srcjar")
 srcJars = append(srcJars, deps.srcJars...)
 srcJars = append(srcJars, j.extraSrcJars...)
 srcJars = append(srcJars, j.properties.Generated_srcjars...)
 srcFiles = srcFiles.FilterOutByExt(".srcjar")

 if j.properties.Jarjar_rules != nil {
  j.expandJarjarRules = android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
 }

 jarName := j.Stem() + ".jar"

 var uniqueJavaFiles android.Paths
 set := make(map[string]bool)
 for _, v := range srcFiles.FilterByExt(".java") {
  if _, found := set[v.String()]; !found {
   set[v.String()] = true
   uniqueJavaFiles = append(uniqueJavaFiles, v)
  }
 }
 var uniqueKtFiles android.Paths
 for _, v := range srcFiles.FilterByExt(".kt") {
  if _, found := set[v.String()]; !found {
   set[v.String()] = true
   uniqueKtFiles = append(uniqueKtFiles, v)
  }
 }

 var uniqueSrcFiles android.Paths
 uniqueSrcFiles = append(uniqueSrcFiles, uniqueJavaFiles...)
 uniqueSrcFiles = append(uniqueSrcFiles, uniqueKtFiles...)
 j.uniqueSrcFiles = uniqueSrcFiles

 // We don't currently run annotation processors in turbine, which means we can't use turbine
 // generated header jars when an annotation processor that generates API is enabled.  One
 // exception (handled further below) is when kotlin sources are enabled, in which case turbine
 // is used to run all of the annotation processors.
 disableTurbine := deps.disableTurbine

 // Collect .java and .kt files for AIDEGen
 j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, uniqueSrcFiles.Strings()...)

 var kotlinHeaderJars android.Paths

 // Prepend extraClasspathJars to classpath so that the resource processor R.jar comes before
 // any dependencies so that it can override any non-final R classes from dependencies with the
 // final R classes from the app.
 flags.classpath = append(android.CopyOf(j.extraClasspathJars), flags.classpath...)

 j.aconfigCacheFiles = append(deps.aconfigProtoFiles, j.properties.Aconfig_Cache_files...)

 var localImplementationJars android.Paths
 var localImplementationJarsContainsDependencies bool

 // If compiling headers then compile them and skip the rest
 if proptools.Bool(j.properties.Headers_only) {
  if srcFiles.HasExt(".kt") {
   ctx.ModuleErrorf("Compiling headers_only with .kt not supported")
  }
  if ctx.Config().IsEnvFalse("TURBINE_ENABLED") || disableTurbine {
   ctx.ModuleErrorf("headers_only is enabled but Turbine is disabled.")
  }

  transitiveStaticLibsHeaderJars := deps.transitiveStaticLibsHeaderJars

  localHeaderJars, _, preJarjarHeaderJarFile := j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName,
   j.extraCombinedJars, manifest)

  combinedHeaderJarFile, jarjared := j.jarjarIfNecessary(ctx, preJarjarHeaderJarFile, jarName, "turbine", false)
  combinedHeaderJarFile, _ = j.repackageFlagsIfNecessary(ctx, combinedHeaderJarFile, jarName, "repackage-turbine")
  if jarjared {
   localHeaderJars = android.Paths{combinedHeaderJarFile}
   transitiveStaticLibsHeaderJars = nil
  } else {
   // Repackaging rules (from jarjar_prefix) are strictly renames, making it safe
   // to process on individual thin jars without pruning or atomicity conflicts
   // (unlike explicit `jarjar_rules` which can contain `keep`/`zap` rules).
   for i, jar := range localHeaderJars {
    distinctName := strings.TrimSuffix(jarName, ".jar") + "." + strconv.Itoa(i) + ".jar"
    repackagedJar, _ := j.repackageFlagsIfNecessary(ctx, jar, distinctName, "repackage-turbine")
    localHeaderJars[i] = repackagedJar
   }
  }

  if ctx.Failed() {
   return nil
  }
  j.headerJarFile = combinedHeaderJarFile
  if deps.headerJarOverride.Valid() {
   j.headerJarFile = deps.headerJarOverride.Path()
  } else {
   j.addKSnapshot(ctx, j.headerJarFile)
  }

  if len(localHeaderJars) > 0 {
   ctx.CheckbuildFile(localHeaderJars...)
  } else {
   // There are no local sources or resources in this module, so there is nothing to checkbuild.
   ctx.UncheckedModule()
  }

  for _, hj := range localHeaderJars {
   j.addKSnapshot(ctx, hj)
  }

  overridableMinSdkVersion := j.overridableProperties.Min_sdk_version.Get(ctx)

  j.outputFile = j.headerJarFile
  return &JavaInfo{
   HeaderJars:                          android.PathsIfNonNil(j.headerJarFile),
   LocalHeaderJarsPreJarjar:            android.PathsIfNonNil(preJarjarHeaderJarFile),
   LocalHeaderJars:                     localHeaderJars,
   TransitiveStaticLibsHeaderJars:      depset.New(depset.PREORDER, localHeaderJars, transitiveStaticLibsHeaderJars),
   TransitiveLibsHeaderJarsForR8:       j.transitiveLibsHeaderJarsForR8,
   TransitiveStaticLibsHeaderJarsForR8: j.transitiveStaticLibsHeaderJarsForR8,
   AidlIncludeDirs:                     j.exportAidlIncludeDirs,
   ExportedPlugins:                     j.exportedPluginJars,
   ExportedPluginClasses:               j.exportedPluginClasses,
   ExportedPluginDisableTurbine:        j.exportedDisableTurbine,
   StubsLinkType:                       j.stubsLinkType,
   AconfigIntermediateCacheOutputPaths: deps.aconfigProtoFiles,
   SdkVersion:                          j.SdkVersion(ctx),
   HasOverrideMinSdkVersion:            overridableMinSdkVersion.IsPresent(),
   Installable:                         BoolDefault(j.properties.Installable, true),
   KSnapshotFiles:                      j.kSnapshotFiles,
  }
 }

 var crossModuleHeaderJars android.Paths
 if ctx.Config().PartialCompileFlags().Enable_inc_kotlin_java_dep {
  crossModuleHeaderJars = android.Paths{}
 }

 if srcFiles.HasExt(".kt") {
  // When using kotlin+kapt, turbine is used to generate annotation processor sources.
  // For ksp, all annotation processing is handled by ksp directory.
  // In either case, annotation processors that generate API are run, so we can later use
  // turbine to generate java headers.
  disableTurbine = false

  // user defined kotlin flags.
  kotlincFlags := j.properties.Kotlincflags
  CheckKotlincFlags(ctx, kotlincFlags)

  // Available kotlin versions can be found at
  // https://github.com/JetBrains/kotlin/blob/master/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt#L560
  // in the `LanguageVersion` class.
  // For now, avoid targeting language versions directly, as we'd like to kee our source
  // code version aligned as much as possible. Ideally, after defaulting to "2", we
  // can remove the "1.9" option entirely, or at least make it emit a warning.
  kotlin_default_lang_version := "2"
  if build_flag_lang_version, ok := ctx.Config().GetBuildFlag("RELEASE_KOTLIN_LANG_VERSION"); ok {
   kotlin_default_lang_version = build_flag_lang_version
  }
  kotlin_lang_version := proptools.StringDefault(j.properties.Kotlin_lang_version, kotlin_default_lang_version)
  switch kotlin_lang_version {
  case "1.9":
   kotlincFlags = append(kotlincFlags, "-language-version 1.9")
  case "2":
   kotlincFlags = append(kotlincFlags, "-Xsuppress-version-warnings", "-Xconsistent-data-class-copy-visibility")
  default:
   ctx.PropertyErrorf("kotlin_lang_version", "Must be one of `1.9` or `2`")
  }

  // Workaround for KT-46512
  kotlincFlags = append(kotlincFlags, "-Xsam-conversions=class")

  // If there are kotlin files, compile them first but pass all the kotlin and java files
  // kotlinc will use the java files to resolve types referenced by the kotlin files, but
  // won't emit any classes for them.
  kotlincFlags = append(kotlincFlags, "-no-stdlib")
  if ctx.Device() {
   kotlincFlags = append(kotlincFlags, "-no-jdk")
  }

  var kotlincPluginFlags []string
  for _, plugin := range deps.kotlinPlugins {
   kotlincPluginFlags = append(kotlincPluginFlags, "-Xplugin="+plugin.String())
  }
  if len(kotlincPluginFlags) > 0 {
   // optimization.
   ctx.Variable(pctx, "kotlincPluginFlags", strings.Join(kotlincPluginFlags, " "))
   flags.kotlincPluginFlags += "$kotlincPluginFlags"
  }
  flags.kotlincDeps = append(flags.kotlincDeps, deps.kotlinPlugins...)

  if deps.composePlugin.Valid() {
   flags.composePluginFlag = "-Xplugin=" + deps.composePlugin.String()
   ctx.Variable(pctx, "composePluginFlag", flags.composePluginFlag)
   flags.kotlincDeps = append(flags.kotlincDeps, deps.composePlugin.Path())
  }
  if deps.composeEmbeddablePlugin.Valid() {
   flags.composeEmbeddablePluginFlag = "-Xplugin=" + deps.composeEmbeddablePlugin.String()
   ctx.Variable(pctx, "composeEmbeddablePluginFlag", flags.composeEmbeddablePluginFlag)
   flags.kotlincDeps = append(flags.kotlincDeps, deps.composeEmbeddablePlugin.Path())
  }

  if len(kotlincFlags) > 0 {
   // Flags with `-J` as a prefix are meant to be passed to java directly.
   // When running the kotlin-incremental-client, flags are first parsed by a bash
   // script that eagerly takes all the leading arguments that start with `-J` and feeds
   // them to java. Any `-J` arguments that occur elsewhere (i.e. after a non-J argument)
   // fail to pass through to java as expected.
   slices.SortStableFunc(kotlincFlags, func(a, b string) int {
    aHasPrefix := strings.HasPrefix(a, "-J")
    bHasPrefix := strings.HasPrefix(b, "-J")

    // If only a has the prefix, it should come before b
    if aHasPrefix && !bHasPrefix {
     return -1
    } else if bHasPrefix && !aHasPrefix {
     return 1
    }
    return 0 // Otherwise maintain their order
   })
   // optimization.
   ctx.Variable(pctx, "kotlincFlags", strings.Join(kotlincFlags, " "))
   flags.kotlincFlags += "$kotlincFlags"
  }

  incrementalKotlin := j.incrementalKotlin(ctx.Config())

  // Collect common .kt files for AIDEGen
  j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, kotlinCommonSrcFiles.Strings()...)

  flags.kotlincClasspath = append(flags.kotlincClasspath, flags.bootClasspath...)
  flags.kotlincClasspath = append(flags.kotlincClasspath, flags.classpath...)

  kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName)
  kotlinHeaderJar := android.PathForModuleOut(ctx, "kotlin_headers", jarName)

  kotlinCompileData := KotlinCompileData{
   diffFile:         kotlinJar.ReplaceExtension(ctx, "source_diff"),
   pcStateFileNew:   kotlinJar.ReplaceExtension(ctx, "pc_state.new"),
   pcStateFilePrior: kotlinJar.ReplaceExtension(ctx, "pc_state"),
  }

  // kotlinSrcJars is just srcJars, but potentially with additional .kt sources appended
  // to it that should not be passed on to javac.
  kotlinSrcJars := srcJars

  if len(flags.processorPath) > 0 {
   if j.useKsp() {
    kspJavaSrcJar := android.PathForModuleOut(ctx, "ksp", "ksp-java-sources.srcjar")
    kspKotlinSrcJar := android.PathForModuleOut(ctx, "ksp", "ksp-kotlin-sources.srcjar")
    kspResJar := android.PathForModuleOut(ctx, "ksp", "ksp-res.jar")
    kspClassJar := android.PathForModuleOut(ctx, "ksp", "ksp-classes.jar")

    kspStub := android.PathForModuleOut(ctx, "ksp", jarName)
    kspCompileData := KotlinCompileData{
     diffFile:         kspStub.ReplaceExtension(ctx, "source_diff"),
     pcStateFileNew:   kspStub.ReplaceExtension(ctx, "pc_state.new"),
     pcStateFilePrior: kspStub.ReplaceExtension(ctx, "pc_state"),
    }

    j.kotlinKsp(ctx, kspJavaSrcJar, kspKotlinSrcJar, kspResJar, kspClassJar, j.properties.Annotation_processor_flags,
     uniqueSrcFiles, kotlinCommonSrcFiles, srcJars, kspCompileData, flags)
    srcJars = append(srcJars, kspJavaSrcJar)
    kotlinSrcJars = append(srcJars, kspKotlinSrcJar)
    localImplementationJars = append(localImplementationJars, kspResJar, kspClassJar)
    // Disable annotation processing in javac, it's already been handled by kapt
    flags.processorPath = nil
    flags.processors = nil

    j.addKSnapshot(ctx, kspClassJar)
   } else {
    // Use kapt for annotation processing
    kaptSrcJar := android.PathForModuleOut(ctx, "kapt", "kapt-sources.jar")
    kaptResJar := android.PathForModuleOut(ctx, "kapt", "kapt-res.jar")
    kotlinKapt(ctx, kaptSrcJar, kaptResJar, uniqueSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
    srcJars = append(srcJars, kaptSrcJar)
    kotlinSrcJars = srcJars
    localImplementationJars = append(localImplementationJars, kaptResJar)
    // Disable annotation processing in javac, it's already been handled by kapt
    flags.processorPath = nil
    flags.processors = nil

    j.addKSnapshot(ctx, kaptSrcJar)
    j.addKSnapshot(ctx, kaptResJar)
   }
  }

  j.kotlinCompile(ctx, kotlinJar, kotlinHeaderJar, uniqueSrcFiles, kotlinCommonSrcFiles, kotlinSrcJars, flags,
   manifest, kotlinCompileData, incrementalKotlin)
  if ctx.Failed() {
   return nil
  }

  kotlinJarPath, _ := j.repackageFlagsIfNecessary(ctx, kotlinJar, jarName, "kotlinc")

  // Let java compile incrementally based on changes in the kotlin jar.
  if crossModuleHeaderJars != nil {
   crossModuleHeaderJars = append(crossModuleHeaderJars, kotlinHeaderJar)
  }

  // Make javac rule depend on the kotlinc rule
  flags.classpath = append(classpath{kotlinHeaderJar}, flags.classpath...)

  localImplementationJars = append(localImplementationJars, kotlinJarPath)

  kotlinHeaderJars = append(kotlinHeaderJars, kotlinHeaderJar)
  j.addKSnapshot(ctx, kotlinHeaderJar)
 }

 j.compiledSrcJars = srcJars

 transitiveStaticLibsHeaderJars := deps.transitiveStaticLibsHeaderJars

 enableSharding := false
 var localHeaderJars android.Paths
 var shardingHeaderJars android.Paths
 var repackagedHeaderJarFile android.Path
 var combinedHeaderJarFile android.Path
 var genAnnoSrcJars android.Paths

 hasErrorproneableFiles := false
 if len(uniqueJavaFiles) > 0 || len(srcJars) > 0 {
  for _, ext := range j.sourceExtensions {
   if ext != ".proto" && ext != ".aidl" {
    // Skip running errorprone on pure proto or pure aidl modules. Some modules take a long time to
    // compile, and it's not useful to have warnings on these generated sources.
    hasErrorproneableFiles = true
    break
   }
  }
 }

 errorproneExplicitlyEnabled := Bool(j.properties.Errorprone.Enabled)
 errorProneEnabled := hasErrorproneableFiles && ctx.Config().RunErrorProne() && j.properties.Errorprone.Enabled == nil

 if ctx.Device() && !ctx.Config().IsEnvFalse("TURBINE_ENABLED") && !disableTurbine {
  if j.properties.Javac_shard_size != nil && *(j.properties.Javac_shard_size) > 0 {
   enableSharding = true
   // Formerly, there was a check here that prevented annotation processors
   // from being used when sharding was enabled, as some annotation processors
   // do not function correctly in sharded environments. It was removed to
   // allow for the use of annotation processors that do function correctly
   // with sharding enabled. See: b/77284273.
  }
  extraJars := slices.Clone(kotlinHeaderJars)
  extraJars = append(extraJars, j.extraCombinedJars...)
  // if we are not sharding, let's first run turbine APT, generate some sources + res, hand them to turbine, plus pass them to javac
  srcJarsForTurbine := slices.Clone(srcJars)
  errorPronePlanned := errorproneExplicitlyEnabled || errorProneEnabled
  if !enableSharding && ctx.Config().GetBuildFlagBool("RELEASE_USE_TURBINE_APT_JAVAC") {
   if len(flags.processorPath) > 0 {
    turbineAptSrcJar := android.PathForModuleOut(ctx, "turbine-apt", "turbine-apt-sources.jar")
    turbineAptResJar := android.PathForModuleOut(ctx, "turbine-apt", "turbine-apt-res.jar")
    TurbineApt(ctx, turbineAptSrcJar, turbineAptResJar, uniqueJavaFiles, srcJars, flags)
    // if errorProne is going to be attempted, let's use javac for AP as there
    // are certain processors that are tied with errorprone. We still pass
    // turbine-apt generated sources to turbine, in case API generating APs
    // were being used.
    srcJarsForTurbine = append(srcJarsForTurbine, turbineAptSrcJar)
    if !errorPronePlanned {
     genAnnoSrcJars = append(genAnnoSrcJars, turbineAptSrcJar)
     localImplementationJars = append(localImplementationJars, turbineAptResJar)
     // Disable annotation processing in javac, it's already been handled here
     flags.processorPath = nil
     flags.processors = nil
    }
   }
  }
  localHeaderJars, shardingHeaderJars, combinedHeaderJarFile = j.compileJavaHeader(ctx, uniqueJavaFiles, srcJarsForTurbine, deps, flags, jarName, extraJars, manifest)

  var jarjared bool
  j.headerJarFile, jarjared = j.jarjarIfNecessary(ctx, combinedHeaderJarFile, jarName, "turbine", false)
  if jarjared {
   // jarjar modifies transitive static dependencies, use the combined header jar and drop the transitive
   // static libs header jars.
   localHeaderJars = android.Paths{j.headerJarFile}
   transitiveStaticLibsHeaderJars = nil
  }
  repackagedHeaderJarFile, _ = j.repackageFlagsIfNecessary(ctx, j.headerJarFile, jarName, "turbine")
  updatedLocalHeaderJars := android.Paths{}
  // Repackaging rules (from jarjar_prefix) are strictly renames, making it safe
  // to process on individual thin jars without pruning or atomicity conflicts
  // (unlike explicit `jarjar_rules` which can contain `keep`/`zap` rules).
  for i, jar := range localHeaderJars {
   // TODO(b/356688296): this shouldn't export both the unmodified and repackaged header jars
   distinctName := strings.TrimSuffix(jarName, ".jar") + "." + strconv.Itoa(i) + ".jar"
   repackagedJar, repackaged := j.repackageFlagsIfNecessary(ctx, jar, distinctName, "repackage-turbine")
   if repackaged {
    updatedLocalHeaderJars = append(updatedLocalHeaderJars, jar, repackagedJar)
   } else {
    updatedLocalHeaderJars = append(updatedLocalHeaderJars, jar)
   }
  }
  localHeaderJars = updatedLocalHeaderJars
 }
 if len(uniqueJavaFiles) > 0 || len(srcJars) > 0 {
  // turbine is disabled when API generating APs are present, in which case,
  // we would want to process annotations before moving to incremental javac
  if ctx.Device() && ctx.Config().PartialCompileFlags().Enable_inc_javac && disableTurbine {
   srcJarsForTurbine := slices.Clone(srcJars)
   if len(flags.processorPath) > 0 {
    genAnnoSrcJar, genResJar := j.generateJavaAnnotations(ctx, jarName, -1, uniqueJavaFiles, srcJars, flags, nil)
    flags.processorPath = nil
    flags.processors = nil
    genAnnoSrcJars = append(genAnnoSrcJars, genAnnoSrcJar)
    localImplementationJars = append(localImplementationJars, genResJar)
    srcJarsForTurbine = append(srcJarsForTurbine, genAnnoSrcJars...)
   }
   // turbine was disabled, lets run it now
   turbineExtraJars := slices.Clone(kotlinHeaderJars)
   turbineExtraJars = append(turbineExtraJars, j.extraCombinedJars...)
   _, shardingHeaderJars, _ = j.compileJavaHeader(ctx, uniqueJavaFiles, srcJarsForTurbine, deps, flags, jarName,
    turbineExtraJars, manifest)
  }

  var extraJarDeps android.Paths
  if errorproneExplicitlyEnabled {
   // If error-prone is enabled, enable errorprone flags on the regular
   // build.
   flags = enableErrorproneFlags(flags)
  } else if errorProneEnabled {
   if ctx.Config().RunErrorProneInline() {
    // On CI, we're not going to toggle back/forth between errorprone and non-errorprone
    // builds, so it's faster if we don't compile the module twice and instead always
    // compile the module with errorprone.
    flags = enableErrorproneFlags(flags)
   } else {
    // Otherwise, if the RUN_ERROR_PRONE environment variable is set, create
    // a new jar file just for compiling with the errorprone compiler to.
    // This is because we don't want to cause the java files to get completely
    // rebuilt every time the state of the RUN_ERROR_PRONE variable changes.
    // We also don't want to run this if errorprone is enabled by default for
    // this module, or else we could have duplicated errorprone messages.
    errorproneFlags := enableErrorproneFlags(flags)
    errorprone := android.PathForModuleOut(ctx, "errorprone", jarName)
    errorproneAnnoSrcJar := android.PathForModuleOut(ctx, "errorprone", "anno.srcjar")

    transformJavaToClasses(ctx, errorprone, -1, uniqueJavaFiles, srcJars, errorproneAnnoSrcJar, false, errorproneFlags, nil,
     "errorprone", "errorprone", nil)

    extraJarDeps = append(extraJarDeps, errorprone)
   }
  }

  if enableSharding {
   if len(shardingHeaderJars) > 0 {
    flags.classpath = append(classpath(slices.Clone(shardingHeaderJars)), flags.classpath...)
   }
   shardSize := int(*(j.properties.Javac_shard_size))
   var shardSrcs []android.Paths
   if len(uniqueJavaFiles) > 0 {
    shardSrcs = android.ShardPaths(uniqueJavaFiles, shardSize)
    for idx, shardSrc := range shardSrcs {
     classes := j.compileJavaClasses(ctx, jarName, idx, shardSrc,
      nil, nil, crossModuleHeaderJars, flags, extraJarDeps, nil)
     classes, _ = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac-"+strconv.Itoa(idx))
     localImplementationJars = append(localImplementationJars, classes)
    }
   }
   if len(srcJars) > 0 {
    // Assume approximately 5 sources per srcjar.
    // For framework-minus-apex in AOSP at the time this was written, there are 266 srcjars, with a mean
    // of 5.8 sources per srcjar, but a median of 1, a standard deviation of 10, and a max of 48 source files.
    shardSrcJarsList := android.ShardPaths(srcJars, shardSize/5)
    startIdx := len(shardSrcs)
    if j.properties.Javac_srcjar_shards != nil && *(j.properties.Javac_srcjar_shards) > 0 && ctx.Config().GetBuildFlagBool("RELEASE_BALANCE_JAVAC_SRCJAR_SHARDS") {
     srcJarShards := int(*(j.properties.Javac_srcjar_shards))
     shardSrcJarsList = []android.Paths{}
     var srcJarSplits android.WritablePaths
     for idx := 0; idx < srcJarShards; idx++ {
      srcJarSplit := android.PathForModuleOut(ctx, "javac", "srcjars"+strconv.Itoa(startIdx+idx)+".jar")
      srcJarSplits = append(srcJarSplits, srcJarSplit)
      shardSrcJarsList = append(shardSrcJarsList, android.Paths{srcJarSplit})
     }
     ctx.Build(pctx, android.BuildParams{
      Rule:        splitSrcJars,
      Description: "javacSplitSrcJars",
      Inputs:      srcJars,
      Outputs:     srcJarSplits,
      Args: map[string]string{
       "rspFile": android.PathForModuleOut(ctx, "javac", "srcjars.rsp").String(),
      },
     })
    }
    for idx, shardSrcJars := range shardSrcJarsList {
     classes := j.compileJavaClasses(ctx, jarName, startIdx+idx,
      nil, shardSrcJars, nil, crossModuleHeaderJars, flags, extraJarDeps, nil)
     classes, _ = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac-"+strconv.Itoa(startIdx+idx))
     localImplementationJars = append(localImplementationJars, classes)
    }
   }
  } else {
   classes := j.compileJavaClasses(ctx, jarName, -1, uniqueJavaFiles, srcJars, shardingHeaderJars, crossModuleHeaderJars, flags, extraJarDeps, genAnnoSrcJars)
   classes, _ = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac")
   localImplementationJars = append(localImplementationJars, classes)
  }
  if ctx.Failed() {
   return nil
  }
 }

 localImplementationJars = append(localImplementationJars, j.extraCombinedJars...)

 j.srcJarArgs, j.srcJarDeps = resourcePathsToJarArgs(srcFiles), srcFiles

 var includeSrcJar android.WritablePath
 if Bool(j.properties.Include_srcs) {
  includeSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+".srcjar")
  TransformResourcesToJar(ctx, includeSrcJar, j.srcJarArgs, j.srcJarDeps)
 }

 dirArgs, dirDeps := ResourceDirsToJarArgs(ctx, j.properties.Java_resource_dirs,
  j.properties.Exclude_java_resource_dirs, j.properties.Exclude_java_resources)
 fileArgs, fileDeps := ResourceFilesToJarArgs(ctx, j.properties.Java_resources.GetOrDefault(ctx, nil), j.properties.Exclude_java_resources)
 fileArgs2, fileDeps2 := ResourceFilesToJarArgs(ctx, j.properties.Device_common_java_resources.GetOrDefault(ctx, nil), nil)
 fileArgs3, fileDeps3 := ResourceFilesToJarArgs(ctx, j.properties.Device_first_java_resources.GetOrDefault(ctx, nil), nil)
 fileArgs = slices.Concat(fileArgs, fileArgs2, fileArgs3)
 fileDeps = slices.Concat(fileDeps, fileDeps2, fileDeps3)
 extraArgs, extraDeps := resourcePathsToJarArgs(j.extraResources), j.extraResources

 var resArgs []string
 var resDeps android.Paths

 resArgs = append(resArgs, dirArgs...)
 resDeps = append(resDeps, dirDeps...)

 resArgs = append(resArgs, fileArgs...)
 resDeps = append(resDeps, fileDeps...)

 resArgs = append(resArgs, extraArgs...)
 resDeps = append(resDeps, extraDeps...)

 var localResourceJars android.Paths
 if len(resArgs) > 0 {
  resourceJar := android.PathForModuleOut(ctx, "res", jarName)
  TransformResourcesToJar(ctx, resourceJar, resArgs, resDeps)
  if ctx.Failed() {
   return nil
  }
  localResourceJars = append(localResourceJars, resourceJar)
 }

 if Bool(j.properties.Include_srcs) {
  localResourceJars = append(localResourceJars, includeSrcJar)
 }

 services := android.PathsForModuleSrc(ctx, j.properties.Services)
 if len(services) > 0 {
  servicesJar := android.PathForModuleOut(ctx, "services", jarName)
  var zipargs []string
  for _, file := range services {
   serviceFile := file.String()
   zipargs = append(zipargs, "-C", filepath.Dir(serviceFile), "-f", serviceFile)
  }
  rule := zip
  args := map[string]string{
   "jarArgs": "-P META-INF/services/ " + strings.Join(proptools.NinjaAndShellEscapeList(zipargs), " "),
  }
  if ctx.Config().UseREWrapper() && ctx.Config().IsEnvTrue("RBE_ZIP") {
   rule = zipRE
   args["implicits"] = strings.Join(services.Strings(), ",")
  }
  ctx.Build(pctx, android.BuildParams{
   Rule:      rule,
   Output:    servicesJar,
   Implicits: services,
   Args:      args,
  })
  localResourceJars = append(localResourceJars, servicesJar)
 }

 completeStaticLibsResourceJars := depset.New(depset.PREORDER, localResourceJars, deps.transitiveStaticLibsResourceJars)

 var combinedResourceJar android.Path
 resourceJars := completeStaticLibsResourceJars.ToList()
 if len(resourceJars) == 1 {
  combinedResourceJar = resourceJars[0]
 } else if len(resourceJars) > 0 {
  combinedJar := android.PathForModuleOut(ctx, "res-combined", jarName)
  TransformJarsToJar(ctx, combinedJar, "for resources", resourceJars, android.OptionalPath{},
   false, nil, nil)
  combinedResourceJar = combinedJar
 }

 // Combine the classes built from sources, any manifests, and any static libraries into
 // classes.jar. If there is only one input jar this step will be skipped.
 var outputFile android.Path
 completeStaticLibsImplementationJars := depset.New(depset.PREORDER, localImplementationJars, deps.transitiveStaticLibsImplementationJars)

 jars := completeStaticLibsImplementationJars.ToList()

 jars = append(jars, j.extraDepCombinedJars...)

 if len(jars) == 1 && !manifest.Valid() {
  // Optimization: skip the combine step as there is nothing to do
  // TODO(ccross): this leaves any module-info.class files, but those should only come from
  // prebuilt dependencies until we support modules in the platform build, so there shouldn't be
  // any if len(extraJars) == 0.

  // moduleStubLinkType determines if the module is the TopLevelStubLibrary generated
  // from sdk_library. The TopLevelStubLibrary contains only one static lib,
  // either with .from-source or .from-text suffix.
  // outputFile should be agnostic to the build configuration,
  // thus copy the single input static lib in order to prevent the static lib from being exposed
  // to the copy rules.
  if stub, _ := moduleStubLinkType(j); stub {
   copiedJar := android.PathForModuleOut(ctx, "combined", jarName)
   ctx.Build(pctx, android.BuildParams{
    Rule:   android.CpRule,
    Input:  jars[0],
    Output: copiedJar,
   })
   completeStaticLibsImplementationJars = depset.New(depset.PREORDER, android.Paths{copiedJar}, nil)
   outputFile = copiedJar
  } else {
   outputFile = jars[0]
   // Don't ksnap this output. It was done elsewhere.
   j.skipKSnapshot(jars[0])
  }
 } else {
  combinedJar := android.PathForModuleOut(ctx, "combined", jarName)
  TransformJarsToJar(ctx, combinedJar, "for javac", jars, manifest,
   false, nil, nil)
  outputFile = combinedJar
 }

 // jarjar implementation jar if necessary
 jarjarFile, jarjarred := j.jarjarIfNecessary(ctx, outputFile, jarName, "", true)
 if jarjarred {
  localImplementationJars = android.Paths{jarjarFile}
  completeStaticLibsImplementationJars = depset.New(depset.PREORDER, localImplementationJars, nil)
  localImplementationJarsContainsDependencies = true
 }
 outputFile = jarjarFile

 // jarjar resource jar if necessary
 if combinedResourceJar != nil {
  resourceJarJarFile, jarjarred := j.jarjarIfNecessary(ctx, combinedResourceJar, jarName, "resource", false)
  combinedResourceJar = resourceJarJarFile
  if jarjarred {
   localResourceJars = android.Paths{resourceJarJarFile}
   completeStaticLibsResourceJars = depset.New(depset.PREORDER, localResourceJars, nil)
  }
 }

 if ctx.Failed() {
  return nil
 }

 if j.ravenizer.enabled {
  ravenizerInput := outputFile
  ravenizerOutput := android.PathForModuleOut(ctx, "ravenizer", "", jarName)

  ravenizerArgs := j.properties.Ravenizer.Flags
  if proptools.Bool(j.properties.Ravenizer.Strip_mockito) {
   ravenizerArgs = append(ravenizerArgs, "--strip-mockito")
  }

  TransformRavenizer(ctx, ravenizerOutput, ravenizerInput, ravenizerArgs)
  outputFile = ravenizerOutput
  localImplementationJars = android.Paths{ravenizerOutput}
  completeStaticLibsImplementationJars = depset.New(depset.PREORDER, localImplementationJars, nil)
  localImplementationJarsContainsDependencies = true
  if combinedResourceJar != nil {
   ravenizerInput = combinedResourceJar
   ravenizerOutput = android.PathForModuleOut(ctx, "ravenizer", "resources", jarName)
   TransformRavenizer(ctx, ravenizerOutput, ravenizerInput, ravenizerArgs)
   combinedResourceJar = ravenizerOutput
   localResourceJars = android.Paths{ravenizerOutput}
   completeStaticLibsResourceJars = depset.New(depset.PREORDER, localResourceJars, nil)
  }
 }

 if j.shouldApiMapper() {
  inputFile := outputFile
  apiMapperFile := android.PathForModuleOut(ctx, "apimapper", jarName)
  ctx.Build(pctx, android.BuildParams{
   Rule:        apimapper,
   Description: "apimapper",
   Input:       inputFile,
   Output:      apiMapperFile,
  })
  outputFile = apiMapperFile
  localImplementationJars = android.Paths{apiMapperFile}
  completeStaticLibsImplementationJars = depset.New(depset.PREORDER, localImplementationJars, nil)
  localImplementationJarsContainsDependencies = true
 }

 // Check package restrictions if necessary.
 if len(j.properties.Permitted_packages) > 0 {
  // Time stamp file created by the package check rule.
  pkgckFile := android.PathForModuleOut(ctx, "package-check.stamp")

  // Create a rule to copy the output jar to another path and add a validate dependency that
  // will check that the jar only contains the permitted packages. The new location will become
  // the output file of this module.
  inputFile := outputFile
  packageCheckOutputFile := android.PathForModuleOut(ctx, "package-check", jarName)
  ctx.Build(pctx, android.BuildParams{
   Rule:   android.CpRule,
   Input:  inputFile,
   Output: packageCheckOutputFile,
   // Make sure that any dependency on the output file will cause ninja to run the package check
   // rule.
   Validation: pkgckFile,
  })
  outputFile = packageCheckOutputFile
  localImplementationJars = android.Paths{packageCheckOutputFile}
  completeStaticLibsImplementationJars = depset.New(depset.PREORDER, localImplementationJars, nil)
  localImplementationJarsContainsDependencies = true

  // Check packages and create a timestamp file when complete.
  CheckJarPackages(ctx, pkgckFile, outputFile, j.properties.Permitted_packages)

  if ctx.Failed() {
   return nil
  }
 }

 j.implementationJarFile = outputFile
 if j.headerJarFile == nil {
  // If this module couldn't generate a header jar (for example due to api generating annotation processors)
  // then use the implementation jar.  Run it through zip2zip first to remove any files in META-INF/services
  // so that javac on modules that depend on this module don't pick up annotation processors (which may be
  // missing their implementations) from META-INF/services/javax.annotation.processing.Processor.
  headerJarFile := android.PathForModuleOut(ctx, "javac-header", jarName)
  convertImplementationJarToHeaderJar(ctx, j.implementationJarFile, headerJarFile)
  j.headerJarFile = headerJarFile
  if len(localImplementationJars) == 1 {
   localHeaderJarFile := android.PathForModuleOut(ctx, "local-javac-header", jarName)
   convertImplementationJarToHeaderJar(ctx, localImplementationJars[0], localHeaderJarFile)
   localHeaderJars = append(localHeaderJars, localHeaderJarFile)
  } else {
   localHeaderJars = append(localHeaderJars, headerJarFile)
  }
  if localImplementationJarsContainsDependencies {
   // If the local implementation jar that is being used as the header jar already has the dependencies
   // combined in then don't also export the transitive static libs header jars.
   transitiveStaticLibsHeaderJars = nil
  }
 }

 // enforce syntax check to jacoco filters for any build (http://b/183622051)
 specs := j.jacocoModuleToZipCommand(ctx)
 if ctx.Failed() {
  return nil
 }

 completeStaticLibsImplementationJarsToCombine := completeStaticLibsImplementationJars

 apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)

 // Enable dex compilation for the APEX variants, unless it is disabled explicitly
 compileDex := Bool(j.dexProperties.Compile_dex) || Bool(j.properties.Installable)

 if j.shouldInstrument(ctx) && (!ctx.Device() || compileDex) {
  instrumentedOutputFile := j.instrument(ctx, flags, outputFile, jarName, specs)
  completeStaticLibsImplementationJarsToCombine = depset.New(depset.PREORDER, android.Paths{instrumentedOutputFile}, nil)
  outputFile = instrumentedOutputFile
 }

 // merge implementation jar with resources if necessary
 var implementationAndResourcesJarsToCombine android.Paths
 combinedResourceJars := completeStaticLibsResourceJars.ToList()
 if len(combinedResourceJars) > 0 {
  implementationAndResourcesJarsToCombine = slices.Concat(combinedResourceJars,
   completeStaticLibsImplementationJarsToCombine.ToList(), j.extraDepCombinedJars)
 }

 if len(implementationAndResourcesJarsToCombine) > 0 {
  combinedJar := android.PathForModuleOut(ctx, "withres", jarName)
  TransformJarsToJar(ctx, combinedJar, "for resources", implementationAndResourcesJarsToCombine, manifest,
   false, nil, nil)
  outputFile = combinedJar
 }

 j.implementationAndResourcesJar = outputFile

 if ctx.Device() && compileDex {
  if j.hasCode(ctx) {
   if j.shouldInstrumentStatic(ctx) {
    j.dexer.extraProguardFlagsFiles = append(j.dexer.extraProguardFlagsFiles,
     android.PathForSource(ctx, "build/make/core/proguard.jacoco.flags"))
   }
   // Dex compilation
   var dexOutputFile android.Path
   params := &compileDexParams{
    flags:         flags,
    sdkVersion:    j.SdkVersion(ctx),
    minSdkVersion: j.MinSdkVersion(ctx),
    classesJar:    outputFile,
    jarName:       jarName,
   }
   if j.GetProfileGuided(ctx) && !j.EnableProfileRewriting(ctx) {
    // If the app uses profile-guided optimization *without* profile rewriting, avoid
    // implicitly enabling full dex optimization, as that can easily break the profile.
    // TODO(b/487652136): Consider requiring apps to explicitly opt in or out of
    // dex optimization when using profile-guided optimization, avoiding uncertainty.
    j.dexer.dexProperties.Optimize.OptimizeByDefault = false
   }
   if j.GetProfileGuided(ctx) && j.optimizeOrObfuscateEnabled(ctx) && !j.EnableProfileRewriting(ctx) {
    ctx.PropertyErrorf("enable_profile_rewriting",
     "Enable_profile_rewriting must be true when profile_guided dexpreopt and R8 optimization/obfuscation is turned on. The attached profile should be sourced from an unoptimized/unobfuscated APK.",
    )
   }
   if j.EnableProfileRewriting(ctx) {
    profile := j.GetProfile(ctx)
    if profile == "" || !j.GetProfileGuided(ctx) {
     ctx.PropertyErrorf("enable_profile_rewriting", "Profile and Profile_guided must be set when enable_profile_rewriting is true")
    }
    params.artProfileInput = &profile
   }
   dexOutputFile, dexArtProfileOutput := j.dexer.compileDex(ctx, params)
   if ctx.Failed() {
    return nil
   }

   // If r8/d8 provides a profile that matches the optimized dex, use that for dexpreopt.
   if dexArtProfileOutput != nil {
    if concretePtr, ok := dexArtProfileOutput.(*android.OutputPath); ok {
     if concretePtr != nil {
      j.dexpreopter.SetRewrittenProfile(dexArtProfileOutput)
     }
    }
   }

   // merge dex jar with resources if necessary
   if len(combinedResourceJars) > 0 {
    dexAndResourceJarsToCombine := append(android.Paths{dexOutputFile}, combinedResourceJars...)

    combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName)
    TransformJarsToJar(ctx, combinedJar, "for dex resources", dexAndResourceJarsToCombine, android.OptionalPath{},
     false, nil, nil)
    if *j.dexProperties.Uncompress_dex {
     combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName)
     TransformZipAlign(ctx, combinedAlignedJar, combinedJar, nil)
     dexOutputFile = combinedAlignedJar
    } else {
     dexOutputFile = combinedJar
    }
   }

   // Initialize the hiddenapi structure.

   j.initHiddenAPI(ctx, makeDexJarPathFromPath(dexOutputFile), j.implementationJarFile, j.dexProperties.Uncompress_dex)

   // Encode hidden API flags in dex file, if needed.
   dexOutputFile = j.hiddenAPIEncodeDex(ctx, dexOutputFile)

   j.dexJarFile = makeDexJarPathFromPath(dexOutputFile)

   // Dexpreopting
   if dexArtProfileOutput != nil {
    libName := android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName())
    if j.SdkLibraryName() != nil && strings.HasSuffix(ctx.ModuleName(), ".impl") {
     libName = strings.TrimSuffix(libName, ".impl")
    }
    j.dexpreopt(ctx, libName, dexOutputFile)
   }

   outputFile = dexOutputFile

   ctx.CheckbuildFile(dexOutputFile)
  } else {
   // There is no code to compile into a dex jar, make sure the resources are propagated
   // to the APK if this is an app.
   j.dexJarFile = makeDexJarPathFromPath(combinedResourceJar)
  }

  if ctx.Failed() {
   return nil
  }
 }

 if ctx.Device() {
  lintSDKVersion := func(apiLevel android.ApiLevel) android.ApiLevel {
   if !apiLevel.IsPreview() {
    return apiLevel
   } else {
    return ctx.Config().DefaultAppTargetSdk(ctx)
   }
  }

  j.linter.name = ctx.ModuleName()
  j.linter.srcs = append(srcFiles, nonGeneratedSrcJars...)
  j.linter.srcJars, _ = android.FilterPathList(srcJars, nonGeneratedSrcJars)
  j.linter.classpath = append(append(android.Paths(nil), flags.bootClasspath...), flags.classpath...)
  j.linter.classes = j.implementationJarFile
  j.linter.minSdkVersion = lintSDKVersion(j.MinSdkVersion(ctx))
  j.linter.targetSdkVersion = lintSDKVersion(j.TargetSdkVersion(ctx))
  j.linter.compileSdkVersion = lintSDKVersion(j.SdkVersion(ctx).ApiLevel)
  j.linter.compileSdkKind = j.SdkVersion(ctx).Kind
  j.linter.javaLanguageLevel = flags.javaVersion.String()
  j.linter.kotlinLanguageLevel = "1.3"
  j.linter.compile_data = android.PathsForModuleSrc(ctx, j.properties.Compile_data)
  if !apexInfo.IsForPlatform() && ctx.Config().HasUnbundledBuildApps() {
   j.linter.buildModuleReportZip = true
  }
  j.linter.lint(ctx)
 }

 j.collectTransitiveSrcFiles(ctx, srcFiles)

 if len(localImplementationJars) > 0 || len(localResourceJars) > 0 || len(localHeaderJars) > 0 {
  ctx.CheckbuildFile(localImplementationJars...)
  ctx.CheckbuildFile(localResourceJars...)
  ctx.CheckbuildFile(localHeaderJars...)
 } else {
  // There are no local sources or resources in this module, so there is nothing to checkbuild.
  ctx.UncheckedModule()
 }

 j.addKSnapshot(ctx, outputFile)
 for _, rJar := range localResourceJars {
  j.addKSnapshot(ctx, rJar)
 }
 for _, hJar := range localHeaderJars {
  j.addKSnapshot(ctx, hJar)
 }
 if combinedResourceJar != nil {
  j.addKSnapshot(ctx, combinedResourceJar)
 }

 // Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource
 j.outputFile = outputFile.WithoutRel()

 if deps.headerJarOverride.Valid() {
  j.headerJarFile = deps.headerJarOverride.Path()
 }

 overridableMinSdkVersion := j.overridableProperties.Min_sdk_version.Get(ctx)

 return &JavaInfo{
  HeaderJars:               android.PathsIfNonNil(j.headerJarFile),
  LocalHeaderJarsPreJarjar: android.PathsIfNonNil(combinedHeaderJarFile),
  RepackagedHeaderJars:     android.PathsIfNonNil(repackagedHeaderJarFile),

  LocalHeaderJars:                        localHeaderJars,
  KotlinHeaderJars:                       kotlinHeaderJars,
  TransitiveStaticLibsHeaderJars:         depset.New(depset.PREORDER, localHeaderJars, transitiveStaticLibsHeaderJars),
  TransitiveStaticLibsImplementationJars: completeStaticLibsImplementationJars,
  TransitiveStaticLibsResourceJars:       completeStaticLibsResourceJars,

  TransitiveLibsHeaderJarsForR8:       j.transitiveLibsHeaderJarsForR8,
  TransitiveStaticLibsHeaderJarsForR8: j.transitiveStaticLibsHeaderJarsForR8,
  ImplementationAndResourcesJars:      android.PathsIfNonNil(j.implementationAndResourcesJar),
  ImplementationJars:                  android.PathsIfNonNil(j.implementationJarFile),
  ResourceJars:                        android.PathsIfNonNil(combinedResourceJar),
  AidlIncludeDirs:                     j.exportAidlIncludeDirs,
  SrcJarArgs:                          j.srcJarArgs,
  SrcJarDeps:                          j.srcJarDeps,
  KSnapshotFiles:                      j.kSnapshotFiles,
  TransitiveSrcFiles:                  j.transitiveSrcFiles,
  ExportedPlugins:                     j.exportedPluginJars,
  ExportedPluginClasses:               j.exportedPluginClasses,
  ExportedPluginDisableTurbine:        j.exportedDisableTurbine,
  JacocoInfo:                          j.jacocoInfo,
  StubsLinkType:                       j.stubsLinkType,
  AconfigIntermediateCacheOutputPaths: j.aconfigCacheFiles,
  SdkVersion:                          j.SdkVersion(ctx),
  OutputFile:                          j.outputFile,
  HasOverrideMinSdkVersion:            overridableMinSdkVersion.IsPresent(),
  Installable:                         BoolDefault(j.properties.Installable, true),
 }
}

func (j *Module) addKSnapshot(ctx android.ModuleContext, jarFile android.Path) {
 if jarFile == nil {
  return
 }
 if skip, exists := j.skipKSnapshotFiles[jarFile.String()]; exists && skip {
  return
 }
 if _, exists := j.kSnapshotFiles[jarFile.String()]; !exists {
  snapshot := SnapshotJarForKotlin(ctx, jarFile.(android.WritablePath))
  j.kSnapshotFiles[jarFile.String()] = snapshot
 }
}

func (j *Module) skipKSnapshot(jarFile android.Path) {
 if jarFile == nil {
  return
 }
 j.skipKSnapshotFiles[jarFile.String()] = true
}

func (j *Module) useCompose(ctx android.BaseModuleContext) bool {
 return android.InList("androidx.compose.runtime_runtime", j.staticLibs(ctx))
}

type collectDepProguardSpecInfoResults struct {
 transitiveProguardFlags                      []depset.DepSet[android.Path]
 transitiveIncludedProguardFlags              []depset.DepSet[android.Path]
 transitiveUnconditionalExportedFlags         []depset.DepSet[android.Path]
 transitiveIncludedUnconditionalExportedFlags []depset.DepSet[android.Path]
}

func collectDepProguardSpecInfo(ctx android.ModuleContext) collectDepProguardSpecInfoResults {
 var results collectDepProguardSpecInfoResults
 ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
  depProguardInfo, _ := android.OtherModuleProvider(ctx, m, ProguardSpecInfoProvider)
  depTag := ctx.OtherModuleDependencyTag(m)

  results.transitiveUnconditionalExportedFlags = append(results.transitiveUnconditionalExportedFlags, depProguardInfo.UnconditionallyExportedProguardFlags)
  results.transitiveIncludedUnconditionalExportedFlags = append(results.transitiveIncludedUnconditionalExportedFlags, depProguardInfo.IncludedUnconditionallyExportedProguardFlags)
  results.transitiveProguardFlags = append(results.transitiveProguardFlags, depProguardInfo.UnconditionallyExportedProguardFlags)
  results.transitiveIncludedProguardFlags = append(results.transitiveIncludedProguardFlags, depProguardInfo.IncludedUnconditionallyExportedProguardFlags)

  if depTag == staticLibTag {
   results.transitiveProguardFlags = append(results.transitiveProguardFlags, depProguardInfo.ProguardFlagsFiles)
   results.transitiveIncludedProguardFlags = append(results.transitiveIncludedProguardFlags, depProguardInfo.IncludedProguardFlagsFiles)
  }
 })

 return results
}

func (j *Module) collectProguardSpecInfo(ctx android.ModuleContext) ProguardSpecInfo {
 transitiveFlags := collectDepProguardSpecInfo(ctx)

 transitiveProguardFlags := transitiveFlags.transitiveProguardFlags
 transitiveIncludedProguardFlags := transitiveFlags.transitiveIncludedProguardFlags
 transitiveUnconditionalExportedFlags := transitiveFlags.transitiveUnconditionalExportedFlags
 transitiveIncludedUnconditionalExportedFlags := transitiveFlags.transitiveIncludedUnconditionalExportedFlags

 proguardFlagsForThisModule := j.ProguardFlagsFiles(ctx)
 directUnconditionalExportedFlags := android.Paths{}
 directIncludedUnconditionalExportedFlags := android.Paths{}
 exportUnconditionally := proptools.Bool(j.dexProperties.Optimize.Export_proguard_flags_files)
 if exportUnconditionally {
  // if we explicitly export, then our unconditional exports are the same as our transitive flags
  transitiveUnconditionalExportedFlags = transitiveFlags.transitiveProguardFlags
  transitiveIncludedUnconditionalExportedFlags = transitiveFlags.transitiveIncludedProguardFlags
  directUnconditionalExportedFlags = proguardFlagsForThisModule.files
  directIncludedUnconditionalExportedFlags = proguardFlagsForThisModule.included
 }

 return ProguardSpecInfo{
  Export_proguard_flags_files: exportUnconditionally,
  ProguardFlagsFiles: depset.New(
   depset.POSTORDER,
   proguardFlagsForThisModule.files,
   transitiveProguardFlags,
  ),
  IncludedProguardFlagsFiles: depset.New(
   depset.POSTORDER,
   proguardFlagsForThisModule.included,
   transitiveIncludedProguardFlags,
  ),
  UnconditionallyExportedProguardFlags: depset.New(
   depset.POSTORDER,
   directUnconditionalExportedFlags,
   transitiveUnconditionalExportedFlags,
  ),
  IncludedUnconditionallyExportedProguardFlags: depset.New(
   depset.POSTORDER,
   directIncludedUnconditionalExportedFlags,
   transitiveIncludedUnconditionalExportedFlags,
  ),
 }

}

// Returns a copy of the supplied flags, but with all the errorprone-related
// fields copied to the regular build's fields.
func enableErrorproneFlags(flags javaBuilderFlags) javaBuilderFlags {
 flags.processorPath = append(flags.errorProneProcessorPath, flags.processorPath...)

 if len(flags.errorProneExtraJavacFlags) > 0 {
  if len(flags.javacFlags) > 0 {
   flags.javacFlags += " " + flags.errorProneExtraJavacFlags
  } else {
   flags.javacFlags = flags.errorProneExtraJavacFlags
  }
 }
 return flags
}

func (j *Module) compileJavaClasses(ctx android.ModuleContext, jarName string, idx int,
 srcFiles, srcJars, localHeaderJars, crossModuleHeaderJars android.Paths, flags javaBuilderFlags, extraJarDeps android.Paths, genAnnoSrcJars android.Paths) android.Path {

 kzipName := pathtools.ReplaceExtension(jarName, "kzip")
 annoSrcJar := android.PathForModuleOut(ctx, "javac", "anno.srcjar")
 if idx >= 0 {
  kzipName = strings.TrimSuffix(jarName, filepath.Ext(jarName)) + strconv.Itoa(idx) + ".kzip"
  annoSrcJar = android.PathForModuleOut(ctx, "javac", "anno-"+strconv.Itoa(idx)+".srcjar")
  jarName += strconv.Itoa(idx)
 }

 classes := android.PathForModuleOut(ctx, "javac", jarName)
 // enable incremental javac when corresponding flags are enabled and
 // header jars are present
 if ctx.Config().PartialCompileFlags().Enable_inc_javac && len(localHeaderJars) > 0 {
  TransformJavaToClassesInc(ctx, classes, srcFiles, srcJars, localHeaderJars, crossModuleHeaderJars, annoSrcJar, flags, extraJarDeps, genAnnoSrcJars)
 } else {
  TransformJavaToClasses(ctx, classes, idx, srcFiles, srcJars, annoSrcJar, flags, extraJarDeps, genAnnoSrcJars)
 }

 if ctx.Config().EmitXrefRules() && ctx.IsPrimaryModule() {
  extractionFile := android.PathForModuleOut(ctx, kzipName)
  emitXrefRule(ctx, extractionFile, idx, srcFiles, srcJars, flags, extraJarDeps)
  j.kytheFiles = append(j.kytheFiles, extractionFile)
 }

 if len(flags.processorPath) > 0 {
  j.annoSrcJars = append(j.annoSrcJars, annoSrcJar)
 }

 return classes
}

func (j *Module) generateJavaAnnotations(ctx android.ModuleContext, jarName string, idx int,
 srcFiles, srcJars android.Paths, flags javaBuilderFlags, extraJarDeps android.Paths) (android.Path, android.Path) {

 annoSrcJar := android.PathForModuleOut(ctx, "javac-apt", "anno.srcjar")
 if idx >= 0 {
  annoSrcJar = android.PathForModuleOut(ctx, "javac-apt", "anno-"+strconv.Itoa(idx)+".srcjar")
  jarName += strconv.Itoa(idx)
 }

 classes := android.PathForModuleOut(ctx, "javac-apt", jarName)
 GenerateJavaAnnotations(ctx, classes, idx, srcFiles, srcJars, annoSrcJar, flags, extraJarDeps)
 return annoSrcJar, classes
}

// Check for invalid kotlinc flags. Only use this for flags explicitly passed by the user,
// since some of these flags may be used internally.
func CheckKotlincFlags(ctx android.ModuleContext, flags []string) {
 for _, flag := range flags {
  flag = strings.TrimSpace(flag)

  if !strings.HasPrefix(flag, "-") {
   ctx.PropertyErrorf("kotlincflags", "Flag `%s` must start with `-`", flag)
  } else if strings.HasPrefix(flag, "-Xintellij-plugin-root") {
   ctx.PropertyErrorf("kotlincflags",
    "Bad flag: `%s`, only use internal compiler for consistency.", flag)
  } else if slices.ContainsFunc(config.KotlincIllegalFlags, func(f string) bool {
   return strings.HasPrefix(flag, f)
  }) {
   ctx.PropertyErrorf("kotlincflags", "Flag `%s` already used by build system", flag)
  } else if flag == "-include-runtime" {
   ctx.PropertyErrorf("kotlincflags", "Bad flag: `%s`, do not include runtime.", flag)
  } else {
   args := strings.Split(flag, " ")
   if args[0] == "-kotlin-home" {
    ctx.PropertyErrorf("kotlincflags",
     "Bad flag: `%s`, kotlin home already set to default (path to kotlinc in the repo).", flag)
   }
  }
 }
}

func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars android.Paths,
 deps deps, flags javaBuilderFlags, jarName string,
 extraJars android.Paths, manifest android.OptionalPath) (localHeaderJars, localHeaderJarsForSharding android.Paths, combinedHeaderJar android.Path) {

 if deps.headerJarOverride.Valid() {
  // If we are sharding, we need the pre-jarjar override path; localHeaderJars always
  // needs the jarjared version.
  localHeaderJars = append(android.Paths{deps.headerJarOverride.Path()}, extraJars...)
  var headerJar android.Path
  if deps.headerJarOverridePreJarjar.Valid() {
   headerJar = deps.headerJarOverridePreJarjar.Path()
  } else {
   headerJar = deps.headerJarOverride.Path()
  }
  localHeaderJarsForSharding = append(android.Paths{headerJar}, extraJars...)
  return localHeaderJars, localHeaderJarsForSharding, deps.headerJarOverride.Path()
 }

 if len(srcFiles) > 0 || len(srcJars) > 0 {
  // Compile java sources into turbine.jar.
  turbineJar := android.PathForModuleOut(ctx, "turbine", jarName)
  TransformJavaToHeaderClasses(ctx, turbineJar, srcFiles, srcJars, flags)
  localHeaderJars = append(localHeaderJars, turbineJar)
 }

 localHeaderJars = append(localHeaderJars, extraJars...)

 // Combine any static header libraries into classes-header.jar. If there is only
 // one input jar this step will be skipped.
 depSet := depset.New(depset.PREORDER, localHeaderJars, deps.transitiveStaticLibsHeaderJars)
 jars := depSet.ToList()

 var combinedHeaderJarOutputPath android.WritablePath
 // we cannot skip the combine step for now if there is only one jar
 // since we have to strip META-INF/TRANSITIVE dir from turbine.jar
 combinedHeaderJarOutputPath = android.PathForModuleOut(ctx, "turbine-combined", jarName)
 TransformJarsToJar(ctx, combinedHeaderJarOutputPath, "for turbine", jars, manifest,
  false, nil, []string{"META-INF/TRANSITIVE"})

 return localHeaderJars, localHeaderJars, combinedHeaderJarOutputPath
}

func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
 classesJar android.Path, jarName string, specs string) android.Path {

 jacocoReportClassesFile := android.PathForModuleOut(ctx, "jacoco-report-classes", jarName)
 instrumentedJar := android.PathForModuleOut(ctx, "jacoco", jarName)

 jacocoInstrumentJar(ctx, instrumentedJar, jacocoReportClassesFile, classesJar, specs)

 j.jacocoInfo.ReportClassesFile = jacocoReportClassesFile
 j.jacocoInfo.ModuleName = android.ModuleNameWithPossibleOverride(ctx)
 // Allow overriding the class before instrument() is called
 if j.jacocoInfo.Class == "" {
  j.jacocoInfo.Class = "JAVA_LIBRARIES"
 }

 return instrumentedJar
}

type providesTransitiveHeaderJarsForR8 struct {
 // set of header jars for all transitive libs deps
 transitiveLibsHeaderJarsForR8 depset.DepSet[android.Path]
 // set of header jars for all transitive static libs deps
 transitiveStaticLibsHeaderJarsForR8 depset.DepSet[android.Path]
}

// collectTransitiveHeaderJarsForR8 visits direct dependencies and collects all transitive libs and static_libs
// header jars.  The semantics of the collected jars are odd (it collects combined jars that contain the static
// libs, but also the static libs, and it collects transitive libs dependencies of static_libs), so these
// are only used to expand the --lib arguments to R8.
func (j *providesTransitiveHeaderJarsForR8) collectTransitiveHeaderJarsForR8(ctx android.ModuleContext) {
 directLibs := android.Paths{}
 directStaticLibs := android.Paths{}
 transitiveLibs := []depset.DepSet[android.Path]{}
 transitiveStaticLibs := []depset.DepSet[android.Path]{}
 ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
  // don't add deps of the prebuilt version of the same library
  if ctx.ModuleName() == android.RemoveOptionalPrebuiltPrefix(module.Name()) {
   return
  }

  if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
   tag := ctx.OtherModuleDependencyTag(module)
   _, isUsesLibDep := tag.(usesLibraryDependencyTag)
   if tag == libTag || tag == r8LibraryJarTag || isUsesLibDep {
    directLibs = append(directLibs, dep.HeaderJars...)
   } else if tag == staticLibTag {
    directStaticLibs = append(directStaticLibs, dep.HeaderJars...)
   } else {
    // Don't propagate transitive libs for other kinds of dependencies.
    return
   }

   transitiveLibs = append(transitiveLibs, dep.TransitiveLibsHeaderJarsForR8)
   transitiveStaticLibs = append(transitiveStaticLibs, dep.TransitiveStaticLibsHeaderJarsForR8)
  }
 })
 j.transitiveLibsHeaderJarsForR8 = depset.New(depset.POSTORDER, directLibs, transitiveLibs)
 j.transitiveStaticLibsHeaderJarsForR8 = depset.New(depset.POSTORDER, directStaticLibs, transitiveStaticLibs)
}

func (j *Module) HeaderJars() android.Paths {
 if j.headerJarFile == nil {
  return nil
 }
 return android.Paths{j.headerJarFile}
}

func (j *Module) ImplementationJars() android.Paths {
 if j.implementationJarFile == nil {
  return nil
 }
 return android.Paths{j.implementationJarFile}
}

func (j *Module) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
 return j.dexJarFile
}

func (j *Module) DexJarInstallPath() android.Path {
 return j.installFile
}

func (j *Module) ImplementationAndResourcesJars() android.Paths {
 if j.implementationAndResourcesJar == nil {
  return nil
 }
 return android.Paths{j.implementationAndResourcesJar}
}

func (j *Module) AidlIncludeDirs() android.Paths {
 // exportAidlIncludeDirs is type android.Paths already
 return j.exportAidlIncludeDirs
}

func (j *Module) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
 return j.classLoaderContexts
}

// Collect information for opening IDE project files in java/jdeps.go.
func (j *Module) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
 if j.expandJarjarRules != nil {
  dpInfo.Jarjar_rules = append(dpInfo.Jarjar_rules, j.expandJarjarRules.String())
 }
 if j.headerJarFile != nil {
  // Add the header jar so that the rdeps can be resolved to the repackaged classes.
  dpInfo.Jars = append(dpInfo.Jars, j.headerJarFile.String())
 }
 dpInfo.Srcs = append(dpInfo.Srcs, j.expandIDEInfoCompiledSrcs...)
 if len(j.aidlSrcs) > 0 {
  dpInfo.Aidl = &android.AidlIdeInfo{
   Srcs: j.aidlSrcs.Strings(),
  }
 }
 if len(j.protoSrcs) > 0 {
  dpInfo.Proto = &android.ProtoIdeInfo{
   Srcs:                  j.protoSrcs.Strings(),
   Type:                  proptools.String(j.protoProperties.Proto.Type),
   CanonicalPathFromRoot: j.protoProperties.Proto.Canonical_path_from_root,
   LocalIncludeDirs:      j.protoProperties.Proto.Local_include_dirs,
  }
 }
 dpInfo.SrcJars = append(dpInfo.SrcJars, j.compiledSrcJars.Strings()...)
 dpInfo.SrcJars = append(dpInfo.SrcJars, j.annoSrcJars.Strings()...)
 dpInfo.Deps = append(dpInfo.Deps, j.CompilerDeps()...)
 dpInfo.Aidl_include_dirs = append(dpInfo.Aidl_include_dirs, j.deviceProperties.Aidl.Include_dirs...)
 dpInfo.Static_libs = append(dpInfo.Static_libs, j.staticLibs(ctx)...)
 dpInfo.Libs = append(dpInfo.Libs, j.libs(ctx)...)
 dpInfo.Associates = append(dpInfo.Associates, j.properties.Associates...)
 dpInfo.Kotlincflags = append(dpInfo.Kotlincflags, j.properties.Kotlincflags...)
 dpInfo.Javacflags = append(dpInfo.Javacflags, j.properties.Javacflags...)
 dpInfo.Annotation_processor_flags = append(dpInfo.Annotation_processor_flags, j.properties.Annotation_processor_flags...)
 dpInfo.Plugins = append(dpInfo.Plugins, j.properties.Plugins...)

 for _, props := range j.GetProperties() {
  if p, ok := props.(android.IdeInfoPopulator); ok {
   p.PopulateIdeInfo(ctx, dpInfo)
  }
 }
}

func (j *Module) CompilerDeps() []string {
 return j.compileDepNames
}

func (j *Module) hasCode(ctx android.ModuleContext) bool {
 srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs.GetOrDefault(ctx, nil),
  j.properties.Exclude_srcs.GetOrDefault(ctx, nil))
 return len(srcFiles) > 0 || len(ctx.GetDirectDepsProxyWithTag(staticLibTag)) > 0
}

// Implements android.ApexModule
func (m *Module) GetDepInSameApexChecker() android.DepInSameApexChecker {
 return JavaDepInSameApexChecker{}
}

// @auto-generate: gob
type JavaDepInSameApexChecker struct {
 android.BaseDepInSameApexChecker
}

func (m JavaDepInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
 return depIsInSameApex(tag)
}

// Implements android.ApexModule
func (j *Module) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel {
 sdkVersionSpec := j.SdkVersion(ctx)
 minSdkVersion := j.MinSdkVersion(ctx)

 // If the module is compiling against core (via sdk_version), skip comparison check.
 if sdkVersionSpec.Kind == android.SdkCore {
  return android.MinApiLevel
 }

 return minSdkVersion
}

func (j *Module) Stem() string {
 if j.stem == "" {
  panic("Stem() called before stem property was set")
 }
 return j.stem
}

func (j *Module) JacocoInfo() JacocoInfo {
 return j.jacocoInfo
}

func (j *Module) collectTransitiveSrcFiles(ctx android.ModuleContext, mine android.Paths) {
 var fromDeps []depset.DepSet[android.Path]
 ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
  tag := ctx.OtherModuleDependencyTag(module)
  if tag == staticLibTag {
   if depInfo, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
    fromDeps = append(fromDeps, depInfo.TransitiveSrcFiles)
   }
  }
 })

 j.transitiveSrcFiles = depset.New(depset.POSTORDER, mine, fromDeps)
}

func (j *Module) IsInstallable() bool {
 return Bool(j.properties.Installable)
}

type sdkLinkType int

const (
 // TODO(jiyong) rename these for better readability. Make the allowed
 // and disallowed link types explicit
 // order is important here. See rank()
 javaCore sdkLinkType = iota
 javaSdk
 javaSystem
 javaModule
 javaSystemServer
 javaPlatform
)

func (lt sdkLinkType) String() string {
 switch lt {
 case javaCore:
  return "core Java API"
 case javaSdk:
  return "Android API"
 case javaSystem:
  return "system API"
 case javaModule:
  return "module API"
 case javaSystemServer:
  return "system server API"
 case javaPlatform:
  return "private API"
 default:
  panic(fmt.Errorf("unrecognized linktype: %d", lt))
 }
}

// rank determines the total order among sdkLinkType. An SDK link type of rank A can link to
// another SDK link type of rank B only when B <= A. For example, a module linking to Android SDK
// can't statically depend on modules that use Platform API.
func (lt sdkLinkType) rank() int {
 return int(lt)
}

type moduleWithSdkDep interface {
 android.Module
 getSdkLinkType(ctx android.BaseModuleContext, name string) (ret sdkLinkType, stubs bool)
}

func sdkLinkTypeFromSdkKind(k android.SdkKind) sdkLinkType {
 switch k {
 case android.SdkCore:
  return javaCore
 case android.SdkSystem:
  return javaSystem
 case android.SdkPublic:
  return javaSdk
 case android.SdkModule:
  return javaModule
 case android.SdkSystemServer:
  return javaSystemServer
 case android.SdkPrivate, android.SdkNone, android.SdkCorePlatform, android.SdkTest:
  return javaPlatform
 default:
  return javaSdk
 }
}

func (m *Module) getSdkLinkType(ctx android.BaseModuleContext, name string) (ret sdkLinkType, stubs bool) {
 switch name {
 case android.SdkCore.DefaultJavaLibraryName(),
  "legacy.core.platform.api.stubs",
  "stable.core.platform.api.stubs",
  "stub-annotations", "private-stub-annotations-jar",
  "core-lambda-stubs",
  "core-generated-annotation-stubs",
  // jacocoagent only uses core APIs, but has to specify a non-core sdk_version so it can use
  // a prebuilt SDK to avoid circular dependencies when it statically included in the bootclasspath.
  "jacocoagent":
  return javaCore, true
 case android.SdkPublic.DefaultJavaLibraryName():
  return javaSdk, true
 case android.SdkSystem.DefaultJavaLibraryName():
  return javaSystem, true
 case android.SdkModule.DefaultJavaLibraryName():
  return javaModule, true
 case android.SdkSystemServer.DefaultJavaLibraryName():
  return javaSystemServer, true
 case android.SdkTest.DefaultJavaLibraryName():
  return javaSystem, true
 }

 if stub, linkType := moduleStubLinkType(m); stub {
  return linkType, true
 }

 ver := m.SdkVersion(ctx)
 if !ver.Valid() {
  panic(fmt.Errorf("sdk_version is invalid. got %q", ver.Raw))
 }

 return sdkLinkTypeFromSdkKind(ver.Kind), false
}

// checkSdkLinkType make sures the given dependency doesn't have a lower SDK link type rank than
// this module's. See the comment on rank() for details and an example.
func (j *Module) checkSdkLinkType(
 ctx android.ModuleContext, dep android.ModuleProxy) {
 if ctx.Host() {
  return
 }

 myLinkType, stubs := j.getSdkLinkType(ctx, ctx.ModuleName())
 if stubs {
  return
 }
 info, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
 if !ok || info.ModuleWithSdkDepInfo == nil {
  panic(fmt.Errorf("dependency doesn't have ModuleWithSdkDepInfo: %v", dep))
 }

 depLinkType := info.ModuleWithSdkDepInfo.SdkLinkType

 if myLinkType.rank() < depLinkType.rank() {
  if allowedViolations, ok := SdkVersionDependencyViolationAllowlist[ctx.ModuleName()]; ok && android.InList(dep.Name(), allowedViolations) {
   return
  }
  ctx.ModuleErrorf("compiles against %v, but dependency %q is compiling against %v. "+
   "In order to fix this, consider adjusting sdk_version: OR platform_apis: "+
   "property of the source or target module so that target module is built "+
   "with the same or smaller API set when compared to the source.",
   myLinkType, ctx.OtherModuleName(dep), depLinkType)
 }
}

func (j *Module) collectDeps(ctx android.ModuleContext) deps {
 var deps deps

 enableStrictDeps := j.properties.Strict_deps != nil && (*j.properties.Strict_deps == "warn" || *j.properties.Strict_deps == "error")
 sdkLinkType, _ := j.getSdkLinkType(ctx, ctx.ModuleName())

 j.collectTransitiveHeaderJarsForR8(ctx)

 var transitiveBootClasspathHeaderJars []depset.DepSet[android.Path]
 var transitiveClasspathHeaderJars []depset.DepSet[android.Path]
 var transitiveJava9ClasspathHeaderJars []depset.DepSet[android.Path]
 var transitiveStaticJarsHeaderLibs []depset.DepSet[android.Path]
 var transitiveStaticJarsImplementationLibs []depset.DepSet[android.Path]
 var transitiveStaticJarsResourceLibs []depset.DepSet[android.Path]
 deps.kSnapshotFiles = make(map[string]android.Path)

 ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
  otherName := ctx.OtherModuleName(module)
  tag := ctx.OtherModuleDependencyTag(module)

  if IsJniDepTag(tag) {
   // Handled by AndroidApp.collectAppDeps
   return
  }
  if tag == certificateTag {
   // Handled by AndroidApp.collectAppDeps
   return
  }

  if sdkInfo, ok := android.OtherModuleProvider(ctx, module, SdkLibraryInfoProvider); ok {
   switch tag {
   case sdkLibTag, libTag, staticLibTag:
    generatingLibsString := android.PrettyConcat(
     getGeneratingLibs(ctx, j.SdkVersion(ctx), module.Name(), sdkInfo), true, "or")
    ctx.ModuleErrorf("cannot depend directly on java_sdk_library %q; try depending on %s instead", module.Name(), generatingLibsString)
   }
  } else if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
   if sdkLinkType != javaPlatform {
    if syspropDep, ok := android.OtherModuleProvider(ctx, module, SyspropPublicStubInfoProvider); ok {
     // dep is a sysprop implementation library, but this module is not linking against
     // the platform, so it gets the sysprop public stubs library instead.  Replace
     // dep with the JavaInfo from the SyspropPublicStubInfoProvider.
     dep = syspropDep.JavaInfo
    }
   }

   maps.Copy(deps.kSnapshotFiles, dep.KSnapshotFiles)

   switch tag {
   case bootClasspathTag:
    deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars...)
    transitiveBootClasspathHeaderJars = append(transitiveBootClasspathHeaderJars, dep.TransitiveStaticLibsHeaderJars)
   case sdkLibTag, libTag, instrumentationForTag:
    if _, ok := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider); ok {
     ctx.ModuleErrorf("a java_plugin (%s) cannot be used as a libs dependency", otherName)
    }
    deps.classpath = append(deps.classpath, dep.HeaderJars...)
    if enableStrictDeps {
     deps.directClasspath = append(deps.directClasspath, dep.LocalHeaderJars...)
    }
    deps.dexClasspath = append(deps.dexClasspath, dep.HeaderJars...)
    if len(dep.RepackagedHeaderJars) == 1 && !slices.Contains(dep.HeaderJars, dep.RepackagedHeaderJars[0]) {
     deps.classpath = append(deps.classpath, dep.RepackagedHeaderJars...)
     deps.dexClasspath = append(deps.dexClasspath, dep.RepackagedHeaderJars...)
    }
    deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...)
    addPlugins(&deps, dep.ExportedPlugins, dep.ExportedPluginClasses...)
    deps.disableTurbine = !ctx.Config().GetBuildFlagBool("RELEASE_USE_TURBINE_APT_JAVAC") && (deps.disableTurbine || dep.ExportedPluginDisableTurbine)

    transitiveClasspathHeaderJars = append(transitiveClasspathHeaderJars, dep.TransitiveStaticLibsHeaderJars)
   case headerJarOverrideTag:
    if dep.HeaderJars == nil {
     ctx.ModuleErrorf("%s does not provide header jars", otherName)
    } else if len(dep.HeaderJars) > 1 {
     ctx.ModuleErrorf("%s provides too many header jars", otherName)
    } else {
     deps.headerJarOverride = android.OptionalPathForPath(dep.HeaderJars[0])
     deps.headerJarOverridePreJarjar = android.OptionalPathForPath(dep.LocalHeaderJarsPreJarjar[0])
     if enableStrictDeps {
      deps.directClasspath = append(deps.directClasspath, dep.LocalHeaderJars...)
     }
    }
   case java9LibTag:
    deps.java9Classpath = append(deps.java9Classpath, dep.HeaderJars...)
    transitiveJava9ClasspathHeaderJars = append(transitiveJava9ClasspathHeaderJars, dep.TransitiveStaticLibsHeaderJars)
   case staticLibTag:
    if _, ok := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider); ok {
     ctx.ModuleErrorf("a java_plugin (%s) cannot be used as a static_libs dependency", otherName)
    }
    deps.classpath = append(deps.classpath, dep.HeaderJars...)
    if enableStrictDeps {
     deps.directClasspath = append(deps.directClasspath, dep.LocalHeaderJars...)
    }
    deps.staticJars = append(deps.staticJars, dep.ImplementationJars...)
    deps.staticHeaderJars = append(deps.staticHeaderJars, dep.HeaderJars...)
    deps.staticResourceJars = append(deps.staticResourceJars, dep.ResourceJars...)
    deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...)
    addPlugins(&deps, dep.ExportedPlugins, dep.ExportedPluginClasses...)
    // Turbine doesn't run annotation processors, so any module that uses an
    // annotation processor that generates API is incompatible with the turbine
    // optimization.
    deps.disableTurbine = !ctx.Config().GetBuildFlagBool("RELEASE_USE_TURBINE_APT_JAVAC") && (deps.disableTurbine || dep.ExportedPluginDisableTurbine)
    deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.AconfigIntermediateCacheOutputPaths...)

    transitiveClasspathHeaderJars = append(transitiveClasspathHeaderJars, dep.TransitiveStaticLibsHeaderJars)
    transitiveStaticJarsHeaderLibs = append(transitiveStaticJarsHeaderLibs, dep.TransitiveStaticLibsHeaderJars)
    transitiveStaticJarsImplementationLibs = append(transitiveStaticJarsImplementationLibs, dep.TransitiveStaticLibsImplementationJars)
    transitiveStaticJarsResourceLibs = append(transitiveStaticJarsResourceLibs, dep.TransitiveStaticLibsResourceJars)
   case pluginTag:
    if plugin, ok := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider); ok {
     if plugin.ProcessorClass != nil {
      addPlugins(&deps, dep.ImplementationAndResourcesJars, *plugin.ProcessorClass)
     } else {
      addPlugins(&deps, dep.ImplementationAndResourcesJars)
     }
     // Turbine doesn't run annotation processors, so any module that uses an
     // annotation processor that generates API is incompatible with the turbine
     // optimization.
     deps.disableTurbine = !ctx.Config().GetBuildFlagBool("RELEASE_USE_TURBINE_APT_JAVAC") && (deps.disableTurbine || plugin.GeneratesApi)
    } else {
     ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName)
    }
   case errorpronePluginTag:
    if _, ok := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider); ok {
     deps.errorProneProcessorPath = append(deps.errorProneProcessorPath, dep.ImplementationAndResourcesJars...)
    } else {
     ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName)
    }
   case javaStrictDepsPluginTag:
    if _, ok := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider); ok {
     deps.javaStrictDepsPluginJars = append(deps.javaStrictDepsPluginJars, dep.ImplementationAndResourcesJars...)
    } else {
     ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName)
    }
   case kotlinStrictDepsPluginTag:
    if _, ok := android.OtherModuleProvider(ctx, module, KotlinPluginInfoProvider); ok {
     deps.kotlinStrictDepsPluginJars = append(deps.kotlinStrictDepsPluginJars, dep.ImplementationAndResourcesJars...)
    } else {
     ctx.PropertyErrorf("plugins", "%q is not a kotlin_plugin module", otherName)
    }
   case exportedPluginTag:
    if plugin, ok := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider); ok {
     j.exportedPluginJars = append(j.exportedPluginJars, dep.ImplementationAndResourcesJars...)
     if plugin.ProcessorClass != nil {
      j.exportedPluginClasses = append(j.exportedPluginClasses, *plugin.ProcessorClass)
     }
     // Turbine doesn't run annotation processors, so any module that uses an
     // annotation processor that generates API is incompatible with the turbine
     // optimization.
     j.exportedDisableTurbine = plugin.GeneratesApi
    } else {
     ctx.PropertyErrorf("exported_plugins", "%q is not a java_plugin module", otherName)
    }
   case composeEmbeddablePluginTag:
    if _, ok := android.OtherModuleProvider(ctx, module, KotlinPluginInfoProvider); ok {
     deps.composeEmbeddablePlugin = android.OptionalPathForPath(dep.ImplementationAndResourcesJars[0])
    } else {
     ctx.PropertyErrorf("kotlin_plugins", "%q is not a kotlin_plugin module", otherName)
    }
   case composePluginTag:
    if _, ok := android.OtherModuleProvider(ctx, module, KotlinPluginInfoProvider); ok {
     deps.composePlugin = android.OptionalPathForPath(dep.ImplementationAndResourcesJars[0])
    } else {
     ctx.PropertyErrorf("kotlin_plugins", "%q is not a kotlin_plugin module", otherName)
    }
   case kotlinPluginTag:
    if _, ok := android.OtherModuleProvider(ctx, module, KotlinPluginInfoProvider); ok {
     deps.kotlinPlugins = append(deps.kotlinPlugins, dep.ImplementationAndResourcesJars...)
    } else {
     ctx.PropertyErrorf("kotlin_plugins", "%q is not a kotlin_plugin module", otherName)
    }
   case syspropPublicStubDepTag:
    // This is a sysprop implementation library, forward the JavaInfoProvider from
    // the corresponding sysprop public stub library as SyspropPublicStubInfoProvider.
    android.SetProvider(ctx, SyspropPublicStubInfoProvider, SyspropPublicStubInfo{
     JavaInfo: dep,
    })
   }
  } else if commonInfo, ok := android.OtherModuleProvider(ctx, module, android.CommonModuleInfoProvider); ok && commonInfo.SourceFiles != nil {
   dep := commonInfo.SourceFiles
   switch tag {
   case sdkLibTag, libTag:
    checkProducesJars(ctx, *dep, module)
    deps.classpath = append(deps.classpath, dep.Srcs...)
    deps.dexClasspath = append(deps.classpath, dep.Srcs...)
    transitiveClasspathHeaderJars = append(transitiveClasspathHeaderJars,
     depset.New(depset.PREORDER, dep.Srcs, nil))
   case staticLibTag:
    checkProducesJars(ctx, *dep, module)
    deps.classpath = append(deps.classpath, dep.Srcs...)
    deps.staticJars = append(deps.staticJars, dep.Srcs...)
    deps.staticHeaderJars = append(deps.staticHeaderJars, dep.Srcs...)

    depHeaderJars := depset.New(depset.PREORDER, dep.Srcs, nil)
    transitiveClasspathHeaderJars = append(transitiveClasspathHeaderJars, depHeaderJars)
    transitiveStaticJarsHeaderLibs = append(transitiveStaticJarsHeaderLibs, depHeaderJars)
    transitiveStaticJarsImplementationLibs = append(transitiveStaticJarsImplementationLibs, depHeaderJars)
   }
  } else if dep, ok := android.OtherModuleProvider(ctx, module, android.CodegenInfoProvider); ok {
   switch tag {
   case staticLibTag:
    deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.IntermediateCacheOutputPaths...)
   }
  } else if dep, ok := android.OtherModuleProvider(ctx, module, DroidStubsInfoProvider); ok {
   deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.AconfigProtoFiles...)
  } else {
   switch tag {
   case bootClasspathTag:
    // If a system modules dependency has been added to the bootclasspath
    // then add its libs to the bootclasspath.
    if sm, ok := android.OtherModuleProvider(ctx, module, SystemModulesProvider); ok {
     deps.bootClasspath = append(deps.bootClasspath, sm.HeaderJars...)
     transitiveBootClasspathHeaderJars = append(transitiveBootClasspathHeaderJars,
      sm.TransitiveStaticLibsHeaderJars)
    } else {
     ctx.PropertyErrorf("boot classpath dependency %q does not provide SystemModulesProvider",
      ctx.OtherModuleName(module))
    }

   case systemModulesTag:
    if deps.systemModules != nil {
     panic("Found two system module dependencies")
    }
    if sm, ok := android.OtherModuleProvider(ctx, module, SystemModulesProvider); ok {
     deps.systemModules = &systemModules{sm.OutputDir, sm.OutputDirDeps}
    } else {
     ctx.PropertyErrorf("system modules dependency %q does not provide SystemModulesProvider",
      ctx.OtherModuleName(module))
    }

   case instrumentationForTag:
    ctx.PropertyErrorf("instrumentation_for", "dependency %q of type %q does not provide JavaInfo so is unsuitable for use with this property", ctx.OtherModuleName(module), ctx.OtherModuleType(module))
   }
  }

  if android.InList(tag, compileDependencyTags) {
   // Add the dependency name to compileDepNames so that it can be recorded in module_bp_java_deps.json
   j.compileDepNames = append(j.compileDepNames, otherName)
  }

  addCLCFromDep(ctx, module, j.classLoaderContexts)
  addMissingOptionalUsesLibsFromDep(ctx, module, &j.usesLibrary)
 })

 deps.transitiveStaticLibsHeaderJars = transitiveStaticJarsHeaderLibs
 deps.transitiveStaticLibsImplementationJars = transitiveStaticJarsImplementationLibs
 deps.transitiveStaticLibsResourceJars = transitiveStaticJarsResourceLibs

 depSet := depset.New(depset.PREORDER, nil, transitiveClasspathHeaderJars)
 deps.classpath = depSet.ToList()
 depSet = depset.New(depset.PREORDER, nil, transitiveBootClasspathHeaderJars)
 deps.bootClasspath = depSet.ToList()
 depSet = depset.New(depset.PREORDER, nil, transitiveJava9ClasspathHeaderJars)
 deps.java9Classpath = depSet.ToList()

 if ctx.Device() {
  sdkDep := decodeSdkDep(ctx, android.SdkContext(j))
  if sdkDep.invalidVersion {
   ctx.AddMissingDependencies(sdkDep.bootclasspath)
   ctx.AddMissingDependencies(sdkDep.java9Classpath)
  } else if sdkDep.useFiles {
   // sdkDep.jar is actually equivalent to turbine header.jar.
   deps.classpath = append(slices.Clone(classpath(sdkDep.jars)), deps.classpath...)
   deps.dexClasspath = append(slices.Clone(classpath(sdkDep.jars)), deps.dexClasspath...)
   deps.aidlPreprocess = sdkDep.aidl
   // Add the sdk module dependency to `compileDepNames`.
   // This ensures that the dependency is reported in `module_bp_java_deps.json`
   // TODO (b/358608607): Move this to decodeSdkDep
   sdkSpec := android.SdkContext(j).SdkVersion(ctx)
   j.compileDepNames = append(j.compileDepNames, fmt.Sprintf("sdk_%s_%s_android", sdkSpec.Kind.String(), sdkSpec.ApiLevel.String()))
  } else {
   deps.aidlPreprocess = sdkDep.aidl
  }
 }

 return deps
}

// Provider for jarjar renaming rules.
//
// Modules can set their jarjar renaming rules with addJarJarRenameRule, and those renamings will be
// passed to all rdeps.  The typical way that these renamings will NOT be inherited is when a module
// links against stubs -- these are not passed through stubs. The classes will remain unrenamed on
// classes until a module with jarjar_prefix is reached, and all as yet unrenamed classes will then
// be renamed from that module.
// TODO: Add another property to suppress the forwarding of
type DependencyUse int

const (
 RenameUseInvalid DependencyUse = iota
 RenameUseInclude
 RenameUseExclude
)

// @auto-generate: gob
type JarJarProviderData struct {
 Rename android.JarJarRename
}

func (this JarJarProviderData) GetDebugString() string {
 return this.Rename.GetDebugString()
}

var JarJarProvider = blueprint.NewProvider[JarJarProviderData]()

var overridableJarJarPrefix = "com.android.internal.hidden_from_bootclasspath"

func init() {
 android.SetJarJarPrefixHandler(mergeJarJarPrefixes)
}

// mergeJarJarPrefixes is called immediately before module.GenerateAndroidBuildActions is called.
// Since there won't be a JarJarProvider, we create the BaseJarJarProvider if any of our deps have
// either JarJarProvider or BaseJarJarProvider.
func mergeJarJarPrefixes(ctx android.ModuleContext) {
 mod := ctx.Module()
 // Explicitly avoid propagating into some module types.
 switch reflect.TypeOf(mod).String() {
 case "*java.Droidstubs":
  return
 }
 jarJarData := collectDirectDepsProviders(ctx)
 if jarJarData != nil {
  providerData := android.BaseJarJarProviderData{
   Rename: jarJarData.Rename,
  }
  ctx.SetBaseJarJarProviderData(&providerData)
 }

}

// Add a jarjar renaming rule to this module, to be inherited to all dependent modules.
func (module *Module) addJarJarRenameRule(original string, renamed string) {
 if module.jarjarRenameRules == nil {
  module.jarjarRenameRules = make(map[string]string)
 }
 module.jarjarRenameRules[original] = renamed
}

func collectDirectDepsProviders(ctx android.ModuleContext) (result *JarJarProviderData) {
 // Gather repackage information from deps
 // If the dep jas a JarJarProvider, it is used.  Otherwise, any BaseJarJarProvider is used.

 module := ctx.Module()
 moduleName := module.Name()

 ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
  tag := ctx.OtherModuleDependencyTag(m)
  // This logic mirrors that in (*Module).collectDeps above.  There are several places
  // where we explicitly return RenameUseExclude, even though it is the default, to
  // indicate that it has been verified to be the case.
  //
  // Note well: there are probably cases that are getting to the unconditional return
  // and are therefore wrong.
  shouldIncludeRenames := func() DependencyUse {
   if moduleName == m.Name() {
    return RenameUseInclude // If we have the same module name, include the renames.
   }
   if sc, ok := module.(android.SdkContext); ok {
    if ctx.Device() {
     sdkDep := decodeSdkDep(ctx, sc)
     if !sdkDep.invalidVersion && sdkDep.useFiles {
      return RenameUseExclude
     }
    }
   }
   if IsJniDepTag(tag) || tag == certificateTag || tag == proguardRaiseTag {
    return RenameUseExclude
   }
   if _, ok := android.OtherModuleProvider(ctx, m, SdkLibraryInfoProvider); ok {
    switch tag {
    case sdkLibTag, libTag:
     return RenameUseExclude // matches collectDeps()
    }
    return RenameUseInvalid // dep is not used in collectDeps()
   } else if ji, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
    switch ji.StubsLinkType {
    case Stubs:
     return RenameUseExclude
    case Implementation:
     return RenameUseInclude
    default:
     //fmt.Printf("collectDirectDepsProviders: %v -> %v StubsLinkType unknown\n", module, m)
     // Fall through to the heuristic logic.
    }
    if _, ok := android.OtherModuleProvider(ctx, m, android.CodegenInfoProvider); ok {
     // Probably a java_aconfig_library module.
     return RenameUseInclude
    }
    switch tag {
    case bootClasspathTag:
     return RenameUseExclude
    case sdkLibTag, libTag, instrumentationForTag:
     return RenameUseInclude
    case java9LibTag:
     return RenameUseExclude
    case staticLibTag:
     return RenameUseInclude
    case pluginTag:
     return RenameUseInclude
    case errorpronePluginTag:
     return RenameUseInclude
    case exportedPluginTag:
     return RenameUseInclude
    case kotlinPluginTag:
     return RenameUseInclude
    default:
     return RenameUseExclude
    }
   } else if commonInfo, ok := android.OtherModuleProvider(ctx, m, android.CommonModuleInfoProvider); ok && commonInfo.SourceFiles != nil {
    switch tag {
    case sdkLibTag, libTag, staticLibTag:
     return RenameUseInclude
    default:
     return RenameUseExclude
    }
   } else if _, ok := android.OtherModuleProvider(ctx, m, android.CodegenInfoProvider); ok {
    return RenameUseInclude
   } else {
    switch tag {
    case bootClasspathTag:
     return RenameUseExclude
    case systemModulesTag:
     return RenameUseInclude
    }
   }
   // If we got here, choose the safer option, which may lead to a build failure, rather
   // than runtime failures on the device.
   return RenameUseExclude
  }

  if result == nil {
   result = &JarJarProviderData{
    Rename: make(map[string]string),
   }
  }
  how := shouldIncludeRenames()
  if how != RenameUseInclude {
   // Nothing to merge.
   return
  }

  merge := func(theirs android.JarJarRename) {
   for orig, renamed := range theirs {
    if preexisting, exists := (*result).Rename[orig]; !exists || preexisting == "" {
     result.Rename[orig] = renamed
    } else if preexisting != "" && renamed != "" && preexisting != renamed {
     if strings.HasPrefix(preexisting, overridableJarJarPrefix) {
      result.Rename[orig] = renamed
     } else if !strings.HasPrefix(renamed, overridableJarJarPrefix) {
      ctx.ModuleErrorf("1. Conflicting jarjar rules inherited for class: %s (%s and %s)", orig, renamed, preexisting, ctx.ModuleName(), m.Name())
      continue
     }
    }
   }
  }
  if theirs, ok := android.OtherModuleProvider(ctx, m, JarJarProvider); ok {
   merge(theirs.Rename)
  } else if theirs := android.OtherModulePointerProviderOrDefault(ctx, m, android.CommonModuleInfoProvider).BaseJarJarProviderData; theirs != nil {
   // TODO: if every java.Module should have a JarJarProvider, and we find only the
   // BaseJarJarProvider, then there is a bug.  Consider seeing if m can be cast
   // to java.Module.
   merge(theirs.Rename)
  }
 })
 return
}

func (this *Module) GetDebugString() string {
 return "sdk_version=" + proptools.String(this.deviceProperties.Sdk_version)
}

// Merge the jarjar rules we inherit from our dependencies, any that have been added directly to
// us, and if it's been set, apply the jarjar_prefix property to rename them.
func (module *Module) collectJarJarRules(ctx android.ModuleContext) *JarJarProviderData {

 // Stop collect jarjar_prefix jarjar rules if the module has test sdk scope.
 // If a module uses test API scope, which means in its source code and static dependencies
 // it could only use API exposed through the test surface. So it should not apply the jarjar
 // rules set by any bootclass path jar
 if ctx.Config().ReleaseJarjarFlagsInFramework() && module.SdkVersion(ctx).Kind == android.SdkTest {
  return nil
 }

 // Gather repackage information from deps
 result := collectDirectDepsProviders(ctx)

 add := func(orig string, renamed string) {
  if result == nil {
   result = &JarJarProviderData{
    Rename: make(map[string]string),
   }
  }
  if renamed != "" {
   if preexisting, exists := (*result).Rename[orig]; exists && preexisting != renamed {
    ctx.ModuleErrorf("Conflicting jarjar rules inherited for class: %s (%s and %s)", orig, renamed, preexisting)
    return
   }
  }
  (*result).Rename[orig] = renamed
 }

 // Update that with entries we've stored for ourself
 for orig, renamed := range module.jarjarRenameRules {
  add(orig, renamed)
 }

 // Update that with entries given in the jarjar_rename property.
 for _, orig := range module.properties.Jarjar_rename {
  add(orig, "")
 }

 // If there are no renamings, then jarjar_prefix does nothing, so skip the extra work.
 if result == nil {
  return nil
 }

 // If they've given us a jarjar_prefix property, then we will use that to rename any classes
 // that have not yet been renamed.
 prefix := proptools.String(module.properties.Jarjar_prefix)
 if prefix != "" {
  if prefix[0] == '.' {
   ctx.PropertyErrorf("jarjar_prefix", "jarjar_prefix can not start with '.'")
   return nil
  }
  if prefix[len(prefix)-1] == '.' {
   ctx.PropertyErrorf("jarjar_prefix", "jarjar_prefix can not end with '.'")
   return nil
  }

  var updated map[string]string
  for orig, renamed := range (*result).Rename {
   if renamed == "" {
    if updated == nil {
     updated = make(map[string]string)
    }
    updated[orig] = prefix + "." + orig
   }
  }
  for orig, renamed := range updated {
   (*result).Rename[orig] = renamed
  }
 }

 return result
}

// Get the jarjar rule text for a given provider for the fully resolved rules. Classes that map
// to "" won't be in this list because they shouldn't be renamed yet.
func getJarJarRuleText(provider *JarJarProviderData) string {
 result := strings.Builder{}
 for _, orig := range android.SortedKeys(provider.Rename) {
  renamed := provider.Rename[orig]
  if renamed != "" {
   result.WriteString("rule ")
   result.WriteString(orig)
   result.WriteString(" ")
   result.WriteString(renamed)
   result.WriteString("\n")
  }
 }
 return result.String()
}

// Repackage the flags if the jarjar rule txt for the flags is generated
func (j *Module) repackageFlagsIfNecessary(ctx android.ModuleContext, infile android.Path, jarName, info string) (android.Path, bool) {
 if j.repackageJarjarRules == nil {
  return infile, false
 }
 repackagedJarjarFile := android.PathForModuleOut(ctx, "repackaged-jarjar", info, jarName)
 TransformJarJar(ctx, repackagedJarjarFile, infile, j.repackageJarjarRules)
 return repackagedJarjarFile, true
}

func (j *Module) jarjarIfNecessary(ctx android.ModuleContext, infile android.Path, jarName, info string, useShards bool) (android.Path, bool) {
 if j.expandJarjarRules == nil {
  return infile, false
 }
 jarjarFile := android.PathForModuleOut(ctx, "jarjar", info, jarName)

 totalShards := 1
 if useShards {
  totalShardsStr := j.properties.Jarjar_shards.GetOrDefault(ctx, "1")
  ts, err := strconv.Atoi(totalShardsStr)
  if err != nil {
   ctx.PropertyErrorf("jarjar_shards", "jarjar_shards must be an integer represented as a string")
   return infile, false
  }
  totalShards = ts
 }
 TransformJarJarWithShards(ctx, jarjarFile, infile, j.expandJarjarRules, totalShards)
 return jarjarFile, true

}

func addPlugins(deps *deps, pluginJars android.Paths, pluginClasses ...string) {
 deps.processorPath = append(deps.processorPath, pluginJars...)
 deps.processorClasses = append(deps.processorClasses, pluginClasses...)
}

// TODO(b/132357300) Generalize SdkLibrarComponentDependency to non-SDK libraries and merge with
// this interface.
type ProvidesUsesLib interface {
 ProvidesUsesLib() *string
}

func (j *Module) ProvidesUsesLib() *string {
 return j.usesLibraryProperties.Provides_uses_lib
}

type ModuleWithStem interface {
 Stem() string
}

var _ ModuleWithStem = (*Module)(nil)

type ModuleWithUsesLibrary interface {
 UsesLibrary() *usesLibrary
}

func (j *Module) UsesLibrary() *usesLibrary {
 return &j.usesLibrary
}

var _ ModuleWithUsesLibrary = (*Module)(nil)

[0.64QuellennavigatorsProjekt 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