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

Quelle  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)

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