summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-08-18 14:36:26 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-08-18 14:36:26 +0000
commite0f43800a5920816448ec001c76f783059764ca6 (patch)
tree449424a4ef2226c9110ca1377911ea36b390a362
parent0a2ee0993b13789da3745bac1f376f8311631902 (diff)
parent96e25f968022e6b368d7809f4f5ea4ab86438836 (diff)
downloadbase-e0f43800a5920816448ec001c76f783059764ca6.tar.gz
Snap for 8962753 from 96e25f968022e6b368d7809f4f5ea4ab86438836 to studio-ee-release
Change-Id: I04c795285fef0c12929e1539cdb2a17258f9698b
-rw-r--r--PREUPLOAD.cfg3
-rw-r--r--adblib/test/src/com/android/adblib/AdbDeviceServicesTest.kt24
-rw-r--r--bazel/BUILD7
-rw-r--r--bazel/avd/src/com/android/tools/bazel/avd/Emulator.java23
-rw-r--r--bazel/common.bazelrc29
-rw-r--r--bazel/coverage/BUILD2
-rwxr-xr-xbazel/perfgate_linux.sh1
-rw-r--r--bazel/perfgate_win.cmd1
-rw-r--r--bazel/proto.bzl4
-rw-r--r--bazel/sdk/README.md6
-rw-r--r--bazel/sdk/dev-sdk-packages3
-rw-r--r--bazel/sdk/prebuilts.studio.sdk.BUILD5
-rwxr-xr-xbazel/studio_coverage.sh1
-rwxr-xr-xbazel/studio_linux.sh2
-rwxr-xr-xbazel/studio_win.cmd1
-rw-r--r--bazel/testSrc/com/android/tools/gradle/BenchmarkTest.java38
-rw-r--r--build-system/BUILD6
-rw-r--r--build-system/builder/src/main/java/com/android/builder/dexing/D8DexArchiveBuilder.java89
-rw-r--r--build-system/builder/src/main/java/com/android/builder/dexing/D8DiagnosticsHandler.java6
-rw-r--r--build-system/gradle-api/api/current.txt6
-rw-r--r--build-system/gradle-api/src/main/java/com/android/build/api/variant/AndroidTest.kt10
-rw-r--r--build-system/gradle-api/src/main/java/com/android/build/api/variant/Sources.kt5
-rw-r--r--build-system/gradle-api/src/main/java/com/android/build/api/variant/TestComponent.kt14
-rwxr-xr-xbuild-system/gradle-core/lint_baseline.xml248
-rw-r--r--build-system/gradle-core/src/apiTest/kotlin/com/android/build/api/apiTest/kotlin/AddCustomSourceTest.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/component/analytics/AnalyticsEnabledSources.kt11
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/component/analytics/AnalyticsEnabledUnitTest.kt11
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/component/impl/AndroidTestImpl.kt36
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ApkCreationConfigImpl.kt3
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ComponentImpl.kt19
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ConsumableCreationConfigImpl.kt25
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/component/impl/DefaultSourcesProvider.kt5
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/component/impl/DefaultSourcesProviderImpl.kt1
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ModelV1LegacySupportImpl.kt9
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/component/impl/OldVariantApiLegacySupportImpl.kt18
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/component/impl/TestFixturesImpl.kt19
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/component/impl/UnitTestImpl.kt20
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/component/impl/features/ManifestPlaceholdersCreationConfigImpl.kt35
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/ApplicationVariantBuilderImpl.kt4
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/ApplicationVariantImpl.kt8
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/DynamicFeatureVariantImpl.kt20
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/LibraryVariantBuilderImpl.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/LibraryVariantImpl.kt5
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/SourceType.kt1
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/SourcesImpl.kt13
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/TestVariantBuilderImpl.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/TestVariantImpl.kt8
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/VariantBuilderImpl.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/VariantImpl.kt21
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/DependencyResourcesComputer.kt17
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/VariantManager.kt60
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/api/AndroidArtifactVariantImpl.java5
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/api/VariantFilter.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/ApkCreationConfig.kt5
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/ApplicationCreationConfig.kt1
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/ComponentCreationConfig.kt5
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/ConsumableCreationConfig.kt3
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/DynamicFeatureCreationConfig.kt1
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/features/ManifestPlaceholdersCreationConfig.kt26
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/legacy/OldVariantApiLegacySupport.kt1
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/MergedAarMetadata.kt6
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/MergedAnnotationProcessorOptions.kt56
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/MergedFlavor.kt24
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/MergedJavaCompileOptions.kt23
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/VariantDslInfo.kt48
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/VariantDslInfoBuilder.kt376
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/VariantDslInfoImpl.kt1218
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/AarProducingComponentDslInfo.kt7
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/AndroidTestComponentDslInfo.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/ApkProducingComponentDslInfo.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/ApplicationVariantDslInfo.kt6
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/ComponentDslInfo.kt17
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/ConsumableComponentDslInfo.kt8
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/DynamicFeatureVariantDslInfo.kt12
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/InstrumentedTestComponentDslInfo.kt5
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/LibraryVariantDslInfo.kt8
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/PublishableComponentDslInfo.kt (renamed from build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/PublishableVariantDslInfo.kt)5
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/TestComponentDslInfo.kt3
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/TestFixturesComponentDslInfo.kt5
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/TestProjectVariantDslInfo.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/TestedVariantDslInfo.kt (renamed from build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/TestedComponentDslInfo.kt)4
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/UnitTestComponentDslInfo.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/VariantDslInfo.kt11
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/AndroidTestComponentDslInfoImpl.kt150
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/ApplicationVariantDslInfoImpl.kt201
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/ComponentDslInfoImpl.kt298
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/ConsumableComponentDslInfoImpl.kt266
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/DslInfoBuilder.kt332
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/DslInfoCommon.kt113
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/DslInfoUtils.kt97
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/DynamicFeatureVariantDslInfoImpl.kt72
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/InstrumentedTestDslInfoImpl.kt95
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/LibraryVariantDslInfoImpl.kt83
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/TestFixturesDslInfoImpl.kt79
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/TestProjectVariantDslInfoImpl.kt157
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/TestedVariantDslInfoImpl.kt60
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/UnitTestComponentDslInfoImpl.kt78
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/VariantDslInfoImpl.kt205
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/coverage/JacocoPropertiesTask.kt3
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/configure/ExperimentalPropertyExtensions.kt35
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/model/CreateCxxAbiModel.kt1
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/model/CxxAbiModel.kt12
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/model/JsonUtil.kt4
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/prefab/CreatePublicationModel.kt5
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/prefab/PackageBuilder.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/prefab/PublicationModel.kt3
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/settings/CxxAbiModelSettingsRewriter.kt78
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dependency/VariantDependenciesBuilder.java308
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/InternalApplicationExtension.kt3
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/InternalDynamicFeatureExtension.kt3
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/InternalLibraryExtension.kt3
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/InternalTestedExtension.kt7
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/feature/BundleAllClasses.kt3
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/fusedlibrary/FusedLibraryPluginUtils.kt73
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/ide/SourceProviderImpl.java2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/ide/v2/Converters.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/lint/AndroidLintAnalysisTask.kt4
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/lint/AndroidLintInputs.kt6
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/AbstractFusedLibraryPlugin.kt302
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/AbstractPrivacySandboxPlugin.kt251
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/FusedLibraryPlugin.kt318
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/PrivacySandboxSdkPlugin.kt244
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/res/LinkAndroidResForBundleTask.kt2
-rwxr-xr-xbuild-system/gradle-core/src/main/java/com/android/build/gradle/internal/res/LinkApplicationAndroidResourcesTask.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/res/PrivacySandboxSdkLinkAndroidResourcesTask.kt2
-rwxr-xr-xbuild-system/gradle-core/src/main/java/com/android/build/gradle/internal/res/namespaced/LinkLibraryAndroidResourcesTask.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/services/LintParallelBuildService.kt135
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/BundleIdeModelProducerTask.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/BundleLibraryClasses.kt3
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/BundleLibraryJavaRes.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/DexMergingTask.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/FeatureDexMergeTask.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/LibraryAarJarsTask.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/LinkManifestForAssetPackTask.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/ManagedDeviceCleanTask.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/ManagedDeviceSetupTask.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeArtProfileTask.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeClassesTask.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeConsumerProguardFilesTask.java2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeFileTask.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeJavaResourceTask.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeNativeDebugMetadataTask.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeNativeLibsTask.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/NdkTask.java3
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/PackageRenderscriptTask.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/ProcessJavaResTask.kt5
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/databinding/DataBindingMergeDependencyArtifactsTask.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/databinding/MergeRFilesForDataBindingTask.kt3
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/featuresplit/PackagedDependenciesWriterTask.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/utils/PublishingUtil.kt11
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/AbstractVariantInputManager.kt21
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/VariantPathHelper.kt89
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/options/BooleanOption.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/BundleAar.kt18
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ExtractDeepLinksTask.kt8
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryBundle.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryManifestMergerTask.kt3
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryMergeArtifactTask.kt3
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryMergeClasses.kt3
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryMergeResourcesTask.kt3
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/GenerateManifestJarTask.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/InvokeManifestMerger.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/MapSourceSetPathsTask.kt3
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/MergeResources.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/MergeSourceSetFolders.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkManifestGeneratorTask.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkManifestMergerTask.kt3
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkMergeDexTask.kt2
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkMergeResourcesTask.kt3
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessAndroidResources.java4
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessApplicationManifest.kt5
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessTestManifest.kt7
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/SourceJarTask.kt3
-rw-r--r--build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ZipMergingTask.kt3
-rw-r--r--build-system/gradle-core/src/test/java/com/android/build/api/component/analytics/AnalyticsEnabledSourcesTest.kt9
-rw-r--r--build-system/gradle-core/src/test/java/com/android/build/api/variant/impl/VariantBuilderImplTest.kt2
-rw-r--r--build-system/gradle-core/src/test/java/com/android/build/gradle/DefaultVariantTest.kt4
-rw-r--r--build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/MergedFlavorTest.kt67
-rw-r--r--build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/VariantBuilderComputeNameTest.kt11
-rw-r--r--build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/VariantDslInfoTest.java61
-rw-r--r--build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/dsl/info/VariantDslInfoTest2.kt (renamed from build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/VariantDslInfoTest2.kt)185
-rw-r--r--build-system/gradle-core/src/test/java/com/android/build/gradle/internal/services/LintParallelBuildServiceTest.kt112
-rw-r--r--build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/AarMetadataTaskTest.kt4
-rw-r--r--build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/CheckAarMetadataTaskTest.kt6
-rw-r--r--build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/TaskMethodModifiersAndAnnotationsTest.kt4
-rw-r--r--build-system/gradle-core/src/test/java/com/android/build/gradle/internal/variant/VariantPathHelperTest.kt11
-rw-r--r--build-system/gradle-core/src/test/java/com/android/build/gradle/tasks/BuildAnalyzerTest.kt355
-rw-r--r--build-system/gradle-core/src/test/resources/com/android/build/gradle/pseudo-api.txt8
-rw-r--r--build-system/integration-test/application/BUILD.bazel2
-rw-r--r--build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/AarPublishTest.kt47
-rw-r--r--build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/CheckAarMetadataTaskTest.kt10
-rw-r--r--build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/DifferentProjectClassLoadersTest.kt10
-rw-r--r--build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/NoCruncherTest.java5
-rw-r--r--build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/ProfileableTest.kt22
-rw-r--r--build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/AarMetadataTaskTest.kt4
-rw-r--r--build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/manifest/ProcessTestManifestTest.kt4
-rw-r--r--build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/resources/UserAddedGeneratedResourcesTest.kt157
-rw-r--r--build-system/integration-test/connected/BUILD.bazel60
-rw-r--r--build-system/integration-test/connected/connected-test.bzl18
-rw-r--r--build-system/integration-test/connected/src/main/java/com/android/build/gradle/integration/connected/utils/EmulatorUtils.kt2
-rw-r--r--build-system/integration-test/connected/src/test/java/com/android/build/gradle/integration/connected/application/PrivacySandboxSdkConnectedTest.kt92
-rw-r--r--build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/BuildSrcProject.kt37
-rw-r--r--build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/GradleProject.kt3
-rw-r--r--build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/app/MinimalSubProject.kt5
-rw-r--r--build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/app/MultiModuleTestProject.java41
-rw-r--r--build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/testprojects/TestProjectBuilderImpl.kt1
-rw-r--r--build-system/integration-test/managed-devices/BUILD.bazel3
-rw-r--r--build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/nativebuild/CmakeBasicProjectTest.kt47
-rw-r--r--build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/ndk/ModuleToModuleDepsTest.kt29
-rw-r--r--build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/ndk/PrefabPublishingTest.kt3
-rw-r--r--build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/ads-sdk-implementation/build.gradle22
-rw-r--r--build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/ads-sdk-implementation/src/main/AndroidManifest.xml4
-rw-r--r--build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/ads-sdk-implementation/src/main/assets/example.txt0
-rw-r--r--build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/ads-sdk-implementation/src/main/java/com/myrbsdk/MyAdsSdkEntryPoint.java44
-rw-r--r--build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/ads-sdk/build.gradle19
-rw-r--r--build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/build.gradle38
-rw-r--r--build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/androidTest/java/com/example/rubidumconsumer/MainActivityTest.kt25
-rw-r--r--build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/main/AndroidManifest.xml26
-rw-r--r--build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/main/java/com/example/rubidumconsumer/MainActivity.java62
-rw-r--r--build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/main/java/com/example/rubidumconsumer/RemoteSdkCallbackImpl.java43
-rw-r--r--build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/main/res/layout/activity_main.xml12
-rw-r--r--build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/main/res/values/strings.xml3
-rw-r--r--build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/build.gradle11
-rw-r--r--build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/gradle.properties2
-rw-r--r--build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/settings.gradle5
-rw-r--r--ddmlib/src/main/java/com/android/ddmlib/internal/DeviceClientMonitorTask.java15
-rw-r--r--ddmlib/src/test/java/com/android/ddmlib/testing/FakeAdbRule.kt12
-rw-r--r--deploy/agent/runtime/android.sdktools.deployer.deployer-runtime-support.iml31
-rw-r--r--device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DefaultProvisionerPlugin.kt4
-rw-r--r--device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProperties.kt93
-rw-r--r--device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProvisioner.kt4
-rw-r--r--device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProvisionerPlugin.kt20
-rw-r--r--device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceState.kt2
-rw-r--r--device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceTemplate.kt12
-rw-r--r--device-provisioner/src/test/com/android/sdklib/deviceprovisioner/DeviceProvisionerTest.kt4
-rw-r--r--fakeadbserver/src/main/java/com/android/fakeadbserver/DeviceState.java27
-rw-r--r--fakeadbserver/src/main/java/com/android/fakeadbserver/FakeAdbServer.java6
-rw-r--r--fakeadbserver/src/main/java/com/android/fakeadbserver/FakeAdbServerConfig.kt1
-rw-r--r--fakeadbserver/src/main/java/com/android/fakeadbserver/execcommandhandlers/GetPropExecCommandHandler.kt19
-rw-r--r--fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/GetPropCommandHandler.java32
-rw-r--r--fakeadbserver/src/main/java/com/android/fakeadbserver/shellv2commandhandlers/GetPropV2CommandHandler.kt19
-rw-r--r--gmaven/src/test/resources/com/android/tools/test/gmaven-aars.txt4
-rw-r--r--gmaven/src/test/resources/com/android/tools/test/gmaven-jars.txt1
-rw-r--r--lint/cli/src/main/java/com/android/tools/lint/LintFixPerformer.kt53
-rw-r--r--lint/cli/src/main/java/com/android/tools/lint/UastEnvironment.kt2
-rw-r--r--lint/cli/src/main/java/com/android/tools/lint/gradle/GroovyGradleVisitor.java6
-rw-r--r--lint/libs/lint-api/src/main/java/com/android/tools/lint/client/api/JarFileIssueRegistry.kt47
-rw-r--r--lint/libs/lint-api/src/main/java/com/android/tools/lint/client/api/LintDriver.kt52
-rw-r--r--lint/libs/lint-api/src/main/java/com/android/tools/lint/client/api/LintJarVerifier.kt75
-rw-r--r--lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/UastLintUtils.kt11
-rw-r--r--lint/libs/lint-api/src/main/java/com/android/tools/lint/helpers/DefaultUastParser.kt4
-rw-r--r--lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/CheckResultDetector.kt15
-rw-r--r--lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/DeprecationDetector.kt16
-rw-r--r--lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/GooglePlaySdkIndex.kt94
-rw-r--r--lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/GradleDetector.kt8
-rw-r--r--lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/PluralsDetector.kt25
-rw-r--r--lint/libs/lint-checks/src/main/resources/sdk-index-offline-snapshot.proto.gzbin9474 -> 9505 bytes
-rw-r--r--lint/libs/lint-tests/src/test/java/com/android/tools/lint/LintFixPerformerTest.kt48
-rw-r--r--lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/CheckResultDetectorTest.kt43
-rw-r--r--lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/DeprecationDetectorTest.kt38
-rw-r--r--lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/GooglePlaySdkIndexTest.kt17
-rw-r--r--lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/GradleDetectorTest.kt70
-rw-r--r--lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/PluralsDetectorTest.java47
-rw-r--r--lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/SdCardDetectorTest.java29
-rw-r--r--lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/infrastructure/SuppressLintTest.kt94
-rw-r--r--lint/libs/lint-tests/src/test/java/com/android/tools/lint/client/api/JarFileIssueRegistryTest.kt27
-rw-r--r--lint/libs/lint-tests/src/test/java/com/android/tools/lint/client/api/LintJarVerifierTest.kt42
-rw-r--r--lint/libs/lint-tests/src/test/java/com/android/tools/lint/detector/api/VersionChecksTest.kt46
-rw-r--r--sdk-common/src/main/java/com/android/ide/common/attribution/TaskCategoryLabel.kt16
-rw-r--r--sdk-common/src/main/java/com/android/ide/common/repository/GradleVersion.java164
-rw-r--r--sdk-common/src/main/java/com/android/ide/common/repository/NetworkCache.kt39
-rw-r--r--sdk-common/src/main/java/com/android/ide/common/resources/AbstractResourceRepository.java4
-rw-r--r--sdk-common/src/test/java/com/android/ide/common/repository/GradleCoordinateTest.java2
-rw-r--r--sdk-common/src/test/java/com/android/ide/common/repository/GradleVersionTest.java1
-rw-r--r--testutils/src/main/java/com/android/testutils/TestUtils.java10
-rw-r--r--utp/android-device-provider-gradle-proto/BUILD7
-rw-r--r--utp/android-test-plugin-host-device-info-proto/BUILD7
-rw-r--r--utp/android-test-plugin-host-retention-proto/BUILD7
-rw-r--r--utp/android-test-plugin-result-listener-gradle-proto/BUILD7
279 files changed, 6420 insertions, 3983 deletions
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 69a6633c0f..2ff19985c5 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -4,11 +4,14 @@ sync-inspection-profiles = ${REPO_ROOT}/tools/repohooks/tools/sync-inspection-pr
[Builtin Hooks]
google_java_format = true
clang_format = true
+ktfmt = true
[Builtin Hooks Options]
google_java_format = --sort-imports
clang_format = --style=google --extensions cc,h --commit HEAD --git-clang-format ${REPO_ROOT}/prebuilts/tools/common/clang-format/git-clang-format --clang-format ${REPO_ROOT}/prebuilts/tools/${BUILD_OS}/clang-format/clang-format${BUILD_OS_EXEC_EXTENSION}
+ktfmt = --include-dirs=device-provisioner --google-style
[Tool Paths]
google-java-format = ${REPO_ROOT}/prebuilts/tools/common/google-java-format/google-java-format
google-java-format-diff = ${REPO_ROOT}/tools/repohooks/tools/google-java-format-diff.py
+ktfmt = ${REPO_ROOT}/prebuilts/tools/common/ktfmt/ktfmt
diff --git a/adblib/test/src/com/android/adblib/AdbDeviceServicesTest.kt b/adblib/test/src/com/android/adblib/AdbDeviceServicesTest.kt
index e1c0504e8c..79a3d96a17 100644
--- a/adblib/test/src/com/android/adblib/AdbDeviceServicesTest.kt
+++ b/adblib/test/src/com/android/adblib/AdbDeviceServicesTest.kt
@@ -97,11 +97,11 @@ class AdbDeviceServicesTest {
# This is some build info
# This is more build info
+ [ro.build.version.release]: [model]
+ [ro.build.version.sdk]: [30]
[ro.product.cpu.abi]: [x86_64]
[ro.product.manufacturer]: [test1]
[ro.product.model]: [test2]
- [ro.build.version.release]: [model]
- [ro.build.version.sdk]: [30]
""".trimIndent()
Assert.assertEquals(expectedOutput, AdbProtocolUtils.byteBufferToString(bytes))
@@ -125,10 +125,11 @@ class AdbDeviceServicesTest {
# This is some build info
# This is more build info
- [ro.product.manufacturer]: [test1]
- [ro.product.model]: [test2]
[ro.build.version.release]: [model]
[ro.build.version.sdk]: [30]
+ [ro.product.cpu.abi]: [x86_64]
+ [ro.product.manufacturer]: [test1]
+ [ro.product.model]: [test2]
""".trimIndent()
Assert.assertEquals(expectedOutput, commandOutput.stdout)
@@ -157,10 +158,11 @@ class AdbDeviceServicesTest {
# This is some build info
# This is more build info
- [ro.product.manufacturer]: [test1]
- [ro.product.model]: [test2]
[ro.build.version.release]: [model]
[ro.build.version.sdk]: [30]
+ [ro.product.cpu.abi]: [x86_64]
+ [ro.product.manufacturer]: [test1]
+ [ro.product.model]: [test2]
""".trimIndent()
Assert.assertEquals(expectedOutput.lines(), lines)
@@ -584,10 +586,11 @@ class AdbDeviceServicesTest {
# This is some build info
# This is more build info
- [ro.product.manufacturer]: [test1]
- [ro.product.model]: [test2]
[ro.build.version.release]: [model]
[ro.build.version.sdk]: [30]
+ [ro.product.cpu.abi]: [x86_64]
+ [ro.product.manufacturer]: [test1]
+ [ro.product.model]: [test2]
""".trimIndent()
Assert.assertEquals(expectedOutput, AdbProtocolUtils.byteBufferToString(bytes))
@@ -613,10 +616,11 @@ class AdbDeviceServicesTest {
# This is some build info
# This is more build info
- [ro.product.manufacturer]: [test1]
- [ro.product.model]: [test2]
[ro.build.version.release]: [model]
[ro.build.version.sdk]: [30]
+ [ro.product.cpu.abi]: [x86_64]
+ [ro.product.manufacturer]: [test1]
+ [ro.product.model]: [test2]
""".trimIndent()
Assert.assertEquals(
diff --git a/bazel/BUILD b/bazel/BUILD
index 1718eaab4d..cb50cf2230 100644
--- a/bazel/BUILD
+++ b/bazel/BUILD
@@ -377,6 +377,13 @@ java_jarjar(
visibility = ["//visibility:public"],
)
+java_jarjar(
+ name = "utp-core-proto-jarjar",
+ srcs = ["//prebuilts/tools/common/m2:utp-core-proto"],
+ rules = "jarjar_rules.txt",
+ visibility = ["//visibility:public"],
+)
+
config_setting(
name = "host_linux",
values = {"host_cpu": "linux"},
diff --git a/bazel/avd/src/com/android/tools/bazel/avd/Emulator.java b/bazel/avd/src/com/android/tools/bazel/avd/Emulator.java
index 5817b25b99..fd133787d9 100644
--- a/bazel/avd/src/com/android/tools/bazel/avd/Emulator.java
+++ b/bazel/avd/src/com/android/tools/bazel/avd/Emulator.java
@@ -16,8 +16,6 @@
package com.android.tools.bazel.avd;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
import org.junit.rules.ExternalResource;
/** JUnit rule that calls the executable generated by the avd rule to start and stop an emulator. */
@@ -40,7 +38,7 @@ public final class Emulator extends ExternalResource {
@Override
public void before() throws Throwable {
System.out.println("Starting emulator");
- System.out.println(exec(devicePath + " " + port));
+ exec(devicePath, port);
System.out.println("Emulator started");
}
@@ -48,25 +46,18 @@ public final class Emulator extends ExternalResource {
public void after() {
try {
System.out.println("Killing emulator");
- System.out.println(exec(devicePath + " kill " + port));
+ exec(devicePath, "kill", port);
System.out.println("Emulator killed");
} catch (Exception ex) {
ex.printStackTrace();
}
}
- private static String exec(String cmd) throws Exception {
- Runtime r = Runtime.getRuntime();
- Process p = r.exec(cmd);
- p.waitFor();
- String res = "";
- try (BufferedReader b = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
- String l = "";
- while ((l = b.readLine()) != null) {
- res += l + "\n";
- }
- }
+ private static void exec(String... cmd) throws Exception {
+ int exitCode = new ProcessBuilder().command(cmd).inheritIO().start().waitFor();
- return res;
+ if (exitCode != 0) {
+ throw new Exception(String.format("Emulator script exited with code: %d", exitCode));
+ }
}
}
diff --git a/bazel/common.bazelrc b/bazel/common.bazelrc
index 0dad12ef52..895c5abd9f 100644
--- a/bazel/common.bazelrc
+++ b/bazel/common.bazelrc
@@ -21,6 +21,35 @@ test --jvmopt='-XX:+UseG1GC'
test --jvmopt='-XX:ErrorFile=$TEST_UNDECLARED_OUTPUTS_DIR/jvm_crash.log'
test --verbose_failures
+# TODO(b/242203555) cleanup opens/exports that was added for JDK17 migration
+test:jdk17 --jvmopt='--add-opens=java.base/java.io=ALL-UNNAMED'
+test:jdk17 --jvmopt='--add-opens=java.base/java.lang=ALL-UNNAMED'
+test:jdk17 --jvmopt='--add-opens=java.base/java.nio.charset=ALL-UNNAMED'
+test:jdk17 --jvmopt='--add-opens=java.base/java.util=ALL-UNNAMED'
+test:jdk17 --jvmopt='--add-opens=java.base/java.util.concurrent=ALL-UNNAMED'
+test:jdk17 --jvmopt='--add-opens=java.desktop/java.awt=ALL-UNNAMED'
+test:jdk17 --jvmopt='--add-opens=java.desktop/java.awt.event=ALL-UNNAMED'
+test:jdk17 --jvmopt='--add-opens=java.desktop/java.awt.peer=ALL-UNNAMED'
+test:jdk17 --jvmopt='--add-opens=java.desktop/javax.swing=ALL-UNNAMED'
+test:jdk17 --jvmopt='--add-opens=java.desktop/javax.swing.plaf.basic=ALL-UNNAMED'
+test:jdk17 --jvmopt='--add-opens=java.desktop/sun.awt=ALL-UNNAMED'
+test:jdk17 --jvmopt='--add-opens=java.desktop/sun.font=ALL-UNNAMED'
+test:jdk17 --jvmopt='--add-exports java.base/jdk.internal.vm=ALL-UNNAMED'
+test:jdk17 --jvmopt='--add-exports=java.desktop/sun.awt.image=ALL-UNNAMED'
+test:jdk17 --jvmopt='--add-exports=java.desktop/sun.java2d=ALL-UNNAMED'
+test:jdk17 --jvmopt='--add-exports=java.desktop/sun.swing=ALL-UNNAMED'
+test:jdk17 --jvmopt='--add-exports=jdk.attach/sun.tools.attach=ALL-UNNAMED'
+test:jdk17 --jvmopt='--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED'
+test:jdk17 --jvmopt='--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED'
+
+build:jdk17 --jvmopt='--add-exports java.base/jdk.internal.vm=ALL-UNNAMED'
+build:jdk17 --jvmopt='--add-exports=java.desktop/sun.awt.image=ALL-UNNAMED'
+build:jdk17 --jvmopt='--add-exports=java.desktop/sun.java2d=ALL-UNNAMED'
+build:jdk17 --jvmopt='--add-exports=java.desktop/sun.swing=ALL-UNNAMED'
+build:jdk17 --jvmopt='--add-exports=jdk.attach/sun.tools.attach=ALL-UNNAMED'
+build:jdk17 --jvmopt='--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED'
+build:jdk17 --jvmopt='--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED'
+
# Local runs require longer timeouts.
test:local --test_timeout=120,600,1800,7200
diff --git a/bazel/coverage/BUILD b/bazel/coverage/BUILD
index 3ec6b48187..bfdf9c316d 100644
--- a/bazel/coverage/BUILD
+++ b/bazel/coverage/BUILD
@@ -996,6 +996,7 @@ coverage_report(
"//tools/apksig:all",
"//tools/apkzlib:apkzlib_tests",
"//tools/base/adblib:adblib.tests.test",
+ "//tools/base/adblib-tools:adblib.tools.tests.test",
"//tools/base/apkparser:studio.android.sdktools.binary-resources_tests",
"//tools/base/apkparser:tools.tests",
"//tools/base/apkparser/analyzer:studio.android.sdktools.analyzer_tests",
@@ -1064,6 +1065,7 @@ coverage_report(
"//tools/base/ddmlib:tools.tests.test",
"//tools/base/deploy/deployer:deployer.tests",
"//tools/base/deploy/deployer:studio.android.sdktools.deployer_tests",
+ "//tools/base/device-provisioner:studio.android.sdktools.device-provisioner_tests",
"//tools/base/draw9patch:studio.android.sdktools.draw9patch_tests",
"//tools/base/dynamic-layout-inspector/agent/appinspection:agent_tests.test",
"//tools/base/fakeadbserver:studio.android.sdktools.fakeadbserver_tests",
diff --git a/bazel/perfgate_linux.sh b/bazel/perfgate_linux.sh
index 360aad42a3..c651747c93 100755
--- a/bazel/perfgate_linux.sh
+++ b/bazel/perfgate_linux.sh
@@ -30,6 +30,7 @@ readonly invocation_id="$(uuidgen)"
${config_options} --config=ants \
--build_metadata=ab_build_id="${BUILD_NUMBER}" \
--build_metadata=ab_target=perfgate-linux \
+ --build_metadata=ANDROID_TEST_INVESTIGATE="http://ab/tests/bazel/${invocation_id}" \
--invocation_id=${invocation_id} \
--build_tag_filters=${build_tag_filters} \
--define=meta_android_build_number=${build_number} \
diff --git a/bazel/perfgate_win.cmd b/bazel/perfgate_win.cmd
index 272a6ce384..c58c3fd27e 100644
--- a/bazel/perfgate_win.cmd
+++ b/bazel/perfgate_win.cmd
@@ -34,6 +34,7 @@ CALL %SCRIPTDIR%bazel.cmd ^
--config=ci --config=ants ^
--build_metadata=ab_build_id=%BUILDNUMBER% ^
--build_metadata=ab_target=perfgate-win ^
+ --build_metadata=ANDROID_TEST_INVESTIGATE="http://ab/tests/bazel/%INVOCATIONID%" ^
--build_tag_filters=-no_windows ^
--invocation_id=%INVOCATIONID% ^
--build_event_binary_file=%DISTDIR%\bazel-%BUILDNUMBER%.bes ^
diff --git a/bazel/proto.bzl b/bazel/proto.bzl
index 3e9801abd9..982f3f9b1d 100644
--- a/bazel/proto.bzl
+++ b/bazel/proto.bzl
@@ -200,7 +200,8 @@ def android_java_proto_library(
protoc_grpc_version = PROTOC_GRPC_VERSION,
java_deps = [],
proto_deps = [],
- visibility = None):
+ visibility = None,
+ **kwargs):
"""Compiles protobuf into a .jar file in Android Studio compatible runtime version.
Unlike java_proto_library rule defined above, android_java_proto_library
@@ -230,6 +231,7 @@ def android_java_proto_library(
protoc_grpc_version = protoc_grpc_version,
java_deps = java_deps,
proto_deps = proto_deps,
+ **kwargs
)
java_jarjar(
name = name,
diff --git a/bazel/sdk/README.md b/bazel/sdk/README.md
index 8190cd2177..e91f83f3ae 100644
--- a/bazel/sdk/README.md
+++ b/bazel/sdk/README.md
@@ -152,7 +152,7 @@ the file from local_manifests.
$ cd /path/to/studio-main/
# This branch name will become the topic name for your CLs so choose a unique name.
-# Of course, your branch name will be different...
+# Of course, your branch name will be different...
$ repo start devsdk+build-tools+19_0_3 \
prebuilts/studio/sdk/darwin \
prebuilts/studio/sdk/linux \
@@ -253,7 +253,7 @@ $ repo forall \
prebuilts/studio/sdk/linux \
prebuilts/studio/sdk/windows \
tools/base \
- -c git add -A; git commit -a -m "Updated SDK with build-tools;19.0.3"
+ -c 'git add -A; git commit -a -m "Updated SDK with build-tools;19.0.3"'
# When uploading, include -t to ensure all code reviews have the
# same topic (the topic will be set to your current branch name).
@@ -317,4 +317,4 @@ $ rm -rf prebuilts/studio/sdk/windows # unless you're windows
$ repo upload --cbr -t
# This opens an editor. Uncomment all SDK branches and save.
- ``` \ No newline at end of file
+ ```
diff --git a/bazel/sdk/dev-sdk-packages b/bazel/sdk/dev-sdk-packages
index 095d83518a..a8dbd83ed7 100644
--- a/bazel/sdk/dev-sdk-packages
+++ b/bazel/sdk/dev-sdk-packages
@@ -19,6 +19,7 @@ build-tools;25.0.0
build-tools;24.0.3
# Platforms.
+platforms;android-TiramisuPrivacySandbox
platforms;android-33
platforms;android-32
platforms;android-31
@@ -53,5 +54,3 @@ cmake;3.22.1
# Instant apps sdk used in integration tests
extras;google;instantapps
-
-ndk;21.4.7075529:**:{**/OWNERS,**/BUILD.bazel}
diff --git a/bazel/sdk/prebuilts.studio.sdk.BUILD b/bazel/sdk/prebuilts.studio.sdk.BUILD
index ec3e3ea333..fbeff3a574 100644
--- a/bazel/sdk/prebuilts.studio.sdk.BUILD
+++ b/bazel/sdk/prebuilts.studio.sdk.BUILD
@@ -84,7 +84,7 @@ filegroup(
srcs = sdk_glob(
include = ["build-tools/30.0.3/**"],
),
- visibility = ["//visibility:private"],
+ visibility = ["//tools/adt/idea/old-agp-tests:__pkg__"],
)
filegroup(
@@ -233,8 +233,9 @@ java_import(
)
platform_filegroup(
- name = "platforms/android-Tiramisu",
+ name = "platforms/android-TiramisuPrivacySandbox",
visibility = [
+ "//prebuilts/studio/buildbenchmarks:__pkg__",
"//tools/base/build-system/integration-test:__subpackages__",
],
)
diff --git a/bazel/studio_coverage.sh b/bazel/studio_coverage.sh
index 7eaaa12e34..dc73ebb09a 100755
--- a/bazel/studio_coverage.sh
+++ b/bazel/studio_coverage.sh
@@ -73,6 +73,7 @@ fi
--build_event_binary_file="${dist_dir:-/tmp}/bazel-${build_number}.bes" \
--profile="${dist_dir:-/tmp}/profile-${build_number}.json.gz" \
--build_metadata=ANDROID_BUILD_ID="${build_number}" \
+ --build_metadata=ANDROID_TEST_INVESTIGATE="http://ab/tests/bazel/${invocation_id}" \
--build_metadata=ab_build_id="${build_number}" \
--build_metadata=ab_target=studio-coverage \
${auth_options} \
diff --git a/bazel/studio_linux.sh b/bazel/studio_linux.sh
index e5554eb1ed..971fba8862 100755
--- a/bazel/studio_linux.sh
+++ b/bazel/studio_linux.sh
@@ -46,6 +46,7 @@ function copy_bazel_artifacts() {(
cp -a ${bin_dir}/tools/adt/idea/studio/android-studio.mac.zip ${artifacts_dir}
cp -a ${bin_dir}/tools/adt/idea/studio/android-studio.mac_arm.zip ${artifacts_dir}
cp -a ${bin_dir}/tools/adt/idea/studio/android-studio_build_manifest.textproto ${artifacts_dir}/android-studio_build_manifest.textproto
+ cp -a ${bin_dir}/tools/adt/idea/studio/android-studio_update_message.html ${artifacts_dir}/android-studio_update_message.html
cp -a ${bin_dir}/tools/adt/idea/studio/updater_deploy.jar ${artifacts_dir}/android-studio-updater.jar
cp -a ${bin_dir}/tools/adt/idea/updater-ui/sdk-patcher.zip ${artifacts_dir}
cp -a ${bin_dir}/tools/adt/idea/native/installer/android-studio-bundle-data.zip ${artifacts_dir}
@@ -137,6 +138,7 @@ function run_bazel_test() {
--build_event_binary_file="${DIST_DIR:-/tmp}/bazel-${BUILD_NUMBER}.bes" \
--define=meta_android_build_number="${BUILD_NUMBER}" \
--build_metadata=ANDROID_BUILD_ID="${BUILD_NUMBER}" \
+ --build_metadata=ANDROID_TEST_INVESTIGATE="http://ab/tests/bazel/${invocation_id}" \
--build_metadata=ab_build_id="${BUILD_NUMBER}" \
--build_metadata=ab_target="${target_name}" \
--test_tag_filters=${test_tag_filters} \
diff --git a/bazel/studio_win.cmd b/bazel/studio_win.cmd
index 00bd3c48da..422b44171f 100755
--- a/bazel/studio_win.cmd
+++ b/bazel/studio_win.cmd
@@ -84,6 +84,7 @@ setlocal
--build_event_binary_file=%DISTDIR%\bazel-%BUILDNUMBER%.bes ^
--test_tag_filters=%TESTTAGFILTERS% ^
--build_metadata=ANDROID_BUILD_ID=%BUILDNUMBER% ^
+ --build_metadata=ANDROID_TEST_INVESTIGATE="http://ab/tests/bazel/%INVOCATIONID%" ^
--build_metadata=ab_build_id=%BUILDNUMBER% ^
--build_metadata=ab_target=studio-win ^
--profile=%DISTDIR%\winprof%BUILDNUMBER%.json.gz ^
diff --git a/bazel/testSrc/com/android/tools/gradle/BenchmarkTest.java b/bazel/testSrc/com/android/tools/gradle/BenchmarkTest.java
index 5a81ebd86d..ea89b6c670 100644
--- a/bazel/testSrc/com/android/tools/gradle/BenchmarkTest.java
+++ b/bazel/testSrc/com/android/tools/gradle/BenchmarkTest.java
@@ -20,6 +20,7 @@ import com.android.SdkConstants;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.testutils.diff.UnifiedDiff;
+import com.android.testutils.TestUtils;
import com.android.tools.gradle.benchmarkassertions.BenchmarkProjectAssertion;
import com.android.tools.perflogger.Benchmark;
import com.android.tools.perflogger.PerfData;
@@ -29,6 +30,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
+import java.nio.file.Path;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
@@ -76,6 +78,7 @@ public class BenchmarkTest {
private String yourKitAgentPath = null;
private String yourKitLibraryPath = null;
private String yourKitSettingsPath = null;
+ private boolean useJdk11 = false;
@Before
public void setUp() throws Exception {
@@ -176,6 +179,10 @@ public class BenchmarkTest {
if (value != null && !value.isEmpty()) {
enableYourKit = Boolean.parseBoolean(value);
}
+ value = System.getProperty("use_jdk11");
+ if (value != null && !value.isEmpty()) {
+ useJdk11 = Boolean.parseBoolean(value);
+ }
yourKitAgentPath = getStringProperty("yourkit_agent_path");
yourKitLibraryPath = getStringProperty("yourkit_library_path");
yourKitSettingsPath = getStringProperty("yourkit_settings");
@@ -314,8 +321,11 @@ public class BenchmarkTest {
}
File projectRoot = new File(src, testProjectGradleRootFromSourceRoot);
- addJvmArgs(
- new File(projectRoot, "gradle.properties"), enableYourKit, src, yourKitAgentPath);
+ File gradleProperties = new File(projectRoot, "gradle.properties");
+ addJvmArgs(gradleProperties, enableYourKit, src, yourKitAgentPath);
+ if (useJdk11) {
+ useJdk11ForGradle(gradleProperties);
+ }
try (Gradle gradle = new Gradle(projectRoot, out, distribution)) {
for (File repo : repos) {
gradle.addRepo(repo);
@@ -424,6 +434,8 @@ public class BenchmarkTest {
String jvmArgs = p.getProperty("org.gradle.jvmargs", "");
jvmArgs += " -XX:+UseParallelGC";
+ jvmArgs += " --add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED";
+ jvmArgs += " --add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED";
// See https://www.yourkit.com/docs/java/help/startup_options.jsp for a comprehensive list
// of all agent options.
if (enableYourKit) {
@@ -455,6 +467,28 @@ public class BenchmarkTest {
}
}
+ /**
+ * Sets java.home to point to JDK11 if Gradle versions is less than 7.3
+ *
+ * Gradle supports JDK17 satrting from version 7.3 Also Gradle prior to 6.9 don't works well
+ * with symlinks, so path from bazel runfiles is resolved to real one.
+ */
+ private void useJdk11ForGradle(File gradleProperties) throws IOException {
+ Path javaPath = TestUtils.getJava11Jdk().resolve("release").toRealPath();
+ Path javaHome = javaPath.getParent();
+
+ Properties p = new Properties();
+ if (gradleProperties.exists()) {
+ try (FileInputStream fis = new FileInputStream(gradleProperties)) {
+ p.load(fis);
+ }
+ }
+ p.put("org.gradle.java.home", javaHome.toString());
+ try (FileWriter fw = new FileWriter(gradleProperties)) {
+ p.store(fw, "");
+ }
+ }
+
private static String hostName() {
if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_LINUX) {
return "Linux";
diff --git a/build-system/BUILD b/build-system/BUILD
index 013f491c13..846ced349b 100644
--- a/build-system/BUILD
+++ b/build-system/BUILD
@@ -99,6 +99,12 @@ filegroup(
)
filegroup(
+ name = "gradle-distrib-7.4",
+ srcs = ["//tools/external/gradle:gradle-distrib-7.4"],
+ visibility = ["//tools/adt/idea/old-agp-tests:__pkg__"],
+)
+
+filegroup(
name = "gradle-distrib-7.3.3",
srcs = ["//tools/external/gradle:gradle-distrib-7.3.3"],
visibility = ["//visibility:public"],
diff --git a/build-system/builder/src/main/java/com/android/builder/dexing/D8DexArchiveBuilder.java b/build-system/builder/src/main/java/com/android/builder/dexing/D8DexArchiveBuilder.java
index 51c0aadec0..1aa65b4fb6 100644
--- a/build-system/builder/src/main/java/com/android/builder/dexing/D8DexArchiveBuilder.java
+++ b/build-system/builder/src/main/java/com/android/builder/dexing/D8DexArchiveBuilder.java
@@ -26,17 +26,22 @@ import com.android.tools.r8.D8Command;
import com.android.tools.r8.Diagnostic;
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.StringConsumer.FileConsumer;
+import com.android.tools.r8.errors.UnsupportedFeatureDiagnostic;
import com.google.common.util.concurrent.MoreExecutors;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
final class D8DexArchiveBuilder extends DexArchiveBuilder {
private static final String INVOKE_CUSTOM =
- "Invoke-customs are only supported starting with Android O";
+ "Invoke-customs are only supported starting with Android O (--min-api 26)";
private static final String DEFAULT_INTERFACE_METHOD =
"Default interface methods are only supported starting with Android N (--min-api 24)";
@@ -56,10 +61,10 @@ final class D8DexArchiveBuilder extends DexArchiveBuilder {
@NonNull Path output,
@Nullable DependencyGraphUpdater<File> desugarGraphUpdater)
throws DexArchiveBuilderException {
- D8DiagnosticsHandler d8DiagnosticsHandler = new InterceptingDiagnosticsHandler();
+ InterceptingDiagnosticsHandler diagnosticsHandler = new InterceptingDiagnosticsHandler();
try {
- D8Command.Builder builder = D8Command.builder(d8DiagnosticsHandler);
+ D8Command.Builder builder = D8Command.builder(diagnosticsHandler);
AtomicInteger entryCount = new AtomicInteger();
input.forEach(
entry -> {
@@ -114,7 +119,7 @@ final class D8DexArchiveBuilder extends DexArchiveBuilder {
D8.run(builder.build(), MoreExecutors.newDirectExecutorService());
} catch (Throwable e) {
- throw getExceptionToRethrow(e, d8DiagnosticsHandler);
+ throw getExceptionToRethrow(e, diagnosticsHandler, dexParams.getWithDesugaring());
}
}
@@ -129,14 +134,52 @@ final class D8DexArchiveBuilder extends DexArchiveBuilder {
@NonNull
private static DexArchiveBuilderException getExceptionToRethrow(
- @NonNull Throwable t, D8DiagnosticsHandler d8DiagnosticsHandler) {
+ @NonNull Throwable t,
+ InterceptingDiagnosticsHandler diagnosticsHandler,
+ boolean isDesugaring) {
StringBuilder msg = new StringBuilder();
msg.append("Error while dexing.");
- for (String hint : d8DiagnosticsHandler.getPendingHints()) {
+ Set<String> unsupportedFeatures = diagnosticsHandler.getUnsupportedFeatures();
+ if (!unsupportedFeatures.isEmpty()) {
+ // Get the largest required level needed to support the features.
+ int minSdkVersion = diagnosticsHandler.getRequiredSdkVersion();
+ if (!isDesugaring) {
+ diagnosticsHandler.addHint(getEnableDesugaringHint(minSdkVersion));
+ } else if (minSdkVersion != -1) {
+ diagnosticsHandler.addHint(
+ "Increase the minSdkVersion to " + minSdkVersion + " or above.\n");
+ }
+ // Construct a new exception to replace the D8 thrown exception.
+ // This avoids the need to maintain pattern-match on D8 exceptions and
+ // instead base matching on the stable diagnostics API.
+ StringBuilder builder = new StringBuilder();
+ if (unsupportedFeatures.contains("invoke-custom")) {
+ builder.append("Error: ").append(INVOKE_CUSTOM);
+ } else if (unsupportedFeatures.contains("default-interface-method")) {
+ builder.append("Error: ").append(DEFAULT_INTERFACE_METHOD);
+ } else if (unsupportedFeatures.contains("static-interface-method")) {
+ builder.append("Error: ").append(STATIC_INTERFACE_METHOD);
+ } else {
+ // If not one of the three above legacy cases, construct an error message with a
+ // line
+ // for each unsupported feature. These are not currently pattern-matched on, so
+ // generalizing the reporting of these can be changed at a later point.
+ List<String> sorted = new ArrayList<>(unsupportedFeatures);
+ sorted.sort(String::compareTo);
+ for (String featureDescriptor : sorted) {
+ builder.append("Error: UnsupportedFeature(")
+ .append(featureDescriptor)
+ .append(")\n");
+ }
+ }
+ Throwable rt = new RuntimeException(builder.toString());
+ rt.addSuppressed(t);
+ t = rt;
+ }
+ for (String hint : diagnosticsHandler.getPendingHints()) {
msg.append(System.lineSeparator());
msg.append(hint);
}
-
return new DexArchiveBuilderException(msg.toString(), t);
}
@@ -156,25 +199,33 @@ final class D8DexArchiveBuilder extends DexArchiveBuilder {
}
private class InterceptingDiagnosticsHandler extends D8DiagnosticsHandler {
+
+ private Set<String> unsupportedFeatureDescriptors = new HashSet<>();
+ private int requiredSdkVersion = -1;
+
public InterceptingDiagnosticsHandler() {
super(D8DexArchiveBuilder.this.dexParams.getMessageReceiver());
}
- @Override
- protected Message convertToMessage(Message.Kind kind, Diagnostic diagnostic) {
-
- if (diagnostic.getDiagnosticMessage().startsWith(INVOKE_CUSTOM)) {
- addHint(getEnableDesugaringHint(26));
- }
+ public int getRequiredSdkVersion() {
+ return requiredSdkVersion;
+ }
- if (diagnostic.getDiagnosticMessage().startsWith(DEFAULT_INTERFACE_METHOD)) {
- addHint(getEnableDesugaringHint(24));
- }
+ public Set<String> getUnsupportedFeatures() {
+ return unsupportedFeatureDescriptors;
+ }
- if (diagnostic.getDiagnosticMessage().startsWith(STATIC_INTERFACE_METHOD)) {
- addHint(getEnableDesugaringHint(24));
+ @Override
+ protected Message convertToMessage(Message.Kind kind, Diagnostic diagnostic) {
+ if (diagnostic instanceof UnsupportedFeatureDiagnostic) {
+ UnsupportedFeatureDiagnostic feature = (UnsupportedFeatureDiagnostic) diagnostic;
+ String featureDescriptor = feature.getFeatureDescriptor();
+ int minSdkVersion = feature.getSupportedApiLevel();
+ unsupportedFeatureDescriptors.add(featureDescriptor);
+ if (requiredSdkVersion < minSdkVersion) {
+ requiredSdkVersion = minSdkVersion;
+ }
}
-
return super.convertToMessage(kind, diagnostic);
}
}
diff --git a/build-system/builder/src/main/java/com/android/builder/dexing/D8DiagnosticsHandler.java b/build-system/builder/src/main/java/com/android/builder/dexing/D8DiagnosticsHandler.java
index bc24ba79b7..c270ab712f 100644
--- a/build-system/builder/src/main/java/com/android/builder/dexing/D8DiagnosticsHandler.java
+++ b/build-system/builder/src/main/java/com/android/builder/dexing/D8DiagnosticsHandler.java
@@ -107,9 +107,13 @@ public class D8DiagnosticsHandler implements DiagnosticsHandler {
protected Message convertToMessage(Message.Kind kind, Diagnostic diagnostic) {
String textMessage = diagnostic.getDiagnosticMessage();
-
Origin origin = diagnostic.getOrigin();
Position positionInOrigin = diagnostic.getPosition();
+ return convertToMessage(kind, textMessage, origin, positionInOrigin);
+ }
+
+ protected Message convertToMessage(
+ Message.Kind kind, String textMessage, Origin origin, Position positionInOrigin) {
SourceFilePosition position;
if (origin instanceof PathOrigin) {
File originFile = ((PathOrigin) origin).getPath().toFile();
diff --git a/build-system/gradle-api/api/current.txt b/build-system/gradle-api/api/current.txt
index aa9eb6489f..495f5e36aa 100644
--- a/build-system/gradle-api/api/current.txt
+++ b/build-system/gradle-api/api/current.txt
@@ -2024,13 +2024,11 @@ package com.android.build.api.variant {
public interface AndroidTest extends com.android.build.api.variant.GeneratesTestApk com.android.build.api.variant.HasAndroidResources com.android.build.api.variant.TestComponent {
method public org.gradle.api.provider.Property<java.lang.String> getApplicationId();
method public org.gradle.api.provider.MapProperty<java.lang.String,? extends com.android.build.api.variant.BuildConfigField<? extends java.io.Serializable>> getBuildConfigFields();
- method public org.gradle.api.provider.MapProperty<java.lang.String,java.lang.String> getManifestPlaceholders();
method public org.gradle.api.provider.Provider<java.lang.String> getNamespace();
method public org.gradle.api.provider.ListProperty<org.gradle.api.file.RegularFile> getProguardFiles();
method public com.android.build.api.variant.SigningConfig? getSigningConfig();
property public abstract org.gradle.api.provider.Property<java.lang.String> applicationId;
property public abstract org.gradle.api.provider.MapProperty<java.lang.String,? extends com.android.build.api.variant.BuildConfigField<? extends java.io.Serializable>> buildConfigFields;
- property public abstract org.gradle.api.provider.MapProperty<java.lang.String,java.lang.String> manifestPlaceholders;
property public abstract org.gradle.api.provider.Provider<java.lang.String> namespace;
property public abstract org.gradle.api.provider.ListProperty<org.gradle.api.file.RegularFile> proguardFiles;
property public abstract com.android.build.api.variant.SigningConfig? signingConfig;
@@ -2493,6 +2491,7 @@ package com.android.build.api.variant {
method public com.android.build.api.variant.SourceDirectories.Layered? getMlModels();
method @Deprecated public com.android.build.api.variant.SourceDirectories.Flat? getRenderscript();
method public com.android.build.api.variant.SourceDirectories.Layered? getRes();
+ method public com.android.build.api.variant.SourceDirectories.Flat? getResources();
method public com.android.build.api.variant.SourceDirectories.Layered? getShaders();
property public abstract com.android.build.api.variant.SourceDirectories.Flat? aidl;
property public abstract com.android.build.api.variant.SourceDirectories.Layered? assets;
@@ -2502,6 +2501,7 @@ package com.android.build.api.variant {
property public abstract com.android.build.api.variant.SourceDirectories.Layered? mlModels;
property @Deprecated public abstract com.android.build.api.variant.SourceDirectories.Flat? renderscript;
property public abstract com.android.build.api.variant.SourceDirectories.Layered? res;
+ property public abstract com.android.build.api.variant.SourceDirectories.Flat? resources;
property public abstract com.android.build.api.variant.SourceDirectories.Layered? shaders;
}
@@ -2509,6 +2509,8 @@ package com.android.build.api.variant {
}
public interface TestComponent extends com.android.build.api.variant.Component {
+ method public org.gradle.api.provider.MapProperty<java.lang.String,java.lang.String> getManifestPlaceholders();
+ property public abstract org.gradle.api.provider.MapProperty<java.lang.String,java.lang.String> manifestPlaceholders;
}
@org.gradle.api.Incubating public interface TestFixtures extends com.android.build.api.variant.GeneratesAar com.android.build.api.variant.Component com.android.build.api.variant.HasAndroidResources {
diff --git a/build-system/gradle-api/src/main/java/com/android/build/api/variant/AndroidTest.kt b/build-system/gradle-api/src/main/java/com/android/build/api/variant/AndroidTest.kt
index 16d12c5d56..4eeda30030 100644
--- a/build-system/gradle-api/src/main/java/com/android/build/api/variant/AndroidTest.kt
+++ b/build-system/gradle-api/src/main/java/com/android/build/api/variant/AndroidTest.kt
@@ -45,16 +45,6 @@ interface AndroidTest : GeneratesTestApk, TestComponent, HasAndroidResources {
val buildConfigFields: MapProperty<String, out BuildConfigField<out Serializable>>
/**
- * [MapProperty] of the variant's manifest placeholders.
- *
- * Placeholders are organized with a key and a value. The value is a [String] that will be
- * used as is in the merged manifest.
- *
- * @return The [MapProperty] with keys as [String].
- */
- val manifestPlaceholders: MapProperty<String, String>
-
- /**
* Variant's signingConfig, initialized by the corresponding DSL element.
* @return Variant's config or null if the variant is not configured for signing.
*/
diff --git a/build-system/gradle-api/src/main/java/com/android/build/api/variant/Sources.kt b/build-system/gradle-api/src/main/java/com/android/build/api/variant/Sources.kt
index 5188957c5d..ea03c3adf4 100644
--- a/build-system/gradle-api/src/main/java/com/android/build/api/variant/Sources.kt
+++ b/build-system/gradle-api/src/main/java/com/android/build/api/variant/Sources.kt
@@ -42,6 +42,11 @@ interface Sources {
val res: SourceDirectories.Layered?
/**
+ * Access to the Java-style resources sources folders.
+ */
+ val resources: SourceDirectories.Flat?
+
+ /**
* Access to the Android assets sources folders.
*/
val assets: SourceDirectories.Layered?
diff --git a/build-system/gradle-api/src/main/java/com/android/build/api/variant/TestComponent.kt b/build-system/gradle-api/src/main/java/com/android/build/api/variant/TestComponent.kt
index 97dc50d78b..a959fb3c4e 100644
--- a/build-system/gradle-api/src/main/java/com/android/build/api/variant/TestComponent.kt
+++ b/build-system/gradle-api/src/main/java/com/android/build/api/variant/TestComponent.kt
@@ -16,4 +16,16 @@
package com.android.build.api.variant
-interface TestComponent: Component
+import org.gradle.api.provider.MapProperty
+
+interface TestComponent: Component {
+ /**
+ * [MapProperty] of the test component's manifest placeholders.
+ *
+ * Placeholders are organized with a key and a value. The value is a [String] that will be
+ * used as is in the merged manifest.
+ *
+ * @return the [MapProperty] with keys as [String]
+ */
+ val manifestPlaceholders: MapProperty<String, String>
+}
diff --git a/build-system/gradle-core/lint_baseline.xml b/build-system/gradle-core/lint_baseline.xml
index b616cbaac8..4d68aa1f6c 100755
--- a/build-system/gradle-core/lint_baseline.xml
+++ b/build-system/gradle-core/lint_baseline.xml
@@ -14,7 +14,7 @@
message="Implicitly using the default locale is a common source of bugs: Use `toLowerCase(Locale)` instead. For strings meant to be internal use `Locale.ROOT`, otherwise `Locale.getDefault()`.">
<location
file="src/main/java/com/android/build/gradle/tasks/FusedLibraryMergeArtifactTask.kt"
- line="152"/>
+ line="155"/>
</issue>
<issue
@@ -22,7 +22,7 @@
message="Implicitly using the default locale is a common source of bugs: Use `toLowerCase(Locale)` instead. For strings meant to be internal use `Locale.ROOT`, otherwise `Locale.getDefault()`.">
<location
file="src/main/java/com/android/build/gradle/tasks/FusedLibraryMergeArtifactTask.kt"
- line="158"/>
+ line="161"/>
</issue>
<issue
@@ -30,7 +30,7 @@
message="Implicitly using the default locale is a common source of bugs: Use `toLowerCase(Locale)` instead. For strings meant to be internal use `Locale.ROOT`, otherwise `Locale.getDefault()`.">
<location
file="src/main/java/com/android/build/gradle/tasks/FusedLibraryMergeArtifactTask.kt"
- line="195"/>
+ line="198"/>
</issue>
<issue
@@ -38,7 +38,7 @@
message="Implicitly using the default locale is a common source of bugs: Use `toLowerCase(Locale)` instead. For strings meant to be internal use `Locale.ROOT`, otherwise `Locale.getDefault()`.">
<location
file="src/main/java/com/android/build/gradle/tasks/FusedLibraryMergeArtifactTask.kt"
- line="201"/>
+ line="204"/>
</issue>
<issue
@@ -56,22 +56,6 @@
id="AvoidByLazy"
message="Avoid `by lazy` for simple lazy initialization">
<location
- file="src/main/java/com/android/build/gradle/internal/plugins/AbstractFusedLibraryPlugin.kt"
- line="56"/>
- </issue>
-
- <issue
- id="AvoidByLazy"
- message="Avoid `by lazy` for simple lazy initialization">
- <location
- file="src/main/java/com/android/build/gradle/internal/plugins/AbstractPrivacySandboxPlugin.kt"
- line="56"/>
- </issue>
-
- <issue
- id="AvoidByLazy"
- message="Avoid `by lazy` for simple lazy initialization">
- <location
file="src/main/java/com/android/build/gradle/internal/test/AbstractTestDataImpl.kt"
line="66"/>
</issue>
@@ -161,7 +145,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/api/component/analytics/AnalyticsEnabledTestVariant.kt"
- line="89"/>
+ line="82"/>
</issue>
<issue
@@ -177,7 +161,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/gradle/internal/plugins/AndroidPluginBaseServices.kt"
- line="56"/>
+ line="54"/>
</issue>
<issue
@@ -185,7 +169,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/gradle/internal/plugins/AndroidPluginBaseServices.kt"
- line="62"/>
+ line="60"/>
</issue>
<issue
@@ -193,7 +177,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/gradle/internal/plugins/AndroidPluginBaseServices.kt"
- line="75"/>
+ line="73"/>
</issue>
<issue
@@ -201,7 +185,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/gradle/internal/plugins/AndroidPluginBaseServices.kt"
- line="98"/>
+ line="96"/>
</issue>
<issue
@@ -224,8 +208,16 @@
id="AvoidByLazy"
message="Avoid `by lazy` for simple lazy initialization">
<location
- file="src/main/java/com/android/build/api/component/impl/AndroidTestImpl.kt"
- line="114"/>
+ file="src/main/java/com/android/build/gradle/internal/core/dsl/impl/AndroidTestComponentDslInfoImpl.kt"
+ line="70"/>
+ </issue>
+
+ <issue
+ id="AvoidByLazy"
+ message="Avoid `by lazy` for simple lazy initialization">
+ <location
+ file="src/main/java/com/android/build/gradle/internal/core/dsl/impl/AndroidTestComponentDslInfoImpl.kt"
+ line="133"/>
</issue>
<issue
@@ -233,7 +225,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/api/component/impl/AndroidTestImpl.kt"
- line="143"/>
+ line="116"/>
</issue>
<issue
@@ -241,7 +233,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/api/component/impl/AndroidTestImpl.kt"
- line="151"/>
+ line="145"/>
</issue>
<issue
@@ -249,7 +241,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/api/component/impl/AndroidTestImpl.kt"
- line="225"/>
+ line="153"/>
</issue>
<issue
@@ -257,7 +249,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/api/component/impl/AndroidTestImpl.kt"
- line="258"/>
+ line="227"/>
</issue>
<issue
@@ -288,6 +280,14 @@
id="AvoidByLazy"
message="Avoid `by lazy` for simple lazy initialization">
<location
+ file="src/main/java/com/android/build/gradle/internal/core/dsl/impl/ApplicationVariantDslInfoImpl.kt"
+ line="76"/>
+ </issue>
+
+ <issue
+ id="AvoidByLazy"
+ message="Avoid `by lazy` for simple lazy initialization">
+ <location
file="src/main/java/com/android/build/api/variant/impl/ApplicationVariantImpl.kt"
line="93"/>
</issue>
@@ -464,8 +464,8 @@
id="AvoidByLazy"
message="Avoid `by lazy` for simple lazy initialization">
<location
- file="src/main/java/com/android/build/api/component/impl/ComponentImpl.kt"
- line="169"/>
+ file="src/main/java/com/android/build/gradle/internal/core/dsl/impl/ComponentDslInfoImpl.kt"
+ line="79"/>
</issue>
<issue
@@ -473,7 +473,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/api/component/impl/ComponentImpl.kt"
- line="205"/>
+ line="167"/>
</issue>
<issue
@@ -481,7 +481,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/api/component/impl/ComponentImpl.kt"
- line="301"/>
+ line="291"/>
</issue>
<issue
@@ -489,7 +489,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/api/component/impl/ComponentImpl.kt"
- line="382"/>
+ line="371"/>
</issue>
<issue
@@ -497,7 +497,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/api/component/impl/ComponentImpl.kt"
- line="390"/>
+ line="379"/>
</issue>
<issue
@@ -505,7 +505,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/api/component/impl/ComponentImpl.kt"
- line="420"/>
+ line="409"/>
</issue>
<issue
@@ -513,7 +513,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/gradle/internal/cxx/gradle/generator/CxxConfigurationModel.kt"
- line="75"/>
+ line="76"/>
</issue>
<issue
@@ -608,22 +608,6 @@
id="AvoidByLazy"
message="Avoid `by lazy` for simple lazy initialization">
<location
- file="src/main/java/com/android/build/gradle/internal/plugins/FusedLibraryPlugin.kt"
- line="55"/>
- </issue>
-
- <issue
- id="AvoidByLazy"
- message="Avoid `by lazy` for simple lazy initialization">
- <location
- file="src/main/java/com/android/build/gradle/internal/plugins/FusedLibraryPlugin.kt"
- line="63"/>
- </issue>
-
- <issue
- id="AvoidByLazy"
- message="Avoid `by lazy` for simple lazy initialization">
- <location
file="src/main/java/com/android/build/gradle/internal/fusedlibrary/FusedLibraryVariantScopeImpl.kt"
line="37"/>
</issue>
@@ -689,7 +673,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/api/variant/impl/LibraryVariantImpl.kt"
- line="121"/>
+ line="120"/>
</issue>
<issue
@@ -704,16 +688,16 @@
id="AvoidByLazy"
message="Avoid `by lazy` for simple lazy initialization">
<location
- file="src/main/java/com/android/build/gradle/internal/databinding/MergingFileLookup.kt"
- line="36"/>
+ file="src/main/java/com/android/build/api/component/impl/features/ManifestPlaceholdersCreationConfigImpl.kt"
+ line="28"/>
</issue>
<issue
id="AvoidByLazy"
message="Avoid `by lazy` for simple lazy initialization">
<location
- file="src/main/java/com/android/build/gradle/internal/ide/v2/NativeModelBuilder.kt"
- line="64"/>
+ file="src/main/java/com/android/build/gradle/internal/databinding/MergingFileLookup.kt"
+ line="36"/>
</issue>
<issue
@@ -721,15 +705,15 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/gradle/internal/ide/v2/NativeModelBuilder.kt"
- line="68"/>
+ line="71"/>
</issue>
<issue
id="AvoidByLazy"
message="Avoid `by lazy` for simple lazy initialization">
<location
- file="src/main/java/com/android/build/gradle/internal/ndk/NdkPlatform.kt"
- line="59"/>
+ file="src/main/java/com/android/build/gradle/internal/ide/v2/NativeModelBuilder.kt"
+ line="75"/>
</issue>
<issue
@@ -737,14 +721,6 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/gradle/internal/ndk/NdkPlatform.kt"
- line="67"/>
- </issue>
-
- <issue
- id="AvoidByLazy"
- message="Avoid `by lazy` for simple lazy initialization">
- <location
- file="src/main/java/com/android/build/gradle/internal/plugins/PrivacySandboxSdkPlugin.kt"
line="59"/>
</issue>
@@ -752,8 +728,8 @@
id="AvoidByLazy"
message="Avoid `by lazy` for simple lazy initialization">
<location
- file="src/main/java/com/android/build/gradle/internal/plugins/PrivacySandboxSdkPlugin.kt"
- line="75"/>
+ file="src/main/java/com/android/build/gradle/internal/ndk/NdkPlatform.kt"
+ line="67"/>
</issue>
<issue
@@ -761,7 +737,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/gradle/internal/plugins/PrivacySandboxSdkPlugin.kt"
- line="94"/>
+ line="92"/>
</issue>
<issue
@@ -912,6 +888,22 @@
id="AvoidByLazy"
message="Avoid `by lazy` for simple lazy initialization">
<location
+ file="src/main/java/com/android/build/gradle/internal/core/dsl/impl/TestProjectVariantDslInfoImpl.kt"
+ line="128"/>
+ </issue>
+
+ <issue
+ id="AvoidByLazy"
+ message="Avoid `by lazy` for simple lazy initialization">
+ <location
+ file="src/main/java/com/android/build/gradle/internal/core/dsl/impl/TestProjectVariantDslInfoImpl.kt"
+ line="140"/>
+ </issue>
+
+ <issue
+ id="AvoidByLazy"
+ message="Avoid `by lazy` for simple lazy initialization">
+ <location
file="src/main/java/com/android/build/api/variant/impl/TestVariantImpl.kt"
line="97"/>
</issue>
@@ -952,23 +944,23 @@
id="AvoidByLazy"
message="Avoid `by lazy` for simple lazy initialization">
<location
- file="src/main/java/com/android/build/api/variant/impl/VariantBuilderImpl.kt"
- line="137"/>
+ file="src/main/java/com/android/build/gradle/internal/core/dsl/impl/UnitTestComponentDslInfoImpl.kt"
+ line="59"/>
</issue>
<issue
id="AvoidByLazy"
message="Avoid `by lazy` for simple lazy initialization">
<location
- file="src/main/java/com/android/build/gradle/internal/core/VariantDslInfoImpl.kt"
- line="142"/>
+ file="src/main/java/com/android/build/api/variant/impl/VariantBuilderImpl.kt"
+ line="137"/>
</issue>
<issue
id="AvoidByLazy"
message="Avoid `by lazy` for simple lazy initialization">
<location
- file="src/main/java/com/android/build/api/variant/impl/VariantImpl.kt"
+ file="src/main/java/com/android/build/gradle/internal/core/dsl/impl/VariantDslInfoImpl.kt"
line="135"/>
</issue>
@@ -977,7 +969,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/api/variant/impl/VariantImpl.kt"
- line="206"/>
+ line="137"/>
</issue>
<issue
@@ -985,7 +977,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/api/variant/impl/VariantImpl.kt"
- line="300"/>
+ line="215"/>
</issue>
<issue
@@ -993,7 +985,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/gradle/internal/variant/VariantPathHelper.kt"
- line="54"/>
+ line="129"/>
</issue>
<issue
@@ -1001,7 +993,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/gradle/internal/variant/VariantPathHelper.kt"
- line="119"/>
+ line="194"/>
</issue>
<issue
@@ -1009,7 +1001,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/gradle/internal/variant/VariantPathHelper.kt"
- line="160"/>
+ line="235"/>
</issue>
<issue
@@ -1017,7 +1009,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/gradle/internal/variant/VariantPathHelper.kt"
- line="163"/>
+ line="238"/>
</issue>
<issue
@@ -1025,7 +1017,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/gradle/internal/variant/VariantPathHelper.kt"
- line="171"/>
+ line="246"/>
</issue>
<issue
@@ -1033,7 +1025,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/gradle/internal/variant/VariantPathHelper.kt"
- line="200"/>
+ line="275"/>
</issue>
<issue
@@ -1041,7 +1033,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/gradle/internal/variant/VariantPathHelper.kt"
- line="210"/>
+ line="285"/>
</issue>
<issue
@@ -1049,7 +1041,7 @@
message="Avoid `by lazy` for simple lazy initialization">
<location
file="src/main/java/com/android/build/gradle/internal/variant/VariantPathHelper.kt"
- line="215"/>
+ line="290"/>
</issue>
<issue
@@ -1073,7 +1065,7 @@
message="Do not use `java.nio.file.Files.copy(Path, Path)`. Instead, use `FileUtils.copyFile(Path, Path)` or Kotlin&apos;s `File#copyTo(File)`">
<location
file="src/main/java/com/android/build/gradle/internal/tasks/AsarToApksTransform.kt"
- line="72"/>
+ line="73"/>
</issue>
<issue
@@ -1081,7 +1073,7 @@
message="This reference is unused: name">
<location
file="src/main/java/com/android/build/gradle/internal/tasks/DependencyReportTask.kt"
- line="49"/>
+ line="51"/>
</issue>
<issue
@@ -1089,7 +1081,7 @@
message="This reference is unused: name">
<location
file="src/main/java/com/android/build/gradle/internal/tasks/DependencyReportTask.kt"
- line="56"/>
+ line="58"/>
</issue>
<issue
@@ -1105,7 +1097,7 @@
message="This reference is unused: FD_OUTPUT">
<location
file="src/main/java/com/android/build/gradle/tasks/FusedLibraryManifestMergerTask.kt"
- line="173"/>
+ line="176"/>
</issue>
<issue
@@ -1129,47 +1121,7 @@
message="This reference is unused: FD_OUTPUT">
<location
file="src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkManifestMergerTask.kt"
- line="80"/>
- </issue>
-
- <issue
- id="NoOp"
- message="This reference is unused: testApplicationId">
- <location
- file="src/main/java/com/android/build/gradle/internal/core/VariantDslInfoImpl.kt"
- line="216"/>
- </issue>
-
- <issue
- id="NoOp"
- message="This reference is unused: testApplicationId">
- <location
- file="src/main/java/com/android/build/gradle/internal/core/VariantDslInfoImpl.kt"
- line="312"/>
- </issue>
-
- <issue
- id="NoOp"
- message="This reference is unused: testInstrumentationRunner">
- <location
- file="src/main/java/com/android/build/gradle/internal/core/VariantDslInfoImpl.kt"
- line="484"/>
- </issue>
-
- <issue
- id="NoOp"
- message="This reference is unused: testHandleProfiling">
- <location
- file="src/main/java/com/android/build/gradle/internal/core/VariantDslInfoImpl.kt"
- line="527"/>
- </issue>
-
- <issue
- id="NoOp"
- message="This reference is unused: testFunctionalTest">
- <location
- file="src/main/java/com/android/build/gradle/internal/core/VariantDslInfoImpl.kt"
- line="548"/>
+ line="83"/>
</issue>
<issue
@@ -1177,7 +1129,7 @@
message="Avoid using `org.gradle.api.Project.exec` as it is incompatible with Gradle instant execution.">
<location
file="src/main/java/com/android/build/gradle/internal/ide/v2/NativeModelBuilder.kt"
- line="56"/>
+ line="63"/>
</issue>
<issue
@@ -1201,7 +1153,7 @@
message="This method should only be accessed from tests or within private scope">
<location
file="src/main/java/com/android/build/gradle/internal/tasks/featuresplit/FeatureSetMetadataWriterTask.kt"
- line="127"/>
+ line="130"/>
</issue>
<issue
@@ -1217,7 +1169,7 @@
message="This method should only be accessed from tests or within private scope">
<location
file="src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkMergeDexTask.kt"
- line="58"/>
+ line="61"/>
</issue>
<issue
@@ -1225,7 +1177,7 @@
message="This method should only be accessed from tests or within private scope">
<location
file="src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkMergeDexTask.kt"
- line="60"/>
+ line="63"/>
</issue>
<issue
@@ -1249,7 +1201,7 @@
message="Use `Integer.valueOf(index)` instead">
<location
file="src/main/java/com/android/build/gradle/internal/tasks/BundleReportDependenciesTask.kt"
- line="79"/>
+ line="81"/>
</issue>
<issue
@@ -1257,7 +1209,7 @@
message="Use `Integer.valueOf(libraryList.size)` instead">
<location
file="src/main/java/com/android/build/gradle/internal/tasks/BundleReportDependenciesTask.kt"
- line="102"/>
+ line="104"/>
</issue>
<issue
@@ -1265,7 +1217,7 @@
message="Use `Integer.valueOf(origIndex)` instead">
<location
file="src/main/java/com/android/build/gradle/internal/tasks/BundleReportDependenciesTask.kt"
- line="112"/>
+ line="114"/>
</issue>
<issue
@@ -1273,7 +1225,7 @@
message="Use `Integer.valueOf(libraryDep.libraryIndex)` instead">
<location
file="src/main/java/com/android/build/gradle/internal/tasks/BundleReportDependenciesTask.kt"
- line="117"/>
+ line="119"/>
</issue>
<issue
@@ -1281,7 +1233,7 @@
message="Use `Integer.valueOf(depIndex)` instead">
<location
file="src/main/java/com/android/build/gradle/internal/tasks/BundleReportDependenciesTask.kt"
- line="120"/>
+ line="122"/>
</issue>
<issue
@@ -1289,7 +1241,7 @@
message="Use `Integer.valueOf(depIndex)` instead">
<location
file="src/main/java/com/android/build/gradle/internal/tasks/BundleReportDependenciesTask.kt"
- line="133"/>
+ line="135"/>
</issue>
<issue
@@ -1409,7 +1361,7 @@
message="Avoid using common ForkJoinPool, directly or indirectly (for example via CompletableFuture). It has a limited set of threads on some machines which leads to hangs. See `go/do-not-freeze`.">
<location
file="src/main/java/com/android/build/gradle/internal/tasks/AsarToApksTransform.kt"
- line="77"/>
+ line="78"/>
</issue>
<issue
@@ -1417,7 +1369,7 @@
message="Avoid using common ForkJoinPool, directly or indirectly (for example via CompletableFuture). It has a limited set of threads on some machines which leads to hangs. See `go/do-not-freeze`.">
<location
file="src/main/java/com/android/build/gradle/internal/tasks/BundleToApkTask.kt"
- line="111"/>
+ line="113"/>
</issue>
<issue
@@ -1425,7 +1377,7 @@
message="Avoid using common ForkJoinPool, directly or indirectly (for example via CompletableFuture). It has a limited set of threads on some machines which leads to hangs. See `go/do-not-freeze`.">
<location
file="src/main/java/com/android/build/gradle/internal/tasks/BundleToStandaloneApkTask.kt"
- line="124"/>
+ line="126"/>
</issue>
<issue
@@ -1449,7 +1401,7 @@
message="Avoid using new ForkJoinPool instances when possible. Prefer using the IntelliJ application pool via `com.intellij.openapi.application.Application#executeOnPooledThread`, or for the Android Gradle Plugin use `com.android.build.gradle.internal.tasks.Workers`. See `go/do-not-freeze`.">
<location
file="src/main/java/com/android/build/gradle/internal/tasks/DexMergingTask.kt"
- line="797"/>
+ line="799"/>
</issue>
</issues>
diff --git a/build-system/gradle-core/src/apiTest/kotlin/com/android/build/api/apiTest/kotlin/AddCustomSourceTest.kt b/build-system/gradle-core/src/apiTest/kotlin/com/android/build/api/apiTest/kotlin/AddCustomSourceTest.kt
index 3c13b7f932..d7ad65620f 100644
--- a/build-system/gradle-core/src/apiTest/kotlin/com/android/build/api/apiTest/kotlin/AddCustomSourceTest.kt
+++ b/build-system/gradle-core/src/apiTest/kotlin/com/android/build/api/apiTest/kotlin/AddCustomSourceTest.kt
@@ -318,7 +318,7 @@ where source files will be generated and added to the compilation task.
Truth.assertThat(output).contains("addCustomSourceTypeInDslAndVariantTest/app/src/main/toml")
Truth.assertThat(output).contains("addCustomSourceTypeInDslAndVariantTest/app/src/debug/toml")
Truth.assertThat(output).contains("addCustomSourceTypeInDslAndVariantTest/app/third_party/debug/toml")
- Truth.assertThat(output).contains("addCustomSourceTypeInDslAndVariantTest/app/build/toml/debugAddCustomSources")
+ Truth.assertThat(output).contains("addCustomSourceTypeInDslAndVariantTest/app/build/generated/toml/debugAddCustomSources")
Truth.assertThat(output).contains("BUILD SUCCESSFUL")
super.onVariantStats {
super.onVariantStats {
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/analytics/AnalyticsEnabledSources.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/analytics/AnalyticsEnabledSources.kt
index a18aa3a901..1928eed5a1 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/component/analytics/AnalyticsEnabledSources.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/analytics/AnalyticsEnabledSources.kt
@@ -130,6 +130,17 @@ open class AnalyticsEnabledSources @Inject constructor(
objectFactory)
}
+ override val resources: SourceDirectories.Flat
+ get() {
+ stats.variantApiAccessBuilder.addVariantPropertiesAccessBuilder().type =
+ VariantPropertiesMethodType.SOURCES_RESOURCES_ACCESS_VALUE
+ return objectFactory.newInstance(
+ AnalyticsEnabledFlat::class.java,
+ delegate.resources,
+ stats,
+ objectFactory)
+ }
+
override fun getByName(name: String): SourceDirectories.Flat {
stats.variantApiAccessBuilder.addVariantPropertiesAccessBuilder().type =
VariantPropertiesMethodType.SOURCES_EXTRAS_ACCESS_VALUE
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/analytics/AnalyticsEnabledUnitTest.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/analytics/AnalyticsEnabledUnitTest.kt
index e90b5434e8..1ca890dc00 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/component/analytics/AnalyticsEnabledUnitTest.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/analytics/AnalyticsEnabledUnitTest.kt
@@ -17,12 +17,21 @@
package com.android.build.api.component.analytics
import com.android.build.api.variant.UnitTest
+import com.android.tools.build.gradle.internal.profile.VariantPropertiesMethodType
import com.google.wireless.android.sdk.stats.GradleBuildVariant
import org.gradle.api.model.ObjectFactory
+import org.gradle.api.provider.MapProperty
import javax.inject.Inject
open class AnalyticsEnabledUnitTest @Inject constructor(
override val delegate: UnitTest,
stats: GradleBuildVariant.Builder,
objectFactory: ObjectFactory
-) : AnalyticsEnabledTestComponent(delegate, stats, objectFactory), UnitTest
+) : AnalyticsEnabledTestComponent(delegate, stats, objectFactory), UnitTest {
+ override val manifestPlaceholders: MapProperty<String, String>
+ get() {
+ stats.variantApiAccessBuilder.addVariantPropertiesAccessBuilder().type =
+ VariantPropertiesMethodType.MANIFEST_PLACEHOLDERS_VALUE
+ return delegate.manifestPlaceholders
+ }
+}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/AndroidTestImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/AndroidTestImpl.kt
index 8497bf44c5..ef37969e38 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/AndroidTestImpl.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/AndroidTestImpl.kt
@@ -21,6 +21,7 @@ import com.android.build.api.artifact.impl.ArtifactsImpl
import com.android.build.api.component.analytics.AnalyticsEnabledAndroidTest
import com.android.build.api.component.impl.features.AndroidResourcesCreationConfigImpl
import com.android.build.api.component.impl.features.BuildConfigCreationConfigImpl
+import com.android.build.api.component.impl.features.ManifestPlaceholdersCreationConfigImpl
import com.android.build.api.component.impl.features.RenderscriptCreationConfigImpl
import com.android.build.api.dsl.CommonExtension
import com.android.build.api.extension.impl.VariantApiOperationsRegistrar
@@ -46,6 +47,7 @@ import com.android.build.gradle.internal.component.VariantCreationConfig
import com.android.build.gradle.internal.component.features.AndroidResourcesCreationConfig
import com.android.build.gradle.internal.component.features.BuildConfigCreationConfig
import com.android.build.gradle.internal.component.features.FeatureNames
+import com.android.build.gradle.internal.component.features.ManifestPlaceholdersCreationConfig
import com.android.build.gradle.internal.component.features.RenderscriptCreationConfig
import com.android.build.gradle.internal.core.VariantSources
import com.android.build.gradle.internal.core.dsl.AndroidTestComponentDslInfo
@@ -124,9 +126,6 @@ open class AndroidTestImpl @Inject constructor(
override val debuggable: Boolean
get() = dslInfo.isDebuggable
- override val profileable: Boolean
- get() = dslInfo.isProfileable
-
override val namespaceForR: Provider<String> = dslInfo.namespaceForR
override val minSdkVersion: AndroidVersion
@@ -150,7 +149,7 @@ open class AndroidTestImpl @Inject constructor(
override val packaging: ApkPackaging by lazy {
ApkPackagingImpl(
- dslInfo.testedVariant!!.packaging,
+ dslInfo.testedVariantDslInfo.packaging,
variantServices,
minSdkVersion.apiLevel
)
@@ -160,9 +159,9 @@ open class AndroidTestImpl @Inject constructor(
get() {
return when {
mainVariant.componentType.isAar -> false
- !dslInfo.getPostProcessingOptions().hasPostProcessingConfiguration() ->
+ !dslInfo.postProcessingOptions.hasPostProcessingConfiguration() ->
mainVariant.minifiedEnabled
- else -> dslInfo.getPostProcessingOptions().codeShrinkerEnabled()
+ else -> dslInfo.postProcessingOptions.codeShrinkerEnabled()
}
}
@@ -170,9 +169,9 @@ open class AndroidTestImpl @Inject constructor(
get() {
return when {
mainVariant.componentType.isAar -> false
- !dslInfo.getPostProcessingOptions().hasPostProcessingConfiguration() ->
+ !dslInfo.postProcessingOptions.hasPostProcessingConfiguration() ->
mainVariant.resourcesShrink
- else -> dslInfo.getPostProcessingOptions().resourcesShrinkingEnabled()
+ else -> dslInfo.postProcessingOptions.resourcesShrinkingEnabled()
}
}
@@ -249,13 +248,16 @@ open class AndroidTestImpl @Inject constructor(
)
}
+ override val manifestPlaceholders: MapProperty<String, String>
+ get() = manifestPlaceholdersCreationConfig.placeholders
+
// ---------------------------------------------------------------------------------------------
// INTERNAL API
// ---------------------------------------------------------------------------------------------
// Even if android resources is disabled in a library project, we still need to merge and link
// external resources to create the test apk.
- override val androidResourcesCreationConfig: AndroidResourcesCreationConfig by lazy {
+ override val androidResourcesCreationConfig: AndroidResourcesCreationConfig by lazy(LazyThreadSafetyMode.NONE) {
AndroidResourcesCreationConfigImpl(
this,
dslInfo,
@@ -263,7 +265,7 @@ open class AndroidTestImpl @Inject constructor(
)
}
- override val buildConfigCreationConfig: BuildConfigCreationConfig? by lazy {
+ override val buildConfigCreationConfig: BuildConfigCreationConfig? by lazy(LazyThreadSafetyMode.NONE) {
if (buildFeatures.buildConfig) {
BuildConfigCreationConfigImpl(
this,
@@ -275,7 +277,7 @@ open class AndroidTestImpl @Inject constructor(
}
}
- override val renderscriptCreationConfig: RenderscriptCreationConfig? by lazy {
+ override val renderscriptCreationConfig: RenderscriptCreationConfig? by lazy(LazyThreadSafetyMode.NONE) {
if (buildFeatures.renderScript) {
RenderscriptCreationConfigImpl(
dslInfo,
@@ -287,6 +289,13 @@ open class AndroidTestImpl @Inject constructor(
}
}
+ override val manifestPlaceholdersCreationConfig: ManifestPlaceholdersCreationConfig by lazy(LazyThreadSafetyMode.NONE) {
+ ManifestPlaceholdersCreationConfigImpl(
+ dslInfo,
+ internalServices
+ )
+ }
+
override val targetSdkVersionOverride: AndroidVersion?
get() = mainVariant.targetSdkVersionOverride
@@ -368,9 +377,6 @@ open class AndroidTestImpl @Inject constructor(
override fun getJava8LangSupportType(): Java8LangSupport = delegate.getJava8LangSupportType()
- override val dslSigningConfig: com.android.build.gradle.internal.dsl.SigningConfig? =
- dslInfo.signingConfig
-
override val defaultGlslcArgs: List<String>
get() = dslInfo.defaultGlslcArgs
override val scopedGlslcArgs: Map<String, List<String>>
@@ -390,7 +396,7 @@ open class AndroidTestImpl @Inject constructor(
get() = isTestCoverageEnabled && mainVariant.componentType.isAar
override val postProcessingFeatures: PostprocessingFeatures?
- get() = dslInfo.getPostProcessingOptions().getPostprocessingFeatures()
+ get() = dslInfo.postProcessingOptions.getPostprocessingFeatures()
// ---------------------------------------------------------------------------------------------
// DO NOT USE, Deprecated DSL APIs.
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ApkCreationConfigImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ApkCreationConfigImpl.kt
index 8efde530c2..8da9ba6214 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ApkCreationConfigImpl.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ApkCreationConfigImpl.kt
@@ -32,9 +32,6 @@ open class ApkCreationConfigImpl<T: ApkCreationConfig>(
val isDebuggable: Boolean
get() = dslInfo.isDebuggable
- val isProfileable: Boolean
- get() = dslInfo.isProfileable
-
override val needsShrinkDesugarLibrary: Boolean
get() {
if (!isCoreLibraryDesugaringEnabled(config)) {
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ComponentImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ComponentImpl.kt
index 66327cc676..8228bd6d98 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ComponentImpl.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ComponentImpl.kt
@@ -45,10 +45,9 @@ import com.android.build.gradle.internal.component.features.InstrumentationCreat
import com.android.build.gradle.internal.component.features.ResValuesCreationConfig
import com.android.build.gradle.internal.component.legacy.OldVariantApiLegacySupport
import com.android.build.gradle.internal.core.ProductFlavor
-import com.android.build.gradle.internal.core.VariantDslInfoImpl
import com.android.build.gradle.internal.core.VariantSources
import com.android.build.gradle.internal.core.dsl.ComponentDslInfo
-import com.android.build.gradle.internal.core.dsl.PublishableVariantDslInfo
+import com.android.build.gradle.internal.core.dsl.PublishableComponentDslInfo
import com.android.build.gradle.internal.dependency.AndroidAttributes
import com.android.build.gradle.internal.dependency.VariantDependencies
import com.android.build.gradle.internal.dependency.getProvidedClasspath
@@ -84,7 +83,6 @@ import org.gradle.api.attributes.DocsType
import org.gradle.api.attributes.LibraryElements
import org.gradle.api.file.FileCollection
import org.gradle.api.file.FileSystemLocation
-import org.gradle.api.provider.MapProperty
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import java.io.File
@@ -202,14 +200,6 @@ abstract class ComponentImpl<DslInfoT: ComponentDslInfo>(
ProductFlavor(it)
}
- override val manifestPlaceholders: MapProperty<String, String> by lazy {
- internalServices.mapPropertyOf(
- String::class.java,
- String::class.java,
- dslInfo.manifestPlaceholders
- )
- }
-
// ---------------------------------------------------------------------------------------------
// Private stuff
// ---------------------------------------------------------------------------------------------
@@ -332,7 +322,7 @@ abstract class ComponentImpl<DslInfoT: ComponentDslInfo>(
outputSpec.publishedConfigTypes.any { it.isPublicationConfig }
if (isPublicationConfigs) {
- val components = (dslInfo as PublishableVariantDslInfo).publishInfo!!.components
+ val components = (dslInfo as PublishableComponentDslInfo).publishInfo!!.components
for(component in components) {
publishIntermediateArtifact(
artifactProvider,
@@ -376,13 +366,12 @@ abstract class ComponentImpl<DslInfoT: ComponentDslInfo>(
override val isAndroidTestCoverageEnabled: Boolean
get() = dslInfo.isAndroidTestCoverageEnabled
- override val modelV1LegacySupport =
- ModelV1LegacySupportImpl(dslInfo as VariantDslInfoImpl)
+ override val modelV1LegacySupport = ModelV1LegacySupportImpl(dslInfo)
override val oldVariantApiLegacySupport: OldVariantApiLegacySupport? by lazy {
OldVariantApiLegacySupportImpl(
this,
- dslInfo as VariantDslInfoImpl,
+ dslInfo,
variantData!!
)
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ConsumableCreationConfigImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ConsumableCreationConfigImpl.kt
index 1e093e97b4..58e57e2312 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ConsumableCreationConfigImpl.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ConsumableCreationConfigImpl.kt
@@ -18,8 +18,8 @@ package com.android.build.api.component.impl
import com.android.build.api.variant.AndroidVersion
import com.android.build.api.variant.impl.getFeatureLevel
import com.android.build.gradle.internal.component.ConsumableCreationConfig
+import com.android.build.gradle.internal.component.DynamicFeatureCreationConfig
import com.android.build.gradle.internal.core.dsl.ConsumableComponentDslInfo
-import com.android.build.gradle.internal.core.dsl.DynamicFeatureVariantDslInfo
import com.android.build.gradle.internal.scope.Java8LangSupport
import com.android.builder.dexing.DexingType
import com.android.builder.errors.IssueReporter
@@ -49,17 +49,20 @@ open class ConsumableCreationConfigImpl<T: ConsumableCreationConfig>(
) {
val dexingType: DexingType
- get() = (dslInfo as? DynamicFeatureVariantDslInfo)?.dexingType ?:
- if (config.isMultiDexEnabled) {
- if (config.minSdkVersion.getFeatureLevel() >= 21 ||
- dslInfo.targetDeployApiFromIDE?.let { it >= 21 } == true
- ) {
- // if minSdkVersion is 21+ or we are deploying to 21+ device, use native multidex
+ get() =
+ if (config is DynamicFeatureCreationConfig) {
+ // dynamic features can always be build in native multidex mode
DexingType.NATIVE_MULTIDEX
- } else DexingType.LEGACY_MULTIDEX
- } else {
- DexingType.MONO_DEX
- }
+ } else if (config.isMultiDexEnabled) {
+ if (config.minSdkVersion.getFeatureLevel() >= 21 ||
+ dslInfo.targetDeployApiFromIDE?.let { it >= 21 } == true
+ ) {
+ // if minSdkVersion is 21+ or we are deploying to 21+ device, use native multidex
+ DexingType.NATIVE_MULTIDEX
+ } else DexingType.LEGACY_MULTIDEX
+ } else {
+ DexingType.MONO_DEX
+ }
fun getNeedsMergedJavaResStream(): Boolean {
// We need to create a stream from the merged java resources if we're in a library module,
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/DefaultSourcesProvider.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/DefaultSourcesProvider.kt
index 3c1461ebd7..cb23259a2c 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/DefaultSourcesProvider.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/DefaultSourcesProvider.kt
@@ -47,6 +47,11 @@ interface DefaultSourcesProvider {
fun getRes(lateAdditionsDelegate: LayeredSourceDirectoriesImpl): List<DirectoryEntries>
/**
+ * the list of sources [DirectoryEntry] for java resources.
+ */
+ fun getResources(lateAdditionsDelegate: FlatSourceDirectoriesImpl): List<DirectoryEntry>
+
+ /**
* the list of [DirectoryEntries] for assets.
*
* The [List] is ordered in ascending order of importance, meaning the first set is meant to be
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/DefaultSourcesProviderImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/DefaultSourcesProviderImpl.kt
index 8f9963fc52..fb7234cca1 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/DefaultSourcesProviderImpl.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/DefaultSourcesProviderImpl.kt
@@ -63,6 +63,7 @@ class DefaultSourcesProviderImpl(
}
override fun getRes(lateAdditionsDelegate: LayeredSourceDirectoriesImpl): List<DirectoryEntries> = component.defaultResSources(lateAdditionsDelegate)
+ override fun getResources(lateAdditionsDelegate: FlatSourceDirectoriesImpl): List<DirectoryEntry> = flattenSourceProviders(lateAdditionsDelegate) { sourceSet -> sourceSet.resources }
override fun getAssets(lateAdditionsDelegate: LayeredSourceDirectoriesImpl): List<DirectoryEntries> = defaultAssetsSources(lateAdditionsDelegate)
override fun getJniLibs(lateAdditionsDelegate: LayeredSourceDirectoriesImpl): List<DirectoryEntries> =
getSourceList(lateAdditionsDelegate, DefaultAndroidSourceSet::jniLibs)
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ModelV1LegacySupportImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ModelV1LegacySupportImpl.kt
index aff7ab573e..822fe0c78c 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ModelV1LegacySupportImpl.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/ModelV1LegacySupportImpl.kt
@@ -18,16 +18,17 @@ package com.android.build.api.component.impl
import com.android.build.gradle.internal.component.legacy.ModelV1LegacySupport
import com.android.build.gradle.internal.core.MergedFlavor
-import com.android.build.gradle.internal.core.VariantDslInfoImpl
+import com.android.build.gradle.internal.core.dsl.ComponentDslInfo
+import com.android.build.gradle.internal.core.dsl.impl.ComponentDslInfoImpl
import org.gradle.api.provider.Provider
class ModelV1LegacySupportImpl(
- private val variantDslInfo: VariantDslInfoImpl
+ private val dslInfo: ComponentDslInfo
): ModelV1LegacySupport {
override val mergedFlavor: MergedFlavor
- get() = variantDslInfo.mergedFlavor
+ get() = (dslInfo as ComponentDslInfoImpl).mergedFlavor
override val dslApplicationId: Provider<String>
- get() = variantDslInfo.applicationId
+ get() = dslInfo.applicationId
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/OldVariantApiLegacySupportImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/OldVariantApiLegacySupportImpl.kt
index ef579427bf..040203ec95 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/OldVariantApiLegacySupportImpl.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/OldVariantApiLegacySupportImpl.kt
@@ -27,7 +27,9 @@ import com.android.build.gradle.internal.component.ComponentCreationConfig
import com.android.build.gradle.internal.component.TestComponentCreationConfig
import com.android.build.gradle.internal.component.legacy.OldVariantApiLegacySupport
import com.android.build.gradle.internal.core.MergedFlavor
-import com.android.build.gradle.internal.core.VariantDslInfoImpl
+import com.android.build.gradle.internal.core.dsl.ApkProducingComponentDslInfo
+import com.android.build.gradle.internal.core.dsl.ComponentDslInfo
+import com.android.build.gradle.internal.core.dsl.impl.ComponentDslInfoImpl
import com.android.build.gradle.internal.dependency.ArtifactCollectionWithExtraArtifact
import com.android.build.gradle.internal.publishing.AndroidArtifacts
import com.android.build.gradle.internal.publishing.PublishingSpecs.Companion.getVariantPublishingSpec
@@ -43,18 +45,20 @@ import java.io.Serializable
class OldVariantApiLegacySupportImpl(
private val component: ComponentCreationConfig,
- private val variantDslInfo: VariantDslInfoImpl,
+ private val dslInfo: ComponentDslInfo,
override val variantData: BaseVariantData
): OldVariantApiLegacySupport {
override val buildTypeObj: BuildType
- get() = variantDslInfo.buildTypeObj
+ get() = (dslInfo as ComponentDslInfoImpl).buildTypeObj
override val productFlavorList: List<ProductFlavor>
- get() = variantDslInfo.productFlavorList
+ get() = dslInfo.productFlavorList
override val mergedFlavor: MergedFlavor
- get() = variantDslInfo.mergedFlavor
+ get() = (dslInfo as ComponentDslInfoImpl).mergedFlavor
override val javaCompileOptions: JavaCompileOptions
- get() = variantDslInfo.javaCompileOptions
+ get() = dslInfo.javaCompileOptions
+ override val dslSigningConfig: com.android.build.gradle.internal.dsl.SigningConfig? =
+ (dslInfo as? ApkProducingComponentDslInfo)?.signingConfig
override fun getJavaClasspathArtifacts(
configType: AndroidArtifacts.ConsumedConfigType,
@@ -155,7 +159,7 @@ class OldVariantApiLegacySupportImpl(
}
override fun addDataBindingArgsToOldVariantApi(args: DataBindingCompilerArguments) {
- variantDslInfo.javaCompileOptions.annotationProcessorOptions
+ dslInfo.javaCompileOptions.annotationProcessorOptions
.compilerArgumentProviders.add(args)
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/TestFixturesImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/TestFixturesImpl.kt
index ba2f384da3..acecbaf670 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/TestFixturesImpl.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/TestFixturesImpl.kt
@@ -35,6 +35,7 @@ import com.android.build.gradle.internal.component.TestFixturesCreationConfig
import com.android.build.gradle.internal.component.VariantCreationConfig
import com.android.build.gradle.internal.component.features.BuildConfigCreationConfig
import com.android.build.gradle.internal.component.features.FeatureNames
+import com.android.build.gradle.internal.component.features.ManifestPlaceholdersCreationConfig
import com.android.build.gradle.internal.component.legacy.OldVariantApiLegacySupport
import com.android.build.gradle.internal.core.VariantSources
import com.android.build.gradle.internal.core.dsl.TestFixturesComponentDslInfo
@@ -89,7 +90,7 @@ open class TestFixturesImpl @Inject constructor(
), TestFixtures, TestFixturesCreationConfig {
override val description: String
- get() = if (dslInfo.hasFlavors()) {
+ get() = if (productFlavorList.isNotEmpty()) {
val sb = StringBuilder(50)
dslInfo.componentIdentity.buildType?.let { sb.appendCapitalized(it) }
sb.append(" build for flavor ")
@@ -110,8 +111,6 @@ open class TestFixturesImpl @Inject constructor(
internalServices.providerOf(String::class.java, variantDslInfo.namespace)
override val debuggable: Boolean
get() = mainVariant.debuggable
- override val profileable: Boolean
- get() = mainVariant.profileable
override val minSdkVersion: AndroidVersion
get() = mainVariant.minSdkVersion
override val targetSdkVersion: AndroidVersion
@@ -121,14 +120,9 @@ open class TestFixturesImpl @Inject constructor(
override val aarMetadata: AarMetadata =
internalServices.newInstance(AarMetadata::class.java).also {
- it.minCompileSdk.set(variantDslInfo.aarMetadata.minCompileSdk ?: 1)
- it.minCompileSdkExtension.set(
- variantDslInfo.aarMetadata.minCompileSdkExtension
- ?: DEFAULT_MIN_COMPILE_SDK_EXTENSION
- )
- it.minAgpVersion.set(
- variantDslInfo.aarMetadata.minAgpVersion ?: DEFAULT_MIN_AGP_VERSION
- )
+ it.minCompileSdk.set(1)
+ it.minCompileSdkExtension.set(DEFAULT_MIN_COMPILE_SDK_EXTENSION)
+ it.minAgpVersion.set(DEFAULT_MIN_AGP_VERSION)
}
override val javaCompilation: JavaCompilation =
@@ -144,6 +138,9 @@ open class TestFixturesImpl @Inject constructor(
override val buildConfigCreationConfig: BuildConfigCreationConfig? = null
+ override val manifestPlaceholdersCreationConfig: ManifestPlaceholdersCreationConfig?
+ get() = mainVariant.manifestPlaceholdersCreationConfig
+
override val targetSdkVersionOverride: AndroidVersion?
get() = mainVariant.targetSdkVersionOverride
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/UnitTestImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/UnitTestImpl.kt
index 877a9dbdb8..bada50a19c 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/UnitTestImpl.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/UnitTestImpl.kt
@@ -20,6 +20,7 @@ import com.android.build.api.artifact.impl.ArtifactsImpl
import com.android.build.api.component.UnitTest
import com.android.build.api.component.analytics.AnalyticsEnabledUnitTest
import com.android.build.api.component.impl.features.AndroidResourcesCreationConfigImpl
+import com.android.build.api.component.impl.features.ManifestPlaceholdersCreationConfigImpl
import com.android.build.api.dsl.CommonExtension
import com.android.build.api.extension.impl.VariantApiOperationsRegistrar
import com.android.build.api.variant.AndroidVersion
@@ -31,9 +32,10 @@ import com.android.build.gradle.internal.component.UnitTestCreationConfig
import com.android.build.gradle.internal.component.VariantCreationConfig
import com.android.build.gradle.internal.component.features.AndroidResourcesCreationConfig
import com.android.build.gradle.internal.component.features.BuildConfigCreationConfig
-import com.android.build.gradle.internal.core.VariantDslInfoImpl
+import com.android.build.gradle.internal.component.features.ManifestPlaceholdersCreationConfig
import com.android.build.gradle.internal.core.VariantSources
import com.android.build.gradle.internal.core.dsl.UnitTestComponentDslInfo
+import com.android.build.gradle.internal.core.dsl.impl.DEFAULT_TEST_RUNNER
import com.android.build.gradle.internal.dependency.VariantDependencies
import com.android.build.gradle.internal.pipeline.TransformManager
import com.android.build.gradle.internal.scope.BuildFeatureValues
@@ -45,6 +47,7 @@ import com.android.build.gradle.internal.tasks.factory.GlobalTaskCreationConfig
import com.android.build.gradle.internal.variant.BaseVariantData
import com.android.build.gradle.internal.variant.VariantPathHelper
import com.google.wireless.android.sdk.stats.GradleBuildVariant
+import org.gradle.api.provider.MapProperty
import org.gradle.api.provider.Provider
import javax.inject.Inject
@@ -105,7 +108,7 @@ open class UnitTestImpl @Inject constructor(
* the instrumentation tag to be present in the merged manifest to process android resources.
*/
override val instrumentationRunner: Provider<String>
- get() = services.provider { VariantDslInfoImpl.DEFAULT_TEST_RUNNER }
+ get() = services.provider { DEFAULT_TEST_RUNNER }
override val testedApplicationId: Provider<String>
get() = mainVariant.applicationId
@@ -113,15 +116,15 @@ open class UnitTestImpl @Inject constructor(
override val debuggable: Boolean
get() = mainVariant.debuggable
- override val profileable: Boolean
- get() = mainVariant.profileable
+ override val manifestPlaceholders: MapProperty<String, String>
+ get() = manifestPlaceholdersCreationConfig.placeholders
// these would normally be public but not for unit-test. They are there to feed the
// manifest but aren't actually used.
override val isTestCoverageEnabled: Boolean
get() = dslInfo.isUnitTestCoverageEnabled
- override val androidResourcesCreationConfig: AndroidResourcesCreationConfig? by lazy {
+ override val androidResourcesCreationConfig: AndroidResourcesCreationConfig? by lazy(LazyThreadSafetyMode.NONE) {
// in case of unit tests, we add the R jar even if android resources are
// disabled (includeAndroidResources) as we want to be able to compile against
// the values inside.
@@ -136,6 +139,13 @@ open class UnitTestImpl @Inject constructor(
}
}
+ override val manifestPlaceholdersCreationConfig: ManifestPlaceholdersCreationConfig by lazy(LazyThreadSafetyMode.NONE) {
+ ManifestPlaceholdersCreationConfigImpl(
+ dslInfo.testedVariantDslInfo,
+ internalServices
+ )
+ }
+
override fun <T : Component> createUserVisibleVariantObject(
projectServices: ProjectServices,
operationsRegistrar: VariantApiOperationsRegistrar<out CommonExtension<*, *, *, *>, out VariantBuilder, out Variant>,
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/features/ManifestPlaceholdersCreationConfigImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/features/ManifestPlaceholdersCreationConfigImpl.kt
new file mode 100644
index 0000000000..ae7bee65c8
--- /dev/null
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/component/impl/features/ManifestPlaceholdersCreationConfigImpl.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.api.component.impl.features
+
+import com.android.build.gradle.internal.component.features.ManifestPlaceholdersCreationConfig
+import com.android.build.gradle.internal.core.dsl.ConsumableComponentDslInfo
+import com.android.build.gradle.internal.services.VariantServices
+import org.gradle.api.provider.MapProperty
+
+class ManifestPlaceholdersCreationConfigImpl(
+ dslInfo: ConsumableComponentDslInfo,
+ internalServices: VariantServices
+): ManifestPlaceholdersCreationConfig {
+ override val placeholders: MapProperty<String, String> by lazy {
+ internalServices.mapPropertyOf(
+ String::class.java,
+ String::class.java,
+ dslInfo.manifestPlaceholders
+ )
+ }
+}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/ApplicationVariantBuilderImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/ApplicationVariantBuilderImpl.kt
index f12c843af7..a93d533abb 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/ApplicationVariantBuilderImpl.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/ApplicationVariantBuilderImpl.kt
@@ -76,11 +76,11 @@ open class ApplicationVariantBuilderImpl @Inject constructor(
}
override var isMinifyEnabled: Boolean =
- dslInfo.getPostProcessingOptions().codeShrinkerEnabled()
+ dslInfo.postProcessingOptions.codeShrinkerEnabled()
set(value) = setMinificationIfPossible("minifyEnabled", value){ field = it }
override var shrinkResources: Boolean =
- dslInfo.getPostProcessingOptions().resourcesShrinkingEnabled()
+ dslInfo.postProcessingOptions.resourcesShrinkingEnabled()
set(value) = setMinificationIfPossible("shrinkResources", value){ field = it }
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/ApplicationVariantImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/ApplicationVariantImpl.kt
index 6c56e364b7..6bb95f7b55 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/ApplicationVariantImpl.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/ApplicationVariantImpl.kt
@@ -179,7 +179,7 @@ open class ApplicationVariantImpl @Inject constructor(
override val debuggable: Boolean
get() = delegate.isDebuggable
override val profileable: Boolean
- get() = delegate.isProfileable
+ get() = dslInfo.isProfileable
override val isCoreLibraryDesugaringEnabled: Boolean
get() = delegate.isCoreLibraryDesugaringEnabled
@@ -203,12 +203,6 @@ open class ApplicationVariantImpl @Inject constructor(
}
// ---------------------------------------------------------------------------------------------
- // DO NOT USE, only present for old variant API.
- // ---------------------------------------------------------------------------------------------
- override val dslSigningConfig: com.android.build.gradle.internal.dsl.SigningConfig? =
- dslInfo.signingConfig
-
- // ---------------------------------------------------------------------------------------------
// DO NOT USE, Deprecated DSL APIs.
// ---------------------------------------------------------------------------------------------
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/DynamicFeatureVariantImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/DynamicFeatureVariantImpl.kt
index f38f247dfa..0a2ca46c11 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/DynamicFeatureVariantImpl.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/DynamicFeatureVariantImpl.kt
@@ -55,6 +55,7 @@ import com.android.build.gradle.internal.variant.BaseVariantData
import com.android.build.gradle.internal.variant.VariantPathHelper
import com.android.build.gradle.options.StringOption
import com.android.builder.dexing.DexingType
+import com.android.builder.errors.IssueReporter
import com.google.wireless.android.sdk.stats.GradleBuildVariant
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
@@ -91,6 +92,17 @@ open class DynamicFeatureVariantImpl @Inject constructor(
), DynamicFeatureVariant, DynamicFeatureCreationConfig, HasAndroidTest, HasTestFixtures {
init {
+ // TODO: Should be removed once we stop implementing all build type interfaces in one class
+ if (dslInfo.isMultiDexSetFromDsl) {
+ services.issueReporter
+ .reportWarning(
+ IssueReporter.Type.GENERIC,
+ "Native multidex is always used for dynamic features. Please " +
+ "remove 'multiDexEnabled true|false' from your " +
+ "build.gradle file."
+ )
+ }
+
dslInfo.multiDexKeepProguard?.let {
artifacts.getArtifactContainer(MultipleArtifact.MULTIDEX_KEEP_PROGUARD)
.addInitialProvider(null, internalServices.toRegularFileProvider(it))
@@ -171,8 +183,6 @@ open class DynamicFeatureVariantImpl @Inject constructor(
override val shouldPackageDesugarLibDex: Boolean = false
override val debuggable: Boolean
get() = delegate.isDebuggable
- override val profileable: Boolean
- get() = delegate.isProfileable
override val isCoreLibraryDesugaringEnabled: Boolean
get() = delegate.isCoreLibraryDesugaringEnabled
@@ -191,12 +201,6 @@ open class DynamicFeatureVariantImpl @Inject constructor(
get() = dslInfo.isAndroidTestCoverageEnabled
// ---------------------------------------------------------------------------------------------
- // DO NOT USE, only present for old variant API.
- // ---------------------------------------------------------------------------------------------
- override val dslSigningConfig: com.android.build.gradle.internal.dsl.SigningConfig? =
- dslInfo.signingConfig
-
- // ---------------------------------------------------------------------------------------------
// DO NOT USE, Deprecated DSL APIs.
// ---------------------------------------------------------------------------------------------
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/LibraryVariantBuilderImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/LibraryVariantBuilderImpl.kt
index 8c147d1061..94e0a1c2c8 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/LibraryVariantBuilderImpl.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/LibraryVariantBuilderImpl.kt
@@ -84,6 +84,6 @@ open class LibraryVariantBuilderImpl @Inject constructor(
}
override var isMinifyEnabled: Boolean =
- dslInfo.getPostProcessingOptions().codeShrinkerEnabled()
+ dslInfo.postProcessingOptions.codeShrinkerEnabled()
set(value) = setMinificationIfPossible("minifyEnabled", value) { field = it }
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/LibraryVariantImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/LibraryVariantImpl.kt
index 5104785a90..ba9fbe7137 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/LibraryVariantImpl.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/LibraryVariantImpl.kt
@@ -125,9 +125,6 @@ open class LibraryVariantImpl @Inject constructor(
override val debuggable: Boolean
get() = dslInfo.isDebuggable
- override val profileable: Boolean
- get() = dslInfo.isProfileable
-
override val isCoreLibraryDesugaringEnabled: Boolean
get() = delegate.isCoreLibraryDesugaringEnabled
@@ -151,7 +148,7 @@ open class LibraryVariantImpl @Inject constructor(
override val resourcesShrink: Boolean
// need to return shrink flag for PostProcessing as this API has the flag for libraries
// return false otherwise
- get() = dslInfo.getPostProcessingOptions()
+ get() = dslInfo.postProcessingOptions
.let { it.hasPostProcessingConfiguration() && it.resourcesShrinkingEnabled() }
override val needsMergedJavaResStream: Boolean = delegate.getNeedsMergedJavaResStream()
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/SourceType.kt b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/SourceType.kt
index 2fb09fe6eb..daec70db14 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/SourceType.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/SourceType.kt
@@ -26,4 +26,5 @@ enum class SourceType(val folder: String) {
RENDERSCRIPT("renderscript"),
RES("res"),
SHADERS("shaders"),
+ JAVA_RESOURCES("resources"),
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/SourcesImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/SourcesImpl.kt
index fd0f3e06a3..5c18bb4971 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/SourcesImpl.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/SourcesImpl.kt
@@ -87,6 +87,19 @@ class SourcesImpl(
updateSourceDirectories(sourceDirectoriesImpl, variantSourceSet?.res)
}
+ override val resources: FlatSourceDirectoriesImpl =
+ FlatSourceDirectoriesImpl(
+ SourceType.JAVA_RESOURCES.name,
+ variantServices,
+ variantSourceSet?.resources?.filter,
+ ).also { sourceDirectoriesImpl ->
+
+ defaultSourceProvider.getResources(sourceDirectoriesImpl).run {
+ sourceDirectoriesImpl.addSources(this)
+ }
+ updateSourceDirectories(sourceDirectoriesImpl, variantSourceSet?.resources)
+ }
+
override val assets: AssetSourceDirectoriesImpl =
AssetSourceDirectoriesImpl(
SourceType.ASSETS.folder,
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/TestVariantBuilderImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/TestVariantBuilderImpl.kt
index 671d348e0b..4fa73fa013 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/TestVariantBuilderImpl.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/TestVariantBuilderImpl.kt
@@ -53,6 +53,6 @@ open class TestVariantBuilderImpl @Inject constructor(
}
override var isMinifyEnabled: Boolean =
- dslInfo.getPostProcessingOptions().codeShrinkerEnabled()
+ dslInfo.postProcessingOptions.codeShrinkerEnabled()
set(value) = setMinificationIfPossible("minifyEnabled", value){ field = it }
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/TestVariantImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/TestVariantImpl.kt
index 17dafc7b87..2bcd964cfa 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/TestVariantImpl.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/TestVariantImpl.kt
@@ -185,8 +185,6 @@ open class TestVariantImpl @Inject constructor(
override val shouldPackageDesugarLibDex: Boolean = delegate.isCoreLibraryDesugaringEnabled(this)
override val debuggable: Boolean
get() = delegate.isDebuggable
- override val profileable: Boolean
- get() = delegate.isProfileable
override val isCoreLibraryDesugaringEnabled: Boolean
get() = delegate.isCoreLibraryDesugaringEnabled
@@ -208,12 +206,6 @@ open class TestVariantImpl @Inject constructor(
get() = false
// ---------------------------------------------------------------------------------------------
- // DO NOT USE, only present for old variant API.
- // ---------------------------------------------------------------------------------------------
- override val dslSigningConfig: com.android.build.gradle.internal.dsl.SigningConfig? =
- dslInfo.signingConfig
-
- // ---------------------------------------------------------------------------------------------
// DO NOT USE, Deprecated DSL APIs.
// ---------------------------------------------------------------------------------------------
override val multiDexKeepFile = dslInfo.multiDexKeepFile
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/VariantBuilderImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/VariantBuilderImpl.kt
index 0d653dd7fb..b30832cd43 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/VariantBuilderImpl.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/VariantBuilderImpl.kt
@@ -152,7 +152,7 @@ abstract class VariantBuilderImpl(
newValue: Boolean,
setter: (Boolean) -> Unit
) {
- if (dslInfo.getPostProcessingOptions().hasPostProcessingConfiguration())
+ if (dslInfo.postProcessingOptions.hasPostProcessingConfiguration())
variantBuilderServices.issueReporter.reportWarning(
IssueReporter.Type.GENERIC,
"You cannot set $varName via Variant API as build uses postprocessing{...} " +
diff --git a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/VariantImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/VariantImpl.kt
index 13bd2a8097..27178e4214 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/VariantImpl.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/api/variant/impl/VariantImpl.kt
@@ -19,6 +19,7 @@ import com.android.build.api.artifact.impl.ArtifactsImpl
import com.android.build.api.component.impl.ComponentImpl
import com.android.build.api.component.impl.UnitTestImpl
import com.android.build.api.component.impl.features.BuildConfigCreationConfigImpl
+import com.android.build.api.component.impl.features.ManifestPlaceholdersCreationConfigImpl
import com.android.build.api.component.impl.features.RenderscriptCreationConfigImpl
import com.android.build.api.component.impl.warnAboutAccessingVariantApiValueForDisabledFeature
import com.android.build.api.variant.AndroidVersion
@@ -36,6 +37,7 @@ import com.android.build.gradle.internal.component.TestFixturesCreationConfig
import com.android.build.gradle.internal.component.VariantCreationConfig
import com.android.build.gradle.internal.component.features.BuildConfigCreationConfig
import com.android.build.gradle.internal.component.features.FeatureNames
+import com.android.build.gradle.internal.component.features.ManifestPlaceholdersCreationConfig
import com.android.build.gradle.internal.component.features.RenderscriptCreationConfig
import com.android.build.gradle.internal.core.MergedNdkConfig
import com.android.build.gradle.internal.core.NativeBuiltType
@@ -176,7 +178,7 @@ abstract class VariantImpl<DslInfoT: VariantDslInfo>(
// INTERNAL API
// ---------------------------------------------------------------------------------------------
- override val buildConfigCreationConfig: BuildConfigCreationConfig? by lazy {
+ override val buildConfigCreationConfig: BuildConfigCreationConfig? by lazy(LazyThreadSafetyMode.NONE) {
if (buildFeatures.buildConfig) {
BuildConfigCreationConfigImpl(
this,
@@ -188,7 +190,7 @@ abstract class VariantImpl<DslInfoT: VariantDslInfo>(
}
}
- override val renderscriptCreationConfig: RenderscriptCreationConfig? by lazy {
+ override val renderscriptCreationConfig: RenderscriptCreationConfig? by lazy(LazyThreadSafetyMode.NONE) {
if (buildFeatures.renderScript) {
RenderscriptCreationConfigImpl(
dslInfo,
@@ -200,10 +202,17 @@ abstract class VariantImpl<DslInfoT: VariantDslInfo>(
}
}
+ override val manifestPlaceholdersCreationConfig: ManifestPlaceholdersCreationConfig by lazy(LazyThreadSafetyMode.NONE) {
+ ManifestPlaceholdersCreationConfigImpl(
+ dslInfo,
+ internalServices
+ )
+ }
+
override val testComponents = mutableMapOf<ComponentType, TestComponentCreationConfig>()
override var testFixturesComponent: TestFixturesCreationConfig? = null
- val externalExtensions: Map<Class<*>, Any>? by lazy {
+ private val externalExtensions: Map<Class<*>, Any>? by lazy {
variantBuilder.getRegisteredExtensions()
}
@@ -296,8 +305,8 @@ abstract class VariantImpl<DslInfoT: VariantDslInfo>(
get() = dslInfo.supportedAbis
override val postProcessingFeatures: PostprocessingFeatures?
- get() = dslInfo.getPostProcessingOptions().getPostprocessingFeatures()
- override val consumerProguardFiles: List<File> by lazy {
+ get() = dslInfo.postProcessingOptions.getPostprocessingFeatures()
+ override val consumerProguardFiles: List<File> by lazy(LazyThreadSafetyMode.NONE) {
immutableListBuilder<File> {
addAll(dslInfo.gatherProguardFiles(ProguardFileType.CONSUMER))
// We include proguardFiles if we're in a dynamic-feature module.
@@ -306,4 +315,6 @@ abstract class VariantImpl<DslInfoT: VariantDslInfo>(
}
}
}
+ override val manifestPlaceholders: MapProperty<String, String>
+ get() = manifestPlaceholdersCreationConfig.placeholders
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/DependencyResourcesComputer.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/DependencyResourcesComputer.kt
index ca15e2190f..62bfefe47e 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/DependencyResourcesComputer.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/DependencyResourcesComputer.kt
@@ -16,6 +16,7 @@
package com.android.build.gradle.internal
import com.android.SdkConstants.FD_RES_VALUES
+import com.android.build.api.variant.impl.DirectoryEntry
import com.android.build.gradle.internal.component.ComponentCreationConfig
import com.android.build.gradle.internal.scope.InternalArtifactType
import com.android.build.gradle.internal.utils.fromDisallowChanges
@@ -231,6 +232,22 @@ abstract class DependencyResourcesComputer {
}
resources.disallowChanges()
+ // Add the user added generated directories to the extraGeneratedResFolders.
+ // this should be cleaned up once the old variant API is removed.
+ creationConfig.sources.res.getVariantSources().get().forEach { directoryEntries ->
+ directoryEntries.directoryEntries
+ .filter {
+ it.isUserAdded && it.isGenerated
+ }
+ .forEach {
+ extraGeneratedResFolders.from(
+ it.asFiles(
+ creationConfig.services::directoryProperty
+ )
+ )
+ }
+ }
+
creationConfig.oldVariantApiLegacySupport?.variantData?.extraGeneratedResFolders?.let {
extraGeneratedResFolders.from(it)
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/VariantManager.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/VariantManager.kt
index 5438e76766..49ddb3af4e 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/VariantManager.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/VariantManager.kt
@@ -44,16 +44,16 @@ import com.android.build.gradle.internal.component.NestedComponentCreationConfig
import com.android.build.gradle.internal.component.TestComponentCreationConfig
import com.android.build.gradle.internal.component.TestFixturesCreationConfig
import com.android.build.gradle.internal.component.VariantCreationConfig
-import com.android.build.gradle.internal.core.VariantDslInfoBuilder
-import com.android.build.gradle.internal.core.VariantDslInfoBuilder.Companion.computeSourceSetName
-import com.android.build.gradle.internal.core.VariantDslInfoBuilder.Companion.getBuilder
-import com.android.build.gradle.internal.core.VariantDslInfoImpl
import com.android.build.gradle.internal.core.dsl.AndroidTestComponentDslInfo
import com.android.build.gradle.internal.core.dsl.ComponentDslInfo
import com.android.build.gradle.internal.core.dsl.TestComponentDslInfo
import com.android.build.gradle.internal.core.dsl.TestFixturesComponentDslInfo
+import com.android.build.gradle.internal.core.dsl.TestedVariantDslInfo
import com.android.build.gradle.internal.core.dsl.UnitTestComponentDslInfo
import com.android.build.gradle.internal.core.dsl.VariantDslInfo
+import com.android.build.gradle.internal.core.dsl.impl.DslInfoBuilder
+import com.android.build.gradle.internal.core.dsl.impl.DslInfoBuilder.Companion.getBuilder
+import com.android.build.gradle.internal.core.dsl.impl.computeSourceSetName
import com.android.build.gradle.internal.crash.ExternalApiUsageException
import com.android.build.gradle.internal.dependency.VariantDependenciesBuilder
import com.android.build.gradle.internal.dsl.BuildType
@@ -169,16 +169,6 @@ class VariantManager<
private lateinit var _buildFeatureValues: BuildFeatureValues
-
- private fun hasDynamicFeatures(): Boolean =
- (dslExtension as? ApplicationExtension)?.dynamicFeatures?.isNotEmpty() ?: false
-
- private fun getCompileSdkVersion(): String? {
- val newExtension = dslExtension as? CommonExtensionImpl<*,*,*,*> ?: throw RuntimeException("Wrong DSL instance")
- return newExtension.compileSdkVersion
- }
-
-
/**
* Creates the variants.
*
@@ -282,12 +272,11 @@ class VariantManager<
getLazyManifestParser(
defaultConfigSourceProvider.manifestFile,
componentType.requiresManifest) { canParseManifest() },
- dslServices,
variantPropertiesApiServices,
oldExtension,
dslExtension,
- hasDynamicFeatures = hasDynamicFeatures(),
- dslExtension.experimentalProperties,
+ project.layout.buildDirectory,
+ dslServices
)
// We must first add the flavors to the variant config, in order to get the proper
@@ -296,8 +285,7 @@ class VariantManager<
variantDslInfoBuilder.addProductFlavor(
productFlavorData.productFlavor, productFlavorData.sourceSet)
}
- val variantDslInfo = variantDslInfoBuilder.createVariantDslInfo(
- project.layout.buildDirectory)
+ val variantDslInfo = variantDslInfoBuilder.createDslInfo()
val componentIdentity = variantDslInfo.componentIdentity
// create the Variant object so that we can run the action which may interrupt the creation
@@ -420,24 +408,24 @@ class VariantManager<
private fun<DslInfoT: ComponentDslInfo> createCompoundSourceSets(
productFlavorList: List<ProductFlavorData<ProductFlavor>>,
- variantDslInfoBuilder: VariantDslInfoBuilder<CommonExtensionT, DslInfoT>) {
- val componentType = variantDslInfoBuilder.componentType
+ dslInfoBuilder: DslInfoBuilder<CommonExtensionT, DslInfoT>) {
+ val componentType = dslInfoBuilder.componentType
if (productFlavorList.isNotEmpty() /* && !variantConfig.getType().isSingleBuildType()*/) {
val variantSourceSet = variantInputModel
.sourceSetManager
.setUpSourceSet(
- computeSourceSetName(variantDslInfoBuilder.name, componentType),
+ computeSourceSetName(dslInfoBuilder.name, componentType),
componentType.isTestComponent) as DefaultAndroidSourceSet
- variantDslInfoBuilder.variantSourceProvider = variantSourceSet
+ dslInfoBuilder.variantSourceProvider = variantSourceSet
}
if (productFlavorList.size > 1) {
val multiFlavorSourceSet = variantInputModel
.sourceSetManager
.setUpSourceSet(
- computeSourceSetName(variantDslInfoBuilder.flavorName,
+ computeSourceSetName(dslInfoBuilder.flavorName,
componentType),
componentType.isTestComponent) as DefaultAndroidSourceSet
- variantDslInfoBuilder.multiFlavorSourceProvider = multiFlavorSourceSet
+ dslInfoBuilder.multiFlavorSourceProvider = multiFlavorSourceSet
}
}
@@ -461,15 +449,15 @@ class VariantManager<
getLazyManifestParser(
testFixturesSourceSet.manifestFile,
testFixturesComponentType.requiresManifest) { canParseManifest() },
- dslServices,
variantPropertiesApiServices,
oldExtension = oldExtension,
extension = dslExtension,
- hasDynamicFeatures = hasDynamicFeatures(),
- testFixtureMainVariantName = mainComponentInfo.variant.name
+ buildDirectory = project.layout.buildDirectory,
+ dslServices = dslServices
)
- variantDslInfoBuilder.productionVariant = mainComponentInfo.variantDslInfo as VariantDslInfoImpl
+ variantDslInfoBuilder.productionVariant =
+ mainComponentInfo.variantDslInfo as TestedVariantDslInfo
val productFlavorList = mainComponentInfo.variantDslInfo.productFlavorList
@@ -484,9 +472,7 @@ class VariantManager<
)
}
}
- val variantDslInfo = variantDslInfoBuilder.createVariantDslInfo(
- project.layout.buildDirectory
- )
+ val variantDslInfo = variantDslInfoBuilder.createDslInfo()
// now that we have the result of the filter, we can continue configuring the variant
createCompoundSourceSets(productFlavorDataList, variantDslInfoBuilder)
@@ -608,13 +594,14 @@ class VariantManager<
getLazyManifestParser(
testSourceSet.manifestFile,
componentType.requiresManifest) { canParseManifest() },
- dslServices,
variantPropertiesApiServices,
oldExtension = oldExtension,
extension = dslExtension,
- hasDynamicFeatures = hasDynamicFeatures())
+ buildDirectory = project.layout.buildDirectory,
+ dslServices = dslServices
+ )
variantDslInfoBuilder.productionVariant =
- testedComponentInfo.variantDslInfo as VariantDslInfoImpl
+ testedComponentInfo.variantDslInfo as TestedVariantDslInfo
variantDslInfoBuilder.inconsistentTestAppId = inconsistentTestAppId
val productFlavorList = testedComponentInfo.variantDslInfo.productFlavorList
@@ -629,8 +616,7 @@ class VariantManager<
it.getTestSourceSet(componentType)!!)
}
}
- val variantDslInfo = variantDslInfoBuilder.createVariantDslInfo(
- project.layout.buildDirectory)
+ val variantDslInfo = variantDslInfoBuilder.createDslInfo()
val apiAccessStats = testedComponentInfo.stats
if (componentType.isApk
&& testedComponentInfo.variantBuilder is HasAndroidTestBuilder) {
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/api/AndroidArtifactVariantImpl.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/api/AndroidArtifactVariantImpl.java
index 8b61525b19..0f81bb5b5d 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/api/AndroidArtifactVariantImpl.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/api/AndroidArtifactVariantImpl.java
@@ -21,7 +21,6 @@ import com.android.annotations.Nullable;
import com.android.build.api.component.impl.ComponentUtils;
import com.android.build.gradle.api.AndroidArtifactVariant;
import com.android.build.gradle.api.BaseVariantOutput;
-import com.android.build.gradle.internal.component.ApkCreationConfig;
import com.android.build.gradle.internal.component.ComponentCreationConfig;
import com.android.build.gradle.internal.services.DslServices;
import com.android.build.gradle.internal.variant.ApkVariantData;
@@ -52,9 +51,9 @@ public abstract class AndroidArtifactVariantImpl extends BaseVariantImpl
@Override
public SigningConfig getSigningConfig() {
- if (component instanceof ApkCreationConfig) {
+ if (component.getOldVariantApiLegacySupport() != null) {
return readOnlyObjectProvider.getSigningConfig(
- ((ApkCreationConfig) component).getDslSigningConfig());
+ component.getOldVariantApiLegacySupport().getDslSigningConfig());
} else return null;
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/api/VariantFilter.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/api/VariantFilter.kt
index c9063a7066..98e09e4219 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/api/VariantFilter.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/api/VariantFilter.kt
@@ -16,7 +16,7 @@
package com.android.build.gradle.internal.api
import com.android.build.api.variant.VariantFilter
-import com.android.build.gradle.internal.core.VariantDslInfoBuilder.Companion.computeName
+import com.android.build.gradle.internal.core.dsl.impl.computeName
import com.android.build.gradle.internal.variant.DimensionCombination
import com.android.builder.core.ComponentType
import com.android.builder.model.BuildType
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/ApkCreationConfig.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/ApkCreationConfig.kt
index c8d4b38beb..ad6d4e767d 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/ApkCreationConfig.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/ApkCreationConfig.kt
@@ -50,11 +50,6 @@ interface ApkCreationConfig: ConsumableCreationConfig {
*/
val signingConfigImpl: SigningConfigImpl?
- /**
- * DO NOT USE, only present for old variant API.
- */
- val dslSigningConfig: com.android.build.gradle.internal.dsl.SigningConfig?
-
val multiDexKeepFile: File?
val bundleConfig: BundleConfigImpl?
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/ApplicationCreationConfig.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/ApplicationCreationConfig.kt
index c01ab18c84..873281130b 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/ApplicationCreationConfig.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/ApplicationCreationConfig.kt
@@ -20,6 +20,7 @@ import com.android.build.api.variant.impl.BundleConfigImpl
import com.android.build.gradle.internal.dsl.NdkOptions
interface ApplicationCreationConfig: ApkCreationConfig, VariantCreationConfig, PublishableCreationConfig {
+ val profileable: Boolean
val consumesFeatureJars: Boolean
val needAssetPackTasks: Boolean
val nativeDebugSymbolLevel: NdkOptions.DebugSymbolLevel
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/ComponentCreationConfig.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/ComponentCreationConfig.kt
index 491d4b60c6..c8e367d6be 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/ComponentCreationConfig.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/ComponentCreationConfig.kt
@@ -32,6 +32,7 @@ import com.android.build.gradle.internal.component.features.AndroidResourcesCrea
import com.android.build.gradle.internal.component.features.AssetsCreationConfig
import com.android.build.gradle.internal.component.features.BuildConfigCreationConfig
import com.android.build.gradle.internal.component.features.InstrumentationCreationConfig
+import com.android.build.gradle.internal.component.features.ManifestPlaceholdersCreationConfig
import com.android.build.gradle.internal.component.features.ResValuesCreationConfig
import com.android.build.gradle.internal.component.legacy.ModelV1LegacySupport
import com.android.build.gradle.internal.component.legacy.OldVariantApiLegacySupport
@@ -49,7 +50,6 @@ import com.android.build.gradle.internal.variant.VariantPathHelper
import com.android.builder.core.ComponentType
import com.google.wireless.android.sdk.stats.GradleBuildVariant
import org.gradle.api.file.FileCollection
-import org.gradle.api.provider.MapProperty
import org.gradle.api.provider.Provider
import java.io.File
import java.util.function.Predicate
@@ -81,8 +81,6 @@ interface ComponentCreationConfig : ComponentIdentity {
val applicationId: Provider<String>
val namespace: Provider<String>
val debuggable: Boolean
- val profileable: Boolean
- val manifestPlaceholders: MapProperty<String, String>
val supportedAbis: Set<String>
val minSdkVersion: AndroidVersion
@@ -98,6 +96,7 @@ interface ComponentCreationConfig : ComponentIdentity {
val resValuesCreationConfig: ResValuesCreationConfig?
val buildConfigCreationConfig: BuildConfigCreationConfig?
val instrumentationCreationConfig: InstrumentationCreationConfig?
+ val manifestPlaceholdersCreationConfig: ManifestPlaceholdersCreationConfig?
// TODO figure out whether these properties are needed by all
// TODO : remove as it is now in Variant.
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/ConsumableCreationConfig.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/ConsumableCreationConfig.kt
index 6a176deb8f..7c2ad5da46 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/ConsumableCreationConfig.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/ConsumableCreationConfig.kt
@@ -25,6 +25,7 @@ import com.android.build.gradle.internal.scope.Java8LangSupport
import com.android.builder.dexing.DexingType
import org.gradle.api.file.RegularFile
import org.gradle.api.provider.ListProperty
+import org.gradle.api.provider.MapProperty
import org.gradle.api.provider.Provider
/**
@@ -81,4 +82,6 @@ interface ConsumableCreationConfig: ComponentCreationConfig {
val defaultGlslcArgs: List<String>
val scopedGlslcArgs: Map<String, List<String>>
+
+ val manifestPlaceholders: MapProperty<String, String>
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/DynamicFeatureCreationConfig.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/DynamicFeatureCreationConfig.kt
index 92882b7fe2..3f518548e9 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/DynamicFeatureCreationConfig.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/DynamicFeatureCreationConfig.kt
@@ -22,6 +22,5 @@ interface DynamicFeatureCreationConfig: VariantCreationConfig, ApkCreationConfig
val featureName: Provider<String>
val resOffset: Provider<Int>
-
val baseModuleDebuggable: Provider<Boolean>
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/features/ManifestPlaceholdersCreationConfig.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/features/ManifestPlaceholdersCreationConfig.kt
new file mode 100644
index 0000000000..640a6e7f40
--- /dev/null
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/features/ManifestPlaceholdersCreationConfig.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.internal.component.features
+
+import org.gradle.api.provider.MapProperty
+
+/**
+ * Creation config for components that support manifest placeholders.
+ */
+interface ManifestPlaceholdersCreationConfig {
+ val placeholders: MapProperty<String, String>
+}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/legacy/OldVariantApiLegacySupport.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/legacy/OldVariantApiLegacySupport.kt
index 85c56a23cc..b8a5b1adab 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/legacy/OldVariantApiLegacySupport.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/component/legacy/OldVariantApiLegacySupport.kt
@@ -34,6 +34,7 @@ interface OldVariantApiLegacySupport {
val mergedFlavor: MergedFlavor
val javaCompileOptions: JavaCompileOptions
val variantData: BaseVariantData
+ val dslSigningConfig: com.android.build.gradle.internal.dsl.SigningConfig?
fun getJavaClasspathArtifacts(
configType: AndroidArtifacts.ConsumedConfigType,
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/MergedAarMetadata.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/MergedAarMetadata.kt
index e3ea292780..feac2bbc6e 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/MergedAarMetadata.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/MergedAarMetadata.kt
@@ -40,4 +40,10 @@ class MergedAarMetadata : MergedOptions<AarMetadata> {
option.minCompileSdkExtension?.let { minCompileSdkExtension = it }
option.minAgpVersion?.let { minAgpVersion = it }
}
+
+ fun append(option: MergedAarMetadata) {
+ option.minCompileSdk?.let { minCompileSdk = it }
+ option.minCompileSdkExtension?.let { minCompileSdkExtension = it }
+ option.minAgpVersion?.let { minAgpVersion = it }
+ }
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/MergedAnnotationProcessorOptions.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/MergedAnnotationProcessorOptions.kt
new file mode 100644
index 0000000000..d4ca11d25c
--- /dev/null
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/MergedAnnotationProcessorOptions.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.internal.core
+
+import com.android.build.gradle.internal.dsl.AnnotationProcessorOptions
+import org.gradle.process.CommandLineArgumentProvider
+
+class MergedAnnotationProcessorOptions:
+ AnnotationProcessorOptions(),
+ MergedOptions<com.android.build.gradle.api.AnnotationProcessorOptions> {
+
+ override fun setClassNames(classNames: MutableList<String>) {
+ this.classNames.clear()
+ this.classNames.addAll(classNames)
+ }
+
+ override fun setArguments(arguments: MutableMap<String, String>) {
+ this.arguments.clear()
+ this.arguments.putAll(arguments)
+ }
+
+ override fun setCompilerArgumentProviders(compilerArgumentProviders: MutableList<CommandLineArgumentProvider>) {
+ this.compilerArgumentProviders.clear()
+ this.compilerArgumentProviders.addAll(compilerArgumentProviders)
+ }
+
+ override val classNames = mutableListOf<String>()
+ override val arguments = mutableMapOf<String, String>()
+ override val compilerArgumentProviders = mutableListOf<CommandLineArgumentProvider>()
+
+ override fun reset() {
+ classNames.clear()
+ arguments.clear()
+ compilerArgumentProviders.clear()
+ }
+
+ override fun append(option: com.android.build.gradle.api.AnnotationProcessorOptions) {
+ classNames.addAll(option.classNames)
+ arguments.putAll(option.arguments)
+ compilerArgumentProviders.addAll(option.compilerArgumentProviders)
+ }
+}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/MergedFlavor.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/MergedFlavor.kt
index a27d25f4c3..a169278716 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/MergedFlavor.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/MergedFlavor.kt
@@ -20,7 +20,7 @@ import com.android.build.api.component.impl.ENABLE_LEGACY_API
import com.android.build.gradle.internal.api.BaseVariantImpl
import com.android.build.gradle.internal.dsl.VectorDrawablesOptions
import com.android.build.gradle.internal.errors.DeprecationReporter
-import com.android.build.gradle.internal.services.DslServices
+import com.android.build.gradle.internal.services.VariantServices
import com.android.build.gradle.options.BooleanOption
import com.android.builder.core.AbstractProductFlavor
import com.android.builder.core.DefaultVectorDrawablesOptions
@@ -36,7 +36,7 @@ import org.gradle.api.provider.Property
class MergedFlavor(
name: String,
private val _applicationId: Property<String>,
- private val dslServices: DslServices
+ private val services: VariantServices
) : AbstractProductFlavor(name), InternalBaseVariant.MergedFlavor {
override var dimension: String? = null
@@ -48,8 +48,8 @@ class MergedFlavor(
override var testHandleProfiling: Boolean? = null
override var testFunctionalTest: Boolean? = null
override var wearAppUnbundled: Boolean? = null
- protected override var _versionCode: Int? = null
- protected override var _versionName: String? = null
+ override var _versionCode: Int? = null
+ override var _versionName: String? = null
override val resourceConfigurations: MutableSet<String> = mutableSetOf()
// in the merged flavor scenario which is still accessible from the old variant API, we need
@@ -57,7 +57,7 @@ class MergedFlavor(
override var applicationId: String?
get() {
// consider throwing an exception instead, as this is not reliable.
- dslServices.deprecationReporter
+ services.deprecationReporter
.reportDeprecatedApi(
"Variant.getApplicationId()",
"MergedFlavor.getApplicationId()",
@@ -65,8 +65,8 @@ class MergedFlavor(
DeprecationReporter.DeprecationTarget.USE_PROPERTIES
)
- if (!dslServices.projectOptions.get(BooleanOption.ENABLE_LEGACY_API)) {
- dslServices.issueReporter
+ if (!services.projectOptions.get(BooleanOption.ENABLE_LEGACY_API)) {
+ services.issueReporter
.reportError(
IssueReporter.Type.GENERIC,
RuntimeException(
@@ -99,8 +99,8 @@ class MergedFlavor(
* @return a new MergedFlavor instance that is a clone of the flavor.
*/
@JvmStatic
- fun clone(productFlavor: ProductFlavor, applicationId: Property<String>, dslServices: DslServices): MergedFlavor {
- val mergedFlavor = MergedFlavor(productFlavor.name, applicationId, dslServices)
+ fun clone(productFlavor: ProductFlavor, applicationId: Property<String>, services: VariantServices): MergedFlavor {
+ val mergedFlavor = MergedFlavor(productFlavor.name, applicationId, services)
mergedFlavor._initWith(productFlavor)
return mergedFlavor
}
@@ -123,9 +123,9 @@ class MergedFlavor(
lowestPriority: ProductFlavor,
flavors: List<ProductFlavor>,
applicationId: Property<String>,
- dslServices: DslServices
+ services: VariantServices
): MergedFlavor {
- val mergedFlavor = clone(lowestPriority, applicationId, dslServices)
+ val mergedFlavor = clone(lowestPriority, applicationId, services)
for (flavor in Lists.reverse(flavors)) {
mergedFlavor.mergeWithHigherPriorityFlavor(flavor)
}
@@ -202,6 +202,6 @@ class MergedFlavor(
| }
|}""".trimMargin()
- dslServices.issueReporter.reportError(IssueReporter.Type.GENERIC, message)
+ services.issueReporter.reportError(IssueReporter.Type.GENERIC, message)
}
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/MergedJavaCompileOptions.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/MergedJavaCompileOptions.kt
index d7b19c9ab7..5bc8be8101 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/MergedJavaCompileOptions.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/MergedJavaCompileOptions.kt
@@ -17,30 +17,23 @@
package com.android.build.gradle.internal.core
import com.android.build.gradle.api.JavaCompileOptions
-import com.android.build.gradle.internal.dsl.AnnotationProcessorOptions
/** Implementation of CoreJavaCompileOptions used to merge multiple configs together. */
-abstract class MergedJavaCompileOptions : JavaCompileOptions,
+class MergedJavaCompileOptions : JavaCompileOptions,
com.android.build.api.dsl.JavaCompileOptions,
MergedOptions<JavaCompileOptions> {
- abstract override val annotationProcessorOptions: AnnotationProcessorOptions
+ override val annotationProcessorOptions = MergedAnnotationProcessorOptions()
+
+ override fun annotationProcessorOptions(action: com.android.build.api.dsl.AnnotationProcessorOptions.() -> Unit) {
+ action.invoke(annotationProcessorOptions)
+ }
override fun reset() {
- annotationProcessorOptions.classNames.clear()
- annotationProcessorOptions.arguments.clear()
- annotationProcessorOptions.compilerArgumentProviders.clear()
+ annotationProcessorOptions.reset()
}
override fun append(option: JavaCompileOptions) {
- annotationProcessorOptions.classNames.addAll(
- option.annotationProcessorOptions.classNames
- )
- annotationProcessorOptions.arguments.putAll(
- option.annotationProcessorOptions.arguments
- )
- annotationProcessorOptions.compilerArgumentProviders.addAll(
- option.annotationProcessorOptions.compilerArgumentProviders
- )
+ annotationProcessorOptions.append(option.annotationProcessorOptions)
}
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/VariantDslInfo.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/VariantDslInfo.kt
deleted file mode 100644
index fc8296a60d..0000000000
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/VariantDslInfo.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * 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 com.android.build.gradle.internal.core
-
-import com.android.build.gradle.internal.core.dsl.AarProducingComponentDslInfo
-import com.android.build.gradle.internal.core.dsl.AndroidTestComponentDslInfo
-import com.android.build.gradle.internal.core.dsl.ApkProducingComponentDslInfo
-import com.android.build.gradle.internal.core.dsl.ApplicationVariantDslInfo
-import com.android.build.gradle.internal.core.dsl.ComponentDslInfo
-import com.android.build.gradle.internal.core.dsl.DynamicFeatureVariantDslInfo
-import com.android.build.gradle.internal.core.dsl.InstrumentedTestComponentDslInfo
-import com.android.build.gradle.internal.core.dsl.LibraryVariantDslInfo
-import com.android.build.gradle.internal.core.dsl.PublishableVariantDslInfo
-import com.android.build.gradle.internal.core.dsl.TestComponentDslInfo
-import com.android.build.gradle.internal.core.dsl.TestFixturesComponentDslInfo
-import com.android.build.gradle.internal.core.dsl.TestProjectVariantDslInfo
-import com.android.build.gradle.internal.core.dsl.TestedComponentDslInfo
-import com.android.build.gradle.internal.core.dsl.UnitTestComponentDslInfo
-
-@Deprecated("Do not use or add any new properties here, use the fine-grained interfaces")
-interface VariantDslInfo: AarProducingComponentDslInfo,
- AndroidTestComponentDslInfo,
- ApkProducingComponentDslInfo,
- ApplicationVariantDslInfo,
- ComponentDslInfo,
- DynamicFeatureVariantDslInfo,
- InstrumentedTestComponentDslInfo,
- LibraryVariantDslInfo,
- PublishableVariantDslInfo,
- TestComponentDslInfo,
- TestedComponentDslInfo,
- TestFixturesComponentDslInfo,
- TestProjectVariantDslInfo,
- UnitTestComponentDslInfo,
- com.android.build.gradle.internal.core.dsl.VariantDslInfo
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/VariantDslInfoBuilder.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/VariantDslInfoBuilder.kt
deleted file mode 100644
index 5d6283d8d3..0000000000
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/VariantDslInfoBuilder.kt
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * 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 com.android.build.gradle.internal.core
-
-import com.android.build.api.component.impl.ComponentIdentityImpl
-import com.android.build.api.dsl.BuildType
-import com.android.build.api.dsl.CommonExtension
-import com.android.build.api.dsl.ProductFlavor
-import com.android.build.api.variant.ComponentIdentity
-import com.android.build.gradle.BaseExtension
-import com.android.build.gradle.internal.api.DefaultAndroidSourceSet
-import com.android.build.gradle.internal.core.VariantDslInfoBuilder.Companion.getBuilder
-import com.android.build.gradle.internal.core.dsl.ComponentDslInfo
-import com.android.build.gradle.internal.dsl.ApplicationPublishingImpl
-import com.android.build.gradle.internal.dsl.DefaultConfig
-import com.android.build.gradle.internal.dsl.InternalApplicationExtension
-import com.android.build.gradle.internal.dsl.InternalLibraryExtension
-import com.android.build.gradle.internal.dsl.LibraryPublishingImpl
-import com.android.build.gradle.internal.dsl.SigningConfig
-import com.android.build.gradle.internal.manifest.ManifestDataProvider
-import com.android.build.gradle.internal.services.DslServices
-import com.android.build.gradle.internal.services.VariantServices
-import com.android.build.gradle.internal.utils.createPublishingInfoForApp
-import com.android.build.gradle.internal.utils.createPublishingInfoForLibrary
-import com.android.build.gradle.internal.utils.toImmutableList
-import com.android.build.gradle.internal.variant.DimensionCombination
-import com.android.builder.core.ComponentType
-import com.android.builder.model.SourceProvider
-import com.android.utils.appendCapitalized
-import com.android.utils.combineAsCamelCase
-import org.gradle.api.file.DirectoryProperty
-
-/** Builder for [VariantDslInfo].
- *
- * This allows setting all temporary items on the builder before actually
- * instantiating the configuration, in order to keep it immutable.
- *
- * Use [getBuilder] as an entry point.
- */
-class VariantDslInfoBuilder<CommonExtensionT: CommonExtension<*, *, *, *>, DslInfoT: ComponentDslInfo> private constructor(
- private val dimensionCombination: DimensionCombination,
- val componentType: ComponentType,
- private val defaultConfig: DefaultConfig,
- private val defaultSourceProvider: SourceProvider,
- private val buildType: BuildType,
- private val buildTypeSourceProvider: SourceProvider? = null,
- private val signingConfigOverride: SigningConfig?,
- private val manifestDataProvider: ManifestDataProvider,
- private val dslServices: DslServices,
- private val variantServices: VariantServices,
- private val oldExtension: BaseExtension,
- private val extension: CommonExtensionT,
- private val hasDynamicFeatures: Boolean,
- private val experimentalProperties: Map<String, Any>,
- private val testFixtureMainVariantName: String?
-) {
-
- companion object {
- /**
- * Returns a new builder
- */
- @JvmStatic
- fun <CommonExtensionT: CommonExtension<*, *, *, *>, DslInfoT: ComponentDslInfo> getBuilder(
- dimensionCombination: DimensionCombination,
- componentType: ComponentType,
- defaultConfig: DefaultConfig,
- defaultSourceSet: SourceProvider,
- buildType: BuildType,
- buildTypeSourceSet: SourceProvider? = null,
- signingConfigOverride: SigningConfig? = null,
- manifestDataProvider: ManifestDataProvider,
- dslServices: DslServices,
- variantServices: VariantServices,
- oldExtension: BaseExtension,
- extension: CommonExtensionT,
- hasDynamicFeatures: Boolean,
- experimentalProperties: Map<String, Any> = mapOf(),
- testFixtureMainVariantName: String? = null
- ): VariantDslInfoBuilder<CommonExtensionT, DslInfoT> {
- return VariantDslInfoBuilder(
- dimensionCombination,
- componentType,
- defaultConfig,
- defaultSourceSet,
- buildType,
- buildTypeSourceSet,
- signingConfigOverride?.let { signingOverride ->
- dslServices.newDecoratedInstance(
- SigningConfig::class.java,
- signingOverride.name,
- dslServices
- ).also {
- it.initWith(signingOverride)
- }
- },
- manifestDataProvider,
- dslServices,
- variantServices,
- oldExtension,
- extension,
- hasDynamicFeatures,
- experimentalProperties,
- testFixtureMainVariantName,
- )
- }
-
- /**
- * Returns the full, unique name of the variant in camel case (starting with a lower case),
- * including BuildType, Flavors and Test (if applicable).
- *
- * This is to be used for the normal variant name. In case of Feature plugin, the library
- * side will be called the same as for library plugins, while the feature side will add
- * 'feature' to the name.
- *
- * Also computes the flavor name if applicable
- */
- @JvmStatic
- @JvmOverloads
- fun computeName(
- dimensionCombination: DimensionCombination,
- componentType: ComponentType,
- flavorNameCallback: ((String) -> Unit)? = null
- ): String {
- // compute the flavor name
- val flavorName = if (dimensionCombination.productFlavors.isNullOrEmpty()) {
- ""
- } else {
- combineAsCamelCase(dimensionCombination.productFlavors, Pair<String,String>::second)
- }
- flavorNameCallback?.let { it(flavorName) }
-
- val sb = StringBuilder()
- val buildType = dimensionCombination.buildType
- if (buildType == null) {
- if (flavorName.isNotEmpty()) {
- sb.append(flavorName)
- } else if (!componentType.isTestComponent && !componentType.isTestFixturesComponent) {
- sb.append("main")
- }
- } else {
- if (flavorName.isNotEmpty()) {
- sb.append(flavorName)
- sb.appendCapitalized(buildType)
- } else {
- sb.append(buildType)
- }
- }
- if (componentType.isNestedComponent) {
- if (sb.isEmpty()) {
- // need the lower case version
- sb.append(componentType.prefix)
- } else {
- sb.append(componentType.suffix)
- }
- }
- return sb.toString()
- }
-
- /**
- * Turns a string into a valid source set name for the given [ComponentType], e.g.
- * "fooBarUnitTest" becomes "testFooBar".
- */
- @JvmStatic
- fun computeSourceSetName(
- baseName: String,
- componentType: ComponentType
- ): String {
- var name = baseName
- if (name.endsWith(componentType.suffix)) {
- name = name.substring(0, name.length - componentType.suffix.length)
- }
- if (!componentType.prefix.isEmpty()) {
- name = componentType.prefix.appendCapitalized(name)
- }
- return name
- }
-
- /**
- * Returns the full, unique name of the variant, including BuildType, flavors and test, dash
- * separated. (similar to full name but with dashes)
- *
- * @return the name of the variant
- */
- @JvmStatic
- fun computeBaseName(
- dimensionCombination: DimensionCombination,
- componentType: ComponentType) : String {
- val sb = StringBuilder()
- if (dimensionCombination.productFlavors.isNotEmpty()) {
- for ((_, name) in dimensionCombination.productFlavors) {
- if (sb.isNotEmpty()) {
- sb.append('-')
- }
- sb.append(name)
- }
- }
-
- dimensionCombination.buildType?.let {
- if (sb.isNotEmpty()) {
- sb.append('-')
- }
- sb.append(it)
- }
-
- if (componentType.isNestedComponent) {
- if (sb.isNotEmpty()) {
- sb.append('-')
- }
- sb.append(componentType.prefix)
- }
-
- if (sb.isEmpty()) {
- sb.append("main")
- }
-
- return sb.toString()
- }
-
- /**
- * Returns a full name that includes the given splits name.
- *
- * @param splitName the split name
- * @return a unique name made up of the variant and split names.
- */
- @JvmStatic
- fun computeFullNameWithSplits(
- variantConfiguration: ComponentIdentity,
- componentType: ComponentType,
- splitName: String): String {
- val sb = StringBuilder()
-
- val flavorName = variantConfiguration.flavorName
-
- if (!flavorName.isNullOrEmpty()) {
- sb.append(flavorName)
- sb.appendCapitalized(splitName)
- } else {
- sb.append(splitName)
- }
-
- variantConfiguration.buildType?.let {
- sb.appendCapitalized(it)
- }
-
- if (componentType.isNestedComponent) {
- sb.append(componentType.suffix)
- }
- return sb.toString()
- }
- }
-
- private lateinit var variantName: String
- private lateinit var multiFlavorName: String
-
- val name: String
- get() {
- if (!::variantName.isInitialized) {
- computeNames()
- }
-
- return variantName
- }
-
- val flavorName: String
- get() {
- if (!::multiFlavorName.isInitialized) {
- computeNames()
- }
- return multiFlavorName
-
- }
-
- private val flavors = mutableListOf<Pair<ProductFlavor, SourceProvider>>()
-
- var variantSourceProvider: DefaultAndroidSourceSet? = null
- var multiFlavorSourceProvider: DefaultAndroidSourceSet? = null
- var productionVariant: VariantDslInfoImpl? = null
- var inconsistentTestAppId: Boolean = false
-
- fun addProductFlavor(
- productFlavor: ProductFlavor,
- sourceProvider: SourceProvider
- ) {
- if (::variantName.isInitialized) {
- throw RuntimeException("call to getName() before calling all addProductFlavor")
- }
- flavors.add(Pair(productFlavor, sourceProvider))
- }
-
- /** Creates a variant configuration */
- fun createVariantDslInfo(buildDirectory: DirectoryProperty): DslInfoT {
- val flavorList = flavors.map { it.first }
-
- val publishingInfo = if (extension is InternalLibraryExtension) {
- createPublishingInfoForLibrary(
- extension.publishing as LibraryPublishingImpl,
- dslServices.projectOptions,
- name,
- buildType,
- flavorList,
- extension.buildTypes,
- extension.productFlavors,
- testFixtureMainVariantName,
- dslServices.issueReporter
- )
- } else if (extension is InternalApplicationExtension) {
- createPublishingInfoForApp(
- extension.publishing as ApplicationPublishingImpl,
- dslServices.projectOptions,
- name,
- hasDynamicFeatures,
- dslServices.issueReporter
- )
- } else null
-
- return VariantDslInfoImpl(
- ComponentIdentityImpl(
- name,
- flavorName,
- dimensionCombination.buildType,
- dimensionCombination.productFlavors
- ),
- componentType,
- defaultConfig,
- buildType,
- // this could be removed once the product flavor is internal only.
- flavorList.toImmutableList(),
- signingConfigOverride,
- productionVariant,
- manifestDataProvider,
- dslServices,
- variantServices,
- buildDirectory,
- publishingInfo,
- experimentalProperties,
- inconsistentTestAppId,
- oldExtension,
- extension
- ) as DslInfoT
- }
-
- fun createVariantSources(): VariantSources {
- return VariantSources(
- name,
- componentType,
- defaultSourceProvider,
- buildTypeSourceProvider,
- flavors.map { it.second }.toImmutableList(),
- multiFlavorSourceProvider,
- variantSourceProvider
- )
- }
-
- /**
- * computes the name for the variant and the multi-flavor combination
- */
- private fun computeNames() {
- variantName = computeName(dimensionCombination, componentType) {
- multiFlavorName = it
- }
- }
-}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/VariantDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/VariantDslInfoImpl.kt
deleted file mode 100644
index 742cd5567f..0000000000
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/VariantDslInfoImpl.kt
+++ /dev/null
@@ -1,1218 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * 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 com.android.build.gradle.internal.core
-
-import com.android.build.api.dsl.AndroidResources
-import com.android.build.api.dsl.ApplicationBuildType
-import com.android.build.api.dsl.ApplicationProductFlavor
-import com.android.build.api.dsl.BuildType
-import com.android.build.api.dsl.CommonExtension
-import com.android.build.api.dsl.CompileOptions
-import com.android.build.api.dsl.DynamicFeatureBuildType
-import com.android.build.api.dsl.LibraryVariantDimension
-import com.android.build.api.dsl.Lint
-import com.android.build.api.dsl.PackagingOptions
-import com.android.build.api.dsl.ProductFlavor
-import com.android.build.api.dsl.TestFixtures
-import com.android.build.api.dsl.TestedExtension
-import com.android.build.api.dsl.VariantDimension
-import com.android.build.api.transform.Transform
-import com.android.build.api.variant.BuildConfigField
-import com.android.build.api.variant.ComponentIdentity
-import com.android.build.api.variant.ResValue
-import com.android.build.api.variant.impl.MutableAndroidVersion
-import com.android.build.api.variant.impl.ResValueKeyImpl
-import com.android.build.gradle.BaseExtension
-import com.android.build.gradle.ProguardFiles
-import com.android.build.gradle.api.JavaCompileOptions
-import com.android.build.gradle.internal.PostprocessingFeatures
-import com.android.build.gradle.internal.ProguardFileType
-import com.android.build.gradle.internal.core.MergedFlavor.Companion.mergeFlavors
-import com.android.build.gradle.internal.core.dsl.ApkProducingComponentDslInfo
-import com.android.build.gradle.internal.core.dsl.TestedComponentDslInfo
-import com.android.build.gradle.internal.cxx.configure.ninja
-import com.android.build.gradle.internal.dsl.BuildType.PostProcessingConfiguration
-import com.android.build.gradle.internal.dsl.CoreExternalNativeBuildOptions
-import com.android.build.gradle.internal.dsl.CoreNdkOptions
-import com.android.build.gradle.internal.dsl.DefaultConfig
-import com.android.build.gradle.internal.dsl.OptimizationImpl
-import com.android.build.gradle.internal.dsl.SigningConfig
-import com.android.build.gradle.internal.manifest.ManifestDataProvider
-import com.android.build.gradle.internal.profile.ProfilingMode
-import com.android.build.gradle.internal.publishing.VariantPublishingInfo
-import com.android.build.gradle.internal.services.DslServices
-import com.android.build.gradle.internal.services.VariantServices
-import com.android.build.gradle.internal.testFixtures.testFixturesFeatureName
-import com.android.build.gradle.options.IntegerOption
-import com.android.build.gradle.options.StringOption
-import com.android.build.gradle.options.Version
-import com.android.builder.core.AbstractProductFlavor
-import com.android.builder.core.BuilderConstants
-import com.android.builder.core.ComponentType
-import com.android.builder.dexing.DexingType
-import com.android.builder.dexing.isLegacyMultiDexMode
-import com.android.builder.errors.IssueReporter
-import com.android.builder.model.BaseConfig
-import com.android.builder.model.ClassField
-import com.android.builder.model.VectorDrawablesOptions
-import com.google.common.collect.ImmutableList
-import com.google.common.collect.ImmutableMap
-import com.google.common.collect.ImmutableSet
-import com.google.common.collect.Lists
-import com.google.common.collect.Maps
-import com.google.common.collect.Sets
-import org.gradle.api.file.DirectoryProperty
-import org.gradle.api.file.RegularFile
-import org.gradle.api.provider.ListProperty
-import org.gradle.api.provider.Property
-import org.gradle.api.provider.Provider
-import java.io.File
-import java.util.concurrent.Callable
-
-/**
- * Represents a variant, initialized from the DSL object model (default config, build type, flavors)
- *
- * This class allows querying for the values set via the DSL model.
- *
- * Use [VariantDslInfoBuilder] to instantiate.
- *
- */
-open class VariantDslInfoImpl internal constructor(
- override val componentIdentity: ComponentIdentity,
- final override val componentType: ComponentType,
- private val defaultConfig: DefaultConfig,
- /**
- * Public because this is needed by the old Variant API. Nothing else should touch this.
- */
- val buildTypeObj: BuildType,
- /** The list of product flavors. Items earlier in the list override later items. */
- override val productFlavorList: List<ProductFlavor>,
- private val signingConfigOverride: SigningConfig? = null,
- /**
- * The production variant. This is only valid for test and test fixtures variants.
- * This is mostly used to derive some property values from the parent when it's either
- * not present in the DSL for this (test/test-fixture) variant, or when it's always
- * derived from the parent (e.g. test fixture namespace).
- */
- private val productionVariant: VariantDslInfoImpl? = null,
- val dataProvider: ManifestDataProvider,
- @Deprecated("Only used for merged flavor")
- private val dslServices: DslServices,
- private val services: VariantServices,
- private val buildDirectory: DirectoryProperty,
- override val publishInfo: VariantPublishingInfo?,
- override val experimentalProperties: Map<String, Any>,
- /**
- * Whether there are inconsistent applicationId in the test.
- * This trigger a mode where the namespaceForR just returns the same as namespace.
- */
- private val inconsistentTestAppId: Boolean,
- @Deprecated("use extension") private val oldExtension: BaseExtension,
- private val extension: CommonExtension<*,*,*,*>
-): VariantDslInfo {
-
- private val dslNamespaceProvider: Provider<String>? = extension.getDslNamespace(componentType)?.let {
- services.provider {
- if (componentType.isTestComponent && extension.testNamespaceEqualsNamespace()) {
- services.issueReporter
- .reportError(
- IssueReporter.Type.GENERIC,
- "namespace and testNamespace have the same value (\"$it\"), which is not allowed."
- )
- }
- it
- }
- }
-
- override val buildType: String?
- get() = componentIdentity.buildType
- override val productFlavors: List<Pair<String, String>>
- get() = componentIdentity.productFlavors
-
- /**
- * This should be mostly private and not used outside of this class.
- * Unfortunately there are a few cases where this cannot happen.
- *
- * Still, DO NOT USE. You should mostly use [VariantDslInfo] which does not give access to this.
- */
- val mergedFlavor: MergedFlavor by lazy {
- mergeFlavors(
- defaultConfig,
- productFlavorList.map { it as com.android.build.gradle.internal.dsl.ProductFlavor },
- applicationId,
- dslServices
- )
- }
-
- /**
- * Optional tested config in case this variant is used for testing another variant.
- *
- * @see ComponentType.isTestComponent
- */
- override val testedVariant: TestedComponentDslInfo?
- get() = if (componentType.isTestComponent) { productionVariant } else null
-
- private val mergedNdkConfig = MergedNdkConfig()
- private val mergedExternalNativeBuildOptions =
- MergedExternalNativeBuildOptions()
- private val mergedJavaCompileOptions =
- dslServices.newDecoratedInstance(MergedJavaCompileOptions::class.java, dslServices)
- private val mergedAarMetadata = MergedAarMetadata()
- private val mergedOptimization = MergedOptimization()
-
- init {
- mergeOptions()
- }
-
- override fun hasFlavors(): Boolean {
- return productFlavorList.isNotEmpty()
- }
-
- // use lazy mechanism as this is referenced by other properties, like applicationId or itself
- override val namespace: Provider<String> by lazy {
- val testedVariant = testedVariant
- when {
- // -------------
- // Special case for test components
- // We first look for a value specified via the DSL - either testNamespace or namespace +
- // ".test". Otherwise, we use the package attribute from either the test manifest or the
- // main manifest (appending ".test" if from the main manifest).
- testedVariant != null -> {
- dslNamespaceProvider
- ?: extension.namespace?.let { services.provider {"$it.test" } }
- ?: testedVariant.namespace.flatMap { testedVariantNamespace ->
- dataProvider.manifestData.map { manifestData ->
- manifestData.packageName ?: "$testedVariantNamespace.test"
- }
- }
- }
-
- // -------------
- // Special case for test fixtures
- // Namespace is always derived from the parent variant's namespace
- componentType.isTestFixturesComponent -> {
- val parentVariant =
- productionVariant
- ?: throw RuntimeException("null parentVariantImpl in test-fixtures VariantDslInfoImpl")
- parentVariant.namespace.map { "$it.$testFixturesFeatureName" }
- }
-
- // -------------
- // Special case for separate test sub-projects
- // If there is no namespace from the DSL or package attribute in the manifest, we use
- // testApplicationId, if present. This allows the test project to not have a manifest if
- // all is declared in the DSL.
- // TODO(b/170945282, b/172361895) Remove this special case - users should use namespace
- // DSL instead of testApplicationId DSL for this... currently a warning
- componentType.isSeparateTestProject -> {
- if (dslNamespaceProvider != null) {
- dslNamespaceProvider
- } else {
- val testAppIdFromFlavors =
- productFlavorList.asSequence().map { it.testApplicationId }
- .firstOrNull { it != null }
- ?: defaultConfig.testApplicationId
-
- dataProvider.manifestData.map {
- it.packageName
- ?: testAppIdFromFlavors?.also {
- val message =
- "Namespace not specified. Please specify a namespace for " +
- "the generated R and BuildConfig classes via " +
- "android.namespace in the test module's " +
- "build.gradle file. Currently, this test module " +
- "uses the testApplicationId " +
- "($testAppIdFromFlavors) as its namespace, but " +
- "version ${Version.VERSION_8_0} of the Android " +
- "Gradle Plugin will require that a namespace be " +
- "specified explicitly like so:\n\n" +
- "android {\n" +
- " namespace '$testAppIdFromFlavors'\n" +
- "}\n\n"
- services.issueReporter
- .reportWarning(IssueReporter.Type.GENERIC, message)
- }
- ?: throw RuntimeException(
- getMissingPackageNameErrorMessage(dataProvider.manifestLocation)
- )
- }
- }
- }
-
- // -------------
- // All other types of projects, get it from the DSL or read it from the manifest.
- else -> dslOrManifestNamespace
- }
- }
-
- override val namespaceForR: Provider<String> by lazy {
- if (inconsistentTestAppId) {
- namespace
- } else {
- if (!componentType.isTestComponent) {
- throw RuntimeException("namespaceForR should only be used by test variants")
- }
-
- val testedVariant = productionVariant!!
-
- // For legacy reason, this code does the following:
- // - If testNamespace is set, use it.
- // - If android.namespace is set, use it with .test added
- // - else, use the variant applicationId.
- // TODO(b/176931684) Remove this and use [namespace] directly everywhere.
- dslNamespaceProvider
- ?: (testedVariant.dslNamespaceProvider?.let { it.map { "$it.test" } }
- ?: applicationId)
- }
- }
-
- // The namespace as specified by the user, either via the DSL or the `package` attribute of the
- // source AndroidManifest.xml
- private val dslOrManifestNamespace: Provider<String> by lazy {
- dslNamespaceProvider
- ?: dataProvider.manifestData.map {
- it.packageName
- ?: throw RuntimeException(
- getMissingPackageNameErrorMessage(dataProvider.manifestLocation)
- )
- }
- }
-
- private fun getMissingPackageNameErrorMessage(manifestLocation: String): String =
- "Package Name not found in $manifestLocation, and namespace not specified. Please " +
- "specify a namespace for the generated R and BuildConfig classes via " +
- "android.namespace in the module's build.gradle file like so:\n\n" +
- "android {\n" +
- " namespace 'com.example.namespace'\n" +
- "}\n\n"
-
- /**
- * Returns the application ID for this variant. This could be coming from the manifest or could
- * be overridden through the product flavors and/or the build type.
- *
- * @return the application ID
- */
- override val applicationId: Property<String> =
- services.newPropertyBackingDeprecatedApi(
- String::class.java,
- initApplicationId()
- )
-
-
- private fun initApplicationId(): Provider<String> {
- // -------------
- // Special case for test components and separate test sub-projects
- if (componentType.isForTesting) {
- // get first non null testAppId from flavors/default config
- val testAppIdFromFlavors =
- productFlavorList.asSequence().map { it.testApplicationId }
- .firstOrNull { it != null }
- ?: defaultConfig.testApplicationId
-
- return if (testAppIdFromFlavors == null) {
- (testedVariant as? ApkProducingComponentDslInfo)?.applicationId?.map {
- "$it.test"
- } ?: namespace
- } else {
- // needed to make nullability work in kotlinc
- val finalTestAppIdFromFlavors: String = testAppIdFromFlavors
- services.provider(Callable { finalTestAppIdFromFlavors })
- }
- }
-
- // -------------
- // All other project types
-
- // get first non null appId from flavors/default config
- val appIdFromFlavors =
- productFlavorList
- .asSequence()
- .filterIsInstance(ApplicationProductFlavor::class.java)
- .map { it.applicationId }
- .firstOrNull { it != null }
- ?: defaultConfig.applicationId
-
- return if (appIdFromFlavors == null) {
- // No appId value set from DSL; use the namespace value from the DSL or manifest.
- // using map will allow us to keep task dependency should the manifest be generated
- // or transformed via a task.
- dslOrManifestNamespace.map { "$it${computeApplicationIdSuffix()}" }
- } else {
- // use value from flavors/defaultConfig
- // needed to make nullability work in kotlinc
- val finalAppIdFromFlavors: String = appIdFromFlavors
- services.provider(
- Callable { "$finalAppIdFromFlavors${computeApplicationIdSuffix()}" })
- }
- }
-
- /**
- * Combines all the appId suffixes into a single one.
- *
- * The suffixes are separated by '.' whether their first char is a '.' or not.
- */
- private fun computeApplicationIdSuffix(): String {
- // for the suffix we combine the suffix from all the flavors. However, we're going to
- // want the higher priority one to be last.
- val suffixes = mutableListOf<String>()
- defaultConfig.applicationIdSuffix?.let {
- suffixes.add(it)
- }
-
- suffixes.addAll(
- productFlavorList
- .asSequence()
- .filterIsInstance(ApplicationProductFlavor::class.java)
- .mapNotNull { it.applicationIdSuffix })
-
- // then we add the build type after.
- (buildTypeObj as? ApplicationBuildType)?.applicationIdSuffix?.let {
- suffixes.add(it)
- }
- val nonEmptySuffixes = suffixes.filter { it.isNotEmpty() }
- return if (nonEmptySuffixes.isNotEmpty()) {
- ".${nonEmptySuffixes.joinToString(separator = ".", transform = { it.removePrefix(".") })}"
- } else {
- ""
- }
- }
-
- override val versionName: Provider<String?>
- get() {
- // This value is meaningless for tests
- if (componentType.isForTesting) {
- val callable: Callable<String?> = Callable { null }
- return services.provider(callable)
- }
-
- // If the version name from the flavors is null, then we read from the manifest and combine
- // with suffixes, unless it's a test at which point we just return.
- // If the name is not-null, we just combine it with suffixes
- val versionNameFromFlavors =
- productFlavorList
- .asSequence()
- .filterIsInstance(ApplicationProductFlavor::class.java)
- .map { it.versionName }
- .firstOrNull { it != null }
- ?: defaultConfig.versionName
-
- return if (versionNameFromFlavors == null) {
- // rely on manifest value
- // using map will allow us to keep task dependency should the manifest be generated or
- // transformed via a task.
- dataProvider.manifestData.map {
- if (it.versionName == null) {
- it.versionName
- } else {
- "${it.versionName}${computeVersionNameSuffix()}"
- }
- }
- } else {
- // use value from flavors
- services.provider(
- Callable { "$versionNameFromFlavors${computeVersionNameSuffix()}" })
- }
- }
-
- private fun computeVersionNameSuffix(): String {
- // for the suffix we combine the suffix from all the flavors. However, we're going to
- // want the higher priority one to be last.
- val suffixes = mutableListOf<String>()
- defaultConfig.versionNameSuffix?.let {
- suffixes.add(it)
- }
-
- suffixes.addAll(
- productFlavorList
- .asSequence()
- .filterIsInstance(ApplicationProductFlavor::class.java)
- .mapNotNull { it.versionNameSuffix })
-
- // then we add the build type after.
- (buildTypeObj as? ApplicationBuildType)?.versionNameSuffix?.let {
- suffixes.add(it)
- }
-
- return if (suffixes.isNotEmpty()) {
- suffixes.joinToString(separator = "")
- } else {
- ""
- }
- }
-
- override val versionCode: Provider<Int?>
- get() {
- // This value is meaningless for tests
- if (componentType.isForTesting) {
- val callable: Callable<Int?> = Callable { null }
- return services.provider(callable)
- }
-
- // If the version code from the flavors is null, then we read from the manifest and combine
- // with suffixes, unless it's a test at which point we just return.
- // If the name is not-null, we just combine it with suffixes
- val versionCodeFromFlavors =
- productFlavorList
- .asSequence()
- .filterIsInstance(ApplicationProductFlavor::class.java)
- .map { it.versionCode }
- .firstOrNull { it != null }
- ?: defaultConfig.versionCode
-
- return if (versionCodeFromFlavors == null) {
- // rely on manifest value
- // using map will allow us to keep task dependency should the manifest be generated or
- // transformed via a task.
- dataProvider.manifestData.map { it.versionCode }
- } else {
- // use value from flavors
- services.provider(Callable { versionCodeFromFlavors })
- }
- }
-
- override fun getInstrumentationRunner(dexingType: DexingType): Provider<String> {
- if (!componentType.isForTesting) {
- throw RuntimeException("instrumentationRunner is not available to non-test variant")
- }
-
- // first check whether the DSL has the info
- val fromFlavor =
- productFlavorList.asSequence().map { it.testInstrumentationRunner }
- .firstOrNull { it != null }
- ?: defaultConfig.testInstrumentationRunner
-
- if (fromFlavor != null) {
- val finalFromFlavor: String = fromFlavor
- return services.provider(Callable { finalFromFlavor })
- }
-
- // else return the value from the Manifest
- return dataProvider.manifestData.map {
- it.instrumentationRunner
- ?: if (dexingType.isLegacyMultiDexMode()) {
- MULTIDEX_TEST_RUNNER
- } else {
- DEFAULT_TEST_RUNNER
- }
- }
- }
-
- /**
- * Returns the instrumentationRunner arguments to use to test this variant, or if the variant is
- * a test, the ones to use to test the tested variant
- */
- override val instrumentationRunnerArguments: Map<String, String>
- get() {
- val variantDslInfo: VariantDslInfoImpl =
- if (componentType.isTestComponent) {
- productionVariant!!
- } else {
- this
- }
- return variantDslInfo.mergedFlavor.testInstrumentationRunnerArguments
- }
-
- override val handleProfiling: Provider<Boolean>
- get() {
- if (!componentType.isForTesting) {
- throw RuntimeException("handleProfiling is not available to non-test variant")
- }
-
- // first check whether the DSL has the info
- val fromFlavor =
- productFlavorList.asSequence().map { it.testHandleProfiling }
- .firstOrNull { it != null }
- ?: defaultConfig.testHandleProfiling
-
- if (fromFlavor != null) {
- val finalFromFlavor: Boolean = fromFlavor
- return services.provider(Callable { finalFromFlavor })
- }
-
- // else return the value from the Manifest
- return dataProvider.manifestData.map { it.handleProfiling ?: DEFAULT_HANDLE_PROFILING }
- }
-
- override val functionalTest: Provider<Boolean>
- get() {
- if (!componentType.isForTesting) {
- throw RuntimeException("functionalTest is not available to non-test variant")
- }
-
- // first check whether the DSL has the info
- val fromFlavor =
- productFlavorList.asSequence().map { it.testFunctionalTest }
- .firstOrNull { it != null }
- ?: defaultConfig.testFunctionalTest
-
- if (fromFlavor != null) {
- val finalFromFlavor: Boolean = fromFlavor
- return services.provider(Callable { finalFromFlavor })
- }
-
- // else return the value from the Manifest
- return dataProvider.manifestData.map { it.functionalTest ?: DEFAULT_FUNCTIONAL_TEST }
- }
-
- override val testLabel: Provider<String?>
- get() {
- if (!componentType.isForTesting) {
- throw RuntimeException("handleProfiling is not available to non-test variant")
- }
-
- // there is actually no DSL value for this.
- return dataProvider.manifestData.map { it.testLabel }
- }
-
- /**
- * The minSdkVersion for this variant.
- *
- * This is only the version declared in the DSL, not including the value present in the Manifest.
- */
- override val minSdkVersion: MutableAndroidVersion
- // if there's a testedVariant, return its value, otherwise return the merged flavor
- // value. If there's no value set, then the default is just the first API Level: 1
- get() = testedVariant?.minSdkVersion
- ?: mergedFlavor.minSdkVersion?.let { MutableAndroidVersion(it.apiLevel, it.codename) }
- ?: MutableAndroidVersion(1)
-
- override val maxSdkVersion: Int?
- get() = mergedFlavor.maxSdkVersion
-
- /**
- * The targetSdkVersion for this variant.
- *
- * This is only the version declared in the DSL, not including the value present in the Manifest.
- */
- override val targetSdkVersion: MutableAndroidVersion?
- // if there's a testedVariant, return its value, otherwise return the merged flavor
- // value. If there's no value set, then return null
- get() = testedVariant?.targetSdkVersion
- ?: mergedFlavor.targetSdkVersion?.let { MutableAndroidVersion(it.apiLevel, it.codename) }
-
- override val renderscriptTarget: Int = mergedFlavor.renderscriptTargetApi ?: -1
-
- override val isWearAppUnbundled: Boolean?
- get() = mergedFlavor.wearAppUnbundled
-
- @Suppress("DEPRECATION")
- override val missingDimensionStrategies: ImmutableMap<String, AbstractProductFlavor.DimensionRequest>
- get() = ImmutableMap.copyOf(mergedFlavor.missingDimensionStrategies)
-
- override val resourceConfigurations: ImmutableSet<String>
- get() = ImmutableSet.copyOf(mergedFlavor.resourceConfigurations)
-
- override val vectorDrawables: VectorDrawablesOptions
- get() = mergedFlavor.vectorDrawables
-
- override fun getBuildConfigFields(): Map<String, BuildConfigField<out java.io.Serializable>> {
- val buildConfigFieldsMap =
- mutableMapOf<String, BuildConfigField<out java.io.Serializable>>()
-
- fun addToListIfNotAlreadyPresent(classField: ClassField, comment: String) {
- if (!buildConfigFieldsMap.containsKey(classField.name)) {
- buildConfigFieldsMap[classField.name] =
- BuildConfigField(classField.type , classField.value, comment)
- }
- }
-
- (buildTypeObj as com.android.build.gradle.internal.dsl.BuildType).buildConfigFields.values.forEach { classField ->
- addToListIfNotAlreadyPresent(classField, "Field from build type: ${buildTypeObj.name}")
- }
-
- for (flavor in productFlavorList) {
- (flavor as com.android.build.gradle.internal.dsl.ProductFlavor).buildConfigFields.values.forEach { classField ->
- addToListIfNotAlreadyPresent(
- classField,
- "Field from product flavor: ${flavor.name}"
- )
- }
- }
- defaultConfig.buildConfigFields.values.forEach { classField ->
- addToListIfNotAlreadyPresent(classField, "Field from default config.")
- }
- return buildConfigFieldsMap
- }
-
- /**
- * Returns a list of generated resource values.
- *
- *
- * Items can be either fields (instance of [com.android.builder.model.ClassField]) or
- * comments (instance of String).
- *
- * @return a list of items.
- */
- override fun getResValues(): Map<ResValue.Key, ResValue> {
- val resValueFields = mutableMapOf<ResValue.Key, ResValue>()
-
- fun addToListIfNotAlreadyPresent(classField: ClassField, comment: String) {
- val key = ResValueKeyImpl(classField.type, classField.name)
- if (!resValueFields.containsKey(key)) {
- resValueFields[key] = ResValue(
- value = classField.value,
- comment = comment
- )
- }
- }
-
- (buildTypeObj as com.android.build.gradle.internal.dsl.BuildType).resValues.values.forEach { classField ->
- addToListIfNotAlreadyPresent(classField, "Value from build type: ${buildTypeObj.name}")
- }
-
- productFlavorList.forEach { flavor ->
- (flavor as com.android.build.gradle.internal.dsl.ProductFlavor).resValues.values.forEach { classField ->
- addToListIfNotAlreadyPresent(
- classField,
- "Value from product flavor: ${flavor.name}"
- )
- }
- }
-
- defaultConfig.resValues.values.forEach { classField ->
- addToListIfNotAlreadyPresent(classField, "Value from default config.")
- }
-
- return resValueFields
- }
-
- override val signingConfig: SigningConfig?
- get() {
- if (componentType.isDynamicFeature ||
- testedVariant?.componentType?.isDynamicFeature == true
- ) {
- return null
- }
- val dslSigningConfig =
- (buildTypeObj as? ApplicationBuildType)?.signingConfig
- ?: mergedFlavor.signingConfig
-
- signingConfigOverride?.let {
- // use enableV1 and enableV2 from the DSL if the override values are null
- if (it.enableV1Signing == null) {
- it.enableV1Signing = dslSigningConfig?.enableV1Signing
- }
- if (it.enableV2Signing == null) {
- it.enableV2Signing = dslSigningConfig?.enableV2Signing
- }
- // use enableV3 and enableV4 from the DSL because they're not injectable
- it.enableV3Signing = dslSigningConfig?.enableV3Signing
- it.enableV4Signing = dslSigningConfig?.enableV4Signing
- return it
- }
- if (dslSigningConfig == null && (isProfileable || isDebuggable)) {
- return extension.signingConfigs.findByName(BuilderConstants.DEBUG) as SigningConfig?
- }
- return dslSigningConfig as SigningConfig?
- }
-
- override val isSigningReady: Boolean
- get() {
- val signingConfig = signingConfig
- return signingConfig != null && signingConfig.isSigningReady
- }
-
- override val isAndroidTestCoverageEnabled: Boolean
- get() = buildTypeObj.enableAndroidTestCoverage || buildTypeObj.isTestCoverageEnabled
-
- override val isUnitTestCoverageEnabled: Boolean
- get() = buildTypeObj.enableUnitTestCoverage || buildTypeObj.isTestCoverageEnabled
-
- /**
- * Returns the merged manifest placeholders. All product flavors are merged first, then build
- * type specific placeholders are added and potentially overrides product flavors values.
- *
- * @return the merged manifest placeholders for a build variant.
- */
- override val manifestPlaceholders: Map<String, String> by lazy {
- val mergedFlavorsPlaceholders: MutableMap<String, String> = mutableMapOf()
- mergedFlavor.manifestPlaceholders.forEach { (key, value) ->
- mergedFlavorsPlaceholders[key] = value.toString()
- }
- // so far, blindly override the build type placeholders
- buildTypeObj.manifestPlaceholders.forEach { (key, value) ->
- mergedFlavorsPlaceholders[key] = value.toString()
- }
- mergedFlavorsPlaceholders
- }
-
- // Only require specific multidex opt-in for legacy multidex.
- override val isMultiDexEnabled: Boolean?
- get() {
- // Only require specific multidex opt-in for legacy multidex.
- return (buildTypeObj as? ApplicationBuildType)?.multiDexEnabled
- ?: mergedFlavor.multiDexEnabled
- }
-
- override val multiDexKeepFile: File?
- get() {
- var value = buildTypeObj.multiDexKeepFile
- if (value != null) {
- return value
- }
- value = mergedFlavor.multiDexKeepFile
- return value
- }
-
- override val multiDexKeepProguard: File?
- get() {
- var value = buildTypeObj.multiDexKeepProguard
- if (value != null) {
- return value
- }
- value = mergedFlavor.multiDexKeepProguard
- return value
- }
-
- // dynamic features can always be build in native multidex mode
- override val dexingType: DexingType?
- get() = if (componentType.isDynamicFeature) {
- if ((buildTypeObj as? ApplicationBuildType)?.multiDexEnabled != null ||
- mergedFlavor.multiDexEnabled != null
- ) {
- dslServices.issueReporter
- .reportWarning(
- IssueReporter.Type.GENERIC,
- "Native multidex is always used for dynamic features. Please " +
- "remove 'multiDexEnabled true|false' from your " +
- "build.gradle file."
- )
- }
- // dynamic features can always be build in native multidex mode
- DexingType.NATIVE_MULTIDEX
- } else null
-
- /** Returns the renderscript support mode. */
- override val renderscriptSupportModeEnabled: Boolean
- get() = mergedFlavor.renderscriptSupportModeEnabled ?: false
-
- /** Returns the renderscript BLAS support mode. */
- override val renderscriptSupportModeBlasEnabled: Boolean
- get() {
- val value = mergedFlavor.renderscriptSupportModeBlasEnabled
- return value ?: false
- }
-
- /** Returns the renderscript NDK mode. */
- override val renderscriptNdkModeEnabled: Boolean
- get() = mergedFlavor.renderscriptNdkModeEnabled ?: false
-
- /** Returns true if the variant output is a bundle. */
- override val isBundled: Boolean
- get() = componentType.isAar // Consider runtime API passed from the IDE only if multi-dex is enabled and the app is debuggable.
-
- /**
- * Returns the API to which device/emulator we're deploying via the IDE or null if not.
- * Can be used to optimize some build steps when deploying via the IDE (for testing).
- *
- * This has no relation with targetSdkVersion from build.gradle/manifest.
- */
- override val targetDeployApiFromIDE: Int? =
- dslServices.projectOptions.get(IntegerOption.IDE_TARGET_DEVICE_API)
-
- /**
- * Merge Gradle specific options from build types, product flavors and default config.
- */
- private fun mergeOptions() {
- computeMergedOptions(
- mergedJavaCompileOptions,
- { javaCompileOptions as JavaCompileOptions },
- { javaCompileOptions as JavaCompileOptions }
- )
- computeMergedOptions(
- mergedNdkConfig,
- { ndk as CoreNdkOptions },
- { ndk as CoreNdkOptions }
- )
- computeMergedOptions(
- mergedExternalNativeBuildOptions,
- { externalNativeBuild as CoreExternalNativeBuildOptions },
- { externalNativeBuild as CoreExternalNativeBuildOptions }
- )
- if (componentType.isAar) {
- computeMergedOptions(
- mergedAarMetadata,
- { (this as LibraryVariantDimension).aarMetadata },
- { (this as LibraryVariantDimension).aarMetadata }
- )
- }
- computeMergedOptions(
- mergedOptimization,
- { optimization as OptimizationImpl },
- { optimization as OptimizationImpl }
- )
- }
-
- override val nativeBuildSystem: NativeBuiltType?
- get() {
- if (externalNativeExperimentalProperties.ninja.path != null) return NativeBuiltType.NINJA
- if (extension.externalNativeBuild.ndkBuild.path != null) return NativeBuiltType.NDK_BUILD
- if (extension.externalNativeBuild.cmake.path != null) return NativeBuiltType.CMAKE
- return null
- }
-
- override val ndkConfig: MergedNdkConfig
- get() = mergedNdkConfig
-
- override val externalNativeBuildOptions: CoreExternalNativeBuildOptions
- get() = mergedExternalNativeBuildOptions
-
- override val aarMetadata: MergedAarMetadata
- get() = mergedAarMetadata
-
- /**
- * Returns the ABI filters associated with the artifact, or empty set if there are no filters.
- *
- * If the list contains values, then the artifact only contains these ABIs and excludes
- * others.
- */
- override val supportedAbis: Set<String>
- get() = if (componentType.isDynamicFeature) setOf() else mergedNdkConfig.abiFilters
-
- override fun getProguardFiles(into: ListProperty<RegularFile>) {
- val result: MutableList<File> = ArrayList(gatherProguardFiles(ProguardFileType.EXPLICIT))
- if (result.isEmpty()) {
- result.addAll(_postProcessingOptions.getDefaultProguardFiles())
- }
-
- val projectDir = services.projectInfo.projectDirectory
- result.forEach { file ->
- into.add(projectDir.file(file.absolutePath))
- }
- }
-
- override fun gatherProguardFiles(type: ProguardFileType): Collection<File> {
- val result: MutableList<File> = ArrayList(defaultConfig.getProguardFiles(type))
- for (flavor in productFlavorList) {
- result.addAll((flavor as com.android.build.gradle.internal.dsl.ProductFlavor).getProguardFiles(type))
- }
- result.addAll(_postProcessingOptions.getProguardFiles(type))
- return result
- }
-
- /**
- * Merge a specific option in GradleVariantConfiguration.
- *
- *
- * It is assumed that merged option type with a method to reset and append is created for the
- * option being merged.
- *
- *
- * The order of priority is BuildType, ProductFlavors, and default config. ProductFlavor
- * added earlier has higher priority than ProductFlavor added later.
- *
- * @param mergedOption The merged option store in the GradleVariantConfiguration.
- * @param getFlavorOption A Function to return the option from a ProductFlavor.
- * @param getBuildTypeOption A Function to return the option from a BuildType.
- * takes priority and overwrite option in the first input argument.
- * @param <CoreOptionsT> The core type of the option being merge.
- * @param <MergedOptionsT> The merge option type.
- </MergedOptionsT></CoreOptionsT> */
- private fun <CoreOptionsT, MergedOptionsT : MergedOptions<CoreOptionsT>> computeMergedOptions(
- mergedOption: MergedOptionsT,
- getFlavorOption: VariantDimension.() -> CoreOptionsT?,
- getBuildTypeOption: BuildType.() -> CoreOptionsT?
- ) {
- mergedOption.reset()
-
- val defaultOption = defaultConfig.getFlavorOption()
- if (defaultOption != null) {
- mergedOption.append(defaultOption)
- }
- // reverse loop for proper order
- for (i in productFlavorList.indices.reversed()) {
- val flavorOption = productFlavorList[i].getFlavorOption()
- if (flavorOption != null) {
- mergedOption.append(flavorOption)
- }
- }
- val buildTypeOption = buildTypeObj.getBuildTypeOption()
- if (buildTypeOption != null) {
- mergedOption.append(buildTypeOption)
- }
- }
-
- override val javaCompileOptions: JavaCompileOptions
- get() = mergedJavaCompileOptions
-
- private var _postProcessingOptions: PostProcessingOptions =
- if ((buildTypeObj as com.android.build.gradle.internal.dsl.BuildType).postProcessingConfiguration == PostProcessingConfiguration.POSTPROCESSING_BLOCK) {
- PostProcessingBlockOptions(
- buildTypeObj.postprocessing, componentType.isTestComponent
- )
- } else object : PostProcessingOptions {
- override fun getProguardFiles(type: ProguardFileType): Collection<File> =
- buildTypeObj.getProguardFiles(type)
-
- override fun getDefaultProguardFiles(): List<File> =
- listOf(
- ProguardFiles.getDefaultProguardFile(
- ProguardFiles.ProguardFile.DONT_OPTIMIZE.fileName,
- buildDirectory
- )
- )
-
- override fun getPostprocessingFeatures(): PostprocessingFeatures? = null
-
- override fun codeShrinkerEnabled() = buildTypeObj.isMinifyEnabled
-
- override fun resourcesShrinkingEnabled(): Boolean = buildTypeObj.isShrinkResources
-
- override fun hasPostProcessingConfiguration() = false
- }
-
- override fun getPostProcessingOptions(): PostProcessingOptions = _postProcessingOptions
-
- // add the lower priority one, to override them with the higher priority ones.
- // cant use merge flavor as it's not a prop on the base class.
- // reverse loop for proper order
- override val defaultGlslcArgs: List<String>
- get() {
- val optionMap: MutableMap<String, String> =
- Maps.newHashMap()
- // add the lower priority one, to override them with the higher priority ones.
- for (option in defaultConfig.shaders.glslcArgs) {
- optionMap[getKey(option)] = option
- }
- // cant use merge flavor as it's not a prop on the base class.
- // reverse loop for proper order
- for (i in productFlavorList.indices.reversed()) {
- for (option in productFlavorList[i].shaders.glslcArgs) {
- optionMap[getKey(option)] = option
- }
- }
- // then the build type
- for (option in buildTypeObj.shaders.glslcArgs) {
- optionMap[getKey(option)] = option
- }
- return Lists.newArrayList(optionMap.values)
- }
-
- // first collect all possible keys.
- override val scopedGlslcArgs: Map<String, List<String>>
- get() {
- val scopedArgs: MutableMap<String, List<String>> =
- Maps.newHashMap()
- // first collect all possible keys.
- val keys = scopedGlslcKeys
- for (key in keys) { // first add to a temp map to resolve overridden values
- val optionMap: MutableMap<String, String> =
- Maps.newHashMap()
- // we're going to go from lower priority, to higher priority elements, and for each
- // start with the non scoped version, and then add the scoped version.
- // 1. default config, global.
- for (option in defaultConfig.shaders.glslcArgs) {
- optionMap[getKey(option)] = option
- }
- // 1b. default config, scoped.
- for (option in defaultConfig.shaders.scopedGlslcArgs[key]) {
- optionMap[getKey(option)] = option
- }
- // 2. the flavors.
- // cant use merge flavor as it's not a prop on the base class.
- // reverse loop for proper order
- for (i in productFlavorList.indices.reversed()) { // global
- for (option in productFlavorList[i].shaders.glslcArgs) {
- optionMap[getKey(option)] = option
- }
- // scoped.
- for (option in productFlavorList[i].shaders.scopedGlslcArgs[key]) {
- optionMap[getKey(option)] = option
- }
- }
- // 3. the build type, global
- for (option in buildTypeObj.shaders.glslcArgs) {
- optionMap[getKey(option)] = option
- }
- // 3b. the build type, scoped.
- for (option in buildTypeObj.shaders.scopedGlslcArgs[key]) {
- optionMap[getKey(option)] = option
- }
- // now add the full value list.
- scopedArgs[key] = ImmutableList.copyOf(optionMap.values)
- }
- return scopedArgs
- }
-
- private val scopedGlslcKeys: Set<String>
- get() {
- val keys: MutableSet<String> =
- Sets.newHashSet()
- keys.addAll(defaultConfig.shaders.scopedGlslcArgs.keySet())
- for (flavor in productFlavorList) {
- keys.addAll(flavor.shaders.scopedGlslcArgs.keySet())
- }
- keys.addAll(buildTypeObj.shaders.scopedGlslcArgs.keySet())
- return keys
- }
-
- override val isDebuggable: Boolean
- get() = ProfilingMode.getProfilingModeType(
- services.projectOptions[StringOption.PROFILING_MODE]
- ).isDebuggable
- ?: (buildTypeObj as? ApplicationBuildType)?.isDebuggable
- ?: false
-
- override val isEmbedMicroApp: Boolean
- get() = (buildTypeObj as? ApplicationBuildType)?.isEmbedMicroApp ?: false
-
- override val isProfileable: Boolean
- get() {
- val fromProfilingModeOption = ProfilingMode.getProfilingModeType(
- services.projectOptions[StringOption.PROFILING_MODE]
- ).isProfileable
- val fromBuildType = (buildTypeObj as? ApplicationBuildType)?.isProfileable
- // When profileable is enabled from the profilingMode option, it ensures all profileable
- // features are supported, therefore the compileSdk => 30.
- val minProfileableSdk = 30
- val compileSdk = extension.compileSdk ?: minProfileableSdk
- if ((fromProfilingModeOption == true || fromBuildType == true)
- && compileSdk < minProfileableSdk
- ) {
- services.issueReporter.reportError(IssueReporter.Type.COMPILE_SDK_VERSION_TOO_LOW,
- """'profileable' is enabled with compile SDK <30.
- Recommended action: If possible, upgrade compileSdk from ${minSdkVersion.apiLevel} to 30."""
- .trimIndent()
- )
- }
- return when {
- fromProfilingModeOption != null -> {
- fromProfilingModeOption
- }
- fromBuildType == true && isDebuggable -> {
- val projectName = services.projectInfo.name
- val message =
- ":$projectName build type '${buildTypeObj.name}' can only have debuggable or profileable enabled.\n" +
- "Only one of these options can be used at a time.\n" +
- "Recommended action: Only set one of debuggable=true and profileable=true.\n"
- services.issueReporter.reportWarning(IssueReporter.Type.GENERIC, message)
- // Disable profileable when profileable and debuggable are both enabled.
- false
- }
- else -> {
- fromBuildType == true
- }
- }
- }
-
- override val isPseudoLocalesEnabled: Boolean
- get() = buildTypeObj.isPseudoLocalesEnabled
-
- override val isCrunchPngs: Boolean?
- get() {
- return when (buildTypeObj) {
- is ApplicationBuildType -> buildTypeObj.isCrunchPngs
- is DynamicFeatureBuildType -> buildTypeObj.isCrunchPngs
- else -> false
- }
- }
-
- @Suppress("OverridingDeprecatedMember", "DEPRECATION")
- override val isCrunchPngsDefault: Boolean
- // does not exist in the new DSL
- get() = (buildTypeObj as com.android.build.gradle.internal.dsl.BuildType).isCrunchPngsDefault
-
- override val isRenderscriptDebuggable: Boolean
- get() = buildTypeObj.isRenderscriptDebuggable
-
- override val renderscriptOptimLevel: Int
- get() = buildTypeObj.renderscriptOptimLevel
-
- override val isJniDebuggable: Boolean
- get() = buildTypeObj.isJniDebuggable
-
- override val testFixtures: TestFixtures
- get() {
- if (extension is TestedExtension) {
- return extension.testFixtures
- }
-
- throw RuntimeException("call to VariantDslInfo.testFixtures on wrong extension type: ${extension.javaClass.name}")
- }
-
- override val androidResources: AndroidResources
- get() = extension.androidResources
-
- override val packaging: PackagingOptions
- get() = extension.packagingOptions
-
- override val compileOptions: CompileOptions
- get() = extension.compileOptions
-
- // when we remove the old DSL (and the old Transforms API) this should be deleted as well.
- override val transforms: List<Transform>
- get() = oldExtension.transforms
-
- override val lintOptions: Lint
- get() = extension.lint
-
- override val ignoredLibraryKeepRules: Set<String>
- get() = mergedOptimization.ignoredLibraryKeepRules
-
- override val ignoreAllLibraryKeepRules: Boolean
- get() = mergedOptimization.ignoreAllLibraryKeepRules
-
- override val externalNativeExperimentalProperties: Map<String, Any>
- get() {
- // merge global and variant properties
- val mergedProperties = mutableMapOf<String, Any>()
- mergedProperties.putAll(extension.externalNativeBuild.experimentalProperties)
- mergedProperties.putAll(
- mergedExternalNativeBuildOptions.externalNativeExperimentalProperties
- )
- return mergedProperties
- }
-
- // Only applicable for testFixtures
- // TODO: Remove once we split up the implementations
- override val testFixturesAndroidResourcesEnabled: Boolean
- get() = productionVariant!!.testFixtures.androidResources
-
- companion object {
-
- const val DEFAULT_TEST_RUNNER = "android.test.InstrumentationTestRunner"
- private const val MULTIDEX_TEST_RUNNER =
- "com.android.test.runner.MultiDexTestRunner"
- private const val DEFAULT_HANDLE_PROFILING = false
- private const val DEFAULT_FUNCTIONAL_TEST = false
-
- private fun getKey(fullOption: String): String {
- val pos = fullOption.lastIndexOf('=')
- return if (pos == -1) {
- fullOption
- } else fullOption.substring(0, pos)
- }
-
- private fun CommonExtension<*, *, *, *>.getDslNamespace(componentType: ComponentType): String? {
- return if (componentType.isTestComponent) {
- (this as TestedExtension).testNamespace
- } else if (componentType.isTestFixturesComponent) {
- null
- } else {
- namespace
- }
- }
-
- private fun CommonExtension<*, *, *, *>.testNamespaceEqualsNamespace(): Boolean =
- this is TestedExtension && testNamespace != null && testNamespace == namespace
- }
-}
-
-private fun BaseConfig.getProguardFiles(type: ProguardFileType): Collection<File> = when (type) {
- ProguardFileType.EXPLICIT -> this.proguardFiles
- ProguardFileType.TEST -> this.testProguardFiles
- ProguardFileType.CONSUMER -> this.consumerProguardFiles
-}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/AarProducingComponentDslInfo.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/AarProducingComponentDslInfo.kt
index 18d6ab66ae..c5759805ff 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/AarProducingComponentDslInfo.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/AarProducingComponentDslInfo.kt
@@ -16,13 +16,8 @@
package com.android.build.gradle.internal.core.dsl
-import com.android.build.gradle.internal.core.MergedAarMetadata
-
/**
* Contains the final dsl info computed from the DSL object model (extension, default config,
* build type, flavors) that are needed by components that produces AARs.
*/
-interface AarProducingComponentDslInfo {
-
- val aarMetadata: MergedAarMetadata
-}
+interface AarProducingComponentDslInfo
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/AndroidTestComponentDslInfo.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/AndroidTestComponentDslInfo.kt
index 0fe5697f5a..9221ef6e74 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/AndroidTestComponentDslInfo.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/AndroidTestComponentDslInfo.kt
@@ -24,7 +24,7 @@ import org.gradle.api.provider.Provider
*
* This class allows querying for the values set via the DSL model.
*
- * Use [VariantDslInfoBuilder] to instantiate.
+ * Use [DslInfoBuilder] to instantiate.
*
* @see [com.android.build.gradle.internal.component.AndroidTestCreationConfig]
*/
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/ApkProducingComponentDslInfo.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/ApkProducingComponentDslInfo.kt
index d8b294e267..e587247846 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/ApkProducingComponentDslInfo.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/ApkProducingComponentDslInfo.kt
@@ -27,8 +27,6 @@ interface ApkProducingComponentDslInfo: ConsumableComponentDslInfo {
val isDebuggable: Boolean
- val isProfileable: Boolean
-
/** Holds all SigningConfig information from the DSL and/or [ProjectOptions]. */
val signingConfig: SigningConfig?
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/ApplicationVariantDslInfo.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/ApplicationVariantDslInfo.kt
index 48de74ae04..7b3c51a2cb 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/ApplicationVariantDslInfo.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/ApplicationVariantDslInfo.kt
@@ -24,11 +24,11 @@ import org.gradle.api.provider.Provider
*
* This class allows querying for the values set via the DSL model.
*
- * Use [VariantDslInfoBuilder] to instantiate.
+ * Use [DslInfoBuilder] to instantiate.
*
* @see [com.android.build.gradle.internal.component.ApplicationCreationConfig]
*/
-interface ApplicationVariantDslInfo: VariantDslInfo, ApkProducingComponentDslInfo, PublishableVariantDslInfo, TestedComponentDslInfo {
+interface ApplicationVariantDslInfo: VariantDslInfo, ApkProducingComponentDslInfo, PublishableComponentDslInfo, TestedVariantDslInfo {
/**
* Returns the version name for this variant. This could be specified by the product flavors,
@@ -50,4 +50,6 @@ interface ApplicationVariantDslInfo: VariantDslInfo, ApkProducingComponentDslInf
val isWearAppUnbundled: Boolean?
val isEmbedMicroApp: Boolean
+
+ val isProfileable: Boolean
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/ComponentDslInfo.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/ComponentDslInfo.kt
index 9698bc680e..0349ec1e2b 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/ComponentDslInfo.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/ComponentDslInfo.kt
@@ -48,8 +48,6 @@ interface ComponentDslInfo: DimensionCombination {
/** The list of product flavors. Items earlier in the list override later items. */
val productFlavorList: List<ProductFlavor>
- fun hasFlavors(): Boolean
-
val missingDimensionStrategies: ImmutableMap<String, AbstractProductFlavor.DimensionRequest>
/**
@@ -128,23 +126,12 @@ interface ComponentDslInfo: DimensionCombination {
*/
fun getResValues(): Map<ResValue.Key, ResValue>
- /**
- * Returns the merged manifest placeholders. All product flavors are merged first, then build
- * type specific placeholders are added and potentially overrides product flavors values.
- *
- * @return the merged manifest placeholders for a build variant.
- */
- val manifestPlaceholders: Map<String, String>
-
- fun getPostProcessingOptions(): PostProcessingOptions
+ val postProcessingOptions: PostProcessingOptions
/**
- * TODO: Clean this up
+ * TODO(b/242515559): Clean this up
*/
val isAndroidTestCoverageEnabled: Boolean
fun gatherProguardFiles(type: ProguardFileType): Collection<File>
-
- // TODO: Move to VariantDslInfo
- val experimentalProperties: Map<String, Any>
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/ConsumableComponentDslInfo.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/ConsumableComponentDslInfo.kt
index 5d9da953b5..bae52ffbb2 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/ConsumableComponentDslInfo.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/ConsumableComponentDslInfo.kt
@@ -78,4 +78,12 @@ interface ConsumableComponentDslInfo: ComponentDslInfo {
* @return a list of items.
*/
fun getBuildConfigFields(): Map<String, BuildConfigField<out Serializable>>
+
+ /**
+ * Returns the merged manifest placeholders. All product flavors are merged first, then build
+ * type specific placeholders are added and potentially overrides product flavors values.
+ *
+ * @return the merged manifest placeholders for a build variant.
+ */
+ val manifestPlaceholders: Map<String, String>
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/DynamicFeatureVariantDslInfo.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/DynamicFeatureVariantDslInfo.kt
index 6759364f3a..bbd20ad14e 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/DynamicFeatureVariantDslInfo.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/DynamicFeatureVariantDslInfo.kt
@@ -16,19 +16,19 @@
package com.android.build.gradle.internal.core.dsl
-import com.android.builder.dexing.DexingType
-
/**
* Represents the dsl info for a dynamic feature variant, initialized from the DSL object model
* (extension, default config, build type, flavors)
*
* This class allows querying for the values set via the DSL model.
*
- * Use [VariantDslInfoBuilder] to instantiate.
+ * Use [DslInfoBuilder] to instantiate.
*
* @see [com.android.build.gradle.internal.component.DynamicFeatureCreationConfig]
*/
-interface DynamicFeatureVariantDslInfo: VariantDslInfo, ApkProducingComponentDslInfo, TestedComponentDslInfo {
- // dynamic features can always be build in native multidex mode
- val dexingType: DexingType?
+interface DynamicFeatureVariantDslInfo:
+ VariantDslInfo,
+ ApkProducingComponentDslInfo,
+ TestedVariantDslInfo {
+ val isMultiDexSetFromDsl: Boolean
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/InstrumentedTestComponentDslInfo.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/InstrumentedTestComponentDslInfo.kt
index 282b2dd21e..43f4ff2b37 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/InstrumentedTestComponentDslInfo.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/InstrumentedTestComponentDslInfo.kt
@@ -32,14 +32,12 @@ interface InstrumentedTestComponentDslInfo {
* @param dexingType the selected dexing type for this variant.
* @return the instrumentation test runner name
*/
- // DO NOT USE, Use CreationConfig and subtypes methods.
fun getInstrumentationRunner(dexingType: DexingType): Provider<String>
/**
* Returns the instrumentationRunner arguments to use to test this variant, or if the variant is
* a test, the ones to use to test the tested variant
*/
- // DO NOT USE, Use CreationConfig and subtypes methods.
val instrumentationRunnerArguments: Map<String, String>
/**
@@ -48,7 +46,6 @@ interface InstrumentedTestComponentDslInfo {
*
* @return the handleProfiling value
*/
- // DO NOT USE, Use CreationConfig and subtypes methods.
val handleProfiling: Provider<Boolean>
/**
@@ -57,10 +54,8 @@ interface InstrumentedTestComponentDslInfo {
*
* @return the functionalTest value
*/
- // DO NOT USE, Use CreationConfig and subtypes methods.
val functionalTest: Provider<Boolean>
/** Gets the test label for this variant */
- // DO NOT USE, Use CreationConfig and subtypes methods.
val testLabel: Provider<String?>
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/LibraryVariantDslInfo.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/LibraryVariantDslInfo.kt
index fef5fdcb60..87cb3b2078 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/LibraryVariantDslInfo.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/LibraryVariantDslInfo.kt
@@ -16,19 +16,21 @@
package com.android.build.gradle.internal.core.dsl
+import com.android.build.gradle.internal.core.MergedAarMetadata
+
/**
* Represents the dsl info for a library variant, initialized from the DSL object model
* (extension, default config, build type, flavors)
*
* This class allows querying for the values set via the DSL model.
*
- * Use [VariantDslInfoBuilder] to instantiate.
+ * Use [DslInfoBuilder] to instantiate.
*
* @see [com.android.build.gradle.internal.component.LibraryCreationConfig]
*/
-interface LibraryVariantDslInfo: VariantDslInfo, AarProducingComponentDslInfo, PublishableVariantDslInfo, TestedComponentDslInfo {
+interface LibraryVariantDslInfo: VariantDslInfo, AarProducingComponentDslInfo, PublishableComponentDslInfo, TestedVariantDslInfo {
+ val aarMetadata: MergedAarMetadata
// TODO: Clean this up
val isDebuggable: Boolean
- val isProfileable: Boolean
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/PublishableVariantDslInfo.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/PublishableComponentDslInfo.kt
index 31c7e070b1..defe4181ca 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/PublishableVariantDslInfo.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/PublishableComponentDslInfo.kt
@@ -22,7 +22,6 @@ import com.android.build.gradle.internal.publishing.VariantPublishingInfo
* Contains the final dsl info computed from the DSL object model (extension, default config,
* build type, flavors) that are needed by publishable components.
*/
-interface PublishableVariantDslInfo {
- // TODO: Remove nullability when implementation is split up
- val publishInfo: VariantPublishingInfo?
+interface PublishableComponentDslInfo {
+ val publishInfo: VariantPublishingInfo
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/TestComponentDslInfo.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/TestComponentDslInfo.kt
index 8071949d4e..599d5e6a28 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/TestComponentDslInfo.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/TestComponentDslInfo.kt
@@ -28,6 +28,5 @@ interface TestComponentDslInfo: ComponentDslInfo {
*
* @see ComponentType.isTestComponent
*/
- // TODO: remove nullability when implementation is split up
- val testedVariant: TestedComponentDslInfo?
+ val testedVariantDslInfo: TestedVariantDslInfo
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/TestFixturesComponentDslInfo.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/TestFixturesComponentDslInfo.kt
index a5de5c482b..e7f27364e6 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/TestFixturesComponentDslInfo.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/TestFixturesComponentDslInfo.kt
@@ -22,10 +22,11 @@ package com.android.build.gradle.internal.core.dsl
*
* This class allows querying for the values set via the DSL model.
*
- * Use [VariantDslInfoBuilder] to instantiate.
+ * Use [DslInfoBuilder] to instantiate.
*
* @see [com.android.build.gradle.internal.component.TestFixturesCreationConfig]
*/
-interface TestFixturesComponentDslInfo: VariantDslInfo, AarProducingComponentDslInfo {
+interface TestFixturesComponentDslInfo
+ : ComponentDslInfo, AarProducingComponentDslInfo, PublishableComponentDslInfo {
val testFixturesAndroidResourcesEnabled: Boolean
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/TestProjectVariantDslInfo.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/TestProjectVariantDslInfo.kt
index 30f1e6378e..53e13d7048 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/TestProjectVariantDslInfo.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/TestProjectVariantDslInfo.kt
@@ -22,7 +22,7 @@ package com.android.build.gradle.internal.core.dsl
*
* This class allows querying for the values set via the DSL model.
*
- * Use [VariantDslInfoBuilder] to instantiate.
+ * Use [DslInfoBuilder] to instantiate.
*
* @see [com.android.build.gradle.internal.component.TestVariantCreationConfig]
*/
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/TestedComponentDslInfo.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/TestedVariantDslInfo.kt
index 7cb4fd01ef..73cc522e2a 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/TestedComponentDslInfo.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/TestedVariantDslInfo.kt
@@ -22,6 +22,8 @@ import com.android.build.api.dsl.TestFixtures
* Contains the final dsl info computed from the DSL object model (extension, default config,
* build type, flavors) that are needed by tested components.
*/
-interface TestedComponentDslInfo: VariantDslInfo {
+interface TestedVariantDslInfo: VariantDslInfo {
val testFixtures: TestFixtures
+
+ val testInstrumentationRunnerArguments: Map<String, String>
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/UnitTestComponentDslInfo.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/UnitTestComponentDslInfo.kt
index 9af92d7b80..7dd346379a 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/UnitTestComponentDslInfo.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/UnitTestComponentDslInfo.kt
@@ -22,7 +22,7 @@ package com.android.build.gradle.internal.core.dsl
*
* This class allows querying for the values set via the DSL model.
*
- * Use [VariantDslInfoBuilder] to instantiate.
+ * Use [DslInfoBuilder] to instantiate.
*
* @see [com.android.build.gradle.internal.component.UnitTestCreationConfig]
*/
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/VariantDslInfo.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/VariantDslInfo.kt
index 63f054e195..12e6799190 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/VariantDslInfo.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/VariantDslInfo.kt
@@ -17,7 +17,6 @@ package com.android.build.gradle.internal.core.dsl
import com.android.build.api.dsl.Lint
import com.android.build.api.dsl.PackagingOptions
-import com.android.build.api.variant.ResValue
import com.android.build.gradle.internal.core.MergedNdkConfig
import com.android.build.gradle.internal.core.NativeBuiltType
import com.android.build.gradle.internal.dsl.CoreExternalNativeBuildOptions
@@ -30,9 +29,6 @@ import org.gradle.api.provider.ListProperty
*/
interface VariantDslInfo: ComponentDslInfo, ConsumableComponentDslInfo {
- /** Returns true if the variant output is a bundle. */
- val isBundled: Boolean
-
val nativeBuildSystem: NativeBuiltType?
val ndkConfig: MergedNdkConfig
@@ -49,18 +45,13 @@ interface VariantDslInfo: ComponentDslInfo, ConsumableComponentDslInfo {
fun getProguardFiles(into: ListProperty<RegularFile>)
- val isRenderscriptDebuggable: Boolean
-
val isJniDebuggable: Boolean
val lintOptions: Lint
val packaging: PackagingOptions
- ////////////////////////////////////////////////////////////////////////////////////////
- // APIs below should only be used at CreationConfig/Variant instantiation time //
- // DO NOT USE THOSE IN TASKS //
- ////////////////////////////////////////////////////////////////////////////////////////
+ val experimentalProperties: Map<String, Any>
val externalNativeExperimentalProperties: Map<String, Any>
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/AndroidTestComponentDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/AndroidTestComponentDslInfoImpl.kt
new file mode 100644
index 0000000000..854a6cd57b
--- /dev/null
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/AndroidTestComponentDslInfoImpl.kt
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.internal.core.dsl.impl
+
+import com.android.build.api.dsl.ApplicationBuildType
+import com.android.build.api.dsl.BuildType
+import com.android.build.api.dsl.ProductFlavor
+import com.android.build.api.variant.ComponentIdentity
+import com.android.build.api.variant.impl.MutableAndroidVersion
+import com.android.build.gradle.BaseExtension
+import com.android.build.gradle.internal.core.dsl.AndroidTestComponentDslInfo
+import com.android.build.gradle.internal.core.dsl.DynamicFeatureVariantDslInfo
+import com.android.build.gradle.internal.core.dsl.TestedVariantDslInfo
+import com.android.build.gradle.internal.dsl.DefaultConfig
+import com.android.build.gradle.internal.dsl.InternalTestedExtension
+import com.android.build.gradle.internal.dsl.SigningConfig
+import com.android.build.gradle.internal.manifest.ManifestDataProvider
+import com.android.build.gradle.internal.profile.ProfilingMode
+import com.android.build.gradle.internal.services.VariantServices
+import com.android.build.gradle.options.StringOption
+import com.android.builder.core.ComponentType
+import com.android.builder.dexing.DexingType
+import org.gradle.api.file.DirectoryProperty
+import org.gradle.api.provider.Property
+import org.gradle.api.provider.Provider
+
+internal class AndroidTestComponentDslInfoImpl(
+ componentIdentity: ComponentIdentity,
+ componentType: ComponentType,
+ defaultConfig: DefaultConfig,
+ buildTypeObj: BuildType,
+ productFlavorList: List<ProductFlavor>,
+ dataProvider: ManifestDataProvider,
+ services: VariantServices,
+ buildDirectory: DirectoryProperty,
+ override val testedVariantDslInfo: TestedVariantDslInfo,
+ /**
+ * Whether there are inconsistent applicationId in the test.
+ * This trigger a mode where the namespaceForR just returns the same as namespace.
+ */
+ private val inconsistentTestAppId: Boolean,
+ private val signingConfigOverride: SigningConfig?,
+ oldExtension: BaseExtension?,
+ extension: InternalTestedExtension<*, *, *, *>
+) : ConsumableComponentDslInfoImpl(
+ componentIdentity,
+ componentType,
+ defaultConfig,
+ buildTypeObj,
+ productFlavorList,
+ services,
+ buildDirectory,
+ oldExtension,
+ extension
+), AndroidTestComponentDslInfo {
+ override val namespace: Provider<String> by lazy {
+ getTestComponentNamespace(extension, services, dataProvider)
+ }
+
+ override val applicationId: Property<String> =
+ services.newPropertyBackingDeprecatedApi(
+ String::class.java,
+ initTestApplicationId(defaultConfig, services)
+ )
+
+ override val minSdkVersion: MutableAndroidVersion
+ get() = testedVariantDslInfo.minSdkVersion
+ override val maxSdkVersion: Int?
+ get() = testedVariantDslInfo.maxSdkVersion
+ override val targetSdkVersion: MutableAndroidVersion?
+ get() = testedVariantDslInfo.targetSdkVersion
+
+ override val namespaceForR: Provider<String> by lazy {
+ if (inconsistentTestAppId) {
+ namespace
+ } else {
+ // For legacy reason, this code does the following:
+ // - If testNamespace is set, use it.
+ // - If android.namespace is set, use it with .test added
+ // - else, use the variant applicationId.
+ // TODO(b/176931684) Remove this and use [namespace] directly everywhere.
+ extension.testNamespace?.let { services.provider { it } }
+ ?: extension.namespace?.let { services.provider { it }.map { "$it.test" } }
+ ?: applicationId
+ }
+ }
+
+ // TODO: Android Test doesn't have isDebuggable dsl in the build type, we should move to using
+ // the value from the tested type
+ override val isDebuggable: Boolean
+ get() = ProfilingMode.getProfilingModeType(
+ services.projectOptions[StringOption.PROFILING_MODE]
+ ).isDebuggable
+ ?: (buildTypeObj as? ApplicationBuildType)?.isDebuggable
+ ?: false
+
+ override val signingConfig: SigningConfig? by lazy {
+ if (testedVariantDslInfo is DynamicFeatureVariantDslInfo) {
+ null
+ } else {
+ getSigningConfig(
+ buildTypeObj,
+ mergedFlavor,
+ signingConfigOverride,
+ extension,
+ services
+ )
+ }
+ }
+
+ override val isSigningReady: Boolean
+ get() = signingConfig?.isSigningReady == true
+
+ private val instrumentedTestDelegate by lazy {
+ InstrumentedTestDslInfoImpl(
+ productFlavorList,
+ defaultConfig,
+ dataProvider,
+ services,
+ testedVariantDslInfo.testInstrumentationRunnerArguments
+ )
+ }
+
+ override fun getInstrumentationRunner(dexingType: DexingType): Provider<String> {
+ return instrumentedTestDelegate.getInstrumentationRunner(dexingType)
+ }
+
+ override val instrumentationRunnerArguments: Map<String, String>
+ get() = instrumentedTestDelegate.instrumentationRunnerArguments
+ override val handleProfiling: Provider<Boolean>
+ get() = instrumentedTestDelegate.handleProfiling
+ override val functionalTest: Provider<Boolean>
+ get() = instrumentedTestDelegate.functionalTest
+ override val testLabel: Provider<String?>
+ get() = instrumentedTestDelegate.testLabel
+}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/ApplicationVariantDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/ApplicationVariantDslInfoImpl.kt
new file mode 100644
index 0000000000..e7c19e7496
--- /dev/null
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/ApplicationVariantDslInfoImpl.kt
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.internal.core.dsl.impl
+
+import com.android.build.api.dsl.ApplicationBuildType
+import com.android.build.api.dsl.ApplicationProductFlavor
+import com.android.build.api.dsl.BuildType
+import com.android.build.api.dsl.ProductFlavor
+import com.android.build.api.variant.ComponentIdentity
+import com.android.build.gradle.BaseExtension
+import com.android.build.gradle.internal.core.dsl.ApplicationVariantDslInfo
+import com.android.build.gradle.internal.dsl.DefaultConfig
+import com.android.build.gradle.internal.dsl.InternalApplicationExtension
+import com.android.build.gradle.internal.dsl.SigningConfig
+import com.android.build.gradle.internal.manifest.ManifestDataProvider
+import com.android.build.gradle.internal.profile.ProfilingMode
+import com.android.build.gradle.internal.publishing.VariantPublishingInfo
+import com.android.build.gradle.internal.services.VariantServices
+import com.android.build.gradle.options.StringOption
+import com.android.builder.core.ComponentType
+import com.android.builder.errors.IssueReporter
+import org.gradle.api.file.DirectoryProperty
+import org.gradle.api.provider.Provider
+
+internal class ApplicationVariantDslInfoImpl(
+ componentIdentity: ComponentIdentity,
+ componentType: ComponentType,
+ defaultConfig: DefaultConfig,
+ buildTypeObj: BuildType,
+ productFlavorList: List<ProductFlavor>,
+ dataProvider: ManifestDataProvider,
+ services: VariantServices,
+ buildDirectory: DirectoryProperty,
+ override val publishInfo: VariantPublishingInfo,
+ private val signingConfigOverride: SigningConfig?,
+ oldExtension: BaseExtension?,
+ extension: InternalApplicationExtension
+) : TestedVariantDslInfoImpl(
+ componentIdentity,
+ componentType,
+ defaultConfig,
+ buildTypeObj,
+ productFlavorList,
+ dataProvider,
+ services,
+ buildDirectory,
+ oldExtension,
+ extension
+), ApplicationVariantDslInfo {
+
+ private val applicationBuildType = buildTypeObj as ApplicationBuildType
+
+ override val isDebuggable: Boolean
+ get() = ProfilingMode.getProfilingModeType(
+ services.projectOptions[StringOption.PROFILING_MODE]
+ ).isDebuggable ?: applicationBuildType.isDebuggable
+
+ override val isProfileable: Boolean
+ get() {
+ val fromProfilingModeOption = ProfilingMode.getProfilingModeType(
+ services.projectOptions[StringOption.PROFILING_MODE]
+ ).isProfileable
+ // When profileable is enabled from the profilingMode option, it ensures all profileable
+ // features are supported, therefore the compileSdk => 30.
+ val minProfileableSdk = 30
+ val compileSdk = extension.compileSdk ?: minProfileableSdk
+ if ((fromProfilingModeOption == true || applicationBuildType.isProfileable) &&
+ compileSdk < minProfileableSdk
+ ) {
+ services.issueReporter.reportError(
+ IssueReporter.Type.COMPILE_SDK_VERSION_TOO_LOW,
+ """'profileable' is enabled with compile SDK <30.
+ Recommended action: If possible, upgrade compileSdk from ${minSdkVersion.apiLevel} to 30."""
+ .trimIndent()
+ )
+ }
+ return when {
+ fromProfilingModeOption != null -> {
+ fromProfilingModeOption
+ }
+
+ applicationBuildType.isProfileable && isDebuggable -> {
+ val projectName = services.projectInfo.name
+ val message =
+ ":$projectName build type '${buildType}' can only have debuggable or profileable enabled.\n" +
+ "Only one of these options can be used at a time.\n" +
+ "Recommended action: Only set one of debuggable=true and profileable=true.\n"
+ services.issueReporter.reportWarning(IssueReporter.Type.GENERIC, message)
+ // Disable profileable when profileable and debuggable are both enabled.
+ false
+ }
+ else -> applicationBuildType.isProfileable
+ }
+ }
+
+ override val signingConfig: SigningConfig? by lazy {
+ getSigningConfig(
+ buildTypeObj,
+ mergedFlavor,
+ signingConfigOverride,
+ extension,
+ services
+ )
+ }
+
+ override val isSigningReady: Boolean
+ get() = signingConfig?.isSigningReady == true
+
+ override val versionName: Provider<String?> by lazy {
+ // If the version name from the flavors is null, then we read from the manifest and combine
+ // with suffixes, unless it's a test at which point we just return.
+ // If the name is not-null, we just combine it with suffixes
+ val versionNameFromFlavors =
+ productFlavorList
+ .asSequence()
+ .filterIsInstance(ApplicationProductFlavor::class.java)
+ .map { it.versionName }
+ .firstOrNull { it != null }
+ ?: defaultConfig.versionName
+
+ if (versionNameFromFlavors == null) {
+ // rely on manifest value
+ // using map will allow us to keep task dependency should the manifest be generated or
+ // transformed via a task.
+ dataProvider.manifestData.map {
+ it.versionName?.let { versionName ->
+ "$versionName${computeVersionNameSuffix()}"
+ }
+ }
+ } else {
+ // use value from flavors
+ services.provider { "$versionNameFromFlavors${computeVersionNameSuffix()}" }
+ }
+ }
+ override val versionCode: Provider<Int?> by lazy {
+ // If the version code from the flavors is null, then we read from the manifest and combine
+ // with suffixes, unless it's a test at which point we just return.
+ // If the name is not-null, we just combine it with suffixes
+ val versionCodeFromFlavors =
+ productFlavorList
+ .asSequence()
+ .filterIsInstance(ApplicationProductFlavor::class.java)
+ .map { it.versionCode }
+ .firstOrNull { it != null }
+ ?: defaultConfig.versionCode
+
+ if (versionCodeFromFlavors == null) {
+ // rely on manifest value
+ // using map will allow us to keep task dependency should the manifest be generated or
+ // transformed via a task.
+ dataProvider.manifestData.map { it.versionCode }
+ } else {
+ // use value from flavors
+ services.provider { versionCodeFromFlavors }
+ }
+ }
+ override val isWearAppUnbundled: Boolean?
+ get() = mergedFlavor.wearAppUnbundled
+ override val isEmbedMicroApp: Boolean
+ get() = applicationBuildType.isEmbedMicroApp
+
+ private fun computeVersionNameSuffix(): String {
+ // for the suffix we combine the suffix from all the flavors. However, we're going to
+ // want the higher priority one to be last.
+ val suffixes = mutableListOf<String>()
+ defaultConfig.versionNameSuffix?.let {
+ suffixes.add(it)
+ }
+
+ suffixes.addAll(
+ productFlavorList
+ .asSequence()
+ .filterIsInstance(ApplicationProductFlavor::class.java)
+ .mapNotNull { it.versionNameSuffix })
+
+ // then we add the build type after.
+ applicationBuildType.versionNameSuffix?.let {
+ suffixes.add(it)
+ }
+
+ return if (suffixes.isNotEmpty()) {
+ suffixes.joinToString(separator = "")
+ } else {
+ ""
+ }
+ }
+}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/ComponentDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/ComponentDslInfoImpl.kt
new file mode 100644
index 0000000000..92e22006e3
--- /dev/null
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/ComponentDslInfoImpl.kt
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.internal.core.dsl.impl
+
+import com.android.build.api.dsl.AndroidResources
+import com.android.build.api.dsl.ApplicationBuildType
+import com.android.build.api.dsl.ApplicationProductFlavor
+import com.android.build.api.dsl.BuildType
+import com.android.build.api.dsl.CommonExtension
+import com.android.build.api.dsl.CompileOptions
+import com.android.build.api.dsl.DynamicFeatureBuildType
+import com.android.build.api.dsl.ProductFlavor
+import com.android.build.api.dsl.VariantDimension
+import com.android.build.api.transform.Transform
+import com.android.build.api.variant.ComponentIdentity
+import com.android.build.api.variant.ResValue
+import com.android.build.api.variant.impl.ResValueKeyImpl
+import com.android.build.gradle.BaseExtension
+import com.android.build.gradle.ProguardFiles
+import com.android.build.gradle.api.JavaCompileOptions
+import com.android.build.gradle.internal.PostprocessingFeatures
+import com.android.build.gradle.internal.ProguardFileType
+import com.android.build.gradle.internal.core.MergedFlavor
+import com.android.build.gradle.internal.core.MergedJavaCompileOptions
+import com.android.build.gradle.internal.core.MergedOptions
+import com.android.build.gradle.internal.core.PostProcessingBlockOptions
+import com.android.build.gradle.internal.core.PostProcessingOptions
+import com.android.build.gradle.internal.core.dsl.ComponentDslInfo
+import com.android.build.gradle.internal.dsl.DefaultConfig
+import com.android.build.gradle.internal.services.VariantServices
+import com.android.builder.core.AbstractProductFlavor
+import com.android.builder.core.ComponentType
+import com.android.builder.model.BaseConfig
+import com.android.builder.model.ClassField
+import com.android.builder.model.VectorDrawablesOptions
+import com.google.common.collect.ImmutableMap
+import com.google.common.collect.ImmutableSet
+import org.gradle.api.file.DirectoryProperty
+import java.io.File
+
+internal abstract class ComponentDslInfoImpl internal constructor(
+ override val componentIdentity: ComponentIdentity,
+ final override val componentType: ComponentType,
+ protected val defaultConfig: DefaultConfig,
+ /**
+ * Public because this is needed by the old Variant API. Nothing else should touch this.
+ */
+ val buildTypeObj: BuildType,
+ override val productFlavorList: List<ProductFlavor>,
+ protected val services: VariantServices,
+ private val buildDirectory: DirectoryProperty,
+ @Deprecated("use extension") private val oldExtension: BaseExtension?,
+ protected val extension: CommonExtension<*, *, *, *>
+): ComponentDslInfo {
+
+ override val buildType: String?
+ get() = componentIdentity.buildType
+ override val productFlavors: List<Pair<String, String>>
+ get() = componentIdentity.productFlavors
+
+ /**
+ * This should be mostly private and not used outside this class, but is still public for legacy
+ * variant API and model v1 support.
+ *
+ * At some point we should remove this and rely on each property to combine dsl values in the
+ * manner that it is meaningful for the property. Take a look at
+ * [VariantDslInfoImpl.initApplicationId] for guidance on how will that look like.
+ *
+ * DO NOT USE. You should mostly use the interfaces which does not give access to this.
+ */
+ val mergedFlavor: MergedFlavor by lazy {
+ MergedFlavor.mergeFlavors(
+ defaultConfig,
+ productFlavorList.map { it as com.android.build.gradle.internal.dsl.ProductFlavor },
+ applicationId,
+ services
+ )
+ }
+
+ final override val javaCompileOptions = MergedJavaCompileOptions()
+
+ init {
+ computeMergedOptions(
+ javaCompileOptions,
+ { javaCompileOptions as JavaCompileOptions },
+ { javaCompileOptions as JavaCompileOptions }
+ )
+ }
+
+ // merged flavor delegates
+
+ override val missingDimensionStrategies: ImmutableMap<String, AbstractProductFlavor.DimensionRequest>
+ get() = ImmutableMap.copyOf(mergedFlavor.missingDimensionStrategies)
+
+ override val resourceConfigurations: ImmutableSet<String>
+ get() = ImmutableSet.copyOf(mergedFlavor.resourceConfigurations)
+
+ override val vectorDrawables: VectorDrawablesOptions
+ get() = mergedFlavor.vectorDrawables
+
+ // extension delegates
+
+ override val compileOptions: CompileOptions
+ get() = extension.compileOptions
+ override val androidResources: AndroidResources
+ get() = extension.androidResources
+ override val transforms: List<Transform>
+ get() = oldExtension?.transforms ?: emptyList()
+
+ // build type delegates
+
+ override val isPseudoLocalesEnabled: Boolean
+ get() = buildTypeObj.isPseudoLocalesEnabled
+
+ override val isAndroidTestCoverageEnabled: Boolean
+ get() = buildTypeObj.enableAndroidTestCoverage || buildTypeObj.isTestCoverageEnabled
+
+ override val isCrunchPngs: Boolean?
+ get() {
+ return when (buildTypeObj) {
+ is ApplicationBuildType -> buildTypeObj.isCrunchPngs
+ is DynamicFeatureBuildType -> buildTypeObj.isCrunchPngs
+ else -> false
+ }
+ }
+
+ override val postProcessingOptions: PostProcessingOptions by lazy {
+ if ((buildTypeObj as com.android.build.gradle.internal.dsl.BuildType)
+ .postProcessingConfiguration ==
+ com.android.build.gradle.internal.dsl.BuildType.PostProcessingConfiguration.POSTPROCESSING_BLOCK
+ ) {
+ PostProcessingBlockOptions(
+ buildTypeObj.postprocessing, componentType.isTestComponent
+ )
+ } else object : PostProcessingOptions {
+ override fun getProguardFiles(type: ProguardFileType): Collection<File> =
+ buildTypeObj.getProguardFiles(type)
+
+ override fun getDefaultProguardFiles(): List<File> =
+ listOf(
+ ProguardFiles.getDefaultProguardFile(
+ ProguardFiles.ProguardFile.DONT_OPTIMIZE.fileName,
+ buildDirectory
+ )
+ )
+
+ override fun getPostprocessingFeatures(): PostprocessingFeatures? = null
+
+ override fun codeShrinkerEnabled() = buildTypeObj.isMinifyEnabled
+
+ override fun resourcesShrinkingEnabled(): Boolean = buildTypeObj.isShrinkResources
+
+ override fun hasPostProcessingConfiguration() = false
+ }
+ }
+
+ override fun gatherProguardFiles(type: ProguardFileType): Collection<File> {
+ val result: MutableList<File> = ArrayList(defaultConfig.getProguardFiles(type))
+ for (flavor in productFlavorList) {
+ result.addAll((flavor as com.android.build.gradle.internal.dsl.ProductFlavor).getProguardFiles(type))
+ }
+ result.addAll(postProcessingOptions.getProguardFiles(type))
+ return result
+ }
+
+ override val isCrunchPngsDefault: Boolean
+ // does not exist in the new DSL
+ get() = (buildTypeObj as com.android.build.gradle.internal.dsl.BuildType).isCrunchPngsDefault
+
+ // helper methods
+
+ override fun getResValues(): Map<ResValue.Key, ResValue> {
+ val resValueFields = mutableMapOf<ResValue.Key, ResValue>()
+
+ fun addToListIfNotAlreadyPresent(classField: ClassField, comment: String) {
+ val key = ResValueKeyImpl(classField.type, classField.name)
+ if (!resValueFields.containsKey(key)) {
+ resValueFields[key] = ResValue(
+ value = classField.value,
+ comment = comment
+ )
+ }
+ }
+
+ (buildTypeObj as com.android.build.gradle.internal.dsl.BuildType).resValues.values.forEach { classField ->
+ addToListIfNotAlreadyPresent(classField, "Value from build type: ${buildTypeObj.name}")
+ }
+
+ productFlavorList.forEach { flavor ->
+ (flavor as com.android.build.gradle.internal.dsl.ProductFlavor).resValues.values.forEach { classField ->
+ addToListIfNotAlreadyPresent(
+ classField,
+ "Value from product flavor: ${flavor.name}"
+ )
+ }
+ }
+
+ defaultConfig.resValues.values.forEach { classField ->
+ addToListIfNotAlreadyPresent(classField, "Value from default config.")
+ }
+
+ return resValueFields
+ }
+
+
+ /**
+ * Merge a specific option in GradleVariantConfiguration.
+ *
+ *
+ * It is assumed that merged option type with a method to reset and append is created for the
+ * option being merged.
+ *
+ *
+ * The order of priority is BuildType, ProductFlavors, and default config. ProductFlavor
+ * added earlier has higher priority than ProductFlavor added later.
+ *
+ * @param mergedOption The merged option store in the GradleVariantConfiguration.
+ * @param getFlavorOption A Function to return the option from a ProductFlavor.
+ * @param getBuildTypeOption A Function to return the option from a BuildType.
+ * takes priority and overwrite option in the first input argument.
+ * @param <CoreOptionsT> The core type of the option being merge.
+ * @param <MergedOptionsT> The merge option type.
+ </MergedOptionsT></CoreOptionsT> */
+ protected fun <CoreOptionsT, MergedOptionsT : MergedOptions<CoreOptionsT>> computeMergedOptions(
+ mergedOption: MergedOptionsT,
+ getFlavorOption: VariantDimension.() -> CoreOptionsT?,
+ getBuildTypeOption: BuildType.() -> CoreOptionsT?
+ ) {
+ mergedOption.reset()
+
+ val defaultOption = defaultConfig.getFlavorOption()
+ if (defaultOption != null) {
+ mergedOption.append(defaultOption)
+ }
+ // reverse loop for proper order
+ for (i in productFlavorList.indices.reversed()) {
+ val flavorOption = productFlavorList[i].getFlavorOption()
+ if (flavorOption != null) {
+ mergedOption.append(flavorOption)
+ }
+ }
+ val buildTypeOption = buildTypeObj.getBuildTypeOption()
+ if (buildTypeOption != null) {
+ mergedOption.append(buildTypeOption)
+ }
+ }
+
+ private fun BaseConfig.getProguardFiles(type: ProguardFileType): Collection<File> = when (type) {
+ ProguardFileType.EXPLICIT -> this.proguardFiles
+ ProguardFileType.TEST -> this.testProguardFiles
+ ProguardFileType.CONSUMER -> this.consumerProguardFiles
+ }
+
+ /**
+ * Combines all the appId suffixes into a single one.
+ *
+ * The suffixes are separated by '.' whether their first char is a '.' or not.
+ */
+ protected fun computeApplicationIdSuffix(): String {
+ // for the suffix we combine the suffix from all the flavors. However, we're going to
+ // want the higher priority one to be last.
+ val suffixes = mutableListOf<String>()
+ defaultConfig.applicationIdSuffix?.let {
+ suffixes.add(it)
+ }
+
+ suffixes.addAll(
+ productFlavorList
+ .asSequence()
+ .filterIsInstance(ApplicationProductFlavor::class.java)
+ .mapNotNull { it.applicationIdSuffix })
+
+ // then we add the build type after.
+ (buildTypeObj as? ApplicationBuildType)?.applicationIdSuffix?.let {
+ suffixes.add(it)
+ }
+ val nonEmptySuffixes = suffixes.filter { it.isNotEmpty() }
+ return if (nonEmptySuffixes.isNotEmpty()) {
+ ".${nonEmptySuffixes.joinToString(separator = ".", transform = { it.removePrefix(".") })}"
+ } else {
+ ""
+ }
+ }
+}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/ConsumableComponentDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/ConsumableComponentDslInfoImpl.kt
new file mode 100644
index 0000000000..a45fc69beb
--- /dev/null
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/ConsumableComponentDslInfoImpl.kt
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.internal.core.dsl.impl
+
+import com.android.build.api.dsl.ApplicationBuildType
+import com.android.build.api.dsl.BuildType
+import com.android.build.api.dsl.CommonExtension
+import com.android.build.api.dsl.ProductFlavor
+import com.android.build.api.variant.BuildConfigField
+import com.android.build.api.variant.ComponentIdentity
+import com.android.build.gradle.BaseExtension
+import com.android.build.gradle.internal.core.MergedOptimization
+import com.android.build.gradle.internal.core.dsl.ConsumableComponentDslInfo
+import com.android.build.gradle.internal.dsl.DefaultConfig
+import com.android.build.gradle.internal.dsl.OptimizationImpl
+import com.android.build.gradle.internal.services.VariantServices
+import com.android.build.gradle.options.IntegerOption
+import com.android.builder.core.ComponentType
+import com.android.builder.model.ClassField
+import com.google.common.collect.ImmutableList
+import com.google.common.collect.Lists
+import com.google.common.collect.Maps
+import com.google.common.collect.Sets
+import org.gradle.api.file.DirectoryProperty
+import java.io.File
+
+internal abstract class ConsumableComponentDslInfoImpl internal constructor(
+ componentIdentity: ComponentIdentity,
+ componentType: ComponentType,
+ defaultConfig: DefaultConfig,
+ buildTypeObj: BuildType,
+ productFlavorList: List<ProductFlavor>,
+ services: VariantServices,
+ buildDirectory: DirectoryProperty,
+ oldExtension: BaseExtension?,
+ extension: CommonExtension<*, *, *, *>
+) : ComponentDslInfoImpl(
+ componentIdentity,
+ componentType,
+ defaultConfig,
+ buildTypeObj,
+ productFlavorList,
+ services,
+ buildDirectory,
+ oldExtension,
+ extension
+), ConsumableComponentDslInfo {
+
+ // merged options
+
+ private val mergedOptimization = MergedOptimization()
+
+ init {
+ mergeOptions()
+ }
+
+ private fun mergeOptions() {
+ computeMergedOptions(
+ mergedOptimization,
+ { optimization as OptimizationImpl },
+ { optimization as OptimizationImpl }
+ )
+ }
+
+ override val ignoredLibraryKeepRules: Set<String>
+ get() = mergedOptimization.ignoredLibraryKeepRules
+
+ override val ignoreAllLibraryKeepRules: Boolean
+ get() = mergedOptimization.ignoreAllLibraryKeepRules
+
+ // merged flavor delegates
+
+ override val renderscriptTarget: Int
+ get() = mergedFlavor.renderscriptTargetApi ?: -1
+ override val renderscriptSupportModeEnabled: Boolean
+ get() = mergedFlavor.renderscriptSupportModeEnabled ?: false
+ override val renderscriptSupportModeBlasEnabled: Boolean
+ get() {
+ val value = mergedFlavor.renderscriptSupportModeBlasEnabled
+ return value ?: false
+ }
+ override val renderscriptNdkModeEnabled: Boolean
+ get() = mergedFlavor.renderscriptNdkModeEnabled ?: false
+
+ override val manifestPlaceholders: Map<String, String> by lazy {
+ val mergedFlavorsPlaceholders: MutableMap<String, String> = mutableMapOf()
+ mergedFlavor.manifestPlaceholders.forEach { (key, value) ->
+ mergedFlavorsPlaceholders[key] = value.toString()
+ }
+ // so far, blindly override the build type placeholders
+ buildTypeObj.manifestPlaceholders.forEach { (key, value) ->
+ mergedFlavorsPlaceholders[key] = value.toString()
+ }
+ mergedFlavorsPlaceholders
+ }
+
+ // build type delegates
+
+ // Only require specific multidex opt-in for legacy multidex.
+ override val isMultiDexEnabled: Boolean?
+ get() {
+ // Only require specific multidex opt-in for legacy multidex.
+ return (buildTypeObj as? ApplicationBuildType)?.multiDexEnabled
+ ?: mergedFlavor.multiDexEnabled
+ }
+ override val multiDexKeepProguard: File?
+ get() {
+ var value = buildTypeObj.multiDexKeepProguard
+ if (value != null) {
+ return value
+ }
+ value = mergedFlavor.multiDexKeepProguard
+ return value
+ }
+ override val multiDexKeepFile: File?
+ get() {
+ var value = buildTypeObj.multiDexKeepFile
+ if (value != null) {
+ return value
+ }
+ value = mergedFlavor.multiDexKeepFile
+ return value
+ }
+
+ override val renderscriptOptimLevel: Int
+ get() = buildTypeObj.renderscriptOptimLevel
+
+ // add the lower priority one, to override them with the higher priority ones.
+ // can't use merge flavor as it's not a prop on the base class.
+ // reverse loop for proper order
+ override val defaultGlslcArgs: List<String>
+ get() {
+ val optionMap: MutableMap<String, String> =
+ Maps.newHashMap()
+ // add the lower priority one, to override them with the higher priority ones.
+ for (option in defaultConfig.shaders.glslcArgs) {
+ optionMap[getKey(option)] = option
+ }
+ // can't use merge flavor as it's not a prop on the base class.
+ // reverse loop for proper order
+ for (i in productFlavorList.indices.reversed()) {
+ for (option in productFlavorList[i].shaders.glslcArgs) {
+ optionMap[getKey(option)] = option
+ }
+ }
+ // then the build type
+ for (option in buildTypeObj.shaders.glslcArgs) {
+ optionMap[getKey(option)] = option
+ }
+ return Lists.newArrayList(optionMap.values)
+ }
+
+ // first collect all possible keys.
+ override val scopedGlslcArgs: Map<String, List<String>>
+ get() {
+ val scopedArgs: MutableMap<String, List<String>> =
+ Maps.newHashMap()
+ // first collect all possible keys.
+ val keys = scopedGlslcKeys
+ for (key in keys) { // first add to a temp map to resolve overridden values
+ val optionMap: MutableMap<String, String> =
+ Maps.newHashMap()
+ // we're going to go from lower priority, to higher priority elements, and for each
+ // start with the non scoped version, and then add the scoped version.
+ // 1. default config, global.
+ for (option in defaultConfig.shaders.glslcArgs) {
+ optionMap[getKey(option)] = option
+ }
+ // 1b. default config, scoped.
+ for (option in defaultConfig.shaders.scopedGlslcArgs[key]) {
+ optionMap[getKey(option)] = option
+ }
+ // 2. the flavors.
+ // can't use merge flavor as it's not a prop on the base class.
+ // reverse loop for proper order
+ for (i in productFlavorList.indices.reversed()) { // global
+ for (option in productFlavorList[i].shaders.glslcArgs) {
+ optionMap[getKey(option)] = option
+ }
+ // scoped.
+ for (option in productFlavorList[i].shaders.scopedGlslcArgs[key]) {
+ optionMap[getKey(option)] = option
+ }
+ }
+ // 3. the build type, global
+ for (option in buildTypeObj.shaders.glslcArgs) {
+ optionMap[getKey(option)] = option
+ }
+ // 3b. the build type, scoped.
+ for (option in buildTypeObj.shaders.scopedGlslcArgs[key]) {
+ optionMap[getKey(option)] = option
+ }
+ // now add the full value list.
+ scopedArgs[key] = ImmutableList.copyOf(optionMap.values)
+ }
+ return scopedArgs
+ }
+
+ // helper methods
+
+ // TODO: move to global scope
+ override val targetDeployApiFromIDE: Int? =
+ services.projectOptions.get(IntegerOption.IDE_TARGET_DEVICE_API)
+
+ override fun getBuildConfigFields(): Map<String, BuildConfigField<out java.io.Serializable>> {
+ val buildConfigFieldsMap =
+ mutableMapOf<String, BuildConfigField<out java.io.Serializable>>()
+
+ fun addToListIfNotAlreadyPresent(classField: ClassField, comment: String) {
+ if (!buildConfigFieldsMap.containsKey(classField.name)) {
+ buildConfigFieldsMap[classField.name] =
+ BuildConfigField(classField.type , classField.value, comment)
+ }
+ }
+
+ (buildTypeObj as com.android.build.gradle.internal.dsl.BuildType).buildConfigFields.values.forEach { classField ->
+ addToListIfNotAlreadyPresent(classField, "Field from build type: ${buildTypeObj.name}")
+ }
+
+ for (flavor in productFlavorList) {
+ (flavor as com.android.build.gradle.internal.dsl.ProductFlavor).buildConfigFields.values.forEach { classField ->
+ addToListIfNotAlreadyPresent(
+ classField,
+ "Field from product flavor: ${flavor.name}"
+ )
+ }
+ }
+ defaultConfig.buildConfigFields.values.forEach { classField ->
+ addToListIfNotAlreadyPresent(classField, "Field from default config.")
+ }
+ return buildConfigFieldsMap
+ }
+
+ private val scopedGlslcKeys: Set<String>
+ get() {
+ val keys: MutableSet<String> =
+ Sets.newHashSet()
+ keys.addAll(defaultConfig.shaders.scopedGlslcArgs.keySet())
+ for (flavor in productFlavorList) {
+ keys.addAll(flavor.shaders.scopedGlslcArgs.keySet())
+ }
+ keys.addAll(buildTypeObj.shaders.scopedGlslcArgs.keySet())
+ return keys
+ }
+
+ private fun getKey(fullOption: String): String {
+ val pos = fullOption.lastIndexOf('=')
+ return if (pos == -1) {
+ fullOption
+ } else fullOption.substring(0, pos)
+ }
+}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/DslInfoBuilder.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/DslInfoBuilder.kt
new file mode 100644
index 0000000000..32401db825
--- /dev/null
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/DslInfoBuilder.kt
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.internal.core.dsl.impl
+
+import com.android.build.api.component.impl.ComponentIdentityImpl
+import com.android.build.api.dsl.BuildType
+import com.android.build.api.dsl.CommonExtension
+import com.android.build.api.dsl.ProductFlavor
+import com.android.build.api.variant.ComponentIdentity
+import com.android.build.gradle.BaseExtension
+import com.android.build.gradle.internal.api.DefaultAndroidSourceSet
+import com.android.build.gradle.internal.core.VariantSources
+import com.android.build.gradle.internal.core.dsl.AndroidTestComponentDslInfo
+import com.android.build.gradle.internal.core.dsl.ApplicationVariantDslInfo
+import com.android.build.gradle.internal.core.dsl.ComponentDslInfo
+import com.android.build.gradle.internal.core.dsl.DynamicFeatureVariantDslInfo
+import com.android.build.gradle.internal.core.dsl.LibraryVariantDslInfo
+import com.android.build.gradle.internal.core.dsl.TestFixturesComponentDslInfo
+import com.android.build.gradle.internal.core.dsl.TestProjectVariantDslInfo
+import com.android.build.gradle.internal.core.dsl.TestedVariantDslInfo
+import com.android.build.gradle.internal.core.dsl.UnitTestComponentDslInfo
+import com.android.build.gradle.internal.dsl.ApplicationPublishingImpl
+import com.android.build.gradle.internal.dsl.DefaultConfig
+import com.android.build.gradle.internal.dsl.InternalApplicationExtension
+import com.android.build.gradle.internal.dsl.InternalDynamicFeatureExtension
+import com.android.build.gradle.internal.dsl.InternalLibraryExtension
+import com.android.build.gradle.internal.dsl.InternalTestExtension
+import com.android.build.gradle.internal.dsl.InternalTestedExtension
+import com.android.build.gradle.internal.dsl.LibraryPublishingImpl
+import com.android.build.gradle.internal.dsl.SigningConfig
+import com.android.build.gradle.internal.manifest.ManifestDataProvider
+import com.android.build.gradle.internal.services.DslServices
+import com.android.build.gradle.internal.services.VariantServices
+import com.android.build.gradle.internal.utils.createPublishingInfoForApp
+import com.android.build.gradle.internal.utils.createPublishingInfoForLibrary
+import com.android.build.gradle.internal.utils.toImmutableList
+import com.android.build.gradle.internal.variant.DimensionCombination
+import com.android.builder.core.ComponentType
+import com.android.builder.core.ComponentTypeImpl
+import com.android.builder.model.SourceProvider
+import org.gradle.api.file.DirectoryProperty
+
+/** Builder for dsl info classes.
+ *
+ * This allows setting all temporary items on the builder before actually
+ * instantiating the configuration, in order to keep it immutable.
+ *
+ * Use [getBuilder] as an entry point.
+ */
+class DslInfoBuilder<CommonExtensionT: CommonExtension<*, *, *, *>, DslInfoT: ComponentDslInfo> private constructor(
+ private val dimensionCombination: DimensionCombination,
+ val componentType: ComponentType,
+ private val defaultConfig: DefaultConfig,
+ private val defaultSourceProvider: SourceProvider,
+ private val buildType: BuildType,
+ private val buildTypeSourceProvider: SourceProvider?,
+ private val signingConfigOverride: SigningConfig?,
+ private val manifestDataProvider: ManifestDataProvider,
+ private val variantServices: VariantServices,
+ private val oldExtension: BaseExtension?,
+ private val extension: CommonExtensionT,
+ private val buildDirectory: DirectoryProperty,
+) {
+
+ companion object {
+ /**
+ * Returns a new builder
+ */
+ @JvmStatic
+ fun <CommonExtensionT: CommonExtension<*, *, *, *>, DslInfoT: ComponentDslInfo> getBuilder(
+ dimensionCombination: DimensionCombination,
+ componentType: ComponentType,
+ defaultConfig: DefaultConfig,
+ defaultSourceSet: SourceProvider,
+ buildType: BuildType,
+ buildTypeSourceSet: SourceProvider?,
+ signingConfigOverride: SigningConfig?,
+ manifestDataProvider: ManifestDataProvider,
+ variantServices: VariantServices,
+ oldExtension: BaseExtension?,
+ extension: CommonExtensionT,
+ buildDirectory: DirectoryProperty,
+ dslServices: DslServices
+ ): DslInfoBuilder<CommonExtensionT, DslInfoT> {
+ return DslInfoBuilder(
+ dimensionCombination,
+ componentType,
+ defaultConfig,
+ defaultSourceSet,
+ buildType,
+ buildTypeSourceSet,
+ signingConfigOverride?.let { signingOverride ->
+ dslServices.newDecoratedInstance(
+ SigningConfig::class.java,
+ signingOverride.name,
+ dslServices
+ ).also {
+ it.initWith(signingOverride)
+ }
+ },
+ manifestDataProvider,
+ variantServices,
+ oldExtension,
+ extension,
+ buildDirectory,
+ )
+ }
+ }
+
+ private lateinit var variantName: String
+ private lateinit var multiFlavorName: String
+
+ val name: String
+ get() {
+ if (!::variantName.isInitialized) {
+ computeNames()
+ }
+
+ return variantName
+ }
+
+ val flavorName: String
+ get() {
+ if (!::multiFlavorName.isInitialized) {
+ computeNames()
+ }
+ return multiFlavorName
+
+ }
+
+ private val flavors = mutableListOf<Pair<ProductFlavor, SourceProvider>>()
+
+ var variantSourceProvider: DefaultAndroidSourceSet? = null
+ var multiFlavorSourceProvider: DefaultAndroidSourceSet? = null
+ var productionVariant: TestedVariantDslInfo? = null
+ var inconsistentTestAppId: Boolean = false
+
+ fun addProductFlavor(
+ productFlavor: ProductFlavor,
+ sourceProvider: SourceProvider
+ ) {
+ if (::variantName.isInitialized) {
+ throw RuntimeException("call to getName() before calling all addProductFlavor")
+ }
+ flavors.add(Pair(productFlavor, sourceProvider))
+ }
+
+ private fun createComponentIdentity(): ComponentIdentity = ComponentIdentityImpl(
+ name,
+ flavorName,
+ dimensionCombination.buildType,
+ dimensionCombination.productFlavors
+ )
+
+ private fun createApplicationVariantDslInfo(): ApplicationVariantDslInfo {
+ return ApplicationVariantDslInfoImpl(
+ componentIdentity = createComponentIdentity(),
+ componentType = componentType,
+ defaultConfig = defaultConfig,
+ buildTypeObj = buildType,
+ productFlavorList = flavors.map { it.first },
+ dataProvider = manifestDataProvider,
+ services = variantServices,
+ buildDirectory = buildDirectory,
+ publishInfo = createPublishingInfoForApp(
+ (extension as InternalApplicationExtension).publishing as ApplicationPublishingImpl,
+ variantServices.projectOptions,
+ name,
+ extension.dynamicFeatures.isNotEmpty(),
+ variantServices.issueReporter
+ ),
+ signingConfigOverride = signingConfigOverride,
+ oldExtension = oldExtension,
+ extension = extension
+ )
+ }
+
+ private fun createLibraryVariantDslInfo(): LibraryVariantDslInfo {
+ return LibraryVariantDslInfoImpl(
+ componentIdentity = createComponentIdentity(),
+ componentType = componentType,
+ defaultConfig = defaultConfig,
+ buildTypeObj = buildType,
+ productFlavorList = flavors.map { it.first },
+ dataProvider = manifestDataProvider,
+ services = variantServices,
+ buildDirectory = buildDirectory,
+ publishInfo = createPublishingInfoForLibrary(
+ (extension as InternalLibraryExtension).publishing as LibraryPublishingImpl,
+ variantServices.projectOptions,
+ name,
+ buildType,
+ flavors.map { it.first },
+ extension.buildTypes,
+ extension.productFlavors,
+ variantServices.issueReporter
+ ),
+ oldExtension = oldExtension,
+ extension = extension
+ )
+ }
+
+ private fun createDynamicFeatureVariantDslInfo(): DynamicFeatureVariantDslInfo {
+ return DynamicFeatureVariantDslInfoImpl(
+ componentIdentity = createComponentIdentity(),
+ componentType = componentType,
+ defaultConfig = defaultConfig,
+ buildTypeObj = buildType,
+ productFlavorList = flavors.map { it.first },
+ dataProvider = manifestDataProvider,
+ services = variantServices,
+ buildDirectory = buildDirectory,
+ oldExtension = oldExtension,
+ extension = extension as InternalDynamicFeatureExtension
+ )
+ }
+
+ private fun createTestProjectVariantDslInfo(): TestProjectVariantDslInfo {
+ return TestProjectVariantDslInfoImpl(
+ componentIdentity = createComponentIdentity(),
+ componentType = componentType,
+ defaultConfig = defaultConfig,
+ buildTypeObj = buildType,
+ productFlavorList = flavors.map { it.first },
+ dataProvider = manifestDataProvider,
+ services = variantServices,
+ buildDirectory = buildDirectory,
+ signingConfigOverride = signingConfigOverride,
+ oldExtension = oldExtension,
+ extension = extension as InternalTestExtension
+ )
+ }
+
+ private fun createTestFixturesComponentDslInfo(): TestFixturesComponentDslInfo {
+ return TestFixturesDslInfoImpl(
+ componentIdentity = createComponentIdentity(),
+ componentType = componentType,
+ defaultConfig = defaultConfig,
+ buildTypeObj = buildType,
+ productFlavorList = flavors.map { it.first },
+ mainVariantDslInfo = productionVariant!!,
+ services = variantServices,
+ buildDirectory = buildDirectory,
+ oldExtension = oldExtension,
+ extension = extension
+ )
+ }
+
+ private fun createUnitTestComponentDslInfo(): UnitTestComponentDslInfo {
+ return UnitTestComponentDslInfoImpl(
+ componentIdentity = createComponentIdentity(),
+ componentType = componentType,
+ defaultConfig = defaultConfig,
+ buildTypeObj = buildType,
+ productFlavorList = flavors.map { it.first },
+ dataProvider = manifestDataProvider,
+ services = variantServices,
+ buildDirectory = buildDirectory,
+ testedVariantDslInfo = productionVariant!!,
+ oldExtension = oldExtension,
+ extension = extension as InternalTestedExtension<*, *, *, *>
+ )
+ }
+
+ private fun createAndroidTestComponentDslInfo(): AndroidTestComponentDslInfo {
+ return AndroidTestComponentDslInfoImpl(
+ componentIdentity = createComponentIdentity(),
+ componentType = componentType,
+ defaultConfig = defaultConfig,
+ buildTypeObj = buildType,
+ productFlavorList = flavors.map { it.first },
+ dataProvider = manifestDataProvider,
+ services = variantServices,
+ buildDirectory = buildDirectory,
+ testedVariantDslInfo = productionVariant!!,
+ inconsistentTestAppId = inconsistentTestAppId,
+ signingConfigOverride = signingConfigOverride,
+ oldExtension = oldExtension,
+ extension = extension as InternalTestedExtension<*, *, *, *>
+ )
+ }
+
+ fun createDslInfo(): DslInfoT {
+ return when (componentType) {
+ ComponentTypeImpl.BASE_APK -> createApplicationVariantDslInfo()
+ ComponentTypeImpl.LIBRARY -> createLibraryVariantDslInfo()
+ ComponentTypeImpl.OPTIONAL_APK -> createDynamicFeatureVariantDslInfo()
+ ComponentTypeImpl.TEST_APK -> createTestProjectVariantDslInfo()
+ ComponentTypeImpl.TEST_FIXTURES -> createTestFixturesComponentDslInfo()
+ ComponentTypeImpl.UNIT_TEST -> createUnitTestComponentDslInfo()
+ ComponentTypeImpl.ANDROID_TEST -> createAndroidTestComponentDslInfo()
+ else -> {
+ throw RuntimeException("Unknown component type ${componentType.name}")
+ }
+ } as DslInfoT
+ }
+
+ fun createVariantSources(): VariantSources {
+ return VariantSources(
+ name,
+ componentType,
+ defaultSourceProvider,
+ buildTypeSourceProvider,
+ flavors.map { it.second }.toImmutableList(),
+ multiFlavorSourceProvider,
+ variantSourceProvider
+ )
+ }
+
+ /**
+ * computes the name for the variant and the multi-flavor combination
+ */
+ private fun computeNames() {
+ variantName = computeName(dimensionCombination, componentType) {
+ multiFlavorName = it
+ }
+ }
+}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/DslInfoCommon.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/DslInfoCommon.kt
new file mode 100644
index 0000000000..08250b9c3a
--- /dev/null
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/DslInfoCommon.kt
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.internal.core.dsl.impl
+
+import com.android.build.api.dsl.ApplicationBuildType
+import com.android.build.api.dsl.BuildType
+import com.android.build.api.dsl.CommonExtension
+import com.android.build.gradle.internal.core.MergedFlavor
+import com.android.build.gradle.internal.core.dsl.ApkProducingComponentDslInfo
+import com.android.build.gradle.internal.core.dsl.ApplicationVariantDslInfo
+import com.android.build.gradle.internal.core.dsl.ComponentDslInfo
+import com.android.build.gradle.internal.core.dsl.TestComponentDslInfo
+import com.android.build.gradle.internal.dsl.DefaultConfig
+import com.android.build.gradle.internal.dsl.InternalTestedExtension
+import com.android.build.gradle.internal.dsl.SigningConfig
+import com.android.build.gradle.internal.manifest.ManifestDataProvider
+import com.android.build.gradle.internal.services.VariantServices
+import com.android.build.gradle.options.BooleanOption
+import com.android.builder.core.BuilderConstants
+import com.android.builder.errors.IssueReporter
+import org.gradle.api.provider.Provider
+
+internal fun TestComponentDslInfo.getTestComponentNamespace(
+ extension: InternalTestedExtension<*, *, *, *>,
+ services: VariantServices,
+ dataProvider: ManifestDataProvider
+): Provider<String> {
+ return extension.testNamespace?.let {
+ services.provider {
+ if (extension.testNamespace == extension.namespace) {
+ services.issueReporter
+ .reportError(
+ IssueReporter.Type.GENERIC,
+ "namespace and testNamespace have the same value (\"$it\"), which is not allowed."
+ )
+ }
+ it
+ }
+ } ?: extension.namespace?.let { services.provider {"$it.test" } }
+ ?: testedVariantDslInfo.namespace.flatMap { testedVariantNamespace ->
+ dataProvider.manifestData.map { manifestData ->
+ manifestData.packageName ?: "$testedVariantNamespace.test"
+ }
+ }
+}
+
+// Special case for test components and separate test sub-projects
+internal fun ComponentDslInfo.initTestApplicationId(
+ defaultConfig: DefaultConfig,
+ services: VariantServices,
+): Provider<String> {
+ // get first non null testAppId from flavors/default config
+ val testAppIdFromFlavors =
+ productFlavorList.asSequence().map { it.testApplicationId }
+ .firstOrNull { it != null }
+ ?: defaultConfig.testApplicationId
+
+ return if (testAppIdFromFlavors != null) {
+ services.provider { testAppIdFromFlavors }
+ } else if (this is TestComponentDslInfo) {
+ (this.testedVariantDslInfo as? ApkProducingComponentDslInfo)?.applicationId?.map {
+ "$it.test"
+ } ?: namespace
+ } else {
+ namespace
+ }
+}
+
+internal fun ApkProducingComponentDslInfo.getSigningConfig(
+ buildTypeObj: BuildType,
+ mergedFlavor: MergedFlavor,
+ signingConfigOverride: SigningConfig?,
+ extension: CommonExtension<*, *, *, *>,
+ services: VariantServices
+): SigningConfig? {
+ val dslSigningConfig =
+ (buildTypeObj as? ApplicationBuildType)?.signingConfig
+ ?: mergedFlavor.signingConfig
+
+ signingConfigOverride?.let {
+ // use enableV1 and enableV2 from the DSL if the override values are null
+ if (it.enableV1Signing == null) {
+ it.enableV1Signing = dslSigningConfig?.enableV1Signing
+ }
+ if (it.enableV2Signing == null) {
+ it.enableV2Signing = dslSigningConfig?.enableV2Signing
+ }
+ // use enableV3 and enableV4 from the DSL because they're not injectable
+ it.enableV3Signing = dslSigningConfig?.enableV3Signing
+ it.enableV4Signing = dslSigningConfig?.enableV4Signing
+ return it
+ }
+ if (services.projectOptions[BooleanOption.ENABLE_DEFAULT_DEBUG_SIGNING_CONFIG] &&
+ dslSigningConfig == null &&
+ ((this as? ApplicationVariantDslInfo)?.isProfileable == true || isDebuggable)) {
+ return extension.signingConfigs.findByName(BuilderConstants.DEBUG) as SigningConfig?
+ }
+ return dslSigningConfig as SigningConfig?
+}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/DslInfoUtils.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/DslInfoUtils.kt
new file mode 100644
index 0000000000..0088c05fda
--- /dev/null
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/DslInfoUtils.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.internal.core.dsl.impl
+
+import com.android.build.gradle.internal.variant.DimensionCombination
+import com.android.builder.core.ComponentType
+import com.android.utils.appendCapitalized
+import com.android.utils.combineAsCamelCase
+
+internal const val DEFAULT_TEST_RUNNER = "android.test.InstrumentationTestRunner"
+internal const val MULTIDEX_TEST_RUNNER =
+ "com.android.test.runner.MultiDexTestRunner"
+internal const val DEFAULT_HANDLE_PROFILING = false
+internal const val DEFAULT_FUNCTIONAL_TEST = false
+
+/**
+ * Returns the full, unique name of the variant in camel case (starting with a lower case),
+ * including BuildType, Flavors and Test (if applicable).
+ *
+ * This is to be used for the normal variant name. In case of Feature plugin, the library
+ * side will be called the same as for library plugins, while the feature side will add
+ * 'feature' to the name.
+ *
+ * Also computes the flavor name if applicable
+ */
+@JvmOverloads
+fun computeName(
+ dimensionCombination: DimensionCombination,
+ componentType: ComponentType,
+ flavorNameCallback: ((String) -> Unit)? = null
+): String {
+ // compute the flavor name
+ val flavorName = if (dimensionCombination.productFlavors.isEmpty()) {
+ ""
+ } else {
+ combineAsCamelCase(dimensionCombination.productFlavors, Pair<String,String>::second)
+ }
+ flavorNameCallback?.let { it(flavorName) }
+
+ val sb = StringBuilder()
+ val buildType = dimensionCombination.buildType
+ if (buildType == null) {
+ if (flavorName.isNotEmpty()) {
+ sb.append(flavorName)
+ } else if (!componentType.isTestComponent && !componentType.isTestFixturesComponent) {
+ sb.append("main")
+ }
+ } else {
+ if (flavorName.isNotEmpty()) {
+ sb.append(flavorName)
+ sb.appendCapitalized(buildType)
+ } else {
+ sb.append(buildType)
+ }
+ }
+ if (componentType.isNestedComponent) {
+ if (sb.isEmpty()) {
+ // need the lower case version
+ sb.append(componentType.prefix)
+ } else {
+ sb.append(componentType.suffix)
+ }
+ }
+ return sb.toString()
+}
+
+/**
+ * Turns a string into a valid source set name for the given [ComponentType], e.g.
+ * "fooBarUnitTest" becomes "testFooBar".
+ */
+fun computeSourceSetName(
+ baseName: String,
+ componentType: ComponentType
+): String {
+ var name = baseName
+ if (name.endsWith(componentType.suffix)) {
+ name = name.substring(0, name.length - componentType.suffix.length)
+ }
+ if (componentType.prefix.isNotEmpty()) {
+ name = componentType.prefix.appendCapitalized(name)
+ }
+ return name
+}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/DynamicFeatureVariantDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/DynamicFeatureVariantDslInfoImpl.kt
new file mode 100644
index 0000000000..482a78a90b
--- /dev/null
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/DynamicFeatureVariantDslInfoImpl.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.internal.core.dsl.impl
+
+import com.android.build.api.dsl.ApplicationBuildType
+import com.android.build.api.dsl.BuildType
+import com.android.build.api.dsl.ProductFlavor
+import com.android.build.api.variant.ComponentIdentity
+import com.android.build.gradle.BaseExtension
+import com.android.build.gradle.internal.core.dsl.DynamicFeatureVariantDslInfo
+import com.android.build.gradle.internal.dsl.DefaultConfig
+import com.android.build.gradle.internal.dsl.InternalDynamicFeatureExtension
+import com.android.build.gradle.internal.dsl.SigningConfig
+import com.android.build.gradle.internal.manifest.ManifestDataProvider
+import com.android.build.gradle.internal.profile.ProfilingMode
+import com.android.build.gradle.internal.services.VariantServices
+import com.android.build.gradle.options.StringOption
+import com.android.builder.core.ComponentType
+import org.gradle.api.file.DirectoryProperty
+
+internal class DynamicFeatureVariantDslInfoImpl(
+ componentIdentity: ComponentIdentity,
+ componentType: ComponentType,
+ defaultConfig: DefaultConfig,
+ buildTypeObj: BuildType,
+ productFlavorList: List<ProductFlavor>,
+ dataProvider: ManifestDataProvider,
+ services: VariantServices,
+ buildDirectory: DirectoryProperty,
+ oldExtension: BaseExtension?,
+ extension: InternalDynamicFeatureExtension
+) : TestedVariantDslInfoImpl(
+ componentIdentity,
+ componentType,
+ defaultConfig,
+ buildTypeObj,
+ productFlavorList,
+ dataProvider,
+ services,
+ buildDirectory,
+ oldExtension,
+ extension
+), DynamicFeatureVariantDslInfo {
+
+ // TODO: Dynamic feature variant doesn't have isDebuggable dsl in the build type, we should only
+ // have `debug` variants be debuggable
+ override val isDebuggable: Boolean
+ get() = ProfilingMode.getProfilingModeType(
+ services.projectOptions[StringOption.PROFILING_MODE]
+ ).isDebuggable
+ ?: (buildTypeObj as? ApplicationBuildType)?.isDebuggable
+ ?: false
+
+ override val signingConfig: SigningConfig? = null
+ override val isSigningReady: Boolean = false
+ override val isMultiDexSetFromDsl: Boolean
+ get() = (buildTypeObj as? ApplicationBuildType)?.multiDexEnabled != null
+}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/InstrumentedTestDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/InstrumentedTestDslInfoImpl.kt
new file mode 100644
index 0000000000..1d901f42c8
--- /dev/null
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/InstrumentedTestDslInfoImpl.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.internal.core.dsl.impl
+
+import com.android.build.api.dsl.ProductFlavor
+import com.android.build.gradle.internal.core.dsl.InstrumentedTestComponentDslInfo
+import com.android.build.gradle.internal.dsl.DefaultConfig
+import com.android.build.gradle.internal.manifest.ManifestDataProvider
+import com.android.build.gradle.internal.services.VariantServices
+import com.android.builder.dexing.DexingType
+import com.android.builder.dexing.isLegacyMultiDexMode
+import org.gradle.api.provider.Provider
+
+internal class InstrumentedTestDslInfoImpl(
+ private val productFlavorList: List<ProductFlavor>,
+ private val defaultConfig: DefaultConfig,
+ private val dataProvider: ManifestDataProvider,
+ private val services: VariantServices,
+ override val instrumentationRunnerArguments: Map<String, String>
+): InstrumentedTestComponentDslInfo {
+ override fun getInstrumentationRunner(dexingType: DexingType): Provider<String> {
+ // first check whether the DSL has the info
+ val fromFlavor =
+ productFlavorList.asSequence().map { it.testInstrumentationRunner }
+ .firstOrNull { it != null }
+ ?: defaultConfig.testInstrumentationRunner
+
+ if (fromFlavor != null) {
+ val finalFromFlavor: String = fromFlavor
+ return services.provider{ finalFromFlavor }
+ }
+
+ // else return the value from the Manifest
+ return dataProvider.manifestData.map {
+ it.instrumentationRunner
+ ?: if (dexingType.isLegacyMultiDexMode()) {
+ MULTIDEX_TEST_RUNNER
+ } else {
+ DEFAULT_TEST_RUNNER
+ }
+ }
+ }
+
+ override val handleProfiling: Provider<Boolean>
+ get() {
+ // first check whether the DSL has the info
+ val fromFlavor =
+ productFlavorList.asSequence().map { it.testHandleProfiling }
+ .firstOrNull { it != null }
+ ?: defaultConfig.testHandleProfiling
+
+ if (fromFlavor != null) {
+ val finalFromFlavor: Boolean = fromFlavor
+ return services.provider { finalFromFlavor }
+ }
+
+ // else return the value from the Manifest
+ return dataProvider.manifestData.map { it.handleProfiling ?: DEFAULT_HANDLE_PROFILING }
+ }
+ override val functionalTest: Provider<Boolean>
+ get() {
+ // first check whether the DSL has the info
+ val fromFlavor =
+ productFlavorList.asSequence().map { it.testFunctionalTest }
+ .firstOrNull { it != null }
+ ?: defaultConfig.testFunctionalTest
+
+ if (fromFlavor != null) {
+ val finalFromFlavor: Boolean = fromFlavor
+ return services.provider { finalFromFlavor }
+ }
+
+ // else return the value from the Manifest
+ return dataProvider.manifestData.map { it.functionalTest ?: DEFAULT_FUNCTIONAL_TEST }
+ }
+ override val testLabel: Provider<String?>
+ get() {
+ // there is actually no DSL value for this.
+ return dataProvider.manifestData.map { it.testLabel }
+ }
+}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/LibraryVariantDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/LibraryVariantDslInfoImpl.kt
new file mode 100644
index 0000000000..2e015c0529
--- /dev/null
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/LibraryVariantDslInfoImpl.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.internal.core.dsl.impl
+
+import com.android.build.api.dsl.BuildType
+import com.android.build.api.dsl.LibraryVariantDimension
+import com.android.build.api.dsl.ProductFlavor
+import com.android.build.api.variant.ComponentIdentity
+import com.android.build.gradle.BaseExtension
+import com.android.build.gradle.internal.core.MergedAarMetadata
+import com.android.build.gradle.internal.core.dsl.LibraryVariantDslInfo
+import com.android.build.gradle.internal.dsl.DefaultConfig
+import com.android.build.gradle.internal.dsl.InternalLibraryExtension
+import com.android.build.gradle.internal.manifest.ManifestDataProvider
+import com.android.build.gradle.internal.profile.ProfilingMode
+import com.android.build.gradle.internal.publishing.VariantPublishingInfo
+import com.android.build.gradle.internal.services.VariantServices
+import com.android.build.gradle.options.StringOption
+import com.android.builder.core.ComponentType
+import org.gradle.api.file.DirectoryProperty
+
+internal class LibraryVariantDslInfoImpl internal constructor(
+ componentIdentity: ComponentIdentity,
+ componentType: ComponentType,
+ defaultConfig: DefaultConfig,
+ buildTypeObj: BuildType,
+ productFlavorList: List<ProductFlavor>,
+ dataProvider: ManifestDataProvider,
+ services: VariantServices,
+ buildDirectory: DirectoryProperty,
+ override val publishInfo: VariantPublishingInfo,
+ oldExtension: BaseExtension?,
+ extension: InternalLibraryExtension
+) : TestedVariantDslInfoImpl(
+ componentIdentity,
+ componentType,
+ defaultConfig,
+ buildTypeObj,
+ productFlavorList,
+ dataProvider,
+ services,
+ buildDirectory,
+ oldExtension,
+ extension
+), LibraryVariantDslInfo {
+
+ override val aarMetadata = MergedAarMetadata()
+
+ init {
+ mergeOptions()
+ }
+
+ private fun mergeOptions() {
+ computeMergedOptions(
+ aarMetadata,
+ { (this as LibraryVariantDimension).aarMetadata },
+ { (this as LibraryVariantDimension).aarMetadata }
+ )
+ }
+
+ // TODO: Library variant doesn't have isDebuggable dsl in the build type, we should only have
+ // `debug` variants be debuggable
+ override val isDebuggable: Boolean
+ get() = ProfilingMode.getProfilingModeType(
+ services.projectOptions[StringOption.PROFILING_MODE]
+ ).isDebuggable
+ ?: (buildTypeObj as? com.android.build.gradle.internal.dsl.BuildType)?.isDebuggable
+ ?: false
+}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/TestFixturesDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/TestFixturesDslInfoImpl.kt
new file mode 100644
index 0000000000..91aabdf73a
--- /dev/null
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/TestFixturesDslInfoImpl.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.internal.core.dsl.impl
+
+import com.android.build.api.dsl.BuildType
+import com.android.build.api.dsl.CommonExtension
+import com.android.build.api.dsl.ProductFlavor
+import com.android.build.api.variant.ComponentIdentity
+import com.android.build.api.variant.impl.MutableAndroidVersion
+import com.android.build.gradle.BaseExtension
+import com.android.build.gradle.internal.core.dsl.PublishableComponentDslInfo
+import com.android.build.gradle.internal.core.dsl.TestFixturesComponentDslInfo
+import com.android.build.gradle.internal.core.dsl.TestedVariantDslInfo
+import com.android.build.gradle.internal.dsl.DefaultConfig
+import com.android.build.gradle.internal.publishing.VariantPublishingInfo
+import com.android.build.gradle.internal.services.VariantServices
+import com.android.build.gradle.internal.testFixtures.testFixturesFeatureName
+import com.android.builder.core.ComponentType
+import org.gradle.api.file.DirectoryProperty
+import org.gradle.api.provider.Property
+import org.gradle.api.provider.Provider
+
+internal class TestFixturesDslInfoImpl(
+ componentIdentity: ComponentIdentity,
+ componentType: ComponentType,
+ defaultConfig: DefaultConfig,
+ buildTypeObj: BuildType,
+ productFlavorList: List<ProductFlavor>,
+ private val mainVariantDslInfo: TestedVariantDslInfo,
+ services: VariantServices,
+ buildDirectory: DirectoryProperty,
+ oldExtension: BaseExtension?,
+ extension: CommonExtension<*, *, *, *>
+) : ComponentDslInfoImpl(
+ componentIdentity,
+ componentType,
+ defaultConfig,
+ buildTypeObj,
+ productFlavorList,
+ services,
+ buildDirectory,
+ oldExtension,
+ extension
+), TestFixturesComponentDslInfo {
+ override val testFixturesAndroidResourcesEnabled: Boolean
+ get() = mainVariantDslInfo.testFixtures.androidResources
+
+ // for test fixtures, these values are always derived from the main variant
+
+ override val namespace: Provider<String> =
+ mainVariantDslInfo.namespace.map { "$it.$testFixturesFeatureName" }
+ override val applicationId: Property<String> = services.newPropertyBackingDeprecatedApi(
+ String::class.java,
+ namespace.map { "$it${computeApplicationIdSuffix()}" }
+ )
+ override val minSdkVersion: MutableAndroidVersion
+ get() = mainVariantDslInfo.minSdkVersion
+ override val maxSdkVersion: Int?
+ get() = mainVariantDslInfo.maxSdkVersion
+ override val targetSdkVersion: MutableAndroidVersion?
+ get() = mainVariantDslInfo.targetSdkVersion
+
+ override val publishInfo: VariantPublishingInfo
+ get() = (mainVariantDslInfo as PublishableComponentDslInfo).publishInfo
+}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/TestProjectVariantDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/TestProjectVariantDslInfoImpl.kt
new file mode 100644
index 0000000000..083b94e0f9
--- /dev/null
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/TestProjectVariantDslInfoImpl.kt
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.internal.core.dsl.impl
+
+import com.android.build.api.dsl.ApplicationBuildType
+import com.android.build.api.dsl.BuildType
+import com.android.build.api.dsl.ProductFlavor
+import com.android.build.api.variant.ComponentIdentity
+import com.android.build.gradle.BaseExtension
+import com.android.build.gradle.internal.core.dsl.TestProjectVariantDslInfo
+import com.android.build.gradle.internal.dsl.DefaultConfig
+import com.android.build.gradle.internal.dsl.InternalTestExtension
+import com.android.build.gradle.internal.dsl.SigningConfig
+import com.android.build.gradle.internal.manifest.ManifestDataProvider
+import com.android.build.gradle.internal.profile.ProfilingMode
+import com.android.build.gradle.internal.services.VariantServices
+import com.android.build.gradle.options.StringOption
+import com.android.build.gradle.options.Version
+import com.android.builder.core.ComponentType
+import com.android.builder.dexing.DexingType
+import com.android.builder.errors.IssueReporter
+import org.gradle.api.file.DirectoryProperty
+import org.gradle.api.provider.Property
+import org.gradle.api.provider.Provider
+
+internal class TestProjectVariantDslInfoImpl(
+ componentIdentity: ComponentIdentity,
+ componentType: ComponentType,
+ defaultConfig: DefaultConfig,
+ buildTypeObj: BuildType,
+ productFlavorList: List<ProductFlavor>,
+ dataProvider: ManifestDataProvider,
+ services: VariantServices,
+ buildDirectory: DirectoryProperty,
+ private val signingConfigOverride: SigningConfig?,
+ oldExtension: BaseExtension?,
+ extension: InternalTestExtension
+) : VariantDslInfoImpl(
+ componentIdentity,
+ componentType,
+ defaultConfig,
+ buildTypeObj,
+ productFlavorList,
+ dataProvider,
+ services,
+ buildDirectory,
+ oldExtension,
+ extension
+), TestProjectVariantDslInfo {
+
+ override val namespace: Provider<String> by lazy {
+ // -------------
+ // Special case for separate test sub-projects
+ // If there is no namespace from the DSL or package attribute in the manifest, we use
+ // testApplicationId, if present. This allows the test project to not have a manifest if
+ // all is declared in the DSL.
+ // TODO(b/170945282, b/172361895) Remove this special case - users should use namespace
+ // DSL instead of testApplicationId DSL for this... currently a warning
+ if (extension.namespace != null) {
+ services.provider { extension.namespace!! }
+ } else {
+ val testAppIdFromFlavors =
+ productFlavorList.asSequence().map { it.testApplicationId }
+ .firstOrNull { it != null }
+ ?: defaultConfig.testApplicationId
+
+ dataProvider.manifestData.map {
+ it.packageName
+ ?: testAppIdFromFlavors?.also {
+ val message =
+ "Namespace not specified. Please specify a namespace for " +
+ "the generated R and BuildConfig classes via " +
+ "android.namespace in the test module's " +
+ "build.gradle file. Currently, this test module " +
+ "uses the testApplicationId " +
+ "($testAppIdFromFlavors) as its namespace, but " +
+ "version ${Version.VERSION_8_0} of the Android " +
+ "Gradle Plugin will require that a namespace be " +
+ "specified explicitly like so:\n\n" +
+ "android {\n" +
+ " namespace '$testAppIdFromFlavors'\n" +
+ "}\n\n"
+ services.issueReporter
+ .reportWarning(IssueReporter.Type.GENERIC, message)
+ }
+ ?: throw RuntimeException(
+ getMissingPackageNameErrorMessage(dataProvider.manifestLocation)
+ )
+ }
+ }
+ }
+
+ override val applicationId: Property<String> =
+ services.newPropertyBackingDeprecatedApi(
+ String::class.java,
+ initTestApplicationId(defaultConfig, services)
+ )
+
+ // TODO: Test project doesn't have isDebuggable dsl in the build type, we should only have
+ // `debug` variants be debuggable
+ override val isDebuggable: Boolean
+ get() = ProfilingMode.getProfilingModeType(
+ services.projectOptions[StringOption.PROFILING_MODE]
+ ).isDebuggable
+ ?: (buildTypeObj as? ApplicationBuildType)?.isDebuggable
+ ?: false
+
+ override val signingConfig: SigningConfig? by lazy {
+ getSigningConfig(
+ buildTypeObj,
+ mergedFlavor,
+ signingConfigOverride,
+ extension,
+ services
+ )
+ }
+
+ override val isSigningReady: Boolean
+ get() = signingConfig?.isSigningReady == true
+
+ private val instrumentedTestDelegate by lazy {
+ InstrumentedTestDslInfoImpl(
+ productFlavorList,
+ defaultConfig,
+ dataProvider,
+ services,
+ mergedFlavor.testInstrumentationRunnerArguments
+ )
+ }
+
+ override fun getInstrumentationRunner(dexingType: DexingType): Provider<String> {
+ return instrumentedTestDelegate.getInstrumentationRunner(dexingType)
+ }
+
+ override val instrumentationRunnerArguments: Map<String, String>
+ get() = instrumentedTestDelegate.instrumentationRunnerArguments
+ override val handleProfiling: Provider<Boolean>
+ get() = instrumentedTestDelegate.handleProfiling
+ override val functionalTest: Provider<Boolean>
+ get() = instrumentedTestDelegate.functionalTest
+ override val testLabel: Provider<String?>
+ get() = instrumentedTestDelegate.testLabel
+}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/TestedVariantDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/TestedVariantDslInfoImpl.kt
new file mode 100644
index 0000000000..7eab99c2f4
--- /dev/null
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/TestedVariantDslInfoImpl.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.internal.core.dsl.impl
+
+import com.android.build.api.dsl.BuildType
+import com.android.build.api.dsl.ProductFlavor
+import com.android.build.api.dsl.TestFixtures
+import com.android.build.api.variant.ComponentIdentity
+import com.android.build.gradle.BaseExtension
+import com.android.build.gradle.internal.core.dsl.TestedVariantDslInfo
+import com.android.build.gradle.internal.dsl.DefaultConfig
+import com.android.build.gradle.internal.dsl.InternalTestedExtension
+import com.android.build.gradle.internal.manifest.ManifestDataProvider
+import com.android.build.gradle.internal.services.VariantServices
+import com.android.builder.core.ComponentType
+import org.gradle.api.file.DirectoryProperty
+
+internal abstract class TestedVariantDslInfoImpl internal constructor(
+ componentIdentity: ComponentIdentity,
+ componentType: ComponentType,
+ defaultConfig: DefaultConfig,
+ buildTypeObj: BuildType,
+ productFlavorList: List<ProductFlavor>,
+ dataProvider: ManifestDataProvider,
+ services: VariantServices,
+ buildDirectory: DirectoryProperty,
+ oldExtension: BaseExtension?,
+ extension: InternalTestedExtension<*, *, *, *>
+) : VariantDslInfoImpl(
+ componentIdentity,
+ componentType,
+ defaultConfig,
+ buildTypeObj,
+ productFlavorList,
+ dataProvider,
+ services,
+ buildDirectory,
+ oldExtension,
+ extension
+), TestedVariantDslInfo {
+
+ override val testFixtures: TestFixtures = extension.testFixtures
+
+ override val testInstrumentationRunnerArguments: Map<String, String>
+ get() = mergedFlavor.testInstrumentationRunnerArguments
+}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/UnitTestComponentDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/UnitTestComponentDslInfoImpl.kt
new file mode 100644
index 0000000000..020b3a1b68
--- /dev/null
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/UnitTestComponentDslInfoImpl.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.internal.core.dsl.impl
+
+import com.android.build.api.dsl.BuildType
+import com.android.build.api.dsl.ProductFlavor
+import com.android.build.api.variant.ComponentIdentity
+import com.android.build.api.variant.impl.MutableAndroidVersion
+import com.android.build.gradle.BaseExtension
+import com.android.build.gradle.internal.core.dsl.TestedVariantDslInfo
+import com.android.build.gradle.internal.core.dsl.UnitTestComponentDslInfo
+import com.android.build.gradle.internal.dsl.DefaultConfig
+import com.android.build.gradle.internal.dsl.InternalTestedExtension
+import com.android.build.gradle.internal.manifest.ManifestDataProvider
+import com.android.build.gradle.internal.services.VariantServices
+import com.android.builder.core.ComponentType
+import org.gradle.api.file.DirectoryProperty
+import org.gradle.api.provider.Property
+import org.gradle.api.provider.Provider
+
+internal class UnitTestComponentDslInfoImpl(
+ componentIdentity: ComponentIdentity,
+ componentType: ComponentType,
+ defaultConfig: DefaultConfig,
+ buildTypeObj: BuildType,
+ productFlavorList: List<ProductFlavor>,
+ dataProvider: ManifestDataProvider,
+ services: VariantServices,
+ buildDirectory: DirectoryProperty,
+ override val testedVariantDslInfo: TestedVariantDslInfo,
+ oldExtension: BaseExtension?,
+ extension: InternalTestedExtension<*, *, *, *>
+) : ComponentDslInfoImpl(
+ componentIdentity,
+ componentType,
+ defaultConfig,
+ buildTypeObj,
+ productFlavorList,
+ services,
+ buildDirectory,
+ oldExtension,
+ extension
+), UnitTestComponentDslInfo {
+
+ override val namespace: Provider<String> by lazy {
+ getTestComponentNamespace(extension, services, dataProvider)
+ }
+
+ override val applicationId: Property<String> =
+ services.newPropertyBackingDeprecatedApi(
+ String::class.java,
+ initTestApplicationId(defaultConfig, services)
+ )
+
+ override val minSdkVersion: MutableAndroidVersion
+ get() = testedVariantDslInfo.minSdkVersion
+ override val maxSdkVersion: Int?
+ get() = testedVariantDslInfo.maxSdkVersion
+ override val targetSdkVersion: MutableAndroidVersion?
+ get() = testedVariantDslInfo.targetSdkVersion
+
+ override val isUnitTestCoverageEnabled: Boolean
+ get() = buildTypeObj.enableUnitTestCoverage || buildTypeObj.isTestCoverageEnabled
+}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/VariantDslInfoImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/VariantDslInfoImpl.kt
new file mode 100644
index 0000000000..54a74c1055
--- /dev/null
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/core/dsl/impl/VariantDslInfoImpl.kt
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.internal.core.dsl.impl
+
+import com.android.build.api.dsl.ApplicationProductFlavor
+import com.android.build.api.dsl.BuildType
+import com.android.build.api.dsl.CommonExtension
+import com.android.build.api.dsl.Lint
+import com.android.build.api.dsl.PackagingOptions
+import com.android.build.api.dsl.ProductFlavor
+import com.android.build.api.variant.ComponentIdentity
+import com.android.build.api.variant.impl.MutableAndroidVersion
+import com.android.build.gradle.BaseExtension
+import com.android.build.gradle.internal.ProguardFileType
+import com.android.build.gradle.internal.core.MergedExternalNativeBuildOptions
+import com.android.build.gradle.internal.core.MergedNdkConfig
+import com.android.build.gradle.internal.core.NativeBuiltType
+import com.android.build.gradle.internal.core.dsl.VariantDslInfo
+import com.android.build.gradle.internal.cxx.configure.ninja
+import com.android.build.gradle.internal.dsl.CoreExternalNativeBuildOptions
+import com.android.build.gradle.internal.dsl.CoreNdkOptions
+import com.android.build.gradle.internal.dsl.DefaultConfig
+import com.android.build.gradle.internal.manifest.ManifestDataProvider
+import com.android.build.gradle.internal.services.VariantServices
+import com.android.builder.core.ComponentType
+import org.gradle.api.file.DirectoryProperty
+import org.gradle.api.file.RegularFile
+import org.gradle.api.provider.ListProperty
+import org.gradle.api.provider.Property
+import org.gradle.api.provider.Provider
+import java.io.File
+
+internal abstract class VariantDslInfoImpl internal constructor(
+ componentIdentity: ComponentIdentity,
+ componentType: ComponentType,
+ defaultConfig: DefaultConfig,
+ buildTypeObj: BuildType,
+ productFlavorList: List<ProductFlavor>,
+ protected val dataProvider: ManifestDataProvider,
+ services: VariantServices,
+ buildDirectory: DirectoryProperty,
+ oldExtension: BaseExtension?,
+ extension: CommonExtension<*, *, *, *>
+) : ConsumableComponentDslInfoImpl(
+ componentIdentity,
+ componentType,
+ defaultConfig,
+ buildTypeObj,
+ productFlavorList,
+ services,
+ buildDirectory,
+ oldExtension,
+ extension
+), VariantDslInfo {
+
+ // merged options
+
+ override val ndkConfig: MergedNdkConfig = MergedNdkConfig()
+ override val externalNativeBuildOptions = MergedExternalNativeBuildOptions()
+
+ override val externalNativeExperimentalProperties: Map<String, Any>
+ get() {
+ // merge global and variant properties
+ val mergedProperties = mutableMapOf<String, Any>()
+ mergedProperties.putAll(extension.externalNativeBuild.experimentalProperties)
+ mergedProperties.putAll(
+ externalNativeBuildOptions.externalNativeExperimentalProperties
+ )
+ return mergedProperties
+ }
+
+ init {
+ mergeOptions()
+ }
+
+ private fun mergeOptions() {
+ computeMergedOptions(
+ ndkConfig,
+ { ndk as CoreNdkOptions },
+ { ndk as CoreNdkOptions }
+ )
+ computeMergedOptions(
+ externalNativeBuildOptions,
+ { externalNativeBuild as CoreExternalNativeBuildOptions },
+ { externalNativeBuild as CoreExternalNativeBuildOptions }
+ )
+ }
+
+ // merged flavor delegates
+
+ override val minSdkVersion: MutableAndroidVersion
+ // if there's a testedVariant, return its value, otherwise return the merged flavor
+ // value. If there's no value set, then the default is just the first API Level: 1
+ get() = mergedFlavor.minSdkVersion?.let { MutableAndroidVersion(it.apiLevel, it.codename) }
+ ?: MutableAndroidVersion(1)
+ override val maxSdkVersion: Int?
+ get() = mergedFlavor.maxSdkVersion
+ override val targetSdkVersion: MutableAndroidVersion?
+ // if there's a testedVariant, return its value, otherwise return the merged flavor
+ // value. If there's no value set, then return null
+ get() = mergedFlavor.targetSdkVersion?.let { MutableAndroidVersion(it.apiLevel, it.codename) }
+
+ // build type delegates
+
+ override val isJniDebuggable: Boolean
+ get() = buildTypeObj.isJniDebuggable
+
+ // extension delegates
+
+ // For main variants we get the namespace from the DSL or read it from the manifest.
+ override val namespace: Provider<String> by lazy {
+ extension.namespace?.let { services.provider { it } }
+ ?: dataProvider.manifestData.map {
+ it.packageName
+ ?: throw RuntimeException(
+ getMissingPackageNameErrorMessage(dataProvider.manifestLocation)
+ )
+ }
+ }
+
+ override val applicationId: Property<String> by lazy {
+ services.newPropertyBackingDeprecatedApi(
+ String::class.java,
+ initApplicationId()
+ )
+ }
+
+ override val nativeBuildSystem: NativeBuiltType?
+ get() {
+ if (externalNativeExperimentalProperties.ninja.path != null) return NativeBuiltType.NINJA
+ if (extension.externalNativeBuild.ndkBuild.path != null) return NativeBuiltType.NDK_BUILD
+ if (extension.externalNativeBuild.cmake.path != null) return NativeBuiltType.CMAKE
+ return null
+ }
+
+ override val supportedAbis: Set<String>
+ get() = if (componentType.isDynamicFeature) setOf() else ndkConfig.abiFilters
+
+ override fun getProguardFiles(into: ListProperty<RegularFile>) {
+ val result: MutableList<File> = ArrayList(gatherProguardFiles(ProguardFileType.EXPLICIT))
+ if (result.isEmpty()) {
+ result.addAll(postProcessingOptions.getDefaultProguardFiles())
+ }
+
+ val projectDir = services.projectInfo.projectDirectory
+ result.forEach { file ->
+ into.add(projectDir.file(file.absolutePath))
+ }
+ }
+
+
+ override val lintOptions: Lint
+ get() = extension.lint
+ override val packaging: PackagingOptions
+ get() = extension.packagingOptions
+ override val experimentalProperties: Map<String, Any>
+ get() = extension.experimentalProperties
+
+ // helper methods
+
+ private fun initApplicationId(): Provider<String> {
+ // get first non null appId from flavors/default config
+ val appIdFromFlavors =
+ productFlavorList
+ .asSequence()
+ .filterIsInstance(ApplicationProductFlavor::class.java)
+ .map { it.applicationId }
+ .firstOrNull { it != null }
+ ?: defaultConfig.applicationId
+
+ return if (appIdFromFlavors == null) {
+ // No appId value set from DSL; use the namespace value from the DSL or manifest.
+ // using map will allow us to keep task dependency should the manifest be generated
+ // or transformed via a task.
+ namespace.map { "$it${computeApplicationIdSuffix()}" }
+ } else {
+ // use value from flavors/defaultConfig
+ // needed to make nullability work in kotlinc
+ val finalAppIdFromFlavors: String = appIdFromFlavors
+ services.provider { "$finalAppIdFromFlavors${computeApplicationIdSuffix()}" }
+ }
+ }
+
+ protected fun getMissingPackageNameErrorMessage(manifestLocation: String): String =
+ "Package Name not found in $manifestLocation, and namespace not specified. Please " +
+ "specify a namespace for the generated R and BuildConfig classes via " +
+ "android.namespace in the module's build.gradle file like so:\n\n" +
+ "android {\n" +
+ " namespace 'com.example.namespace'\n" +
+ "}\n\n"
+}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/coverage/JacocoPropertiesTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/coverage/JacocoPropertiesTask.kt
index a12f867bfb..b38398e926 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/coverage/JacocoPropertiesTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/coverage/JacocoPropertiesTask.kt
@@ -19,10 +19,12 @@ import com.android.build.gradle.internal.component.ComponentCreationConfig
import com.android.build.gradle.internal.component.ConsumableCreationConfig
import com.android.build.gradle.internal.pipeline.OriginalStream
import com.android.build.gradle.internal.scope.InternalArtifactType
+import com.android.build.gradle.internal.tasks.BuildAnalyzer
import com.android.build.gradle.internal.tasks.NonIncrementalTask
import com.android.build.gradle.internal.tasks.factory.VariantTaskCreationAction
import com.android.build.gradle.internal.utils.setDisallowChanges
import com.android.builder.utils.zipEntry
+import com.android.ide.common.attribution.TaskCategoryLabel
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskProvider
@@ -43,6 +45,7 @@ import java.util.jar.JarOutputStream
* simply executing the task.
*/
@DisableCachingByDefault
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.TEST])
abstract class JacocoPropertiesTask : NonIncrementalTask() {
@get:OutputFile
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/configure/ExperimentalPropertyExtensions.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/configure/ExperimentalPropertyExtensions.kt
index 696e515ba3..2783c47390 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/configure/ExperimentalPropertyExtensions.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/configure/ExperimentalPropertyExtensions.kt
@@ -121,9 +121,42 @@ private fun Map<String, Any>.propertyAsSet(name : String) : Set<String> {
*/
private fun Map<String, Any>.propertyAsList(name : String) : List<String> {
val value = get(name) ?: return listOf()
+ return propertyValueAsList(value)
+}
+
+/**
+ * Convert [Any] from Gradle DSL to a List<String>.
+ */
+private fun propertyValueAsList(value : Any) : List<String> {
return when (value) {
is List<*> -> value.map { "$it" }
is Set<*> -> value.map { "$it" }
- else -> error("${value.javaClass}")
+ else -> error("Could not convert from ${value.javaClass} to List<String>")
+ }
+}
+
+/**
+ * This is the experimental flag analog of [com.android.build.api.dsl.PrefabPackagingOptions].
+ */
+data class PrefabExperimentalPackagingOptions(
+ /**
+ * export_libraries may specify either literal arguments to be used as-is, intra-package
+ * references, or inter-package references. This field is optional.
+ */
+ val exportLibraries : List<String>?
+)
+
+/**
+ * Retrieve user's experimental settings for an individual Prefab publishing module.
+ */
+fun VariantCreationConfig.getPrefabExperimentalPackagingOptions(module : String)
+ : PrefabExperimentalPackagingOptions {
+ var exportLibraries : List<String>? = null
+ for((key, value) in externalNativeExperimentalProperties) {
+ if (key != "prefab.${module}.exportLibraries") continue
+ exportLibraries = propertyValueAsList(value)
}
+ return PrefabExperimentalPackagingOptions(
+ exportLibraries = exportLibraries
+ )
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/model/CreateCxxAbiModel.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/model/CreateCxxAbiModel.kt
index 2f90297992..4a2d77bddc 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/model/CreateCxxAbiModel.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/model/CreateCxxAbiModel.kt
@@ -88,6 +88,7 @@ fun createCxxAbiModel(
},
buildSettings = createBuildSettingsFromFile(module.buildSettingsFile),
fullConfigurationHash = configurationHash,
+ fullConfigurationHashKey = "",
configurationArguments = listOf(),
isActiveAbi = validAbiList.contains(abi),
prefabFolder = join(variantCxxBuildFolder, "prefab", abi.tag),
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/model/CxxAbiModel.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/model/CxxAbiModel.kt
index fda7ba770b..73b4f2415a 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/model/CxxAbiModel.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/model/CxxAbiModel.kt
@@ -99,6 +99,11 @@ data class CxxAbiModel(
val fullConfigurationHash: String,
/**
+ * The string value used to calculate [fullConfigurationHash]
+ */
+ val fullConfigurationHashKey: String,
+
+ /**
* The inputs used to compute [fullConfigurationHash]
*/
val configurationArguments: List<String>,
@@ -440,6 +445,13 @@ val CxxAbiModel.platformCode
} ?: ""
/**
+ * File that holds the key for the hashed subfolder.
+ * ex, $moduleRootFolder/.cxx/Debug/{hashcode}/hash_key.txt
+ */
+val CxxAbiModel.cxxBuildHashKeyFile : File get() =
+ cxxBuildFolder.parentFile.resolve("hash_key.txt")
+
+/**
* Construct a ninja command-line with [args] at the end.
*/
fun CxxAbiModel.createNinjaCommand(args: List<String>) : List<String> {
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/model/JsonUtil.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/model/JsonUtil.kt
index 77787f90d5..2513402358 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/model/JsonUtil.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/model/JsonUtil.kt
@@ -16,7 +16,9 @@
package com.android.build.gradle.internal.cxx.model
+import com.android.build.gradle.internal.cxx.io.writeTextIfDifferent
import com.android.build.gradle.internal.cxx.json.PlainFileGsonTypeAdaptor
+import com.android.build.gradle.internal.cxx.json.jsonStringOf
import com.android.repository.Revision
import com.google.gson.GsonBuilder
import com.google.gson.TypeAdapter
@@ -83,6 +85,8 @@ fun createCxxAbiModelFromJson(json: String): CxxAbiModel {
fun CxxAbiModel.writeJsonToFile() {
modelOutputFile.parentFile.mkdirs()
modelOutputFile.writeText(toJsonString())
+ cxxBuildHashKeyFile.parentFile.mkdirs()
+ cxxBuildHashKeyFile.writeTextIfDifferent(fullConfigurationHashKey)
}
/**
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/prefab/CreatePublicationModel.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/prefab/CreatePublicationModel.kt
index 9230edb2fc..4dda257ecf 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/prefab/CreatePublicationModel.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/prefab/CreatePublicationModel.kt
@@ -17,6 +17,7 @@
package com.android.build.gradle.internal.cxx.prefab
import com.android.build.gradle.internal.component.LibraryCreationConfig
+import com.android.build.gradle.internal.cxx.configure.getPrefabExperimentalPackagingOptions
import com.android.build.gradle.internal.cxx.gradle.generator.CxxConfigurationModel
import com.android.build.gradle.internal.cxx.logging.errorln
import com.android.build.gradle.internal.cxx.model.jsonFile
@@ -37,6 +38,7 @@ fun createPrefabPublication(
configurationModel: CxxConfigurationModel,
libraryVariant : LibraryCreationConfig
) : PrefabPublication {
+
val abis = configurationModel.activeAbis.map { abi ->
PrefabAbiPublication(
abiName = abi.abi.tag,
@@ -48,12 +50,15 @@ fun createPrefabPublication(
)
}
val modules = libraryVariant.global.prefab.map { options ->
+ val experimentalSettings = libraryVariant.getPrefabExperimentalPackagingOptions(options.name)
+
PrefabModulePublication(
moduleName = options.name,
moduleLibraryName = options.libraryName,
moduleHeaders = options.headers?.let { headers ->
libraryVariant.services.projectInfo.projectDirectory.dir(headers).asFile.absoluteFile
},
+ moduleExportLibraries = experimentalSettings.exportLibraries ?: listOf(),
abis = abis
)
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/prefab/PackageBuilder.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/prefab/PackageBuilder.kt
index c3d79f9d37..98acb5a911 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/prefab/PackageBuilder.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/prefab/PackageBuilder.kt
@@ -141,7 +141,7 @@ private class PrefabPackageBuilder(
writeJsonFileIfDifferent(
moduleDir.resolve("module.json"),
ModuleMetadataV1(
- exportLibraries = emptyList(),
+ exportLibraries = module.moduleExportLibraries,
libraryName = module.moduleLibraryName
)
)
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/prefab/PublicationModel.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/prefab/PublicationModel.kt
index d3055f4d5a..bc21b41dd7 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/prefab/PublicationModel.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/prefab/PublicationModel.kt
@@ -68,6 +68,9 @@ data class PrefabModulePublication(
val moduleHeaders : File?,
@get:Input
@get:Optional
+ val moduleExportLibraries : List<String>,
+ @get:Input
+ @get:Optional
val moduleLibraryName : String?,
@get:Nested
val abis : List<PrefabAbiPublication>
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/settings/CxxAbiModelSettingsRewriter.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/settings/CxxAbiModelSettingsRewriter.kt
index 6c8b0b60fd..3c2791941d 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/settings/CxxAbiModelSettingsRewriter.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/cxx/settings/CxxAbiModelSettingsRewriter.kt
@@ -90,6 +90,7 @@ import com.google.common.collect.Lists
import org.gradle.api.file.ProjectLayout
import org.gradle.api.provider.ProviderFactory
import java.io.File
+import com.android.Version
/**
* Rewrite the CxxAbiModel in three phases:
@@ -189,27 +190,78 @@ private fun CxxAbiModel.supportNdkR14AndEarlier() : CxxAbiModel {
}
/**
- * Calculate hash and plug it into the model.
+ * Calculate hash and plug it into the model. Return the new model along with the text that
+ * was hashed.
+ *
+ * The user can pass arbitrary parameters to CMake (or ndk-build) so we can't guard against every
+ * case that could make the hash local-machine-specific. This is best effort, works in the default
+ * case, and we provide the hash_key.txt file (written later) to be able to diagnose problems.
+ * The consequence of a non-portable paths is that hypothetical caching tech (ccache, reclient,
+ * gomacc, etc) may not be able to share results. However, build results will still be accurate.
*/
-private fun CxxAbiModel.calculateConfigurationHash() =
- copy(fullConfigurationHash = sha256Of(configurationArguments))
+private fun CxxAbiModel.calculateConfigurationHash() : CxxAbiModel {
+ var header =
+ """
+ # Values used to calculate the hash in this folder name.
+ # Should not depend on the absolute path of the project itself.
+ # - AGP: ${Version.ANDROID_GRADLE_PLUGIN_VERSION}.
+ # - ${'$'}NDK is the path to NDK ${variant.module.ndkVersion}.
+ # - ${'$'}PROJECT is the path to the parent folder of the root Gradle build file.
+ # - ${'$'}ABI is the ABI to be built with. The specific value doesn't contribute to the value of the hash.
+ # - ${'$'}HASH is the hash value computed from this text.
+
+ """.trimIndent()
+
+ var arguments = configurationArguments.joinToString("\n")
+ .replace(variant.module.ndkFolder.path, "\$NDK")
+ .replace(variant.module.project.rootBuildGradleFolder.path, "\$PROJECT")
+ .replace(NDK_ABI.ref, "\$ABI")
+ .replace(NDK_CONFIGURATION_HASH.ref, "\$HASH")
+
+ if (variant.module.cmake != null) {
+ header += """
+ # - ${'$'}CMAKE is the path to CMake ${variant.module.cmake.minimumCmakeVersion}.
+
+ """.trimIndent()
+ arguments = arguments.replace(variant.module.cmake.cmakeExe!!.path, "\$CMAKE")
+
+ }
+
+ if (variant.module.ninjaExe != null) {
+ header += """
+ # - ${'$'}NINJA is the path to Ninja.
+
+ """.trimIndent()
+ arguments = arguments.replace(variant.module.ninjaExe.path, "\$NINJA")
+ }
+
+ val hashKey = header + arguments.replace("\\", "/")
+
+ return copy(
+ fullConfigurationHash = sha256Of(hashKey, includeGradleVersionInHash = false),
+ fullConfigurationHashKey = hashKey
+ )
+}
/**
* Finally, expand all of the post-hash macros.
*/
-private fun CxxAbiModel.expandConfigurationHashMacros() = rewrite { _, value ->
- reifyString(value) { tokenMacro ->
- when(tokenMacro) {
- NDK_ABI.qualifiedName,
- NDK_CONFIGURATION_HASH.qualifiedName,
- NDK_FULL_CONFIGURATION_HASH.qualifiedName -> {
- val macro = Macro.lookup(tokenMacro) ?: error("Unrecognized macro: $tokenMacro")
- resolveMacroValue(macro)
+private fun CxxAbiModel.expandConfigurationHashMacros() : CxxAbiModel {
+ val result = rewrite { _, value ->
+ reifyString(value) { tokenMacro ->
+ when(tokenMacro) {
+ NDK_ABI.qualifiedName,
+ NDK_CONFIGURATION_HASH.qualifiedName,
+ NDK_FULL_CONFIGURATION_HASH.qualifiedName -> {
+ val macro = Macro.lookup(tokenMacro) ?: error("Unrecognized macro: $tokenMacro")
+ resolveMacroValue(macro)
+ }
+ else ->
+ error(tokenMacro)
}
- else ->
- error(tokenMacro)
}
}
+ return result
}
/**
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dependency/VariantDependenciesBuilder.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dependency/VariantDependenciesBuilder.java
index 4a89d11469..95969820ed 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dependency/VariantDependenciesBuilder.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dependency/VariantDependenciesBuilder.java
@@ -44,7 +44,8 @@ import com.android.build.gradle.internal.api.DefaultAndroidSourceSet;
import com.android.build.gradle.internal.attributes.VariantAttr;
import com.android.build.gradle.internal.component.VariantCreationConfig;
import com.android.build.gradle.internal.core.dsl.ComponentDslInfo;
-import com.android.build.gradle.internal.core.dsl.PublishableVariantDslInfo;
+import com.android.build.gradle.internal.core.dsl.PublishableComponentDslInfo;
+import com.android.build.gradle.internal.core.dsl.VariantDslInfo;
import com.android.build.gradle.internal.dsl.AbstractPublishing;
import com.android.build.gradle.internal.dsl.ModulePropertyKeys;
import com.android.build.gradle.internal.publishing.AndroidArtifacts;
@@ -63,6 +64,7 @@ import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -424,182 +426,177 @@ public class VariantDependenciesBuilder {
if (componentType.getPublishToRepository()) {
VariantPublishingInfo variantPublish =
- ((PublishableVariantDslInfo) dslInfo).getPublishInfo();
- if (variantPublish != null) {
- // if the variant is a library, we need to make both a runtime and an API
- // configurations, and they both must contain transitive dependencies
- if (componentType.isAar()) {
- LibraryElements aar =
- factory.named(
- LibraryElements.class,
- AndroidArtifacts.ArtifactType.AAR.getType());
- LibraryElements jar = factory.named(LibraryElements.class, LibraryElements.JAR);
- Bundling bundling = factory.named(Bundling.class, EXTERNAL);
- Category library = factory.named(Category.class, Category.LIBRARY);
- Category documentation = factory.named(Category.class, Category.DOCUMENTATION);
- DocsType sources = factory.named(DocsType.class, DocsType.SOURCES);
- DocsType javaDoc = factory.named(DocsType.class, DocsType.JAVADOC);
-
- for (ComponentPublishingInfo component : variantPublish.getComponents()) {
-
- String buildTypeAttribute = null;
- Map<Attribute<ProductFlavorAttr>, ProductFlavorAttr> flavorAttributes =
- Maps.newHashMap();
- if (component.getAttributesConfig() != null) {
- buildTypeAttribute = component.getAttributesConfig().getBuildType();
- for (String dimensionName :
- component.getAttributesConfig().getFlavorDimensions()) {
- Attribute<ProductFlavorAttr> attribute =
- ProductFlavorAttr.of(dimensionName);
- flavorAttributes.put(
- attribute,
- requireNonNull(publicationFlavorMap.get(attribute)));
- }
+ ((PublishableComponentDslInfo) dslInfo).getPublishInfo();
+ // if the variant is a library, we need to make both a runtime and an API
+ // configurations, and they both must contain transitive dependencies
+ if (componentType.isAar()) {
+ LibraryElements aar =
+ factory.named(
+ LibraryElements.class, AndroidArtifacts.ArtifactType.AAR.getType());
+ LibraryElements jar = factory.named(LibraryElements.class, LibraryElements.JAR);
+ Bundling bundling = factory.named(Bundling.class, EXTERNAL);
+ Category library = factory.named(Category.class, Category.LIBRARY);
+ Category documentation = factory.named(Category.class, Category.DOCUMENTATION);
+ DocsType sources = factory.named(DocsType.class, DocsType.SOURCES);
+ DocsType javaDoc = factory.named(DocsType.class, DocsType.JAVADOC);
+
+ for (ComponentPublishingInfo component : variantPublish.getComponents()) {
+
+ String buildTypeAttribute = null;
+ Map<Attribute<ProductFlavorAttr>, ProductFlavorAttr> flavorAttributes =
+ Maps.newHashMap();
+ if (component.getAttributesConfig() != null) {
+ buildTypeAttribute = component.getAttributesConfig().getBuildType();
+ for (String dimensionName :
+ component.getAttributesConfig().getFlavorDimensions()) {
+ Attribute<ProductFlavorAttr> attribute =
+ ProductFlavorAttr.of(dimensionName);
+ flavorAttributes.put(
+ attribute, requireNonNull(publicationFlavorMap.get(attribute)));
}
+ }
- String capitalizedComponentName =
- StringHelper.usLocaleCapitalize(component.getComponentName());
-
- Configuration apiPublication =
+ String capitalizedComponentName =
+ StringHelper.usLocaleCapitalize(component.getComponentName());
+
+ Configuration apiPublication =
+ createLibraryPublishingConfiguration(
+ configurations,
+ variantName
+ + "Variant"
+ + capitalizedComponentName
+ + "ApiPublication",
+ capitalizedComponentName
+ + "component API publication for "
+ + variantName,
+ apiUsage,
+ aar,
+ bundling,
+ library,
+ null,
+ buildTypeAttribute,
+ flavorAttributes);
+ apiPublication.setExtendsFrom(apiClasspaths);
+ elements.put(
+ new PublishedConfigSpec(API_PUBLICATION, component), apiPublication);
+
+ Configuration runtimePublication =
+ createLibraryPublishingConfiguration(
+ configurations,
+ variantName
+ + "Variant"
+ + capitalizedComponentName
+ + "RuntimePublication",
+ capitalizedComponentName
+ + "Runtime publication for "
+ + variantName,
+ runtimeUsage,
+ aar,
+ bundling,
+ library,
+ null,
+ buildTypeAttribute,
+ flavorAttributes);
+ runtimePublication.extendsFrom(runtimeClasspath);
+ elements.put(
+ new PublishedConfigSpec(RUNTIME_PUBLICATION, component),
+ runtimePublication);
+
+ if (component.getWithSourcesJar()) {
+ Configuration sourcePublication =
createLibraryPublishingConfiguration(
configurations,
variantName
+ "Variant"
+ capitalizedComponentName
- + "ApiPublication",
+ + "SourcePublication",
capitalizedComponentName
- + "component API publication for "
+ + "Source publication for"
+ variantName,
- apiUsage,
- aar,
+ runtimeUsage,
+ jar,
bundling,
- library,
- null,
+ documentation,
+ sources,
buildTypeAttribute,
flavorAttributes);
- apiPublication.setExtendsFrom(apiClasspaths);
+
elements.put(
- new PublishedConfigSpec(API_PUBLICATION, component),
- apiPublication);
+ new PublishedConfigSpec(SOURCE_PUBLICATION, component),
+ sourcePublication);
+ }
- Configuration runtimePublication =
+ if (component.getWithJavadocJar()) {
+ Configuration javaDocPublication =
createLibraryPublishingConfiguration(
configurations,
variantName
+ "Variant"
+ capitalizedComponentName
- + "RuntimePublication",
+ + "JavaDocPublication",
capitalizedComponentName
- + "Runtime publication for "
+ + "JavaDoc publication for"
+ variantName,
runtimeUsage,
- aar,
+ jar,
bundling,
- library,
- null,
+ documentation,
+ javaDoc,
buildTypeAttribute,
flavorAttributes);
- runtimePublication.extendsFrom(runtimeClasspath);
elements.put(
- new PublishedConfigSpec(RUNTIME_PUBLICATION, component),
- runtimePublication);
-
- if (component.getWithSourcesJar()) {
- Configuration sourcePublication =
- createLibraryPublishingConfiguration(
- configurations,
- variantName
- + "Variant"
- + capitalizedComponentName
- + "SourcePublication",
- capitalizedComponentName
- + "Source publication for"
- + variantName,
- runtimeUsage,
- jar,
- bundling,
- documentation,
- sources,
- buildTypeAttribute,
- flavorAttributes);
-
- elements.put(
- new PublishedConfigSpec(SOURCE_PUBLICATION, component),
- sourcePublication);
- }
-
- if (component.getWithJavadocJar()) {
- Configuration javaDocPublication =
- createLibraryPublishingConfiguration(
- configurations,
- variantName
- + "Variant"
- + capitalizedComponentName
- + "JavaDocPublication",
- capitalizedComponentName
- + "JavaDoc publication for"
- + variantName,
- runtimeUsage,
- jar,
- bundling,
- documentation,
- javaDoc,
- buildTypeAttribute,
- flavorAttributes);
- elements.put(
- new PublishedConfigSpec(JAVA_DOC_PUBLICATION, component),
- javaDocPublication);
- }
+ new PublishedConfigSpec(JAVA_DOC_PUBLICATION, component),
+ javaDocPublication);
}
- } else {
- // For APK, no transitive dependencies, and no api vs runtime configs.
- // However we have 2 publications, one for bundle, one for Apk
- for (ComponentPublishingInfo component : variantPublish.getComponents()) {
- if (component.getType() == AbstractPublishing.Type.APK) {
- Configuration apkPublication =
- createPublishingConfig(
- configurations,
- variantName + "ApkPublication",
- "APK publication for " + variantName,
- buildType,
- publicationFlavorMap,
- null /*variantNameAttr*/,
- null /*Usage*/,
- factory.named(
- LibraryElements.class,
- AndroidArtifacts.ArtifactType.APK.getType()),
- null);
- elements.put(
- new PublishedConfigSpec(
- APK_PUBLICATION, component.getComponentName(), false),
- apkPublication);
- apkPublication.setVisible(false);
- apkPublication.setCanBeConsumed(false);
- } else {
- assert component.getType() == AbstractPublishing.Type.AAB
- : "Publication artifact type for this application project "
- + "is not APK or AAB.";
-
- Configuration aabPublication =
- createPublishingConfig(
- configurations,
- variantName + "AabPublication",
- "Bundle Publication for " + variantName,
- buildType,
- publicationFlavorMap,
- null /*variantNameAttr*/,
- null /*Usage*/,
- factory.named(
- LibraryElements.class,
- AndroidArtifacts.ArtifactType.BUNDLE.getType()),
- null);
- elements.put(
- new PublishedConfigSpec(
- AAB_PUBLICATION, component.getComponentName(), false),
- aabPublication);
- aabPublication.setVisible(false);
- aabPublication.setCanBeConsumed(false);
- }
+ }
+ } else {
+ // For APK, no transitive dependencies, and no api vs runtime configs.
+ // However we have 2 publications, one for bundle, one for Apk
+ for (ComponentPublishingInfo component : variantPublish.getComponents()) {
+ if (component.getType() == AbstractPublishing.Type.APK) {
+ Configuration apkPublication =
+ createPublishingConfig(
+ configurations,
+ variantName + "ApkPublication",
+ "APK publication for " + variantName,
+ buildType,
+ publicationFlavorMap,
+ null /*variantNameAttr*/,
+ null /*Usage*/,
+ factory.named(
+ LibraryElements.class,
+ AndroidArtifacts.ArtifactType.APK.getType()),
+ null);
+ elements.put(
+ new PublishedConfigSpec(
+ APK_PUBLICATION, component.getComponentName(), false),
+ apkPublication);
+ apkPublication.setVisible(false);
+ apkPublication.setCanBeConsumed(false);
+ } else {
+ assert component.getType() == AbstractPublishing.Type.AAB
+ : "Publication artifact type for this application project "
+ + "is not APK or AAB.";
+
+ Configuration aabPublication =
+ createPublishingConfig(
+ configurations,
+ variantName + "AabPublication",
+ "Bundle Publication for " + variantName,
+ buildType,
+ publicationFlavorMap,
+ null /*variantNameAttr*/,
+ null /*Usage*/,
+ factory.named(
+ LibraryElements.class,
+ AndroidArtifacts.ArtifactType.BUNDLE.getType()),
+ null);
+ elements.put(
+ new PublishedConfigSpec(
+ AAB_PUBLICATION, component.getComponentName(), false),
+ aabPublication);
+ aabPublication.setVisible(false);
+ aabPublication.setCanBeConsumed(false);
}
}
}
@@ -674,9 +671,16 @@ public class VariantDependenciesBuilder {
configuration.getOutgoing().capability(capability));
}
+ Map<String, Object> experimentalProperties;
+
+ if (dslInfo instanceof VariantDslInfo) {
+ experimentalProperties = ((VariantDslInfo) dslInfo).getExperimentalProperties();
+ } else {
+ experimentalProperties = Collections.emptyMap();
+ }
+
boolean isSelfInstrumenting =
- ModulePropertyKeys.SELF_INSTRUMENTING.getValueAsBoolean(
- dslInfo.getExperimentalProperties());
+ ModulePropertyKeys.SELF_INSTRUMENTING.getValueAsBoolean(experimentalProperties);
return new VariantDependencies(
variantName,
dslInfo.getComponentType(),
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/InternalApplicationExtension.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/InternalApplicationExtension.kt
index cb5a22ecd2..49d8d1c237 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/InternalApplicationExtension.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/InternalApplicationExtension.kt
@@ -29,8 +29,7 @@ import org.gradle.api.Action
/** See [InternalCommonExtension] */
interface InternalApplicationExtension :
ApplicationExtension,
- InternalTestedExtension,
- InternalCommonExtension<
+ InternalTestedExtension<
ApplicationBuildFeatures,
ApplicationBuildType,
ApplicationDefaultConfig,
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/InternalDynamicFeatureExtension.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/InternalDynamicFeatureExtension.kt
index 12ada143b2..ac038f2380 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/InternalDynamicFeatureExtension.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/InternalDynamicFeatureExtension.kt
@@ -25,8 +25,7 @@ import com.android.build.api.dsl.DynamicFeatureProductFlavor
/** See [InternalCommonExtension] */
interface InternalDynamicFeatureExtension :
DynamicFeatureExtension,
- InternalTestedExtension,
- InternalCommonExtension<
+ InternalTestedExtension<
DynamicFeatureBuildFeatures,
DynamicFeatureBuildType,
DynamicFeatureDefaultConfig,
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/InternalLibraryExtension.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/InternalLibraryExtension.kt
index 38f7bbe2b9..e4a04de779 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/InternalLibraryExtension.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/InternalLibraryExtension.kt
@@ -27,8 +27,7 @@ import org.gradle.api.Action
/** See [InternalCommonExtension] */
interface InternalLibraryExtension :
LibraryExtension,
- InternalTestedExtension,
- InternalCommonExtension<
+ InternalTestedExtension<
LibraryBuildFeatures,
LibraryBuildType,
LibraryDefaultConfig,
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/InternalTestedExtension.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/InternalTestedExtension.kt
index a63005a365..1c8ea263b2 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/InternalTestedExtension.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/InternalTestedExtension.kt
@@ -21,6 +21,11 @@ import com.android.build.api.dsl.TestedExtension
import org.gradle.api.Action
/** See [InternalCommonExtension] */
-interface InternalTestedExtension: TestedExtension {
+interface InternalTestedExtension<BuildFeaturesT : com.android.build.api.dsl.BuildFeatures,
+ BuildTypeT : com.android.build.api.dsl.BuildType,
+ DefaultConfigT : com.android.build.api.dsl.DefaultConfig,
+ ProductFlavorT : com.android.build.api.dsl.ProductFlavor>
+ : TestedExtension,
+ InternalCommonExtension<BuildFeaturesT, BuildTypeT, DefaultConfigT, ProductFlavorT> {
fun testFixtures(action: Action<TestFixtures>)
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/feature/BundleAllClasses.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/feature/BundleAllClasses.kt
index 7dd0a54551..d0b2db1889 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/feature/BundleAllClasses.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/feature/BundleAllClasses.kt
@@ -24,9 +24,11 @@ import com.android.build.gradle.internal.packaging.JarCreatorType
import com.android.build.gradle.internal.profile.ProfileAwareWorkAction
import com.android.build.gradle.internal.publishing.AndroidArtifacts
import com.android.build.gradle.internal.scope.InternalArtifactType
+import com.android.build.gradle.internal.tasks.BuildAnalyzer
import com.android.build.gradle.internal.tasks.NonIncrementalTask
import com.android.build.gradle.internal.tasks.factory.VariantTaskCreationAction
import com.android.build.gradle.internal.utils.fromDisallowChanges
+import com.android.ide.common.attribution.TaskCategoryLabel
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.FileVisitDetails
import org.gradle.api.file.RegularFileProperty
@@ -54,6 +56,7 @@ import java.util.zip.Deflater
* simply executing the task.
*/
@DisableCachingByDefault
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.ZIPPING])
abstract class BundleAllClasses : NonIncrementalTask() {
@get:OutputFile
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/fusedlibrary/FusedLibraryPluginUtils.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/fusedlibrary/FusedLibraryPluginUtils.kt
new file mode 100644
index 0000000000..c7d5659334
--- /dev/null
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/fusedlibrary/FusedLibraryPluginUtils.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.internal.fusedlibrary
+
+import com.android.build.api.artifact.Artifact
+import com.android.build.api.artifact.impl.ArtifactsImpl
+import com.android.build.api.attributes.BuildTypeAttr
+import com.android.build.gradle.internal.DependencyConfigurator
+import com.android.build.gradle.internal.SdkComponentsBuildService
+import com.android.build.gradle.internal.publishing.AndroidArtifacts
+import com.android.build.gradle.internal.services.DslServices
+import com.android.build.gradle.internal.services.DslServicesImpl
+import com.android.build.gradle.internal.services.ProjectServices
+import com.android.build.gradle.internal.tasks.factory.TaskCreationAction
+import com.android.build.gradle.internal.tasks.factory.TaskFactoryImpl
+import org.gradle.api.DefaultTask
+import org.gradle.api.Project
+import org.gradle.api.artifacts.Configuration
+import org.gradle.api.artifacts.component.ComponentIdentifier
+import org.gradle.api.attributes.Usage
+import org.gradle.api.file.RegularFile
+import org.gradle.api.provider.Provider
+import org.gradle.api.specs.Spec
+
+fun createTasks(
+ project: Project,
+ artifacts: ArtifactsImpl,
+ artifactForPublication: Artifact.Single<RegularFile>,
+ tasksCreationActions: List<TaskCreationAction<out DefaultTask>>
+) {
+ val taskProviders = TaskFactoryImpl(project.tasks).let { taskFactory ->
+ tasksCreationActions.map { creationAction ->
+ taskFactory.register(creationAction)
+ }
+ }
+
+ // create anchor tasks
+ project.tasks.register("assemble") { assembleTask ->
+ artifactForPublication?.let { artifactTypeForPublication ->
+ assembleTask.dependsOn(artifacts.get(artifactTypeForPublication))
+ } ?: taskProviders.forEach { assembleTask.dependsOn(it) }
+ }
+}
+
+fun configureTransforms(project: Project, projectServices: ProjectServices) {
+ DependencyConfigurator(project, projectServices)
+ .configureGeneralTransforms(namespacedAndroidResources = false)
+}
+
+fun getDslServices(project: Project, projectServices: ProjectServices): DslServices {
+ val sdkComponentsBuildService: Provider<SdkComponentsBuildService> =
+ SdkComponentsBuildService.RegistrationAction(
+ project,
+ projectServices.projectOptions
+ ).execute()
+
+ return DslServicesImpl(projectServices, sdkComponentsBuildService)
+}
+
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/ide/SourceProviderImpl.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/ide/SourceProviderImpl.java
index f9a7e593ec..2d6bb94aa3 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/ide/SourceProviderImpl.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/ide/SourceProviderImpl.java
@@ -87,7 +87,7 @@ final class SourceProviderImpl implements SourceProvider, Serializable {
this.manifestFile = sourceProvider.getManifestFile();
this.javaDirs = getSourcesForIdeModel(variantSources.getJava());
this.kotlinDirs = getSourcesForIdeModel(variantSources.getKotlin());
- this.resourcesDirs = sourceProvider.getResourcesDirectories();
+ this.resourcesDirs = getSourcesForIdeModel(variantSources.getResources());
this.aidlDirs = sourceProvider.getAidlDirectories();
this.rsDirs = sourceProvider.getRenderscriptDirectories();
this.resDirs =
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/ide/v2/Converters.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/ide/v2/Converters.kt
index 5831ad78d4..37b6726884 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/ide/v2/Converters.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/ide/v2/Converters.kt
@@ -213,7 +213,7 @@ internal fun DefaultAndroidSourceSet.convert(
manifestFile = manifestFile,
javaDirectories = variantSourcesForModel(sources.java),
kotlinDirectories = variantSourcesForModel(sources.kotlin),
- resourcesDirectories = resourcesDirectories,
+ resourcesDirectories = variantSourcesForModel(sources.resources),
aidlDirectories = if (features.aidl) aidlDirectories else null,
renderscriptDirectories = if (features.renderScript) renderscriptDirectories else null,
resDirectories = if (features.androidResources) variantSourcesForModel(sources.res) else null,
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/lint/AndroidLintAnalysisTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/lint/AndroidLintAnalysisTask.kt
index 2c530bb721..c52445c2ad 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/lint/AndroidLintAnalysisTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/lint/AndroidLintAnalysisTask.kt
@@ -26,6 +26,7 @@ import com.android.build.gradle.internal.publishing.AndroidArtifacts
import com.android.build.gradle.internal.scope.InternalArtifactType
import com.android.build.gradle.internal.services.TaskCreationServices
import com.android.build.gradle.internal.services.getBuildService
+import com.android.build.gradle.internal.services.getLintParallelBuildService
import com.android.build.gradle.internal.tasks.BuildAnalyzer
import com.android.build.gradle.internal.tasks.NonIncrementalTask
import com.android.build.gradle.internal.tasks.factory.VariantTaskCreationAction
@@ -354,6 +355,9 @@ abstract class AndroidLintAnalysisTask : NonIncrementalTask() {
}
systemPropertyInputs.initialize(project.providers, LintMode.ANALYSIS)
environmentVariableInputs.initialize(project.providers, LintMode.ANALYSIS)
+ this.usesService(
+ services.buildServiceRegistry.getLintParallelBuildService(services.projectOptions)
+ )
}
fun configureForStandalone(
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/lint/AndroidLintInputs.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/lint/AndroidLintInputs.kt
index 7fc3007e13..e2d9cb5ec4 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/lint/AndroidLintInputs.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/lint/AndroidLintInputs.kt
@@ -42,6 +42,7 @@ import com.android.build.gradle.internal.publishing.AndroidArtifacts
import com.android.build.gradle.internal.scope.InternalArtifactType
import com.android.build.gradle.internal.scope.ProjectInfo
import com.android.build.gradle.internal.services.LintClassLoaderBuildService
+import com.android.build.gradle.internal.services.LintParallelBuildService
import com.android.build.gradle.internal.services.TaskCreationServices
import com.android.build.gradle.internal.services.getBuildService
import com.android.build.gradle.internal.utils.fromDisallowChanges
@@ -255,7 +256,10 @@ abstract class LintTool {
// Default to using the main Gradle daemon heap size to smooth the transition
// for build authors.
it.forkOptions.maxHeapSize =
- workerHeapSize.orNull ?: "${Runtime.getRuntime().maxMemory() / 1024 / 1024}m"
+ LintParallelBuildService.calculateLintHeapSize(
+ workerHeapSize.orNull,
+ Runtime.getRuntime().maxMemory()
+ )
}
}
workQueue.submit(AndroidLintWorkAction::class.java) { parameters ->
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/AbstractFusedLibraryPlugin.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/AbstractFusedLibraryPlugin.kt
deleted file mode 100644
index 88a62d7070..0000000000
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/AbstractFusedLibraryPlugin.kt
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * 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 com.android.build.gradle.internal.plugins
-
-import com.android.build.api.artifact.Artifact
-import com.android.build.api.attributes.BuildTypeAttr
-import com.android.build.gradle.internal.DependencyConfigurator
-import com.android.build.gradle.internal.SdkComponentsBuildService
-import com.android.build.gradle.internal.fusedlibrary.FusedLibraryVariantScope
-import com.android.build.gradle.internal.fusedlibrary.SegregatingConstraintHandler
-import com.android.build.gradle.internal.publishing.AndroidArtifacts
-import com.android.build.gradle.internal.services.Aapt2DaemonBuildService
-import com.android.build.gradle.internal.services.Aapt2ThreadPoolBuildService
-import com.android.build.gradle.internal.services.DslServicesImpl
-import com.android.build.gradle.internal.tasks.factory.TaskCreationAction
-import com.android.build.gradle.internal.tasks.factory.TaskFactoryImpl
-import com.google.wireless.android.sdk.stats.GradleBuildProfileSpan
-import groovy.namespace.QName
-import groovy.util.Node
-import org.gradle.api.DefaultTask
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-import org.gradle.api.artifacts.ArtifactCollection
-import org.gradle.api.artifacts.Configuration
-import org.gradle.api.artifacts.component.LibraryBinaryIdentifier
-import org.gradle.api.artifacts.component.ModuleComponentIdentifier
-import org.gradle.api.artifacts.component.ProjectComponentIdentifier
-import org.gradle.api.attributes.Usage
-import org.gradle.api.component.SoftwareComponentFactory
-import org.gradle.api.file.RegularFile
-import org.gradle.api.provider.Provider
-import org.gradle.api.publish.maven.MavenPom
-import org.gradle.api.publish.maven.MavenPublication
-import org.gradle.build.event.BuildEventsListenerRegistry
-import org.gradle.internal.component.external.model.ModuleComponentArtifactIdentifier
-
-abstract class AbstractFusedLibraryPlugin (
- protected val softwareComponentFactory: SoftwareComponentFactory,
- listenerRegistry: BuildEventsListenerRegistry,
-): AndroidPluginBaseServices(listenerRegistry), Plugin<Project> {
-
- val dslServices by lazy {
- withProject("dslServices") { project ->
- val sdkComponentsBuildService: Provider<SdkComponentsBuildService> =
- SdkComponentsBuildService.RegistrationAction(
- project,
- projectServices.projectOptions
- ).execute()
-
- DslServicesImpl(
- projectServices,
- sdkComponentsBuildService
- )
- }
- }
-
- abstract val variantScope: FusedLibraryVariantScope
-
- internal fun createTasks(
- project: Project,
- variantScope: FusedLibraryVariantScope,
- tasksCreationActions: List<TaskCreationAction<out DefaultTask>>,
- ) {
- configureTransforms(project)
- val taskProviders = TaskFactoryImpl(project.tasks).let { taskFactory ->
- tasksCreationActions.map { creationAction ->
- taskFactory.register(creationAction)
- }
- }
-
- // create anchor tasks
- project.tasks.register("assemble") { assembleTask ->
- artifactForPublication?.let { artifactTypeForPublication ->
- assembleTask.dependsOn(variantScope.artifacts.get(artifactTypeForPublication))
- } ?: taskProviders.forEach { assembleTask.dependsOn(it) }
- }
- }
-
- /**
- * Returns the artifact type that will be used for maven publication or null if nothing is to
- * be published to maven.
- */
- abstract val artifactForPublication: Artifact.Single<RegularFile>?
-
- abstract val artifactTypeForPublication: AndroidArtifacts.ArtifactType
-
- override fun apply(project: Project) {
- super.basePluginApply(project)
-
- // so far by default, we consume and publish only 'debug' variant
-
- // 'include' is the configuration that users will use to indicate which dependencies should
- // be fused.
- val includeConfigurations = project.configurations.create("include").also {
- it.isCanBeConsumed = false
- val buildType: BuildTypeAttr = project.objects.named(BuildTypeAttr::class.java, "debug")
- it.attributes.attribute(
- BuildTypeAttr.ATTRIBUTE,
- buildType,
- )
- }
-
- // This is the internal configuration that will be used to feed tasks that require access
- // to the resolved 'include' dependency. It is for JAVA_API usage which mean all transitive
- // dependencies that are implementation() scoped will not be included.
- val includeApiClasspath = project.configurations.create("includeApiClasspath").also {
- it.isCanBeConsumed = false
- it.attributes.attribute(
- Usage.USAGE_ATTRIBUTE,
- project.objects.named(Usage::class.java, Usage.JAVA_API)
- )
- val buildType: BuildTypeAttr = project.objects.named(BuildTypeAttr::class.java, "debug")
- it.attributes.attribute(
- BuildTypeAttr.ATTRIBUTE,
- buildType,
- )
- it.extendsFrom(includeConfigurations)
- }
- variantScope.incomingConfigurations.addConfiguration(includeApiClasspath)
-
- // This is the configuration that will contain all the JAVA_API dependencies that are not
- // fused in the resulting aar library.
- val includedApiUnmerged = project.configurations.create("includeApiUnmerged").also {
- it.isCanBeConsumed = true
- it.isCanBeResolved = true
- it.incoming.beforeResolve(
- SegregatingConstraintHandler(
- includeApiClasspath,
- it,
- variantScope.mergeSpec,
- project,
- )
- )
- }
-
- // This is the internal configuration that will be used to feed tasks that require access
- // to the resolved 'include' dependency. It is for JAVA_RUNTIME usage which mean all transitive
- // dependencies that are implementation() scoped will be included.
- val includeRuntimeClasspath = project.configurations.create("includeRuntimeClasspath").also {
- it.isCanBeConsumed = false
- it.isCanBeResolved = true
-
- it.attributes.attribute(
- Usage.USAGE_ATTRIBUTE,
- project.objects.named(Usage::class.java, Usage.JAVA_RUNTIME)
- )
- val buildType: BuildTypeAttr = project.objects.named(BuildTypeAttr::class.java, "debug")
- it.attributes.attribute(
- BuildTypeAttr.ATTRIBUTE,
- buildType,
- )
-
- it.extendsFrom(includeConfigurations)
- }
- variantScope.incomingConfigurations.addConfiguration(includeRuntimeClasspath)
-
- // This is the configuration that will contain all the JAVA_RUNTIME dependencies that are
- // not fused in the resulting aar library.
- val includeRuntimeUnmerged = project.configurations.create("includeRuntimeUnmerged").also {
- it.isCanBeConsumed = false
- it.isCanBeResolved = true
- it.incoming.beforeResolve(
- SegregatingConstraintHandler(
- includeConfigurations,
- it,
- variantScope.mergeSpec,
- project,
- )
- )
- }
-
- // we are only interested in the last provider in the chain of transformers for this bundle.
- // Obviously, this is theoretical at this point since there is no variant API to replace
- // artifacts, there is always only one.
- val bundleTaskProvider = artifactForPublication?.let {
- variantScope
- .artifacts
- .getArtifactContainer(it)
- .getTaskProviders()
- .last()
- }
-
- // this is the outgoing configuration for JAVA_API scoped declarations, it will contain
- // this module and all transitive non merged dependencies
-
- fun configureApiRuntimeElements(elements: Configuration) {
- elements.isCanBeResolved = false
- elements.isCanBeConsumed = true
- elements.isTransitive = true
-
- if (bundleTaskProvider != null) {
- elements.outgoing.variants { variants ->
- variants.create(artifactTypeForPublication.type) {variant ->
- variant.artifact(bundleTaskProvider) { artifact ->
- artifact.type = artifactTypeForPublication.type
- }
- }
- }
- }
- }
-
- val includeApiElements = project.configurations.create("apiElements") { apiElements ->
- configureApiRuntimeElements(apiElements)
- apiElements.attributes.attribute(
- Usage.USAGE_ATTRIBUTE,
- project.objects.named(Usage::class.java, Usage.JAVA_API)
- )
- apiElements.extendsFrom(includedApiUnmerged)
- }
-
- // this is the outgoing configuration for JAVA_RUNTIME scoped declarations, it will contain
- // this module and all transitive non merged dependencies
- val includeRuntimeElements = project.configurations.create("runtimeElements") { runtimeElements ->
- configureApiRuntimeElements(runtimeElements)
- runtimeElements.attributes.attribute(
- Usage.USAGE_ATTRIBUTE,
- project.objects.named(Usage::class.java, Usage.JAVA_RUNTIME)
- )
- runtimeElements.extendsFrom(includeRuntimeUnmerged)
- }
-
- maybePublishToMaven(
- project,
- includeApiElements,
- includeRuntimeElements,
- includeRuntimeUnmerged
- )
- }
-
- override fun configureProject(project: Project) {
- val projectOptions = projectServices.projectOptions
- Aapt2ThreadPoolBuildService.RegistrationAction(project, projectOptions).execute()
- Aapt2DaemonBuildService.RegistrationAction(project, projectOptions).execute()
- }
-
- protected abstract fun maybePublishToMaven(
- project: Project,
- includeApiElements: Configuration,
- includeRuntimeElements: Configuration,
- includeRuntimeUnmerged: Configuration
- )
-
- fun component(
- publication: MavenPublication,
- unmergedArtifacts: ArtifactCollection,
- ) {
-
- publication.pom { pom: MavenPom ->
- pom.withXml { xml ->
- val dependenciesNode = xml.asNode().let {
- it.children().firstOrNull { node ->
- ((node as Node).name() as QName).qualifiedName == "dependencies"
- } ?: it.appendNode("dependencies")
- } as Node
-
- unmergedArtifacts.forEach { artifact ->
- if (artifact.id is ModuleComponentArtifactIdentifier) {
- when (val moduleIdentifier = artifact.id.componentIdentifier) {
- is ModuleComponentIdentifier -> {
- val dependencyNode = dependenciesNode.appendNode("dependency")
- dependencyNode.appendNode("groupId", moduleIdentifier.group)
- dependencyNode.appendNode("artifactId", moduleIdentifier.module)
- dependencyNode.appendNode("version", moduleIdentifier.version)
- dependencyNode.appendNode("scope", "runtime")
- }
- is ProjectComponentIdentifier -> println("Project : ${moduleIdentifier.projectPath}")
- is LibraryBinaryIdentifier -> println("Library : ${moduleIdentifier.projectPath}")
- else -> println("Unknown dependency ${moduleIdentifier.javaClass} : $artifact")
- }
- } else {
- println("Unknown module ${artifact.id.javaClass} : ${artifact.id}")
- }
- }
- }
- }
- }
-
- fun configureTransforms(project: Project) {
- configuratorService.recordBlock(
- GradleBuildProfileSpan.ExecutionType.ARTIFACT_TRANSFORM,
- project.path,
- null
- ) {
- DependencyConfigurator(project, projectServices)
- .configureGeneralTransforms(namespacedAndroidResources = false)
- }
- }
-}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/AbstractPrivacySandboxPlugin.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/AbstractPrivacySandboxPlugin.kt
deleted file mode 100644
index eb252ab2d4..0000000000
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/AbstractPrivacySandboxPlugin.kt
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * 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 com.android.build.gradle.internal.plugins
-
-import com.android.build.api.artifact.Artifact
-import com.android.build.api.attributes.BuildTypeAttr
-import com.android.build.gradle.internal.DependencyConfigurator
-import com.android.build.gradle.internal.SdkComponentsBuildService
-import com.android.build.gradle.internal.fusedlibrary.FusedLibraryVariantScope
-import com.android.build.gradle.internal.fusedlibrary.SegregatingConstraintHandler
-import com.android.build.gradle.internal.privaysandboxsdk.PrivacySandboxSdkVariantScope
-import com.android.build.gradle.internal.publishing.AndroidArtifacts
-import com.android.build.gradle.internal.services.Aapt2DaemonBuildService
-import com.android.build.gradle.internal.services.Aapt2ThreadPoolBuildService
-import com.android.build.gradle.internal.services.DslServicesImpl
-import com.android.build.gradle.internal.tasks.factory.TaskCreationAction
-import com.android.build.gradle.internal.tasks.factory.TaskFactoryImpl
-import com.google.wireless.android.sdk.stats.GradleBuildProfileSpan
-import groovy.namespace.QName
-import groovy.util.Node
-import org.gradle.api.DefaultTask
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-import org.gradle.api.artifacts.ArtifactCollection
-import org.gradle.api.artifacts.Configuration
-import org.gradle.api.artifacts.component.LibraryBinaryIdentifier
-import org.gradle.api.artifacts.component.ModuleComponentIdentifier
-import org.gradle.api.artifacts.component.ProjectComponentIdentifier
-import org.gradle.api.attributes.Usage
-import org.gradle.api.component.SoftwareComponentFactory
-import org.gradle.api.file.RegularFile
-import org.gradle.api.provider.Provider
-import org.gradle.api.publish.maven.MavenPom
-import org.gradle.api.publish.maven.MavenPublication
-import org.gradle.build.event.BuildEventsListenerRegistry
-import org.gradle.internal.component.external.model.ModuleComponentArtifactIdentifier
-
-abstract class AbstractPrivacySandboxPlugin(
- listenerRegistry: BuildEventsListenerRegistry,
-): AndroidPluginBaseServices(listenerRegistry), Plugin<Project> {
-
- val dslServices by lazy {
- withProject("dslServices") { project ->
- val sdkComponentsBuildService: Provider<SdkComponentsBuildService> =
- SdkComponentsBuildService.RegistrationAction(
- project,
- projectServices.projectOptions
- ).execute()
-
- DslServicesImpl(
- projectServices,
- sdkComponentsBuildService
- )
- }
- }
-
- abstract val variantScope: PrivacySandboxSdkVariantScope
-
- internal fun createTasks(
- project: Project,
- variantScope: PrivacySandboxSdkVariantScope,
- tasksCreationActions: List<TaskCreationAction<out DefaultTask>>,
- ) {
- configureTransforms(project)
- val taskProviders = TaskFactoryImpl(project.tasks).let { taskFactory ->
- tasksCreationActions.map { creationAction ->
- taskFactory.register(creationAction)
- }
- }
-
- // create anchor tasks
- project.tasks.register("assemble") { assembleTask ->
- artifactForPublication?.let { artifactTypeForPublication ->
- assembleTask.dependsOn(variantScope.artifacts.get(artifactTypeForPublication))
- } ?: taskProviders.forEach { assembleTask.dependsOn(it) }
- }
- }
-
- /**
- * Returns the artifact type that will be used for maven publication or null if nothing is to
- * be published to maven.
- */
- internal abstract val artifactForPublication: Artifact.Single<RegularFile>?
-
- internal abstract val artifactTypeForPublication: AndroidArtifacts.ArtifactType
-
- override fun apply(project: Project) {
- super.basePluginApply(project)
-
- // so far by default, we consume and publish only 'debug' variant
-
- // 'include' is the configuration that users will use to indicate which dependencies should
- // be fused.
- val includeConfigurations = project.configurations.create("include").also {
- it.isCanBeConsumed = false
- val buildType: BuildTypeAttr = project.objects.named(BuildTypeAttr::class.java, "debug")
- it.attributes.attribute(
- BuildTypeAttr.ATTRIBUTE,
- buildType,
- )
- }
-
- // This is the internal configuration that will be used to feed tasks that require access
- // to the resolved 'include' dependency. It is for JAVA_API usage which mean all transitive
- // dependencies that are implementation() scoped will not be included.
- val includeApiClasspath = project.configurations.create("includeApiClasspath").also {
- it.isCanBeConsumed = false
- it.attributes.attribute(
- Usage.USAGE_ATTRIBUTE,
- project.objects.named(Usage::class.java, Usage.JAVA_API)
- )
- val buildType: BuildTypeAttr = project.objects.named(BuildTypeAttr::class.java, "debug")
- it.attributes.attribute(
- BuildTypeAttr.ATTRIBUTE,
- buildType,
- )
- it.extendsFrom(includeConfigurations)
- }
- variantScope.incomingConfigurations.addConfiguration(includeApiClasspath)
-
- // This is the configuration that will contain all the JAVA_API dependencies that are not
- // fused in the resulting aar library.
- val includedApiUnmerged = project.configurations.create("includeApiUnmerged").also {
- it.isCanBeConsumed = true
- it.isCanBeResolved = true
- it.incoming.beforeResolve(
- SegregatingConstraintHandler(
- includeApiClasspath,
- it,
- variantScope.mergeSpec,
- project,
- )
- )
- }
-
- // This is the internal configuration that will be used to feed tasks that require access
- // to the resolved 'include' dependency. It is for JAVA_RUNTIME usage which mean all transitive
- // dependencies that are implementation() scoped will be included.
- val includeRuntimeClasspath = project.configurations.create("includeRuntimeClasspath").also {
- it.isCanBeConsumed = false
- it.isCanBeResolved = true
-
- it.attributes.attribute(
- Usage.USAGE_ATTRIBUTE,
- project.objects.named(Usage::class.java, Usage.JAVA_RUNTIME)
- )
- val buildType: BuildTypeAttr = project.objects.named(BuildTypeAttr::class.java, "debug")
- it.attributes.attribute(
- BuildTypeAttr.ATTRIBUTE,
- buildType,
- )
-
- it.extendsFrom(includeConfigurations)
- }
- variantScope.incomingConfigurations.addConfiguration(includeRuntimeClasspath)
-
- // This is the configuration that will contain all the JAVA_RUNTIME dependencies that are
- // not fused in the resulting aar library.
- val includeRuntimeUnmerged = project.configurations.create("includeRuntimeUnmerged").also {
- it.isCanBeConsumed = false
- it.isCanBeResolved = true
- it.incoming.beforeResolve(
- SegregatingConstraintHandler(
- includeConfigurations,
- it,
- variantScope.mergeSpec,
- project,
- )
- )
- }
-
- // we are only interested in the last provider in the chain of transformers for this bundle.
- // Obviously, this is theoretical at this point since there is no variant API to replace
- // artifacts, there is always only one.
- val bundleTaskProvider = artifactForPublication?.let {
- variantScope
- .artifacts
- .getArtifactContainer(it)
- .getTaskProviders()
- .last()
- }
-
- // this is the outgoing configuration for JAVA_API scoped declarations, it will contain
- // this module and all transitive non merged dependencies
-
- fun configureApiRuntimeElements(elements: Configuration) {
- elements.isCanBeResolved = false
- elements.isCanBeConsumed = true
- elements.isTransitive = true
-
- if (bundleTaskProvider != null) {
- elements.outgoing.variants { variants ->
- variants.create(artifactTypeForPublication.type) {variant ->
- variant.artifact(bundleTaskProvider) { artifact ->
- artifact.type = artifactTypeForPublication.type
- }
- }
- }
- }
- }
-
- val includeApiElements = project.configurations.create("apiElements") { apiElements ->
- configureApiRuntimeElements(apiElements)
- apiElements.attributes.attribute(
- Usage.USAGE_ATTRIBUTE,
- project.objects.named(Usage::class.java, Usage.JAVA_API)
- )
- }
-
- // this is the outgoing configuration for JAVA_RUNTIME scoped declarations, it will contain
- // this module and all transitive non merged dependencies
- val includeRuntimeElements = project.configurations.create("runtimeElements") { runtimeElements ->
- configureApiRuntimeElements(runtimeElements)
- runtimeElements.attributes.attribute(
- Usage.USAGE_ATTRIBUTE,
- project.objects.named(Usage::class.java, Usage.JAVA_RUNTIME)
- )
- }
- }
-
- override fun configureProject(project: Project) {
- val projectOptions = projectServices.projectOptions
- Aapt2ThreadPoolBuildService.RegistrationAction(project, projectOptions).execute()
- Aapt2DaemonBuildService.RegistrationAction(project, projectOptions).execute()
- }
-
- private fun configureTransforms(project: Project) {
- configuratorService.recordBlock(
- GradleBuildProfileSpan.ExecutionType.ARTIFACT_TRANSFORM,
- project.path,
- null
- ) {
- DependencyConfigurator(project, projectServices)
- .configureGeneralTransforms(namespacedAndroidResources = false)
- }
- }
-}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/FusedLibraryPlugin.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/FusedLibraryPlugin.kt
index 560172ad3e..a98dc55c71 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/FusedLibraryPlugin.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/FusedLibraryPlugin.kt
@@ -17,23 +17,37 @@
package com.android.build.gradle.internal.plugins
import com.android.build.api.artifact.Artifact
+import com.android.build.api.artifact.impl.ArtifactsImpl
import com.android.build.api.attributes.BuildTypeAttr
import com.android.build.api.dsl.FusedLibraryExtension
import com.android.build.gradle.internal.dsl.FusedLibraryExtensionImpl
import com.android.build.gradle.internal.fusedlibrary.FusedLibraryInternalArtifactType
+import com.android.build.gradle.internal.fusedlibrary.FusedLibraryVariantScope
import com.android.build.gradle.internal.fusedlibrary.FusedLibraryVariantScopeImpl
+import com.android.build.gradle.internal.fusedlibrary.SegregatingConstraintHandler
+import com.android.build.gradle.internal.fusedlibrary.configureTransforms
+import com.android.build.gradle.internal.fusedlibrary.createTasks
+import com.android.build.gradle.internal.fusedlibrary.getDslServices
import com.android.build.gradle.internal.publishing.AndroidArtifacts
+import com.android.build.gradle.internal.services.DslServices
import com.android.build.gradle.internal.tasks.MergeJavaResourceTask
import com.android.build.gradle.tasks.FusedLibraryBundleAar
import com.android.build.gradle.tasks.FusedLibraryBundleClasses
-import com.android.build.gradle.tasks.FusedLibraryMergeClasses
import com.android.build.gradle.tasks.FusedLibraryClassesRewriteTask
import com.android.build.gradle.tasks.FusedLibraryManifestMergerTask
import com.android.build.gradle.tasks.FusedLibraryMergeArtifactTask
+import com.android.build.gradle.tasks.FusedLibraryMergeClasses
import com.android.build.gradle.tasks.FusedLibraryMergeResourcesTask
import com.google.wireless.android.sdk.stats.GradleBuildProject
+import groovy.namespace.QName
+import groovy.util.Node
+import org.gradle.api.Plugin
import org.gradle.api.Project
+import org.gradle.api.artifacts.ArtifactCollection
import org.gradle.api.artifacts.Configuration
+import org.gradle.api.artifacts.component.LibraryBinaryIdentifier
+import org.gradle.api.artifacts.component.ModuleComponentIdentifier
+import org.gradle.api.artifacts.component.ProjectComponentIdentifier
import org.gradle.api.attributes.Bundling
import org.gradle.api.attributes.Category
import org.gradle.api.attributes.LibraryElements
@@ -41,18 +55,25 @@ import org.gradle.api.attributes.Usage
import org.gradle.api.component.SoftwareComponentFactory
import org.gradle.api.file.RegularFile
import org.gradle.api.publish.PublishingExtension
+import org.gradle.api.publish.maven.MavenPom
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.build.event.BuildEventsListenerRegistry
+import org.gradle.internal.component.external.model.ModuleComponentArtifactIdentifier
import javax.inject.Inject
@Suppress("UnstableApiUsage")
class FusedLibraryPlugin @Inject constructor(
- softwareComponentFactory: SoftwareComponentFactory,
- listenerRegistry: BuildEventsListenerRegistry,
-): AbstractFusedLibraryPlugin(softwareComponentFactory, listenerRegistry) {
+ private val softwareComponentFactory: SoftwareComponentFactory,
+ listenerRegistry: BuildEventsListenerRegistry,
+) : AndroidPluginBaseServices(listenerRegistry), Plugin<Project> {
+
+ val dslServices: DslServices by lazy(LazyThreadSafetyMode.NONE) {
+ withProject("dslServices") { project ->
+ getDslServices(project, projectServices)
+ }
+ }
- // so far, there is only one variant.
- override val variantScope by lazy {
+ private val variantScope: FusedLibraryVariantScope by lazy(LazyThreadSafetyMode.NONE) {
withProject("variantScope") { project ->
FusedLibraryVariantScopeImpl(
project
@@ -60,45 +81,48 @@ class FusedLibraryPlugin @Inject constructor(
}
}
- private val extension: FusedLibraryExtension by lazy {
+ private val extension: FusedLibraryExtension by lazy(LazyThreadSafetyMode.NONE) {
withProject("extension") { project ->
instantiateExtension(project)
}
}
+ override fun configureProject(project: Project) {
+ }
+
override fun configureExtension(project: Project) {
extension
}
private fun instantiateExtension(project: Project): FusedLibraryExtension {
- val fusedLibraryExtensionImpl= dslServices.newDecoratedInstance(
- FusedLibraryExtensionImpl::class.java,
- dslServices,
+ val fusedLibraryExtensionImpl = dslServices.newDecoratedInstance(
+ FusedLibraryExtensionImpl::class.java,
+ dslServices,
)
abstract class Extension(
- val publicExtensionImpl: FusedLibraryExtensionImpl,
+ val publicExtensionImpl: FusedLibraryExtensionImpl,
): FusedLibraryExtension by publicExtensionImpl
return project.extensions.create(
- FusedLibraryExtension::class.java,
- "android",
- Extension::class.java,
- fusedLibraryExtensionImpl
+ FusedLibraryExtension::class.java,
+ "android",
+ Extension::class.java,
+ fusedLibraryExtensionImpl
)
}
- override fun maybePublishToMaven(
- project: Project,
- includeApiElements: Configuration,
- includeRuntimeElements: Configuration,
- includeRuntimeUnmerged: Configuration
+ private fun maybePublishToMaven(
+ project: Project,
+ includeApiElements: Configuration,
+ includeRuntimeElements: Configuration,
+ includeRuntimeUnmerged: Configuration
) {
val bundleTaskProvider = variantScope
.artifacts
- .getArtifactContainer(artifactForPublication)
+ .getArtifactContainer(FusedLibraryInternalArtifactType.BUNDLED_LIBRARY)
.getTaskProviders()
.last()
@@ -107,27 +131,27 @@ class FusedLibraryPlugin @Inject constructor(
it.isCanBeResolved = false
it.isVisible = false
it.attributes.attribute(
- Usage.USAGE_ATTRIBUTE,
- project.objects.named(Usage::class.java, Usage.JAVA_API)
+ Usage.USAGE_ATTRIBUTE,
+ project.objects.named(Usage::class.java, Usage.JAVA_API)
)
it.attributes.attribute(
- Bundling.BUNDLING_ATTRIBUTE,
- project.objects.named(Bundling::class.java, Bundling.EXTERNAL)
+ Bundling.BUNDLING_ATTRIBUTE,
+ project.objects.named(Bundling::class.java, Bundling.EXTERNAL)
)
it.attributes.attribute(
- Category.CATEGORY_ATTRIBUTE,
- project.objects.named(Category::class.java, Category.LIBRARY)
+ Category.CATEGORY_ATTRIBUTE,
+ project.objects.named(Category::class.java, Category.LIBRARY)
)
it.attributes.attribute(
- LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE,
- project.objects.named(
- LibraryElements::class.java,
- AndroidArtifacts.ArtifactType.AAR.type
- )
+ LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE,
+ project.objects.named(
+ LibraryElements::class.java,
+ AndroidArtifacts.ArtifactType.AAR.type
+ )
)
it.attributes.attribute(
- BuildTypeAttr.ATTRIBUTE,
- project.objects.named(BuildTypeAttr::class.java, "debug")
+ BuildTypeAttr.ATTRIBUTE,
+ project.objects.named(BuildTypeAttr::class.java, "debug")
)
it.extendsFrom(includeApiElements)
variantScope.outgoingConfigurations.addConfiguration(it)
@@ -141,27 +165,27 @@ class FusedLibraryPlugin @Inject constructor(
it.isCanBeResolved = false
it.isVisible = false
it.attributes.attribute(
- Usage.USAGE_ATTRIBUTE,
- project.objects.named(Usage::class.java, Usage.JAVA_RUNTIME)
+ Usage.USAGE_ATTRIBUTE,
+ project.objects.named(Usage::class.java, Usage.JAVA_RUNTIME)
)
it.attributes.attribute(
- Bundling.BUNDLING_ATTRIBUTE,
- project.objects.named(Bundling::class.java, Bundling.EXTERNAL)
+ Bundling.BUNDLING_ATTRIBUTE,
+ project.objects.named(Bundling::class.java, Bundling.EXTERNAL)
)
it.attributes.attribute(
- Category.CATEGORY_ATTRIBUTE,
- project.objects.named(Category::class.java, Category.LIBRARY)
+ Category.CATEGORY_ATTRIBUTE,
+ project.objects.named(Category::class.java, Category.LIBRARY)
)
it.attributes.attribute(
- LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE,
- project.objects.named(
- LibraryElements::class.java,
- AndroidArtifacts.ArtifactType.AAR.type
- )
+ LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE,
+ project.objects.named(
+ LibraryElements::class.java,
+ AndroidArtifacts.ArtifactType.AAR.type
+ )
)
it.attributes.attribute(
- BuildTypeAttr.ATTRIBUTE,
- project.objects.named(BuildTypeAttr::class.java, "debug")
+ BuildTypeAttr.ATTRIBUTE,
+ project.objects.named(BuildTypeAttr::class.java, "debug")
)
it.extendsFrom(includeRuntimeElements)
variantScope.outgoingConfigurations.addConfiguration(it)
@@ -185,19 +209,52 @@ class FusedLibraryPlugin @Inject constructor(
project.afterEvaluate {
project.extensions.findByType(PublishingExtension::class.java)?.also {
component(
- it.publications.create("maven", MavenPublication::class.java)
- .also { mavenPublication ->
- mavenPublication.from(adhocComponent)
- }, includeRuntimeUnmerged.incoming.artifacts
+ it.publications.create("maven", MavenPublication::class.java)
+ .also { mavenPublication ->
+ mavenPublication.from(adhocComponent)
+ }, includeRuntimeUnmerged.incoming.artifacts
)
}
}
}
+ fun component(publication: MavenPublication, unmergedArtifacts: ArtifactCollection) {
+ publication.pom { pom: MavenPom ->
+ pom.withXml { xml ->
+ val dependenciesNode = xml.asNode().let {
+ it.children().firstOrNull { node ->
+ ((node as Node).name() as QName).qualifiedName == "dependencies"
+ } ?: it.appendNode("dependencies")
+ } as Node
+
+ unmergedArtifacts.forEach { artifact ->
+ if (artifact.id is ModuleComponentArtifactIdentifier) {
+ when (val moduleIdentifier = artifact.id.componentIdentifier) {
+ is ModuleComponentIdentifier -> {
+ val dependencyNode = dependenciesNode.appendNode("dependency")
+ dependencyNode.appendNode("groupId", moduleIdentifier.group)
+ dependencyNode.appendNode("artifactId", moduleIdentifier.module)
+ dependencyNode.appendNode("version", moduleIdentifier.version)
+ dependencyNode.appendNode("scope", "runtime")
+ }
+ is ProjectComponentIdentifier -> println("Project : ${moduleIdentifier.projectPath}")
+ is LibraryBinaryIdentifier -> println("Library : ${moduleIdentifier.projectPath}")
+ else -> println("Unknown dependency ${moduleIdentifier.javaClass} : $artifact")
+ }
+ } else {
+ println("Unknown module ${artifact.id.javaClass} : ${artifact.id}")
+ }
+ }
+ }
+ }
+ }
+
override fun createTasks(project: Project) {
+ configureTransforms(project, projectServices)
createTasks(
project,
- variantScope,
+ variantScope.artifacts,
+ FusedLibraryInternalArtifactType.BUNDLED_LIBRARY,
listOf(
FusedLibraryClassesRewriteTask.CreationAction(variantScope),
FusedLibraryManifestMergerTask.CreationAction(variantScope),
@@ -210,12 +267,157 @@ class FusedLibraryPlugin @Inject constructor(
)
}
- override fun getAnalyticsPluginType(): GradleBuildProject.PluginType =
- GradleBuildProject.PluginType.FUSED_LIBRARIES
+ override fun getAnalyticsPluginType(): GradleBuildProject.PluginType =
+ GradleBuildProject.PluginType.FUSED_LIBRARIES
+
+ override fun apply(project: Project) {
+ super.basePluginApply(project)
+
+ // so far by default, we consume and publish only 'debug' variant
+
+ // 'include' is the configuration that users will use to indicate which dependencies should
+ // be fused.
+ val includeConfigurations = project.configurations.create("include").also {
+ it.isCanBeConsumed = false
+ val buildType: BuildTypeAttr = project.objects.named(BuildTypeAttr::class.java, "debug")
+ it.attributes.attribute(
+ BuildTypeAttr.ATTRIBUTE,
+ buildType,
+ )
+ }
+ // This is the internal configuration that will be used to feed tasks that require access
+ // to the resolved 'include' dependency. It is for JAVA_API usage which mean all transitive
+ // dependencies that are implementation() scoped will not be included.
+ val includeApiClasspath = project.configurations.create("includeApiClasspath").also {
+ it.isCanBeConsumed = false
+ it.attributes.attribute(
+ Usage.USAGE_ATTRIBUTE,
+ project.objects.named(Usage::class.java, Usage.JAVA_API)
+ )
+ val buildType: BuildTypeAttr = project.objects.named(BuildTypeAttr::class.java, "debug")
+ it.attributes.attribute(
+ BuildTypeAttr.ATTRIBUTE,
+ buildType,
+ )
+ it.extendsFrom(includeConfigurations)
+ }
+ // This is the configuration that will contain all the JAVA_API dependencies that are not
+ // fused in the resulting aar library.
+ val includedApiUnmerged = project.configurations.create("includeApiUnmerged").also {
+ it.isCanBeConsumed = true
+ it.isCanBeResolved = true
+ it.incoming.beforeResolve(
+ SegregatingConstraintHandler(
+ includeApiClasspath,
+ it,
+ variantScope.mergeSpec,
+ project,
+ )
+ )
+ }
+ // This is the internal configuration that will be used to feed tasks that require access
+ // to the resolved 'include' dependency. It is for JAVA_RUNTIME usage which mean all transitive
+ // dependencies that are implementation() scoped will be included.
+ val includeRuntimeClasspath =
+ project.configurations.create("includeRuntimeClasspath").also {
+ it.isCanBeConsumed = false
+ it.isCanBeResolved = true
+
+ it.attributes.attribute(
+ Usage.USAGE_ATTRIBUTE,
+ project.objects.named(Usage::class.java, Usage.JAVA_RUNTIME)
+ )
+ val buildType: BuildTypeAttr =
+ project.objects.named(BuildTypeAttr::class.java, "debug")
+ it.attributes.attribute(
+ BuildTypeAttr.ATTRIBUTE,
+ buildType,
+ )
+
+ it.extendsFrom(includeConfigurations)
+ }
+ // This is the configuration that will contain all the JAVA_RUNTIME dependencies that are
+ // not fused in the resulting aar library.
+ val includeRuntimeUnmerged = project.configurations.create("includeRuntimeUnmerged").also {
+ it.isCanBeConsumed = false
+ it.isCanBeResolved = true
+ it.incoming.beforeResolve(
+ SegregatingConstraintHandler(
+ includeConfigurations,
+ it,
+ variantScope.mergeSpec,
+ project,
+ )
+ )
+ }
+ // this is the outgoing configuration for JAVA_API scoped declarations, it will contain
+ // this module and all transitive non merged dependencies
+ fun configureElements(
+ elements: Configuration,
+ usage: String,
+ artifacts: ArtifactsImpl,
+ publicationArtifact: Artifact.Single<RegularFile>,
+ publicationArtifactType: AndroidArtifacts.ArtifactType
+ ) {
+ // we are only interested in the last provider in the chain of transformers for this bundle.
+ // Obviously, this is theoretical at this point since there is no variant API to replace
+ // artifacts, there is always only one.
+ val bundleTaskProvider = publicationArtifact.let {
+ artifacts
+ .getArtifactContainer(it)
+ .getTaskProviders()
+ .last()
+ }
+ elements.attributes.attribute(
+ Usage.USAGE_ATTRIBUTE,
+ project.objects.named(Usage::class.java, usage)
+ )
+ elements.isCanBeResolved = false
+ elements.isCanBeConsumed = true
+ elements.isTransitive = true
+
+ elements.outgoing.variants { variants ->
+ variants.create(publicationArtifactType.type) { variant ->
+ variant.artifact(bundleTaskProvider) { artifact ->
+ artifact.type = publicationArtifactType.type
+ }
+ }
+ }
+ }
- override val artifactForPublication: Artifact.Single<RegularFile>
- get() = FusedLibraryInternalArtifactType.BUNDLED_LIBRARY
+ val includeApiElements =
+ project.configurations.create("apiElements") { apiElements ->
+ configureElements(
+ apiElements,
+ Usage.JAVA_API,
+ variantScope.artifacts,
+ FusedLibraryInternalArtifactType.BUNDLED_LIBRARY,
+ AndroidArtifacts.ArtifactType.AAR)
- override val artifactTypeForPublication: AndroidArtifacts.ArtifactType
- get() = AndroidArtifacts.ArtifactType.AAR
+ apiElements.extendsFrom(includedApiUnmerged)
+ }
+ // this is the outgoing configuration for JAVA_RUNTIME scoped declarations, it will contain
+ // this module and all transitive non merged dependencies
+ val includeRuntimeElements =
+ project.configurations.create("runtimeElements") { runtimeElements ->
+ configureElements(
+ runtimeElements,
+ Usage.JAVA_RUNTIME,
+ variantScope.artifacts,
+ FusedLibraryInternalArtifactType.BUNDLED_LIBRARY,
+ AndroidArtifacts.ArtifactType.AAR)
+ runtimeElements.extendsFrom(includeRuntimeUnmerged)
+ }
+
+ val configurationsToAdd = listOf(includeApiClasspath, includeRuntimeClasspath)
+ configurationsToAdd.forEach { configuration ->
+ variantScope.incomingConfigurations.addConfiguration(configuration)
+ }
+ maybePublishToMaven(
+ project,
+ includeApiElements,
+ includeRuntimeElements,
+ includeRuntimeUnmerged
+ )
+ }
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/PrivacySandboxSdkPlugin.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/PrivacySandboxSdkPlugin.kt
index 762746fb79..07bab17956 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/PrivacySandboxSdkPlugin.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/PrivacySandboxSdkPlugin.kt
@@ -17,9 +17,15 @@
package com.android.build.gradle.internal.plugins
import com.android.build.api.artifact.Artifact
+import com.android.build.api.artifact.impl.ArtifactsImpl
+import com.android.build.api.attributes.BuildTypeAttr
import com.android.build.api.dsl.PrivacySandboxSdkExtension
import com.android.build.gradle.internal.dsl.InternalPrivacySandboxSdkExtension
import com.android.build.gradle.internal.dsl.PrivacySandboxSdkExtensionImpl
+import com.android.build.gradle.internal.fusedlibrary.SegregatingConstraintHandler
+import com.android.build.gradle.internal.fusedlibrary.configureTransforms
+import com.android.build.gradle.internal.fusedlibrary.createTasks
+import com.android.build.gradle.internal.fusedlibrary.getDslServices
import com.android.build.gradle.internal.privaysandboxsdk.PrivacySandboxSdkInternalArtifactType
import com.android.build.gradle.internal.privaysandboxsdk.PrivacySandboxSdkVariantScope
import com.android.build.gradle.internal.privaysandboxsdk.PrivacySandboxSdkVariantScopeImpl
@@ -27,6 +33,7 @@ import com.android.build.gradle.internal.publishing.AndroidArtifacts
import com.android.build.gradle.internal.res.PrivacySandboxSdkLinkAndroidResourcesTask
import com.android.build.gradle.internal.services.Aapt2DaemonBuildService
import com.android.build.gradle.internal.services.Aapt2ThreadPoolBuildService
+import com.android.build.gradle.internal.services.DslServices
import com.android.build.gradle.internal.services.TaskCreationServicesImpl
import com.android.build.gradle.internal.services.VersionedSdkLoaderService
import com.android.build.gradle.internal.tasks.AppMetadataTask
@@ -47,99 +54,250 @@ import com.android.build.gradle.tasks.PrivacySandboxSdkMergeResourcesTask
import com.android.repository.Revision
import com.google.wireless.android.sdk.stats.GradleBuildProject
import org.gradle.api.GradleException
+import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
+import org.gradle.api.attributes.Usage
import org.gradle.api.component.SoftwareComponentFactory
import org.gradle.api.file.RegularFile
import org.gradle.build.event.BuildEventsListenerRegistry
import javax.inject.Inject
class PrivacySandboxSdkPlugin @Inject constructor(
- listenerRegistry: BuildEventsListenerRegistry,
-): AbstractPrivacySandboxPlugin(listenerRegistry) {
+ val softwareComponentFactory: SoftwareComponentFactory,
+ listenerRegistry: BuildEventsListenerRegistry,
+) : AndroidPluginBaseServices(listenerRegistry), Plugin<Project> {
- private val versionedSdkLoaderService: VersionedSdkLoaderService by lazy {
+ val dslServices: DslServices by lazy(LazyThreadSafetyMode.NONE) {
+ withProject("dslServices") { project ->
+ getDslServices(project, projectServices)
+ }
+ }
+
+ private val versionedSdkLoaderService: VersionedSdkLoaderService by lazy(LazyThreadSafetyMode.NONE) {
withProject("versionedSdkLoaderService") { project ->
VersionedSdkLoaderService(
- dslServices,
- project,
- {
- variantScope.compileSdkVersion
- },
- {
- Revision.parseRevision(extension.buildToolsVersion, Revision.Precision.MICRO)
- },
+ dslServices,
+ project,
+ { variantScope.compileSdkVersion },
+ {
+ Revision.parseRevision(extension.buildToolsVersion,
+ Revision.Precision.MICRO)
+ },
)
}
}
// so far, there is only one variant.
- override val variantScope: PrivacySandboxSdkVariantScope by lazy {
+ private val variantScope: PrivacySandboxSdkVariantScope by lazy {
withProject("variantScope") { project ->
PrivacySandboxSdkVariantScopeImpl(
- project,
- TaskCreationServicesImpl(projectServices),
- { extension },
- {
- BootClasspathConfigImpl(
+ project,
+ TaskCreationServicesImpl(projectServices),
+ { extension },
+ ) {
+ BootClasspathConfigImpl(
project,
projectServices,
versionedSdkLoaderService,
null,
false
- )
- }
- )
+ )
+ }
}
}
- private val extension: PrivacySandboxSdkExtension by lazy {
+ private val extension: PrivacySandboxSdkExtension by lazy(LazyThreadSafetyMode.NONE)
+ {
withProject("extension") { project ->
instantiateExtension(project)
}
}
+ override fun configureProject(project: Project) {
+ val projectOptions = projectServices.projectOptions
+ Aapt2ThreadPoolBuildService.RegistrationAction(project, projectOptions).execute()
+ Aapt2DaemonBuildService.RegistrationAction(project, projectOptions).execute()
+ }
+
override fun configureExtension(project: Project) {
extension
}
override fun apply(project: Project) {
- super.apply(project)
+ super.basePluginApply(project)
if (!projectServices.projectOptions[BooleanOption.PRIVACY_SANDBOX_SDK_SUPPORT]) {
throw GradleException(
"Privacy Sandbox SDK support is experimental, and must be explicitly enabled.\n" +
- "To enable support, add\n" +
- " ${BooleanOption.PRIVACY_SANDBOX_SDK_SUPPORT.propertyName}=true\n" +
- "to your project's gradle.properties file."
+ "To enable support, add\n" +
+ " ${BooleanOption.PRIVACY_SANDBOX_SDK_SUPPORT.propertyName}=true\n" +
+ "to your project's gradle.properties file."
+ )
+ }
+
+ // so far by default, we consume and publish only 'debug' variant
+
+ // 'include' is the configuration that users will use to indicate which dependencies should
+ // be fused.
+ val includeConfigurations = project.configurations.create("include").also {
+ it.isCanBeConsumed = false
+ val buildType: BuildTypeAttr = project.objects.named(BuildTypeAttr::class.java, "debug")
+ it.attributes.attribute(
+ BuildTypeAttr.ATTRIBUTE,
+ buildType,
+ )
+ }
+ // This is the internal configuration that will be used to feed tasks that require access
+ // to the resolved 'include' dependency. It is for JAVA_API usage which mean all transitive
+ // dependencies that are implementation() scoped will not be included.
+ val includeApiClasspath = project.configurations.create("includeApiClasspath").also {
+ it.isCanBeConsumed = false
+ it.attributes.attribute(
+ Usage.USAGE_ATTRIBUTE,
+ project.objects.named(Usage::class.java, Usage.JAVA_API)
+ )
+ val buildType: BuildTypeAttr = project.objects.named(BuildTypeAttr::class.java, "debug")
+ it.attributes.attribute(
+ BuildTypeAttr.ATTRIBUTE,
+ buildType,
+ )
+ it.extendsFrom(includeConfigurations)
+ }
+ // This is the configuration that will contain all the JAVA_API dependencies that are not
+ // fused in the resulting aar library.
+ val includedApiUnmerged = project.configurations.create("includeApiUnmerged").also {
+ it.isCanBeConsumed = true
+ it.isCanBeResolved = true
+ it.incoming.beforeResolve(
+ SegregatingConstraintHandler(
+ includeApiClasspath,
+ it,
+ variantScope.mergeSpec,
+ project,
+ )
+ )
+ }
+ // This is the internal configuration that will be used to feed tasks that require access
+ // to the resolved 'include' dependency. It is for JAVA_RUNTIME usage which mean all transitive
+ // dependencies that are implementation() scoped will be included.
+ val includeRuntimeClasspath =
+ project.configurations.create("includeRuntimeClasspath").also {
+ it.isCanBeConsumed = false
+ it.isCanBeResolved = true
+
+ it.attributes.attribute(
+ Usage.USAGE_ATTRIBUTE,
+ project.objects.named(Usage::class.java, Usage.JAVA_RUNTIME)
+ )
+ val buildType: BuildTypeAttr =
+ project.objects.named(BuildTypeAttr::class.java, "debug")
+ it.attributes.attribute(
+ BuildTypeAttr.ATTRIBUTE,
+ buildType,
+ )
+
+ it.extendsFrom(includeConfigurations)
+ }
+ // This is the configuration that will contain all the JAVA_RUNTIME dependencies that are
+ // not fused in the resulting aar library.
+ val includeRuntimeUnmerged = project.configurations.create("includeRuntimeUnmerged").also {
+ it.isCanBeConsumed = false
+ it.isCanBeResolved = true
+ it.incoming.beforeResolve(
+ SegregatingConstraintHandler(
+ includeConfigurations,
+ it,
+ variantScope.mergeSpec,
+ project,
+ )
+ )
+ }
+ // this is the outgoing configuration for JAVA_API scoped declarations, it will contain
+ // this module and all transitive non merged dependencies
+ fun configureElements(
+ elements: Configuration,
+ usage: String,
+ artifacts: ArtifactsImpl,
+ publicationArtifact: Artifact.Single<RegularFile>,
+ publicationArtifactType: AndroidArtifacts.ArtifactType
+ ) {
+ // we are only interested in the last provider in the chain of transformers for this bundle.
+ // Obviously, this is theoretical at this point since there is no variant API to replace
+ // artifacts, there is always only one.
+ val bundleTaskProvider = publicationArtifact.let {
+ artifacts
+ .getArtifactContainer(it)
+ .getTaskProviders()
+ .last()
+ }
+ elements.attributes.attribute(
+ Usage.USAGE_ATTRIBUTE,
+ project.objects.named(Usage::class.java, usage)
)
+ elements.isCanBeResolved = false
+ elements.isCanBeConsumed = true
+ elements.isTransitive = true
+
+ elements.outgoing.variants { variants ->
+ variants.create(publicationArtifactType.type) { variant ->
+ variant.artifact(bundleTaskProvider) { artifact ->
+ artifact.type = publicationArtifactType.type
+ }
+ }
+ }
+ }
+ project.configurations.create("apiElements") { apiElements ->
+ configureElements(
+ apiElements,
+ Usage.JAVA_API,
+ variantScope.artifacts,
+ PrivacySandboxSdkInternalArtifactType.ASAR,
+ AndroidArtifacts.ArtifactType.ANDROID_PRIVACY_SANDBOX_SDK_ARCHIVE)
+
+ apiElements.extendsFrom(includedApiUnmerged)
+ }
+ // this is the outgoing configuration for JAVA_RUNTIME scoped declarations, it will contain
+ // this module and all transitive non merged dependencies
+ project.configurations.create("runtimeElements") { runtimeElements ->
+ configureElements(
+ runtimeElements,
+ Usage.JAVA_RUNTIME,
+ variantScope.artifacts,
+ PrivacySandboxSdkInternalArtifactType.ASAR,
+ AndroidArtifacts.ArtifactType.ANDROID_PRIVACY_SANDBOX_SDK_ARCHIVE)
+ runtimeElements.extendsFrom(includeRuntimeUnmerged)
+ }
+ val configurationsToAdd = listOf(includeApiClasspath, includeRuntimeClasspath)
+ configurationsToAdd.forEach { configuration ->
+ variantScope.incomingConfigurations.addConfiguration(configuration)
}
- Aapt2ThreadPoolBuildService.RegistrationAction(project, projectServices.projectOptions).execute()
- Aapt2DaemonBuildService.RegistrationAction(project, projectServices.projectOptions).execute()
}
private fun instantiateExtension(project: Project): PrivacySandboxSdkExtension {
- val sdkLibraryExtensionImpl= dslServices.newDecoratedInstance(
- PrivacySandboxSdkExtensionImpl::class.java,
- dslServices,
+ val sdkLibraryExtensionImpl = dslServices.newDecoratedInstance(
+ PrivacySandboxSdkExtensionImpl::class.java,
+ dslServices,
)
abstract class Extension(
- val publicExtensionImpl: PrivacySandboxSdkExtensionImpl,
+ val publicExtensionImpl: PrivacySandboxSdkExtensionImpl,
): InternalPrivacySandboxSdkExtension by publicExtensionImpl
return project.extensions.create(
- PrivacySandboxSdkExtension::class.java,
- "android",
- Extension::class.java,
- sdkLibraryExtensionImpl
+ PrivacySandboxSdkExtension::class.java,
+ "android",
+ Extension::class.java,
+ sdkLibraryExtensionImpl
)
}
override fun createTasks(project: Project) {
+ configureTransforms(project, projectServices)
createTasks(
project,
- variantScope,
+ variantScope.artifacts,
+ PrivacySandboxSdkInternalArtifactType.ASAR,
listOf(
AppMetadataTask.PrivacySandboxSdkCreationAction(variantScope),
FusedLibraryMergeClasses.PrivacySandboxSdkCreationAction(variantScope),
@@ -154,18 +312,10 @@ class PrivacySandboxSdkPlugin @Inject constructor(
PerModuleBundleTask.PrivacySandboxSdkCreationAction(variantScope),
PackagePrivacySandboxSdkBundle.CreationAction(variantScope),
ValidateSigningTask.PrivacySandboxSdkCreationAction(variantScope),
- ) + FusedLibraryMergeArtifactTask.getCreationActions(variantScope),
+ ) + FusedLibraryMergeArtifactTask.getCreationActions(variantScope)
)
}
- override fun getAnalyticsPluginType(): GradleBuildProject.PluginType =
- GradleBuildProject.PluginType.PRIVACY_SANDBOX_SDK
-
- /**
- * ASB only get published to Play Store, not maven
- */
- override val artifactForPublication: Artifact.Single<RegularFile> = PrivacySandboxSdkInternalArtifactType.ASAR
-
- override val artifactTypeForPublication: AndroidArtifacts.ArtifactType
- get() = AndroidArtifacts.ArtifactType.ANDROID_PRIVACY_SANDBOX_SDK_ARCHIVE
+ override fun getAnalyticsPluginType(): GradleBuildProject.PluginType =
+ GradleBuildProject.PluginType.PRIVACY_SANDBOX_SDK
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/res/LinkAndroidResForBundleTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/res/LinkAndroidResForBundleTask.kt
index 3cb9c5ec11..dcfbfa01f5 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/res/LinkAndroidResForBundleTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/res/LinkAndroidResForBundleTask.kt
@@ -74,7 +74,7 @@ import java.io.IOException
* Task to link app resources into a proto format so that it can be consumed by the bundle tool.
*/
@CacheableTask
-@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.ANDROID_RESOURCES])
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.ANDROID_RESOURCES, TaskCategoryLabel.LINKING])
abstract class LinkAndroidResForBundleTask : NonIncrementalTask() {
@get:Input
abstract val debuggable: Property<Boolean>
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/res/LinkApplicationAndroidResourcesTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/res/LinkApplicationAndroidResourcesTask.kt
index af1e42bb11..9e562613ab 100755
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/res/LinkApplicationAndroidResourcesTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/res/LinkApplicationAndroidResourcesTask.kt
@@ -105,7 +105,7 @@ import java.nio.file.Files
import javax.inject.Inject
@CacheableTask
-@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.ANDROID_RESOURCES])
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.ANDROID_RESOURCES, TaskCategoryLabel.LINKING])
abstract class LinkApplicationAndroidResourcesTask @Inject constructor(objects: ObjectFactory) :
ProcessAndroidResources() {
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/res/PrivacySandboxSdkLinkAndroidResourcesTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/res/PrivacySandboxSdkLinkAndroidResourcesTask.kt
index 69211e4eae..8ecc9d10d3 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/res/PrivacySandboxSdkLinkAndroidResourcesTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/res/PrivacySandboxSdkLinkAndroidResourcesTask.kt
@@ -61,7 +61,7 @@ import java.io.File
* Invokes AAPT2 link on the merged resources of all library dependencies into the .ap_ format.
*/
@CacheableTask
-@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.ANDROID_RESOURCES])
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.ANDROID_RESOURCES, TaskCategoryLabel.LINKING])
abstract class PrivacySandboxSdkLinkAndroidResourcesTask : NonIncrementalTask() {
@get:Input
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/res/namespaced/LinkLibraryAndroidResourcesTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/res/namespaced/LinkLibraryAndroidResourcesTask.kt
index 1fad278e07..1019b7983e 100755
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/res/namespaced/LinkLibraryAndroidResourcesTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/res/namespaced/LinkLibraryAndroidResourcesTask.kt
@@ -56,7 +56,7 @@ import java.io.File
* Task to link the resources in a library project into an AAPT2 static library.
*/
@CacheableTask
-@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.ANDROID_RESOURCES])
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.ANDROID_RESOURCES, TaskCategoryLabel.LINKING])
abstract class LinkLibraryAndroidResourcesTask : NonIncrementalTask() {
@get:InputFiles
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/services/LintParallelBuildService.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/services/LintParallelBuildService.kt
new file mode 100644
index 0000000000..512da2e1b9
--- /dev/null
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/services/LintParallelBuildService.kt
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.internal.services
+
+import com.android.build.gradle.options.BooleanOption
+import com.android.build.gradle.options.ProjectOptions
+import com.android.build.gradle.options.StringOption.LINT_HEAP_SIZE
+import com.sun.management.OperatingSystemMXBean
+import org.gradle.api.logging.Logging
+import org.gradle.api.services.BuildService
+import org.gradle.api.services.BuildServiceParameters
+import org.gradle.api.services.BuildServiceRegistry
+import java.lang.management.ManagementFactory
+import java.util.Locale
+
+/**
+ * [LintParallelBuildService] limits the number of lint workers to avoid running out of memory.
+ */
+abstract class LintParallelBuildService : BuildService<BuildServiceParameters.None> {
+
+ companion object {
+ fun calculateMaxParallelUsages(
+ projectOptions: ProjectOptions,
+ maxRuntimeMemory: Long,
+ totalPhysicalMemory: Long?
+ ): Int? {
+ return if (projectOptions.get(BooleanOption.RUN_LINT_IN_PROCESS)) {
+ calculateMaxParallelUsagesInProcess(maxRuntimeMemory)
+ } else {
+ calculateMaxParallelUsagesOutOfProcess(
+ projectOptions,
+ maxRuntimeMemory,
+ totalPhysicalMemory ?: return null
+ )
+ }
+ }
+
+ private fun calculateMaxParallelUsagesInProcess(maxRuntimeMemory: Long): Int {
+ // We assume lint will use about 512 megabytes per analysis task.
+ val memoryPerLintTask = 512 * 1024 * 1024
+ // Multiply maxRuntimeMemory by 0.75 to save memory for other things too
+ val maxLintMemory = (maxRuntimeMemory * 0.75).toLong()
+ return Math.floorDiv(maxLintMemory, memoryPerLintTask).coerceAtLeast(1).toInt()
+ }
+
+ private fun calculateMaxParallelUsagesOutOfProcess(
+ projectOptions: ProjectOptions,
+ maxRuntimeMemory: Long,
+ totalPhysicalMemory: Long
+ ): Int {
+ val maxParallelUsage =
+ Math.floorDiv(
+ totalPhysicalMemory,
+ parseLintHeapSize(
+ calculateLintHeapSize(projectOptions.get(LINT_HEAP_SIZE), maxRuntimeMemory)
+ )
+ )
+ // Leave space for at least the gradle daemon and the kotlin daemon
+ return (maxParallelUsage - 2).coerceAtLeast(1).toInt()
+ }
+
+ // Default to using the main Gradle daemon heap size if no lint heap size is specified
+ fun calculateLintHeapSize(
+ userSpecifiedLintHeapSize: String?,
+ maxRuntimeMemory: Long
+ ): String = userSpecifiedLintHeapSize ?: "${maxRuntimeMemory / 1024 / 1024}m"
+
+ private fun parseLintHeapSize(lintHeapSize: String): Long {
+ val value = lintHeapSize.lowercase(Locale.US)
+ val longOrNull = when {
+ value.toLongOrNull() != null -> value.toLongOrNull()
+ value.endsWith("k") -> {
+ value.substring(0, value.length-1).toLongOrNull()?.let { it * 1024 }
+ }
+ value.endsWith("m") -> {
+ value.substring(0, value.length-1).toLongOrNull()?.let { it * 1024 * 1024 }
+ }
+ value.endsWith("g") -> {
+ value.substring(0, value.length-1)
+ .toLongOrNull()
+ ?.let { it * 1024 * 1024 * 1024 }
+ }
+ else -> {
+ null
+ }
+ }
+ return longOrNull
+ ?: throw RuntimeException(
+ "Failed to parse ${LINT_HEAP_SIZE.propertyName} \"$lintHeapSize\"."
+ )
+ }
+ }
+}
+
+/**
+ * Returns a Provider of the [LintParallelBuildService].
+ *
+ * Use this function instead of [getBuildService] to get the [LintParallelBuildService] because we
+ * don't want an instance of the [LintParallelBuildService] per class loader.
+ *
+ * This function uses registerIfAbsent in order to ensure locking when accessing build services.
+ */
+fun BuildServiceRegistry.getLintParallelBuildService(projectOptions: ProjectOptions) =
+ registerIfAbsent("LintParallelBuildService", LintParallelBuildService::class.java) { spec ->
+ spec.maxParallelUsages
+ .set(
+ LintParallelBuildService.calculateMaxParallelUsages(
+ projectOptions,
+ Runtime.getRuntime().maxMemory(),
+ getTotalPhysicalMemory()
+ )
+ )
+ }
+
+private fun getTotalPhysicalMemory() = try {
+ (ManagementFactory.getOperatingSystemMXBean() as OperatingSystemMXBean).totalPhysicalMemorySize
+} catch (t: Throwable) {
+ Logging.getLogger(LintParallelBuildService::class.java)
+ .info("Failed to read total available memory", t)
+ null
+}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/BundleIdeModelProducerTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/BundleIdeModelProducerTask.kt
index eed0be8b18..5c2738599d 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/BundleIdeModelProducerTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/BundleIdeModelProducerTask.kt
@@ -23,6 +23,7 @@ import com.android.build.gradle.internal.component.ApkCreationConfig
import com.android.build.gradle.internal.scope.InternalArtifactType
import com.android.build.gradle.internal.tasks.factory.VariantTaskCreationAction
import com.android.build.gradle.internal.utils.setDisallowChanges
+import com.android.ide.common.attribution.TaskCategoryLabel
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.*
@@ -35,6 +36,7 @@ import org.gradle.work.DisableCachingByDefault
* could outweigh its benefit.
*/
@DisableCachingByDefault
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.SYNC])
abstract class BundleIdeModelProducerTask : NonIncrementalTask() {
@get:InputFile
@get:PathSensitive(PathSensitivity.NAME_ONLY)
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/BundleLibraryClasses.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/BundleLibraryClasses.kt
index 9388a4c0d5..301c40e600 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/BundleLibraryClasses.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/BundleLibraryClasses.kt
@@ -38,6 +38,7 @@ import com.android.build.gradle.options.BooleanOption
import com.android.build.gradle.tasks.toSerializable
import com.android.builder.dexing.isJarFile
import com.android.builder.files.SerializableFileChanges
+import com.android.ide.common.attribution.TaskCategoryLabel
import com.android.utils.FileUtils
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.DirectoryProperty
@@ -136,6 +137,7 @@ private fun BundleLibraryClassesInputs.configureWorkerActionParams(
* simply executing the task.
*/
@DisableCachingByDefault
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.ZIPPING])
abstract class BundleLibraryClassesDir: NewIncrementalTask(), BundleLibraryClassesInputs {
@get:OutputDirectory
@@ -200,6 +202,7 @@ abstract class BundleLibraryClassesDir: NewIncrementalTask(), BundleLibraryClass
* simply executing the task.
*/
@DisableCachingByDefault
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.ZIPPING])
abstract class BundleLibraryClassesJar : NonIncrementalTask(), BundleLibraryClassesInputs {
@get:OutputFile
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/BundleLibraryJavaRes.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/BundleLibraryJavaRes.kt
index dfe88b8fdc..abd95af8be 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/BundleLibraryJavaRes.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/BundleLibraryJavaRes.kt
@@ -48,7 +48,7 @@ import java.util.zip.Deflater
* simply executing the task.
*/
@DisableCachingByDefault
-@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.JAVA_RESOURCES])
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.JAVA_RESOURCES, TaskCategoryLabel.ZIPPING])
abstract class BundleLibraryJavaRes : NonIncrementalTask() {
@get:OutputFile
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/DexMergingTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/DexMergingTask.kt
index 9a583186a5..402e24ab3f 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/DexMergingTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/DexMergingTask.kt
@@ -108,7 +108,7 @@ import kotlin.math.min
* the impacted buckets (those containing changed input dex files).
*/
@CacheableTask
-@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.DEXING])
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.DEXING, TaskCategoryLabel.MERGING])
abstract class DexMergingTask : NewIncrementalTask() {
/**
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/FeatureDexMergeTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/FeatureDexMergeTask.kt
index 3f088a1f34..bec34a3aab 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/FeatureDexMergeTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/FeatureDexMergeTask.kt
@@ -35,7 +35,7 @@ import org.gradle.work.DisableCachingByDefault
* A task merging dex files in dynamic feature modules into a single artifact type.
*/
@DisableCachingByDefault
-@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.DEXING])
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.DEXING, TaskCategoryLabel.MERGING])
abstract class FeatureDexMergeTask : NonIncrementalTask() {
@get:InputFiles
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/LibraryAarJarsTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/LibraryAarJarsTask.kt
index 7cc05aa9bb..189131d094 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/LibraryAarJarsTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/LibraryAarJarsTask.kt
@@ -28,6 +28,7 @@ import com.android.build.gradle.internal.tasks.factory.VariantTaskCreationAction
import com.android.build.gradle.internal.utils.setDisallowChanges
import com.android.builder.packaging.JarCreator
import com.android.builder.packaging.JarMerger
+import com.android.ide.common.attribution.TaskCategoryLabel
import com.android.tools.lint.typedefs.TypedefRemover
import com.android.utils.FileUtils
import org.gradle.api.file.ConfigurableFileCollection
@@ -64,6 +65,7 @@ import java.util.zip.Deflater
// TODO(b/132975663): add workers
@CacheableTask
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.ZIPPING])
abstract class LibraryAarJarsTask : NonIncrementalTask() {
@get:Nested
@get:Optional
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/LinkManifestForAssetPackTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/LinkManifestForAssetPackTask.kt
index bf57a7ede2..50d6ab4f44 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/LinkManifestForAssetPackTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/LinkManifestForAssetPackTask.kt
@@ -50,7 +50,7 @@ import java.io.File
* producing a linked manifest file suitable for packaging in the Android App Bundle.
*/
@DisableCachingByDefault
-@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.MANIFEST])
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.MANIFEST, TaskCategoryLabel.LINKING])
abstract class LinkManifestForAssetPackTask : NonIncrementalTask() {
/**
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/ManagedDeviceCleanTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/ManagedDeviceCleanTask.kt
index 999b8214ff..e4d3e749e8 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/ManagedDeviceCleanTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/ManagedDeviceCleanTask.kt
@@ -24,6 +24,7 @@ import com.android.build.gradle.internal.services.getBuildService
import com.android.build.gradle.internal.tasks.factory.GlobalTaskCreationAction
import com.android.build.gradle.internal.tasks.factory.GlobalTaskCreationConfig
import com.android.build.gradle.internal.utils.setDisallowChanges
+import com.android.ide.common.attribution.TaskCategoryLabel
import com.google.common.annotations.VisibleForTesting
import org.gradle.api.logging.Logging
import org.gradle.api.provider.ListProperty
@@ -37,6 +38,7 @@ import org.gradle.work.DisableCachingByDefault
* Task for clearing the gradle avd folder of avd devices.
*/
@DisableCachingByDefault
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.TEST])
abstract class ManagedDeviceCleanTask: NonIncrementalGlobalTask() {
@get: Internal
abstract val avdService: Property<AvdComponentsBuildService>
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/ManagedDeviceSetupTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/ManagedDeviceSetupTask.kt
index de238d91ed..c419c5a640 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/ManagedDeviceSetupTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/ManagedDeviceSetupTask.kt
@@ -31,6 +31,7 @@ import com.android.build.gradle.internal.tasks.factory.GlobalTaskCreationAction
import com.android.build.gradle.internal.tasks.factory.GlobalTaskCreationConfig
import com.android.build.gradle.internal.testing.utp.ManagedDeviceImageSuggestionGenerator
import com.android.build.gradle.internal.utils.setDisallowChanges
+import com.android.ide.common.attribution.TaskCategoryLabel
import com.android.repository.Revision
import com.android.testing.utils.computeSystemImageHashFromDsl
import com.android.testing.utils.isWearTvOrAutoDevice
@@ -61,6 +62,7 @@ private val loggerWrapper = LoggerWrapper.getLogger(ManagedDeviceSetupTask::clas
* device.
*/
@DisableCachingByDefault
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.TEST])
abstract class ManagedDeviceSetupTask: NonIncrementalGlobalTask() {
@get: Internal
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeArtProfileTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeArtProfileTask.kt
index e3d8aa4a96..df092b8b57 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeArtProfileTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeArtProfileTask.kt
@@ -33,7 +33,7 @@ import org.gradle.api.tasks.TaskProvider
import org.gradle.work.DisableCachingByDefault
@DisableCachingByDefault
-@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.ART_PROFILE])
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.ART_PROFILE, TaskCategoryLabel.MERGING])
abstract class MergeArtProfileTask: MergeFileTask() {
@get:[InputFiles PathSensitive(PathSensitivity.RELATIVE)]
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeClassesTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeClassesTask.kt
index 6f3405b1f3..2ae9012ebd 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeClassesTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeClassesTask.kt
@@ -27,6 +27,7 @@ import com.android.build.gradle.internal.scope.InternalArtifactType
import com.android.build.gradle.internal.tasks.factory.VariantTaskCreationAction
import com.android.build.gradle.internal.utils.fromDisallowChanges
import com.android.builder.dexing.ClassFileInput.CLASS_MATCHER
+import com.android.ide.common.attribution.TaskCategoryLabel
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
@@ -45,6 +46,7 @@ import java.util.zip.Deflater
* classes to the correct APKs via the Dex Splitter.
*/
@CacheableTask
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.MERGING])
abstract class MergeClassesTask : NonIncrementalTask() {
@get:Classpath
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeConsumerProguardFilesTask.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeConsumerProguardFilesTask.java
index 74e0462393..bcbf3eee51 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeConsumerProguardFilesTask.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeConsumerProguardFilesTask.java
@@ -46,7 +46,7 @@ import org.gradle.work.DisableCachingByDefault;
* @see MergeFileTask
*/
@DisableCachingByDefault
-@BuildAnalyzer(taskCategoryLabels = {TaskCategoryLabel.OPTIMIZATION})
+@BuildAnalyzer(taskCategoryLabels = {TaskCategoryLabel.OPTIMIZATION, TaskCategoryLabel.MERGING})
public abstract class MergeConsumerProguardFilesTask extends MergeFileTask {
private boolean isDynamicFeature;
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeFileTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeFileTask.kt
index 81d6d1a44f..a453c72717 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeFileTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeFileTask.kt
@@ -15,6 +15,7 @@
*/
package com.android.build.gradle.internal.tasks
+import com.android.ide.common.attribution.TaskCategoryLabel
import com.android.utils.FileUtils
import com.google.common.base.Charsets
import com.google.common.io.Files
@@ -37,6 +38,7 @@ import java.io.IOException
* simply executing the task.
*/
@DisableCachingByDefault
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.MERGING])
abstract class MergeFileTask : NonIncrementalTask() {
@get:InputFiles
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeJavaResourceTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeJavaResourceTask.kt
index b1ddc416b3..89452ea375 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeJavaResourceTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeJavaResourceTask.kt
@@ -68,7 +68,7 @@ import javax.inject.Inject
* Task to merge java resources from multiple modules
*/
@DisableCachingByDefault
-@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.JAVA_RESOURCES])
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.JAVA_RESOURCES, TaskCategoryLabel.MERGING])
abstract class MergeJavaResourceTask
@Inject constructor(objects: ObjectFactory) : NewIncrementalTask() {
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeNativeDebugMetadataTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeNativeDebugMetadataTask.kt
index f5703b97c7..ac0a3fdf8f 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeNativeDebugMetadataTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeNativeDebugMetadataTask.kt
@@ -53,7 +53,7 @@ import java.io.File
* simply executing the task.
*/
@DisableCachingByDefault
-@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.NATIVE, TaskCategoryLabel.METADATA])
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.NATIVE, TaskCategoryLabel.METADATA, TaskCategoryLabel.MERGING])
abstract class MergeNativeDebugMetadataTask : NonIncrementalTask() {
@get:SkipWhenEmpty
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeNativeLibsTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeNativeLibsTask.kt
index bf47ae0d72..2e13c845fc 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeNativeLibsTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/MergeNativeLibsTask.kt
@@ -69,7 +69,7 @@ import org.gradle.work.DisableCachingByDefault
* Task to merge native libs from a project and possibly its dependencies
*/
@DisableCachingByDefault
-@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.NATIVE])
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.NATIVE, TaskCategoryLabel.MERGING])
abstract class MergeNativeLibsTask : NonIncrementalTask() {
@get:InputFiles
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/NdkTask.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/NdkTask.java
index 4fa2b13791..2b15d06093 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/NdkTask.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/NdkTask.java
@@ -20,6 +20,8 @@ import com.android.annotations.Nullable;
import com.android.build.gradle.internal.dsl.CoreNdkOptions;
import java.util.List;
import java.util.Set;
+
+import com.android.ide.common.attribution.TaskCategoryLabel;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.Optional;
@@ -27,6 +29,7 @@ import org.gradle.work.DisableCachingByDefault;
/** Base task for tasks that require an NdkConfig */
@DisableCachingByDefault
+@BuildAnalyzer(taskCategoryLabels = {TaskCategoryLabel.NATIVE})
public abstract class NdkTask extends NonIncrementalTask {
@Nullable
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/PackageRenderscriptTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/PackageRenderscriptTask.kt
index 091f7988f2..a27a83ae24 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/PackageRenderscriptTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/PackageRenderscriptTask.kt
@@ -30,7 +30,7 @@ import java.io.File
/** task packaging the rs headers */
@DisableCachingByDefault
-@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.RENDERSCRIPT])
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.RENDERSCRIPT, TaskCategoryLabel.ZIPPING])
abstract class PackageRenderscriptTask : Sync(), VariantAwareTask {
@get:OutputDirectory
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/ProcessJavaResTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/ProcessJavaResTask.kt
index 28aa26b7d0..a47c93a8a8 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/ProcessJavaResTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/ProcessJavaResTask.kt
@@ -15,7 +15,6 @@
*/
package com.android.build.gradle.internal.tasks
-import com.android.build.gradle.api.AndroidSourceSet
import com.android.build.gradle.internal.component.ComponentCreationConfig
import com.android.build.gradle.internal.scope.InternalArtifactType
import com.android.build.gradle.internal.tasks.factory.VariantTaskCreationAction
@@ -75,9 +74,7 @@ abstract class ProcessJavaResTask : Sync(), VariantAwareTask {
) {
super.configure(task)
- for (sourceProvider in creationConfig.variantSources.sortedSourceProviders) {
- task.from((sourceProvider as AndroidSourceSet).resources.getSourceFiles())
- }
+ task.from(creationConfig.sources.resources.getAsFileTrees())
task.duplicatesStrategy = DuplicatesStrategy.INCLUDE
}
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/databinding/DataBindingMergeDependencyArtifactsTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/databinding/DataBindingMergeDependencyArtifactsTask.kt
index 3543501291..177bc75384 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/databinding/DataBindingMergeDependencyArtifactsTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/databinding/DataBindingMergeDependencyArtifactsTask.kt
@@ -48,7 +48,7 @@ import java.io.File
* simply executing the task.
*/
@DisableCachingByDefault
-@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.DATA_BINDING])
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.DATA_BINDING, TaskCategoryLabel.MERGING])
abstract class DataBindingMergeDependencyArtifactsTask : NonIncrementalTask() {
/**
* Classes available at Runtime. We extract BR files from there so that even if there is no
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/databinding/MergeRFilesForDataBindingTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/databinding/MergeRFilesForDataBindingTask.kt
index d837c6432c..d6905573b4 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/databinding/MergeRFilesForDataBindingTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/databinding/MergeRFilesForDataBindingTask.kt
@@ -19,8 +19,10 @@ package com.android.build.gradle.internal.tasks.databinding
import com.android.build.gradle.internal.component.ComponentCreationConfig
import com.android.build.gradle.internal.publishing.AndroidArtifacts
import com.android.build.gradle.internal.scope.InternalArtifactType
+import com.android.build.gradle.internal.tasks.BuildAnalyzer
import com.android.build.gradle.internal.tasks.NonIncrementalTask
import com.android.build.gradle.internal.tasks.factory.VariantTaskCreationAction
+import com.android.ide.common.attribution.TaskCategoryLabel
import org.gradle.api.file.FileCollection
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.Classpath
@@ -38,6 +40,7 @@ import org.gradle.work.DisableCachingByDefault
* simply executing the task.
*/
@DisableCachingByDefault
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.MERGING, TaskCategoryLabel.ANDROID_RESOURCES])
abstract class MergeRFilesForDataBindingTask : NonIncrementalTask() {
private val NEW_LINE = "\n".toByteArray()
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/featuresplit/PackagedDependenciesWriterTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/featuresplit/PackagedDependenciesWriterTask.kt
index ab80a6dff3..de3249b1d1 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/featuresplit/PackagedDependenciesWriterTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/featuresplit/PackagedDependenciesWriterTask.kt
@@ -54,7 +54,7 @@ private val aarOrJarType = Action { container: AttributeContainer ->
/** Task to write the list of transitive dependencies. */
@CacheableTask
-@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.HELP])
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.METADATA])
abstract class PackagedDependenciesWriterTask : NonIncrementalTask() {
@get:OutputFile
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/utils/PublishingUtil.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/utils/PublishingUtil.kt
index 25f4df9075..396480c618 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/utils/PublishingUtil.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/utils/PublishingUtil.kt
@@ -40,17 +40,14 @@ fun createPublishingInfoForLibrary(
flavorList: List<ProductFlavor>,
buildTypes: NamedDomainObjectContainer<out BuildType>,
productFlavors: NamedDomainObjectContainer<out ProductFlavor>,
- testFixtureMainVariantName: String?,
issueReporter: IssueReporter
): VariantPublishingInfo {
val optIn = publishingFeatureOptIn(publishing as AbstractPublishing<SingleVariant>, projectOptions)
val components = mutableListOf<ComponentPublishingInfo>()
- // attach the testFixtures variants to the main variant component
- val variantBasedComponentName = testFixtureMainVariantName ?: variantName
if (!optIn) {
components.add(ComponentPublishingInfo(
- variantBasedComponentName,
+ variantName,
AbstractPublishing.Type.AAR))
components.add(ComponentPublishingInfo(
@@ -66,15 +63,11 @@ fun createPublishingInfoForLibrary(
ensureComponentNameUniqueness(publishing, issueReporter)
val singleVariant = publishing.singleVariants.find {
- if (testFixtureMainVariantName != null) {
- it.variantName == testFixtureMainVariantName
- } else {
it.variantName == variantName
- }
}
if (singleVariant != null) {
components.add(ComponentPublishingInfo(
- variantBasedComponentName,
+ variantName,
AbstractPublishing.Type.AAR,
withSourcesJar = singleVariant.withSourcesJar,
withJavadocJar = singleVariant.withJavadocJar
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/AbstractVariantInputManager.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/AbstractVariantInputManager.kt
index 848203779f..650232fd88 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/AbstractVariantInputManager.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/AbstractVariantInputManager.kt
@@ -18,16 +18,15 @@ package com.android.build.gradle.internal.variant
import com.android.build.gradle.internal.BuildTypeData
import com.android.build.gradle.internal.ProductFlavorData
import com.android.build.gradle.internal.api.DefaultAndroidSourceSet
-import com.android.build.gradle.internal.core.VariantDslInfoBuilder.Companion.computeSourceSetName
import com.android.build.gradle.internal.dependency.SourceSetManager
import com.android.build.gradle.internal.dsl.BuildType
import com.android.build.gradle.internal.dsl.SigningConfig
import com.android.build.gradle.internal.plugins.DslContainerProvider
import com.android.build.gradle.internal.services.DslServices
-import com.android.build.gradle.options.BooleanOption
import com.android.builder.core.BuilderConstants
import com.android.builder.core.ComponentType
import com.android.builder.core.ComponentTypeImpl
+import com.android.utils.appendCapitalized
/**
* Abstract Class responsible for handling the DSL containers of flavors/build types and processing
@@ -174,6 +173,24 @@ abstract class AbstractVariantInputManager<
}
companion object {
+ /**
+ * Turns a string into a valid source set name for the given [ComponentType], e.g.
+ * "fooBarUnitTest" becomes "testFooBar".
+ */
+ private fun computeSourceSetName(
+ baseName: String,
+ componentType: ComponentType
+ ): String {
+ var name = baseName
+ if (name.endsWith(componentType.suffix)) {
+ name = name.substring(0, name.length - componentType.suffix.length)
+ }
+ if (!componentType.prefix.isEmpty()) {
+ name = componentType.prefix.appendCapitalized(name)
+ }
+ return name
+ }
+
private fun checkName(name: String, displayName: String) {
checkPrefix(
name,
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/VariantPathHelper.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/VariantPathHelper.kt
index b5001e39b8..82c063c3d2 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/VariantPathHelper.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/VariantPathHelper.kt
@@ -18,8 +18,7 @@ package com.android.build.gradle.internal.variant
import com.android.SdkConstants
import com.android.build.api.dsl.ProductFlavor
-import com.android.build.gradle.internal.core.VariantDslInfoBuilder
-import com.android.build.gradle.internal.core.VariantDslInfoImpl
+import com.android.build.api.variant.ComponentIdentity
import com.android.build.gradle.internal.core.dsl.ApkProducingComponentDslInfo
import com.android.build.gradle.internal.core.dsl.ComponentDslInfo
import com.android.build.gradle.internal.services.DslServices
@@ -27,6 +26,7 @@ import com.android.build.gradle.options.IntegerOption
import com.android.build.gradle.options.StringOption
import com.android.builder.core.BuilderConstants
import com.android.builder.core.ComponentType
+import com.android.utils.appendCapitalized
import com.android.utils.combineAsCamelCase
import com.android.utils.toStrings
import com.google.common.base.Joiner
@@ -42,6 +42,81 @@ class VariantPathHelper(
private val dslServices: DslServices
) {
+ companion object {
+ /**
+ * Returns the full, unique name of the variant, including BuildType, flavors and test, dash
+ * separated. (similar to full name but with dashes)
+ *
+ * @return the name of the variant
+ */
+ @JvmStatic
+ fun computeBaseName(
+ dimensionCombination: DimensionCombination,
+ componentType: ComponentType) : String {
+ val sb = StringBuilder()
+ if (dimensionCombination.productFlavors.isNotEmpty()) {
+ for ((_, name) in dimensionCombination.productFlavors) {
+ if (sb.isNotEmpty()) {
+ sb.append('-')
+ }
+ sb.append(name)
+ }
+ }
+
+ dimensionCombination.buildType?.let {
+ if (sb.isNotEmpty()) {
+ sb.append('-')
+ }
+ sb.append(it)
+ }
+
+ if (componentType.isNestedComponent) {
+ if (sb.isNotEmpty()) {
+ sb.append('-')
+ }
+ sb.append(componentType.prefix)
+ }
+
+ if (sb.isEmpty()) {
+ sb.append("main")
+ }
+
+ return sb.toString()
+ }
+
+ /**
+ * Returns a full name that includes the given splits name.
+ *
+ * @param splitName the split name
+ * @return a unique name made up of the variant and split names.
+ */
+ @JvmStatic
+ fun computeFullNameWithSplits(
+ variantConfiguration: ComponentIdentity,
+ componentType: ComponentType,
+ splitName: String): String {
+ val sb = StringBuilder()
+
+ val flavorName = variantConfiguration.flavorName
+
+ if (!flavorName.isNullOrEmpty()) {
+ sb.append(flavorName)
+ sb.appendCapitalized(splitName)
+ } else {
+ sb.append(splitName)
+ }
+
+ variantConfiguration.buildType?.let {
+ sb.appendCapitalized(it)
+ }
+
+ if (componentType.isNestedComponent) {
+ sb.append(componentType.suffix)
+ }
+ return sb.toString()
+ }
+ }
+
/**
* Returns a unique directory name (can include multiple folders) for the variant, based on
* build type, flavor and test.
@@ -75,7 +150,7 @@ class VariantPathHelper(
)
)
}
- builder.add((dslInfo as VariantDslInfoImpl).buildTypeObj.name)
+ builder.add(dslInfo.buildType!!)
builder.build()
}
@@ -103,7 +178,7 @@ class VariantPathHelper(
* @return a unique name made up of the variant and split names.
*/
fun computeFullNameWithSplits(splitName: String): String {
- return VariantDslInfoBuilder.computeFullNameWithSplits(
+ return computeFullNameWithSplits(
dslInfo.componentIdentity,
dslInfo.componentType,
splitName
@@ -117,8 +192,8 @@ class VariantPathHelper(
* @return the name of the variant
*/
val baseName: String by lazy {
- VariantDslInfoBuilder.computeBaseName(
- dslInfo as VariantDslInfoImpl,
+ computeBaseName(
+ dslInfo,
dslInfo.componentType
)
}
@@ -137,7 +212,7 @@ class VariantPathHelper(
}
}
sb.append(splitName).append('-')
- sb.append((dslInfo as VariantDslInfoImpl).buildTypeObj.name)
+ sb.append(dslInfo.buildType!!)
if (dslInfo.componentType.isNestedComponent) {
sb.append('-').append(dslInfo.componentType.prefix)
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/options/BooleanOption.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/options/BooleanOption.kt
index a5d7d1cdb3..ae4c72e334 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/options/BooleanOption.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/options/BooleanOption.kt
@@ -117,6 +117,7 @@ enum class BooleanOption(
*/
BUILD_FEATURE_MLMODELBINDING("android.defaults.buildfeatures.mlmodelbinding", false, ApiStage.Experimental),
+ ENABLE_DEFAULT_DEBUG_SIGNING_CONFIG("android.experimental.useDefaultDebugSigningConfigForProfileableBuildtypes", false, ApiStage.Experimental),
ENABLE_PROFILE_JSON("android.enableProfileJson", false, FeatureStage.Experimental),
DISALLOW_DEPENDENCY_RESOLUTION_AT_CONFIGURATION("android.dependencyResolutionAtConfigurationTime.disallow", false, FeatureStage.Experimental),
ENABLE_TEST_SHARDING("android.androidTest.shardBetweenDevices", false, FeatureStage.Experimental),
@@ -203,6 +204,7 @@ enum class BooleanOption(
PRIVACY_SANDBOX_SDK_SUPPORT("android.experimental.privacysandboxsdk.enable", false, FeatureStage.Experimental),
+ BUILD_ANALYZER_TASK_LABELS("android.experimental.buildanalyzer.tasklabels.enable", false, FeatureStage.Experimental),
/* ------------------------
* SOFTLY-ENFORCED FEATURES
*/
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/BundleAar.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/BundleAar.kt
index 484e28872b..f076b22a85 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/BundleAar.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/BundleAar.kt
@@ -142,8 +142,7 @@ abstract class BundleAar : Zip(), VariantAwareTask {
creationConfig.artifacts.get(
InternalArtifactType.DATA_BINDING_BASE_CLASS_LOG_ARTIFACT),
prependToCopyPath(
- DataBindingBuilder.DATA_BINDING_CLASS_LOG_ROOT_FOLDER_IN_AAR
- )
+ DataBindingBuilder.DATA_BINDING_CLASS_LOG_ROOT_FOLDER_IN_AAR)
)
}
@@ -394,11 +393,14 @@ abstract class BundleAar : Zip(), VariantAwareTask {
}
companion object {
- private fun prependToCopyPath(pathSegment: String) = Action { copySpec: CopySpec ->
- copySpec.eachFile { fileCopyDetails: FileCopyDetails ->
- fileCopyDetails.relativePath =
- fileCopyDetails.relativePath.prepend(pathSegment)
- }
- }
+
+ private fun prependToCopyPath(pathSegment: String, includeEmptyDirs: Boolean = false) =
+ Action { copySpec: CopySpec ->
+ copySpec.includeEmptyDirs = includeEmptyDirs
+ copySpec.eachFile { fileCopyDetails: FileCopyDetails ->
+ fileCopyDetails.relativePath =
+ fileCopyDetails.relativePath.prepend(pathSegment)
+ }
+ }
}
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ExtractDeepLinksTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ExtractDeepLinksTask.kt
index d89a337db3..5e710b3759 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ExtractDeepLinksTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ExtractDeepLinksTask.kt
@@ -25,6 +25,7 @@ import com.android.build.gradle.internal.tasks.NonIncrementalTask
import com.android.build.gradle.internal.tasks.factory.VariantTaskCreationAction
import com.android.ide.common.attribution.TaskCategoryLabel
import com.android.ide.common.blame.SourceFilePosition
+import com.android.build.gradle.internal.utils.setDisallowChanges
import com.android.manifmerger.NavigationXmlDocumentData
import com.android.manifmerger.NavigationXmlLoader
import com.android.utils.FileUtils
@@ -155,7 +156,12 @@ abstract class ExtractDeepLinksTask: NonIncrementalTask() {
}
}
)
- task.manifestPlaceholders.set(creationConfig.manifestPlaceholders)
+ task.manifestPlaceholders.setDisallowChanges(
+ creationConfig.manifestPlaceholdersCreationConfig?.placeholders,
+ handleNullable = {
+ empty()
+ }
+ )
task.forAar.set(forAar)
}
}
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryBundle.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryBundle.kt
index c3c0af4850..b9b76541e4 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryBundle.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryBundle.kt
@@ -31,6 +31,7 @@ import org.gradle.api.tasks.bundling.Jar
import org.gradle.work.DisableCachingByDefault
@DisableCachingByDefault(because = "Task does not calculate anything, only creates a jar.")
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.AAR_PACKAGING])
abstract class FusedLibraryBundle: Jar() {
// We have to explicitly repeat the output file as the artifacts API expects a
@@ -105,6 +106,7 @@ abstract class FusedLibraryBundleAar: FusedLibraryBundle() {
}
@DisableCachingByDefault(because = "Task does not calculate anything, only creates a jar.")
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.ZIPPING])
abstract class FusedLibraryBundleClasses: FusedLibraryBundle() {
class CreationAction(
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryManifestMergerTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryManifestMergerTask.kt
index 625de74e21..fe1df0e324 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryManifestMergerTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryManifestMergerTask.kt
@@ -23,12 +23,14 @@ import com.android.build.gradle.internal.fusedlibrary.FusedLibraryInternalArtifa
import com.android.build.gradle.internal.fusedlibrary.FusedLibraryVariantScope
import com.android.build.gradle.internal.profile.ProfileAwareWorkAction
import com.android.build.gradle.internal.publishing.AndroidArtifacts
+import com.android.build.gradle.internal.tasks.BuildAnalyzer
import com.android.build.gradle.internal.tasks.configureVariantProperties
import com.android.build.gradle.internal.tasks.factory.TaskCreationAction
import com.android.build.gradle.internal.tasks.manifest.ManifestProviderImpl
import com.android.build.gradle.internal.tasks.manifest.mergeManifests
import com.android.build.gradle.internal.utils.setDisallowChanges
import com.android.build.gradle.tasks.ProcessApplicationManifest.Companion.getArtifactName
+import com.android.ide.common.attribution.TaskCategoryLabel
import com.android.manifmerger.ManifestMerger2
import com.android.utils.FileUtils
import org.gradle.api.artifacts.ArtifactCollection
@@ -52,6 +54,7 @@ import java.io.File
* Merges Manifests from libraries that will be included with in fused library.
*/
@CacheableTask
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.MERGING, TaskCategoryLabel.MANIFEST, TaskCategoryLabel.FUSING])
abstract class FusedLibraryManifestMergerTask : ManifestProcessorTask() {
@get:Internal
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryMergeArtifactTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryMergeArtifactTask.kt
index 112f49a87b..20321ea5dc 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryMergeArtifactTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryMergeArtifactTask.kt
@@ -31,10 +31,12 @@ import com.android.build.gradle.internal.fusedlibrary.FusedLibraryVariantScope
import com.android.build.gradle.internal.privaysandboxsdk.PrivacySandboxSdkVariantScope
import com.android.build.gradle.internal.profile.ProfileAwareWorkAction
import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactType
+import com.android.build.gradle.internal.tasks.BuildAnalyzer
import com.android.build.gradle.internal.tasks.NonIncrementalTask
import com.android.build.gradle.internal.tasks.configureVariantProperties
import com.android.build.gradle.internal.tasks.factory.TaskCreationAction
import com.android.build.gradle.internal.utils.setDisallowChanges
+import com.android.ide.common.attribution.TaskCategoryLabel
import com.android.utils.usLocaleCapitalize
import org.gradle.api.attributes.Usage
import org.gradle.api.file.ConfigurableFileCollection
@@ -62,6 +64,7 @@ import java.io.File
* once this feature is supported in the fused library plugin.
*/
@CacheableTask
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.MERGING, TaskCategoryLabel.FUSING])
abstract class FusedLibraryMergeArtifactTask : NonIncrementalTask() {
@get:Input
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryMergeClasses.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryMergeClasses.kt
index 93d0d9530c..93bddcea87 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryMergeClasses.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryMergeClasses.kt
@@ -20,8 +20,10 @@ import com.android.build.gradle.internal.fusedlibrary.FusedLibraryInternalArtifa
import com.android.build.gradle.internal.fusedlibrary.FusedLibraryVariantScope
import com.android.build.gradle.internal.privaysandboxsdk.PrivacySandboxSdkVariantScope
import com.android.build.gradle.internal.publishing.AndroidArtifacts
+import com.android.build.gradle.internal.tasks.BuildAnalyzer
import com.android.build.gradle.internal.tasks.factory.TaskCreationAction
import com.android.builder.dexing.ClassFileInput.CLASS_MATCHER
+import com.android.ide.common.attribution.TaskCategoryLabel
import com.android.utils.FileUtils
import org.gradle.api.DefaultTask
import org.gradle.api.attributes.Usage
@@ -43,6 +45,7 @@ import java.util.jar.JarFile
* merge classes.jar coming from included libraries in fused libraries plugin.
*/
@DisableCachingByDefault(because = "No calculation is made, merging classes. ")
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.MERGING, TaskCategoryLabel.FUSING])
abstract class FusedLibraryMergeClasses: DefaultTask() {
@get:OutputDirectory
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryMergeResourcesTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryMergeResourcesTask.kt
index bd9204d8bf..d0c766ab8f 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryMergeResourcesTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/FusedLibraryMergeResourcesTask.kt
@@ -25,10 +25,12 @@ import com.android.build.gradle.internal.profile.AnalyticsService
import com.android.build.gradle.internal.publishing.AndroidArtifacts
import com.android.build.gradle.internal.scope.InternalArtifactType
import com.android.build.gradle.internal.services.getBuildService
+import com.android.build.gradle.internal.tasks.BuildAnalyzer
import com.android.build.gradle.internal.tasks.NonIncrementalGlobalTask
import com.android.build.gradle.internal.tasks.Workers
import com.android.build.gradle.internal.tasks.factory.TaskCreationAction
import com.android.build.gradle.internal.utils.setDisallowChanges
+import com.android.ide.common.attribution.TaskCategoryLabel
import com.android.ide.common.blame.MergingLog
import com.android.ide.common.rendering.api.ResourceNamespace
import com.android.ide.common.resources.CopyToOutputDirectoryResourceCompilationService
@@ -61,6 +63,7 @@ import java.io.File
* handled by the AGP MergeResources task.
*/
@CacheableTask
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.MERGING, TaskCategoryLabel.ANDROID_RESOURCES, TaskCategoryLabel.FUSING])
abstract class FusedLibraryMergeResourcesTask : NonIncrementalGlobalTask() {
@get:OutputDirectory
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/GenerateManifestJarTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/GenerateManifestJarTask.kt
index cc81c575b6..117f1e191d 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/GenerateManifestJarTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/GenerateManifestJarTask.kt
@@ -43,7 +43,7 @@ import org.gradle.api.tasks.TaskProvider
* This manifest class is used for accessing Android Manifest custom permission names.
*/
@CacheableTask
-@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.MANIFEST])
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.MANIFEST, TaskCategoryLabel.ZIPPING])
abstract class GenerateManifestJarTask : NonIncrementalTask() {
@get:InputFile
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/InvokeManifestMerger.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/InvokeManifestMerger.kt
index 90029ab7c6..236982a0ab 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/InvokeManifestMerger.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/InvokeManifestMerger.kt
@@ -41,7 +41,7 @@ import org.gradle.work.DisableCachingByDefault
* or overlay manifests
*/
@DisableCachingByDefault
-@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.MANIFEST])
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.MANIFEST, TaskCategoryLabel.MERGING])
abstract class InvokeManifestMerger : NonIncrementalTask(), Supplier<File> {
@get:InputFile
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/MapSourceSetPathsTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/MapSourceSetPathsTask.kt
index 943ac20bfb..6a987858cd 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/MapSourceSetPathsTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/MapSourceSetPathsTask.kt
@@ -4,11 +4,13 @@ import com.android.SdkConstants
import com.android.build.gradle.internal.component.ComponentCreationConfig
import com.android.build.gradle.internal.publishing.AndroidArtifacts
import com.android.build.gradle.internal.scope.InternalArtifactType
+import com.android.build.gradle.internal.tasks.BuildAnalyzer
import com.android.build.gradle.internal.tasks.NonIncrementalTask
import com.android.build.gradle.internal.tasks.factory.features.AndroidResourcesTaskCreationAction
import com.android.build.gradle.internal.tasks.factory.VariantTaskCreationAction
import com.android.build.gradle.internal.tasks.factory.features.AndroidResourcesTaskCreationActionImpl
import com.android.build.gradle.internal.utils.setDisallowChanges
+import com.android.ide.common.attribution.TaskCategoryLabel
import com.android.ide.common.resources.writeIdentifiedSourceSetsFile
import com.android.utils.FileUtils
import org.gradle.api.file.ConfigurableFileCollection
@@ -33,6 +35,7 @@ import java.io.File
* Produces a file which lists project resource source set directories with an identifier.
*/
@DisableCachingByDefault
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.ANDROID_RESOURCES])
abstract class MapSourceSetPathsTask : NonIncrementalTask() {
@get:Input
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/MergeResources.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/MergeResources.kt
index b8cdf73f90..cb67be719a 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/MergeResources.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/MergeResources.kt
@@ -103,7 +103,7 @@ import javax.xml.bind.JAXBException
import javax.xml.parsers.DocumentBuilderFactory
@CacheableTask
-@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.ANDROID_RESOURCES])
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.ANDROID_RESOURCES, TaskCategoryLabel.MERGING])
abstract class MergeResources : NewIncrementalTask() {
// ----- PUBLIC TASK API -----
/** Directory to write the merged resources to */
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/MergeSourceSetFolders.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/MergeSourceSetFolders.kt
index ed0716b91b..19d1ed0f86 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/MergeSourceSetFolders.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/MergeSourceSetFolders.kt
@@ -69,7 +69,7 @@ import java.io.File
import java.io.IOException
@CacheableTask
-@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.SOURCE_PROCESSING])
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.SOURCE_PROCESSING, TaskCategoryLabel.MERGING])
abstract class MergeSourceSetFolders : NewIncrementalTask() {
@get:OutputDirectory
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkManifestGeneratorTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkManifestGeneratorTask.kt
index b1f5f295f9..46cb45a1e6 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkManifestGeneratorTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkManifestGeneratorTask.kt
@@ -31,7 +31,7 @@ import org.gradle.work.DisableCachingByDefault
// Disable caching since we only create a small text file.
@DisableCachingByDefault
-@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.SOURCE_GENERATION])
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.SOURCE_GENERATION, TaskCategoryLabel.MANIFEST])
abstract class PrivacySandboxSdkManifestGeneratorTask: NonIncrementalTask() {
@get:OutputFile
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkManifestMergerTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkManifestMergerTask.kt
index 4fd70cd0cc..4d8750442a 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkManifestMergerTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkManifestMergerTask.kt
@@ -22,9 +22,11 @@ import com.android.build.gradle.internal.fusedlibrary.FusedLibraryInternalArtifa
import com.android.build.gradle.internal.privaysandboxsdk.PrivacySandboxSdkInternalArtifactType
import com.android.build.gradle.internal.privaysandboxsdk.PrivacySandboxSdkVariantScope
import com.android.build.gradle.internal.publishing.AndroidArtifacts
+import com.android.build.gradle.internal.tasks.BuildAnalyzer
import com.android.build.gradle.internal.tasks.configureVariantProperties
import com.android.build.gradle.internal.tasks.factory.TaskCreationAction
import com.android.build.gradle.internal.utils.setDisallowChanges
+import com.android.ide.common.attribution.TaskCategoryLabel
import com.android.utils.FileUtils
import org.gradle.api.attributes.Usage
import org.gradle.api.file.RegularFileProperty
@@ -35,6 +37,7 @@ import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.TaskProvider
@CacheableTask
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.MERGING, TaskCategoryLabel.MANIFEST])
abstract class PrivacySandboxSdkManifestMergerTask: FusedLibraryManifestMergerTask() {
@get: InputFile
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkMergeDexTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkMergeDexTask.kt
index 3fe04500df..20936cfe03 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkMergeDexTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkMergeDexTask.kt
@@ -43,7 +43,7 @@ import org.gradle.work.Incremental
import org.gradle.work.InputChanges
@CacheableTask
-@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.DEXING])
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.DEXING, TaskCategoryLabel.MERGING])
abstract class PrivacySandboxSdkMergeDexTask: NewIncrementalTask() {
@get:Incremental
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkMergeResourcesTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkMergeResourcesTask.kt
index 04f3c05f91..f66d6fb3ac 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkMergeResourcesTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/PrivacySandboxSdkMergeResourcesTask.kt
@@ -25,11 +25,13 @@ import com.android.build.gradle.internal.publishing.AndroidArtifacts
import com.android.build.gradle.internal.res.Aapt2FromMaven
import com.android.build.gradle.internal.services.Aapt2Input
import com.android.build.gradle.internal.services.getBuildService
+import com.android.build.gradle.internal.tasks.BuildAnalyzer
import com.android.build.gradle.internal.tasks.NonIncrementalTask
import com.android.build.gradle.internal.tasks.Workers
import com.android.build.gradle.internal.tasks.configureVariantProperties
import com.android.build.gradle.internal.tasks.factory.TaskCreationAction
import com.android.build.gradle.internal.utils.setDisallowChanges
+import com.android.ide.common.attribution.TaskCategoryLabel
import com.android.ide.common.workers.WorkerExecutorFacade
import org.gradle.api.attributes.Usage
import org.gradle.api.file.ConfigurableFileCollection
@@ -54,6 +56,7 @@ import org.gradle.api.tasks.TaskProvider
* handled by the AGP MergeResources task.
*/
@CacheableTask
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.MERGING, TaskCategoryLabel.ANDROID_RESOURCES])
abstract class PrivacySandboxSdkMergeResourcesTask : NonIncrementalTask() {
@get:OutputDirectory
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessAndroidResources.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessAndroidResources.java
index b52120e8d5..f5bd0e4724 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessAndroidResources.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessAndroidResources.java
@@ -22,10 +22,13 @@ import com.android.build.api.variant.impl.VariantOutputConfigurationImplKt;
import com.android.build.api.variant.impl.VariantOutputImpl;
import com.android.build.gradle.internal.component.ComponentCreationConfig;
import com.android.build.gradle.internal.component.ConsumableCreationConfig;
+import com.android.build.gradle.internal.tasks.BuildAnalyzer;
import com.android.build.gradle.internal.tasks.NewIncrementalTask;
+import com.android.ide.common.attribution.TaskCategoryLabel;
import com.android.utils.FileUtils;
import com.google.common.base.Preconditions;
import java.io.File;
+
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.Internal;
@@ -37,6 +40,7 @@ import org.gradle.work.Incremental;
/** Base class for process resources / create R class task, to satisfy existing variants API. */
@DisableCachingByDefault
+@BuildAnalyzer(taskCategoryLabels = {TaskCategoryLabel.ANDROID_RESOURCES})
public abstract class ProcessAndroidResources extends NewIncrementalTask {
protected VariantOutputImpl mainSplit;
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessApplicationManifest.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessApplicationManifest.kt
index 70ac09fad1..ba1aeb1754 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessApplicationManifest.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessApplicationManifest.kt
@@ -20,6 +20,7 @@ import com.android.build.api.variant.impl.VariantOutputImpl
import com.android.build.api.variant.impl.getApiString
import com.android.build.gradle.internal.LoggerWrapper
import com.android.build.gradle.internal.component.ApkCreationConfig
+import com.android.build.gradle.internal.component.ApplicationCreationConfig
import com.android.build.gradle.internal.component.DynamicFeatureCreationConfig
import com.android.build.gradle.internal.component.VariantCreationConfig
import com.android.build.gradle.internal.dependency.ArtifactCollectionWithExtraArtifact.ExtraComponentIdentifier
@@ -456,7 +457,9 @@ abstract class ProcessApplicationManifest : ManifestProcessorTask() {
}
task.packageOverride.setDisallowChanges(creationConfig.applicationId)
task.namespace.setDisallowChanges(creationConfig.namespace)
- task.profileable.setDisallowChanges(creationConfig.profileable)
+ task.profileable.setDisallowChanges(
+ (creationConfig as? ApplicationCreationConfig)?.profileable ?: false
+ )
task.testOnly.setDisallowChanges(
ProfilingMode.getProfilingModeType(
creationConfig.services.projectOptions[StringOption.PROFILING_MODE]
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessTestManifest.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessTestManifest.kt
index f8a4cfb334..6d995acf01 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessTestManifest.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ProcessTestManifest.kt
@@ -507,7 +507,12 @@ abstract class ProcessTestManifest : ManifestProcessorTask() {
ArtifactScope.ALL,
AndroidArtifacts.ArtifactType.MANIFEST
)
- task.placeholdersValues.setDisallowChanges(creationConfig.manifestPlaceholders)
+ task.placeholdersValues.setDisallowChanges(
+ creationConfig.manifestPlaceholdersCreationConfig?.placeholders,
+ handleNullable = {
+ empty()
+ }
+ )
if (!creationConfig.global.namespacedAndroidResources) {
task.navigationJsons = project.files(
creationConfig
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/SourceJarTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/SourceJarTask.kt
index 77018fa3fd..a24f8dbc96 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/SourceJarTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/SourceJarTask.kt
@@ -20,8 +20,10 @@ import com.android.SdkConstants
import com.android.build.gradle.internal.component.ComponentCreationConfig
import com.android.build.gradle.internal.scope.InternalArtifactType
import com.android.build.gradle.internal.scope.getOutputPath
+import com.android.build.gradle.internal.tasks.BuildAnalyzer
import com.android.build.gradle.internal.tasks.VariantAwareTask
import com.android.build.gradle.internal.tasks.factory.VariantTaskCreationAction
+import com.android.ide.common.attribution.TaskCategoryLabel
import org.gradle.api.attributes.DocsType
import org.gradle.api.file.DuplicatesStrategy
import org.gradle.api.tasks.Internal
@@ -31,6 +33,7 @@ import org.gradle.api.tasks.util.PatternSet
import org.gradle.work.DisableCachingByDefault
@DisableCachingByDefault
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.ZIPPING])
abstract class SourceJarTask : Jar(), VariantAwareTask {
@Internal
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ZipMergingTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ZipMergingTask.kt
index 2447834f19..68e57238b3 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ZipMergingTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ZipMergingTask.kt
@@ -21,8 +21,10 @@ import com.android.build.gradle.internal.component.ComponentCreationConfig
import com.android.build.gradle.internal.packaging.JarCreatorFactory
import com.android.build.gradle.internal.packaging.JarCreatorType
import com.android.build.gradle.internal.scope.InternalArtifactType
+import com.android.build.gradle.internal.tasks.BuildAnalyzer
import com.android.build.gradle.internal.tasks.NonIncrementalTask
import com.android.build.gradle.internal.tasks.factory.VariantTaskCreationAction
+import com.android.ide.common.attribution.TaskCategoryLabel
import com.android.utils.FileUtils
import com.google.common.annotations.VisibleForTesting
import org.gradle.api.file.RegularFileProperty
@@ -39,6 +41,7 @@ import java.util.zip.Deflater
/** Task to merge the res/classes intermediate jars from a library into a single one */
@CacheableTask
+@BuildAnalyzer(taskCategoryLabels = [TaskCategoryLabel.ZIPPING, TaskCategoryLabel.MERGING])
abstract class ZipMergingTask : NonIncrementalTask() {
@get:InputFiles
diff --git a/build-system/gradle-core/src/test/java/com/android/build/api/component/analytics/AnalyticsEnabledSourcesTest.kt b/build-system/gradle-core/src/test/java/com/android/build/api/component/analytics/AnalyticsEnabledSourcesTest.kt
index 9d49113ae2..2729b58fc1 100644
--- a/build-system/gradle-core/src/test/java/com/android/build/api/component/analytics/AnalyticsEnabledSourcesTest.kt
+++ b/build-system/gradle-core/src/test/java/com/android/build/api/component/analytics/AnalyticsEnabledSourcesTest.kt
@@ -123,6 +123,15 @@ class AnalyticsEnabledSourcesTest {
)
}
+ @Test
+ fun getResources() {
+ testAnalytics(
+ SourceDirectories.Flat::class.java,
+ Sources::resources,
+ VariantPropertiesMethodType.SOURCES_RESOURCES_ACCESS_VALUE
+ )
+ }
+
private fun <T: SourceDirectories> testAnalytics(
type: Class<T>,
accessor: (sources: Sources) -> T?,
diff --git a/build-system/gradle-core/src/test/java/com/android/build/api/variant/impl/VariantBuilderImplTest.kt b/build-system/gradle-core/src/test/java/com/android/build/api/variant/impl/VariantBuilderImplTest.kt
index e25bd08b51..fe620caf90 100644
--- a/build-system/gradle-core/src/test/java/com/android/build/api/variant/impl/VariantBuilderImplTest.kt
+++ b/build-system/gradle-core/src/test/java/com/android/build/api/variant/impl/VariantBuilderImplTest.kt
@@ -18,7 +18,7 @@ package com.android.build.api.variant.impl
import com.android.build.api.variant.ComponentIdentity
import com.android.build.api.variant.VariantBuilder
-import com.android.build.gradle.internal.core.VariantDslInfo
+import com.android.build.gradle.internal.core.dsl.VariantDslInfo
import com.android.build.gradle.internal.services.ProjectServices
import com.android.build.gradle.internal.services.VariantBuilderServices
import com.google.common.truth.Truth
diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/DefaultVariantTest.kt b/build-system/gradle-core/src/test/java/com/android/build/gradle/DefaultVariantTest.kt
index 5fd9108ad3..9656a4c34f 100644
--- a/build-system/gradle-core/src/test/java/com/android/build/gradle/DefaultVariantTest.kt
+++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/DefaultVariantTest.kt
@@ -20,7 +20,7 @@ import com.android.AndroidProjectTypes
import com.android.build.api.variant.VariantFilter
import com.android.build.api.variant.impl.VariantImpl
import com.android.build.gradle.internal.component.VariantCreationConfig
-import com.android.build.gradle.internal.core.VariantDslInfoBuilder
+import com.android.build.gradle.internal.core.dsl.impl.computeName
import com.android.build.gradle.internal.dsl.ApplicationBuildFeaturesImpl
import com.android.build.gradle.internal.scope.BuildFeatureValuesImpl
import com.android.build.gradle.internal.tasks.factory.GlobalTaskCreationConfig
@@ -492,7 +492,7 @@ class DefaultVariantTest: AbstractVariantInputModelTest<String>() {
Mockito.`when`(globalTaskCreationConfig.services).thenReturn(dslServices)
for (variant in variantComputer.computeVariants()) {
- val name = VariantDslInfoBuilder.computeName(variant, componentType)
+ val name = computeName(variant, componentType)
val flavors = variant.productFlavors.map {
(given.productFlavors[it.second] ?: error("Cant find flavor ${it.second}")).productFlavor
diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/MergedFlavorTest.kt b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/MergedFlavorTest.kt
index eac76485d5..d74257d228 100644
--- a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/MergedFlavorTest.kt
+++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/MergedFlavorTest.kt
@@ -21,8 +21,10 @@ import com.android.build.gradle.internal.fixtures.FakeGradleProperty
import com.android.build.gradle.internal.fixtures.FakeProviderFactory
import com.android.build.gradle.internal.fixtures.FakeSyncIssueReporter
import com.android.build.gradle.internal.services.DslServices
+import com.android.build.gradle.internal.services.VariantServices
import com.android.build.gradle.internal.services.createDslServices
import com.android.build.gradle.internal.services.createProjectServices
+import com.android.build.gradle.internal.services.createVariantPropertiesApiServices
import com.android.build.gradle.options.BooleanOption
import com.android.build.gradle.options.ProjectOptions
import com.android.builder.core.AbstractProductFlavor
@@ -80,10 +82,11 @@ class MergedFlavorTest {
custom2.applicationId = "com.custom2.app"
}
}
- private lateinit var dslServices: DslServices
+ private lateinit var dslServices: DslServices
+ private lateinit var services: VariantServices
- private fun initDslServices(enableLegacyApi: Boolean, throwOnError: Boolean = !enableLegacyApi) {
+ private fun initservices(enableLegacyApi: Boolean, throwOnError: Boolean = !enableLegacyApi) {
val properties =
ImmutableMap.builder<String, Any>()
properties.put(
@@ -100,26 +103,36 @@ class MergedFlavorTest {
issueReporter = FakeSyncIssueReporter(throwOnError = throwOnError)
)
)
+
+ services = createVariantPropertiesApiServices(
+ createProjectServices(
+ projectOptions = ProjectOptions(
+ ImmutableMap.of(),
+ FakeProviderFactory(FakeProviderFactory.factory, properties.build())
+ ),
+ issueReporter = FakeSyncIssueReporter(throwOnError = throwOnError)
+ )
+ )
}
@Test
fun testClone() {
- initDslServices(true)
- val flavor = MergedFlavor.clone(custom, FakeGradleProperty("com.forty.two"), dslServices)
+ initservices(true)
+ val flavor = MergedFlavor.clone(custom, FakeGradleProperty("com.forty.two"), services)
assertThat(flavor.toString().substringAfter("{"))
.isEqualTo(custom.toString().substringAfter("{"))
CopyOfTester.assertAllGettersCalled(
MergedFlavor::class.java,
flavor,
listOf("getApplicationId")
- ) { MergedFlavor.clone(it, FakeGradleProperty("com.forty.two"), dslServices) }
+ ) { MergedFlavor.clone(it, FakeGradleProperty("com.forty.two"), services) }
}
@Test
fun testMergeOnDefault() {
- initDslServices(true)
+ initservices(true)
val flavor =
- MergedFlavor.mergeFlavors(defaultFlavor, ImmutableList.of(custom), FakeGradleProperty("com.forty.two"), dslServices)
+ MergedFlavor.mergeFlavors(defaultFlavor, ImmutableList.of(custom), FakeGradleProperty("com.forty.two"), services)
assertThat(flavor.minSdkVersion?.apiLevel).isEqualTo(42)
assertThat(flavor.targetSdkVersion?.apiLevel).isEqualTo(43)
@@ -135,10 +148,10 @@ class MergedFlavorTest {
@Test
fun testMergeOnCustom() {
- initDslServices(true)
+ initservices(true)
val flavor =
- MergedFlavor.mergeFlavors(custom, ImmutableList.of(defaultFlavor),FakeGradleProperty("com.forty.two"), dslServices)
+ MergedFlavor.mergeFlavors(custom, ImmutableList.of(defaultFlavor),FakeGradleProperty("com.forty.two"), services)
assertThat(flavor.minSdkVersion?.apiLevel).isEqualTo(42)
assertThat(flavor.targetSdkVersion?.apiLevel).isEqualTo(43)
@@ -154,13 +167,13 @@ class MergedFlavorTest {
@Test
fun testMergeDefaultOnDefault() {
- initDslServices(enableLegacyApi = false, throwOnError = false)
+ initservices(enableLegacyApi = false, throwOnError = false)
val defaultFlavor2 = productFlavor("default2")
val flavor =
MergedFlavor
.mergeFlavors(
- defaultFlavor2, ImmutableList.of(defaultFlavor), FakeGradleProperty("com.forty.two"), dslServices)
+ defaultFlavor2, ImmutableList.of(defaultFlavor), FakeGradleProperty("com.forty.two"), services)
assertThat(flavor.minSdkVersion).isNull()
assertThat(flavor.targetSdkVersion).isNull()
@@ -176,8 +189,8 @@ class MergedFlavorTest {
@Test
fun testResourceConfigMerge() {
- initDslServices(true)
- val flavor = MergedFlavor.mergeFlavors(custom2, ImmutableList.of(custom), FakeGradleProperty("com.forty.two"), dslServices)
+ initservices(true)
+ val flavor = MergedFlavor.mergeFlavors(custom2, ImmutableList.of(custom), FakeGradleProperty("com.forty.two"), services)
val configs = flavor.resourceConfigurations
assertThat(configs).containsExactly("hdpi", "ldpi")
@@ -185,8 +198,8 @@ class MergedFlavorTest {
@Test
fun testManifestPlaceholdersMerge() {
- initDslServices(true)
- val flavor = MergedFlavor.mergeFlavors(custom2, ImmutableList.of(custom), FakeGradleProperty("com.forty.two"), dslServices)
+ initservices(true)
+ val flavor = MergedFlavor.mergeFlavors(custom2, ImmutableList.of(custom), FakeGradleProperty("com.forty.two"), services)
val manifestPlaceholders = flavor.manifestPlaceholders
assertThat(manifestPlaceholders)
@@ -195,8 +208,8 @@ class MergedFlavorTest {
@Test
fun testResValuesMerge() {
- initDslServices(true)
- val flavor = MergedFlavor.mergeFlavors(custom2, ImmutableList.of(custom), FakeGradleProperty("com.forty.two"), dslServices)
+ initservices(true)
+ val flavor = MergedFlavor.mergeFlavors(custom2, ImmutableList.of(custom), FakeGradleProperty("com.forty.two"), services)
val resValues = flavor.resValues
assertThat(resValues).hasSize(3)
@@ -207,9 +220,9 @@ class MergedFlavorTest {
@Test
fun testBuildConfigFieldMerge() {
- initDslServices(true)
+ initservices(true)
- val flavor = MergedFlavor.mergeFlavors(custom2, ImmutableList.of(custom), FakeGradleProperty("com.forty.two"), dslServices)
+ val flavor = MergedFlavor.mergeFlavors(custom2, ImmutableList.of(custom), FakeGradleProperty("com.forty.two"), services)
val buildConfigFields = flavor.buildConfigFields
assertThat(buildConfigFields).hasSize(3)
@@ -220,7 +233,7 @@ class MergedFlavorTest {
@Test
fun testMergeMultiple() {
- initDslServices(true)
+ initservices(true)
val custom3 = productFlavor("custom3")
custom3.minSdkVersion = DefaultApiVersion(102)
@@ -228,7 +241,7 @@ class MergedFlavorTest {
custom3.versionNameSuffix = "custom3"
val flavor =
- MergedFlavor.mergeFlavors(custom, ImmutableList.of(custom3, custom2), FakeGradleProperty("com.forty.two"), dslServices)
+ MergedFlavor.mergeFlavors(custom, ImmutableList.of(custom3, custom2), FakeGradleProperty("com.forty.two"), services)
assertThat(flavor.minSdkVersion).isEqualTo(
DefaultApiVersion(
@@ -241,13 +254,13 @@ class MergedFlavorTest {
@Test
fun testSecondDimensionOverwritesDefault() {
- initDslServices(true)
+ initservices(true)
val custom3 = productFlavor("custom3")
custom3.minSdkVersion = DefaultApiVersion(102)
val flavor =
- MergedFlavor.mergeFlavors(custom, ImmutableList.of(custom3, custom2), FakeGradleProperty("com.forty.two"), dslServices)
+ MergedFlavor.mergeFlavors(custom, ImmutableList.of(custom3, custom2), FakeGradleProperty("com.forty.two"), services)
assertThat(flavor.minSdkVersion).isEqualTo(
DefaultApiVersion(
102
@@ -259,8 +272,8 @@ class MergedFlavorTest {
@Test
fun testSetVersionCodeError() {
- initDslServices(false)
- val flavor = MergedFlavor.clone(defaultFlavor, FakeGradleProperty("com.forty.two"), dslServices)
+ initservices(false)
+ val flavor = MergedFlavor.clone(defaultFlavor, FakeGradleProperty("com.forty.two"), services)
try {
flavor.versionCode = 123
fail("Setting versionCode should result in RuntimeException from issueReporter")
@@ -281,8 +294,8 @@ class MergedFlavorTest {
@Test
fun testSetVersionNameError() {
- initDslServices(false)
- val flavor = MergedFlavor.clone(defaultFlavor, FakeGradleProperty("com.forty.two"), dslServices)
+ initservices(false)
+ val flavor = MergedFlavor.clone(defaultFlavor, FakeGradleProperty("com.forty.two"), services)
try {
flavor.versionName = "foo"
fail("Setting versionName should result in RuntimeException from issueReporter")
diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/VariantBuilderComputeNameTest.kt b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/VariantBuilderComputeNameTest.kt
index bb457b642a..6a3f5bbe26 100644
--- a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/VariantBuilderComputeNameTest.kt
+++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/VariantBuilderComputeNameTest.kt
@@ -17,7 +17,10 @@
package com.android.build.gradle.internal.core
import com.android.build.api.component.impl.ComponentIdentityImpl
+import com.android.build.gradle.internal.core.dsl.impl.computeName
import com.android.build.gradle.internal.variant.DimensionCombinationImpl
+import com.android.build.gradle.internal.variant.VariantPathHelper.Companion.computeBaseName
+import com.android.build.gradle.internal.variant.VariantPathHelper.Companion.computeFullNameWithSplits
import com.android.builder.core.ComponentType
import com.android.builder.core.ComponentTypeImpl
import com.android.testutils.AbstractBuildGivenBuildExpectTest
@@ -205,14 +208,14 @@ class VariantBuilderComputeNameTest :
override fun defaultWhen(given: GivenBuilder): ResultBuilder {
val varCombo = DimensionCombinationImpl(given.buildType, given.flavors)
- var flavorName: String = ""
+ var flavorName = ""
return ResultBuilder().also {
- it.name = VariantDslInfoBuilder.computeName(varCombo, given.componentType) {
+ it.name = computeName(varCombo, given.componentType) {
flavorName = it
}
- it.baseName = VariantDslInfoBuilder.computeBaseName(varCombo, given.componentType)
- it.fullNameWithSplit = VariantDslInfoBuilder.computeFullNameWithSplits(
+ it.baseName = computeBaseName(varCombo, given.componentType)
+ it.fullNameWithSplit = computeFullNameWithSplits(
ComponentIdentityImpl(
it.name,
flavorName,
diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/VariantDslInfoTest.java b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/VariantDslInfoTest.java
index f56845f1c2..862175ec11 100644
--- a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/VariantDslInfoTest.java
+++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/VariantDslInfoTest.java
@@ -19,12 +19,15 @@ package com.android.build.gradle.internal.core;
import static com.google.common.truth.Truth.assertThat;
import com.android.annotations.Nullable;
-import com.android.build.api.dsl.CommonExtension;
import com.android.build.api.variant.AndroidVersion;
import com.android.build.api.variant.impl.MutableAndroidVersion;
import com.android.build.gradle.BaseExtension;
+import com.android.build.gradle.internal.core.dsl.ApplicationVariantDslInfo;
+import com.android.build.gradle.internal.core.dsl.impl.DslInfoBuilder;
+import com.android.build.gradle.internal.dsl.ApplicationPublishingImpl;
import com.android.build.gradle.internal.dsl.BuildType;
import com.android.build.gradle.internal.dsl.DefaultConfig;
+import com.android.build.gradle.internal.dsl.InternalApplicationExtension;
import com.android.build.gradle.internal.dsl.ProductFlavor;
import com.android.build.gradle.internal.dsl.SigningConfig;
import com.android.build.gradle.internal.fixtures.FakeDeprecationReporter;
@@ -46,7 +49,6 @@ import com.android.builder.model.ApiVersion;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.io.File;
-import java.util.Collections;
import java.util.List;
import kotlin.Pair;
import org.gradle.api.Project;
@@ -54,7 +56,6 @@ import org.gradle.api.file.DirectoryProperty;
import org.junit.Test;
import org.mockito.Mockito;
-/** Test cases for {@link VariantDslInfo}. */
public class VariantDslInfoTest {
private DefaultConfig defaultConfig;
@@ -75,7 +76,7 @@ public class VariantDslInfoTest {
SigningConfig override = signingConfig("override");
override.storePassword("override");
- VariantDslInfo variant = getVariant(override);
+ ApplicationVariantDslInfo variant = getVariant(override);
assertThat(variant.getSigningConfig()).isEqualTo(override);
}
@@ -92,7 +93,7 @@ public class VariantDslInfoTest {
SigningConfig override = signingConfig("override");
override.storePassword("override");
- VariantDslInfo variant = getVariant(override);
+ ApplicationVariantDslInfo variant = getVariant(override);
assertThat(variant.getSigningConfig()).isEqualTo(override);
}
@@ -104,7 +105,7 @@ public class VariantDslInfoTest {
AndroidVersion minSdkVersion = new MutableAndroidVersion(5);
defaultConfig.setMinSdkVersion(minSdkVersion.getApiLevel());
- VariantDslInfo variant = getVariant();
+ ApplicationVariantDslInfo variant = getVariant();
assertThat(variant.getMinSdkVersion()).isEqualTo(minSdkVersion);
}
@@ -119,7 +120,7 @@ public class VariantDslInfoTest {
assertThat(defaultConfig.getMinSdk()).isEqualTo(5);
assertThat(defaultConfig.getMinSdkPreview()).isNull();
- VariantDslInfo variant = getVariant();
+ ApplicationVariantDslInfo variant = getVariant();
assertThat(variant.getMinSdkVersion())
.isEqualTo(
@@ -137,7 +138,7 @@ public class VariantDslInfoTest {
assertThat(defaultConfig.getMinSdk()).isEqualTo(25);
assertThat(defaultConfig.getMinSdkPreview()).isEqualTo("O");
- VariantDslInfo variant = getVariant();
+ ApplicationVariantDslInfo variant = getVariant();
assertThat(variant.getMinSdkVersion())
.isEqualTo(
@@ -149,7 +150,7 @@ public class VariantDslInfoTest {
public void testGetMinSdkVersionDefault() {
initNoDeviceApiInjection();
- VariantDslInfo variant = getVariant();
+ ApplicationVariantDslInfo variant = getVariant();
assertThat(variant.getMinSdkVersion()).isEqualTo(new MutableAndroidVersion(1));
}
@@ -163,7 +164,7 @@ public class VariantDslInfoTest {
assertThat(defaultConfig.getTargetSdk()).isEqualTo(5);
assertThat(defaultConfig.getTargetSdkPreview()).isNull();
- VariantDslInfo variant = getVariant();
+ ApplicationVariantDslInfo variant = getVariant();
assertThat(variant.getTargetSdkVersion()).isEqualTo(targetSdkVersion);
}
@@ -178,7 +179,7 @@ public class VariantDslInfoTest {
assertThat(defaultConfig.getTargetSdk()).isEqualTo(25);
assertThat(defaultConfig.getTargetSdkPreview()).isEqualTo("O");
- VariantDslInfo variant = getVariant();
+ ApplicationVariantDslInfo variant = getVariant();
assertThat(variant.getTargetSdkVersion()).isEqualTo(targetSdkVersion);
}
@@ -190,7 +191,7 @@ public class VariantDslInfoTest {
MutableAndroidVersion targetSdkVersion = new MutableAndroidVersion(9);
defaultConfig.setTargetSdkVersion(targetSdkVersion.getApiLevel());
- VariantDslInfo variant = getVariant();
+ ApplicationVariantDslInfo variant = getVariant();
assertThat(variant.getTargetSdkVersion()).isEqualTo(targetSdkVersion);
}
@@ -199,7 +200,7 @@ public class VariantDslInfoTest {
public void testGetTargetSdkVersionDefault() {
initNoDeviceApiInjection();
- VariantDslInfo variant = getVariant();
+ ApplicationVariantDslInfo variant = getVariant();
assertThat(variant.getTargetSdkVersion()).isNull();
}
@@ -213,7 +214,7 @@ public class VariantDslInfoTest {
buildType.setMultiDexEnabled(true);
buildType.setDebuggable(false);
- VariantDslInfo variant = getVariant();
+ ApplicationVariantDslInfo variant = getVariant();
assertThat(variant.getMinSdkVersion().getApiLevel()).isEqualTo(16);
assertThat(variant.getTargetDeployApiFromIDE()).isEqualTo(18);
@@ -228,7 +229,7 @@ public class VariantDslInfoTest {
buildType.setMultiDexEnabled(false);
buildType.setDebuggable(true);
- VariantDslInfo variant = getVariant();
+ ApplicationVariantDslInfo variant = getVariant();
assertThat(variant.getMinSdkVersion().getApiLevel()).isEqualTo(16);
assertThat(variant.getTargetDeployApiFromIDE()).isEqualTo(18);
@@ -243,7 +244,7 @@ public class VariantDslInfoTest {
buildType.setMultiDexEnabled(true);
buildType.setDebuggable(true);
- VariantDslInfo variant = getVariant();
+ ApplicationVariantDslInfo variant = getVariant();
assertThat(variant.getMinSdkVersion().getApiLevel()).isEqualTo(16);
assertThat(variant.getTargetDeployApiFromIDE()).isEqualTo(18);
@@ -258,7 +259,7 @@ public class VariantDslInfoTest {
buildType.setMultiDexEnabled(true);
buildType.setDebuggable(true);
- VariantDslInfo variant = getVariant();
+ ApplicationVariantDslInfo variant = getVariant();
assertThat(variant.getMinSdkVersion().getApiLevel()).isEqualTo(16);
assertThat(variant.getTargetDeployApiFromIDE()).isEqualTo(22);
@@ -271,23 +272,27 @@ public class VariantDslInfoTest {
defaultConfig.applicationId("com.example.mapp");
buildType.applicationIdSuffix("");
- VariantDslInfo variant = getVariant();
+ ApplicationVariantDslInfo variant = getVariant();
assertThat(variant.getApplicationId().get()).isEqualTo("com.example.mapp");
}
- private VariantDslInfo getVariant() {
+ private ApplicationVariantDslInfo getVariant() {
return createVariant(null /*signingOverride*/);
}
- private VariantDslInfo getVariant(SigningConfig signingOverride) {
+ private ApplicationVariantDslInfo getVariant(SigningConfig signingOverride) {
return createVariant(signingOverride /*signingOverride*/);
}
- private VariantDslInfo createVariant(SigningConfig signingOverride) {
+ private ApplicationVariantDslInfo createVariant(SigningConfig signingOverride) {
+
+ InternalApplicationExtension extension = Mockito.mock(InternalApplicationExtension.class);
+ Mockito.when(extension.getPublishing())
+ .thenReturn(Mockito.mock(ApplicationPublishingImpl.class));
List<Pair<String, String>> flavors = ImmutableList.of(new Pair<>("dimension1", "flavor"));
- VariantDslInfoBuilder<?, ?> builder =
- VariantDslInfoBuilder.getBuilder(
+ DslInfoBuilder<?, ApplicationVariantDslInfo> builder =
+ DslInfoBuilder.getBuilder(
new DimensionCombinationImpl("debug", flavors),
ComponentTypeImpl.BASE_APK,
defaultConfig,
@@ -296,17 +301,15 @@ public class VariantDslInfoTest {
new MockSourceProvider("debug"),
signingOverride,
Mockito.mock(LazyManifestParser.class),
- dslServices,
variantServices,
Mockito.mock(BaseExtension.class),
- Mockito.mock(CommonExtension.class),
- false,
- Collections.emptyMap(),
- null /* testFixtureMainVariantName */);
+ extension,
+ Mockito.mock(DirectoryProperty.class),
+ dslServices);
builder.addProductFlavor(flavorConfig, new MockSourceProvider("custom"));
- return (VariantDslInfo) builder.createVariantDslInfo(Mockito.mock(DirectoryProperty.class));
+ return builder.createDslInfo();
}
private void initWithInjectedDeviceApi(int deviceApi) {
diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/VariantDslInfoTest2.kt b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/dsl/info/VariantDslInfoTest2.kt
index a66d8a3d86..e56bb27e21 100644
--- a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/VariantDslInfoTest2.kt
+++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/core/dsl/info/VariantDslInfoTest2.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,19 +14,22 @@
* limitations under the License.
*/
-package com.android.build.gradle.internal.core
+package com.android.build.gradle.internal.core.dsl.info
-import com.android.build.api.dsl.BuildFeatures
-import com.android.build.api.dsl.CommonExtension
-import com.android.build.api.dsl.TestedExtension
import com.android.build.api.variant.ComponentIdentity
-import com.android.build.gradle.BaseExtension
import com.android.build.gradle.internal.VariantManager
+import com.android.build.gradle.internal.core.dsl.AndroidTestComponentDslInfo
+import com.android.build.gradle.internal.core.dsl.ApplicationVariantDslInfo
+import com.android.build.gradle.internal.core.dsl.ComponentDslInfo
+import com.android.build.gradle.internal.core.dsl.impl.AndroidTestComponentDslInfoImpl
+import com.android.build.gradle.internal.core.dsl.impl.ApplicationVariantDslInfoImpl
import com.android.build.gradle.internal.dsl.BuildType
import com.android.build.gradle.internal.dsl.DefaultConfig
+import com.android.build.gradle.internal.dsl.InternalApplicationExtension
import com.android.build.gradle.internal.dsl.ProductFlavor
import com.android.build.gradle.internal.manifest.ManifestData
import com.android.build.gradle.internal.manifest.ManifestDataProvider
+import com.android.build.gradle.internal.publishing.VariantPublishingInfo
import com.android.build.gradle.internal.services.DslServices
import com.android.build.gradle.internal.services.ProjectServices
import com.android.build.gradle.internal.services.createDslServices
@@ -276,27 +279,6 @@ class VariantDslInfoTest2 :
}
@Test
- fun `instrumentationRunner on non test`() {
- given {
- // no specific manifest info
- manifestData { }
- }
-
- // provide a custom convert action to only call VariantDslInfo.instrumentationRunner
- // as it's not normally called for non-test variant type.
- convertToResult {
- instrumentationRunner = it.getInstrumentationRunner(DexingType.NATIVE_MULTIDEX).orNull
- }
-
- exceptionRule.expect(RuntimeException::class.java)
- exceptionRule.expectMessage("instrumentationRunner is not available to non-test variant")
-
- expect {
- // value is not relevant here since exception will be thrown
- }
- }
-
- @Test
fun `instrumentationRunner from defaultConfig`() {
given {
// no specific manifest info
@@ -395,27 +377,6 @@ class VariantDslInfoTest2 :
}
@Test
- fun `handleProfiling on non test`() {
- given {
- // no specific manifest info
- manifestData { }
- }
-
- // provide a custom convert action to call VariantDslInfo.handleProfiling
- // even though this is not a test componentType
- convertToResult {
- handleProfiling = it.handleProfiling.orNull
- }
-
- exceptionRule.expect(RuntimeException::class.java)
- exceptionRule.expectMessage("handleProfiling is not available to non-test variant")
-
- expect {
- // value is not relevant here since exception will be thrown
- }
- }
-
- @Test
fun `handleProfiling from defaultConfig`() {
given {
// no specific manifest info
@@ -514,27 +475,6 @@ class VariantDslInfoTest2 :
}
@Test
- fun `functionalTest on non test`() {
- given {
- // no specific manifest info
- manifestData { }
- }
-
- // provide a custom convert action to call VariantDslInfo.functionalTest
- // even though this is not a test componentType
- convertToResult {
- functionalTest = it.functionalTest.orNull
- }
-
- exceptionRule.expect(RuntimeException::class.java)
- exceptionRule.expectMessage("functionalTest is not available to non-test variant")
-
- expect {
- // value is not relevant here since exception will be thrown
- }
- }
-
- @Test
fun `functionalTest from defaultConfig`() {
given {
// no specific manifest info
@@ -859,28 +799,16 @@ class VariantDslInfoTest2 :
override fun instantiateGiven() = GivenData(dslServices)
override fun instantiateResult() = ResultData()
- interface TestedFullExtension: CommonExtension<
- BuildFeatures,
- com.android.build.api.dsl.BuildType,
- com.android.build.api.dsl.DefaultConfig,
- com.android.build.api.dsl.ProductFlavor
- >, TestedExtension
-
- override fun defaultWhen(given: GivenData): ResultData? {
+ override fun defaultWhen(given: GivenData): ResultData {
val componentIdentity = Mockito.mock(ComponentIdentity::class.java)
Mockito.`when`(componentIdentity.name).thenReturn("compIdName")
- val extension = if (given.componentType.isTestComponent) {
- Mockito.mock(TestedFullExtension::class.java).also {
- Mockito.`when`(it.namespace).thenReturn(given.namespace)
+ val extension = Mockito.mock(InternalApplicationExtension::class.java).also {
+ Mockito.`when`(it.namespace).thenReturn(given.namespace)
+ if (given.componentType.isTestComponent) {
Mockito.`when`(it.testNamespace).thenReturn(given.testNamespace)
}
- } else {
- Mockito.mock(CommonExtension::class.java).also {
- Mockito.`when`(it.namespace).thenReturn(given.namespace)
- }
}
- val oldExtension = Mockito.mock(BaseExtension::class.java)
// this does not quite test what VariantManager does because this only checks
// for the product flavors of that one variant, while VariantManager looks
@@ -889,72 +817,67 @@ class VariantDslInfoTest2 :
given.flavors
)
- val parentVariant =
- if (given.componentType.isNestedComponent) {
- VariantDslInfoImpl(
+ val mainVariant = ApplicationVariantDslInfoImpl(
+ componentIdentity = componentIdentity,
+ componentType = given.testedcomponentType,
+ defaultConfig = given.defaultConfig,
+ buildTypeObj = given.buildType,
+ productFlavorList = given.flavors,
+ dataProvider = DirectManifestDataProvider(given.manifestData, projectServices),
+ services = services,
+ buildDirectory = buildDirectory,
+ publishInfo = VariantPublishingInfo(emptyList()),
+ extension = extension,
+ oldExtension = null,
+ signingConfigOverride = null,
+ )
+
+ val dslInfo = when (given.componentType) {
+ ComponentTypeImpl.ANDROID_TEST -> {
+ AndroidTestComponentDslInfoImpl(
componentIdentity = componentIdentity,
componentType = given.testedcomponentType,
defaultConfig = given.defaultConfig,
buildTypeObj = given.buildType,
productFlavorList = given.flavors,
+ dataProvider = DirectManifestDataProvider(given.testManifestData, projectServices),
+ testedVariantDslInfo = mainVariant,
signingConfigOverride = null,
- productionVariant = null,
- dataProvider = DirectManifestDataProvider(given.manifestData, projectServices),
- dslServices = dslServices,
+ inconsistentTestAppId = inconsistentTestAppId,
services = services,
buildDirectory = buildDirectory,
- publishInfo = null,
- experimentalProperties = mapOf(),
- inconsistentTestAppId = false,
extension = extension,
- oldExtension = oldExtension
+ oldExtension = null
)
- } else { null }
-
- val variantDslInfo = VariantDslInfoImpl(
- componentIdentity = componentIdentity,
- componentType = given.componentType,
- defaultConfig = given.defaultConfig,
- buildTypeObj = given.buildType,
- productFlavorList = given.flavors,
- signingConfigOverride = null,
- productionVariant = parentVariant,
- dataProvider =
- if (given.componentType.isTestComponent) {
- DirectManifestDataProvider(given.testManifestData, projectServices)
- } else {
- DirectManifestDataProvider(given.manifestData, projectServices)
- },
- dslServices = dslServices,
- services = services,
- buildDirectory = buildDirectory,
- experimentalProperties = mapOf(),
- publishInfo = null,
- inconsistentTestAppId = inconsistentTestAppId,
- extension = extension,
- oldExtension = oldExtension
- )
+ }
+ ComponentTypeImpl.BASE_APK -> {
+ mainVariant
+ }
+ else -> {
+ throw RuntimeException("Unexpected type")
+ }
+ }
return instantiateResult().also {
if (convertAction != null) {
- convertAction?.invoke(it, variantDslInfo)
+ convertAction?.invoke(it, dslInfo)
} else {
- it.versionCode = variantDslInfo.versionCode.orNull
- it.versionName = variantDslInfo.versionName.orNull
+ it.versionCode = (dslInfo as? ApplicationVariantDslInfo)?.versionCode?.orNull
+ it.versionName = (dslInfo as? ApplicationVariantDslInfo)?.versionName?.orNull
// only query these if this is not a test.
- if (given.componentType.isForTesting) {
- it.instrumentationRunner = variantDslInfo.getInstrumentationRunner(given.dexingType).orNull
- it.handleProfiling = variantDslInfo.handleProfiling.get()
- it.functionalTest = variantDslInfo.functionalTest.get()
+ if (dslInfo is AndroidTestComponentDslInfo) {
+ it.instrumentationRunner = dslInfo.getInstrumentationRunner(given.dexingType).orNull
+ it.handleProfiling = dslInfo.handleProfiling.get()
+ it.functionalTest = dslInfo.functionalTest.get()
}
try {
- it.namespace = variantDslInfo.namespace.orNull
+ it.namespace = dslInfo.namespace.orNull
} catch (e: RuntimeException) {
// RuntimeException can be thrown when ManifestData.packageName is null
it.namespace = null
}
try {
- it.namespaceForR = variantDslInfo.namespaceForR.orNull
+ it.namespaceForR = (dslInfo as? AndroidTestComponentDslInfo)?.namespaceForR?.orNull
} catch (e: RuntimeException) {
// RuntimeException can be thrown when ManifestData.packageName is null
it.namespaceForR = null
@@ -974,14 +897,14 @@ class VariantDslInfoTest2 :
}
/** optional conversion action from variantDslInfo to result Builder. */
- private var convertAction: (ResultData.(variantInfo: VariantDslInfo) -> Unit)? = null
+ private var convertAction: (ResultData.(variantInfo: ComponentDslInfo) -> Unit)? = null
/**
* registers a custom conversion from variantDslInfo to ResultBuilder.
* This avoid having to use when {} which requires implementing all that defaultWhen()
* does.
*/
- private fun convertToResult(action: ResultData.(variantInfo: VariantDslInfo) -> Unit) {
+ private fun convertToResult(action: ResultData.(variantInfo: ComponentDslInfo) -> Unit) {
convertAction = action
}
diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/services/LintParallelBuildServiceTest.kt b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/services/LintParallelBuildServiceTest.kt
new file mode 100644
index 0000000000..6fde02c568
--- /dev/null
+++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/services/LintParallelBuildServiceTest.kt
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.internal.services
+
+import com.android.build.gradle.options.BooleanOption
+import com.android.build.gradle.options.ProjectOptions
+import com.android.build.gradle.options.StringOption
+import com.google.common.truth.Truth
+import kotlin.test.fail
+import org.junit.Rule
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+
+/** Unit tests for [LintParallelBuildService] */
+class LintParallelBuildServiceTest {
+
+ @get:Rule
+ val rule: MockitoRule = MockitoJUnit.rule()
+
+ @Mock
+ lateinit var projectOptions: ProjectOptions
+
+ @Test fun testCalculateMaxParallelUsages() {
+ // first test in process cases
+ Mockito.`when`(projectOptions.get(BooleanOption.RUN_LINT_IN_PROCESS)).thenReturn(true)
+
+ // Check normal case
+ Truth.assertThat(
+ LintParallelBuildService.calculateMaxParallelUsages(
+ projectOptions,
+ maxRuntimeMemory = 20 * GB,
+ totalPhysicalMemory = 40 * GB
+ )
+ ).isEqualTo(30)
+
+ // Check case when there's not enough memory, but should still return 1
+ Truth.assertThat(
+ LintParallelBuildService.calculateMaxParallelUsages(
+ projectOptions,
+ maxRuntimeMemory = 0,
+ totalPhysicalMemory = 40 * GB
+ )
+ ).isEqualTo(1)
+
+ // then test out of process cases
+ Mockito.`when`(projectOptions.get(BooleanOption.RUN_LINT_IN_PROCESS)).thenReturn(false)
+
+ // Check no specified lint heap size
+ Mockito.`when`(projectOptions.get(StringOption.LINT_HEAP_SIZE)).thenReturn(null)
+ Truth.assertThat(
+ LintParallelBuildService.calculateMaxParallelUsages(
+ projectOptions,
+ maxRuntimeMemory = 10 * GB,
+ totalPhysicalMemory = 40 * GB
+ )
+ ).isEqualTo(2)
+
+ // Check with specified lint heap size
+ Mockito.`when`(projectOptions.get(StringOption.LINT_HEAP_SIZE)).thenReturn("2g")
+ Truth.assertThat(
+ LintParallelBuildService.calculateMaxParallelUsages(
+ projectOptions,
+ maxRuntimeMemory = 10 * GB,
+ totalPhysicalMemory = 40 * GB
+ )
+ ).isEqualTo(18)
+
+ // Check case when there's not enough memory, but should still return 1
+ Truth.assertThat(
+ LintParallelBuildService.calculateMaxParallelUsages(
+ projectOptions,
+ maxRuntimeMemory = 1 * GB,
+ totalPhysicalMemory = 1 * GB
+ )
+ ).isEqualTo(1)
+
+ // Check case when user specifies invalid lint heap size
+ Mockito.`when`(projectOptions.get(StringOption.LINT_HEAP_SIZE)).thenReturn("invalid")
+ try {
+ LintParallelBuildService.calculateMaxParallelUsages(
+ projectOptions,
+ maxRuntimeMemory = 1 * GB,
+ totalPhysicalMemory = 1 * GB
+ )
+ fail("expected RuntimeException")
+ } catch (e: RuntimeException) {
+ Truth.assertThat(e.message)
+ .isEqualTo(
+ "Failed to parse ${StringOption.LINT_HEAP_SIZE.propertyName} \"invalid\"."
+ )
+ }
+ }
+}
+
+private const val GB = 1024 * 1024 * 1024L
diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/AarMetadataTaskTest.kt b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/AarMetadataTaskTest.kt
index f43b85f83c..5bd21056fc 100644
--- a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/AarMetadataTaskTest.kt
+++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/AarMetadataTaskTest.kt
@@ -76,7 +76,7 @@ class AarMetadataTaskTest {
task.minCompileSdk.set(28)
task.minCompileSdkExtension.set(1)
task.minAgpVersion.set("7.0.0")
- task.forceCompileSdkPreview.set("Tiramisu")
+ task.forceCompileSdkPreview.set("TiramisuPrivacySandbox")
task.taskAction()
checkAarMetadataFile(
@@ -86,7 +86,7 @@ class AarMetadataTaskTest {
minCompileSdk = "28",
minCompileSdkExtension = "1",
minAgpVersion = "7.0.0",
- compileSdkPreview = "Tiramisu"
+ compileSdkPreview = "TiramisuPrivacySandbox"
)
}
diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/CheckAarMetadataTaskTest.kt b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/CheckAarMetadataTaskTest.kt
index e7ba183ea0..a76a66b8dc 100644
--- a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/CheckAarMetadataTaskTest.kt
+++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/CheckAarMetadataTaskTest.kt
@@ -447,7 +447,7 @@ class CheckAarMetadataTaskTest {
minCompileSdk = 28,
minCompileSdkExtension = 0,
minAgpVersion = "3.0.0",
- forceCompileSdkPreview = "Tiramisu"
+ forceCompileSdkPreview = "TiramisuPrivacySandbox"
)
},
identifier = FakeComponentIdentifier("displayName")
@@ -468,13 +468,13 @@ class CheckAarMetadataTaskTest {
An issue was found when checking AAR metadata:
1. Dependency 'displayName' requires libraries and applications that
- depend on it to compile against codename "Tiramisu" of the
+ depend on it to compile against codename "TiramisuPrivacySandbox" of the
Android APIs.
:app is currently compiled against android-28.
Recommended action: Use a different version of dependency 'displayName',
- or set compileSdkPreview to "Tiramisu" in your build.gradle
+ or set compileSdkPreview to "TiramisuPrivacySandbox" in your build.gradle
file if you intend to experiment with that preview SDK.
""".trimIndent()
)
diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/TaskMethodModifiersAndAnnotationsTest.kt b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/TaskMethodModifiersAndAnnotationsTest.kt
index c283e00014..91cfc37d3d 100644
--- a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/TaskMethodModifiersAndAnnotationsTest.kt
+++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/TaskMethodModifiersAndAnnotationsTest.kt
@@ -16,7 +16,7 @@
package com.android.build.gradle.internal.tasks
-import com.android.build.gradle.internal.core.VariantDslInfo
+import com.android.build.gradle.internal.core.dsl.ComponentDslInfo
import com.android.build.gradle.tasks.PackageAndroidArtifact
import com.android.ide.common.workers.WorkerExecutorFacade
import com.google.common.reflect.ClassPath
@@ -183,7 +183,7 @@ class TaskMethodModifiersAndAnnotationsTest {
@Test
fun checkVariantConfigurationIsNotAField() {
- Truth.assertThat(findTaskFieldsOfType(VariantDslInfo::class.java)).isEmpty()
+ Truth.assertThat(findTaskFieldsOfType(ComponentDslInfo::class.java)).isEmpty()
}
@Test
diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/variant/VariantPathHelperTest.kt b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/variant/VariantPathHelperTest.kt
index 20b4cff3a8..db89949f56 100644
--- a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/variant/VariantPathHelperTest.kt
+++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/variant/VariantPathHelperTest.kt
@@ -16,9 +16,7 @@
package com.android.build.gradle.internal.variant
-import com.android.build.api.dsl.BuildType
-import com.android.build.gradle.internal.core.VariantDslInfo
-import com.android.build.gradle.internal.core.VariantDslInfoImpl
+import com.android.build.gradle.internal.core.dsl.ComponentDslInfo
import com.android.build.gradle.internal.services.DslServices
import com.android.build.gradle.options.BooleanOption
import com.android.build.gradle.options.IntegerOption
@@ -33,7 +31,6 @@ import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.Mock
-import org.mockito.Mockito
import org.mockito.Mockito.`when`
import org.mockito.Mockito.doReturn
import org.mockito.junit.MockitoJUnit
@@ -52,7 +49,7 @@ internal class VariantPathHelperTest {
}
@Mock
- lateinit var variantDslInfo: VariantDslInfoImpl
+ lateinit var variantDslInfo: ComponentDslInfo
@Mock
lateinit var dslServices: DslServices
@@ -65,9 +62,7 @@ internal class VariantPathHelperTest {
`when`(dslServices.projectOptions).thenReturn(projectOptions)
`when`(variantDslInfo.componentType).thenReturn(ComponentTypeImpl.LIBRARY)
`when`(variantDslInfo.productFlavorList).thenReturn(emptyList())
- val buildType = Mockito.mock(BuildType::class.java)
- `when`(buildType.name).thenReturn("apk_location")
- `when`(variantDslInfo.buildTypeObj).thenReturn(buildType)
+ `when`(variantDslInfo.buildType).thenReturn("apk_location")
}
@Test
diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/tasks/BuildAnalyzerTest.kt b/build-system/gradle-core/src/test/java/com/android/build/gradle/tasks/BuildAnalyzerTest.kt
index 67c79d76e2..1ba8a8d57b 100644
--- a/build-system/gradle-core/src/test/java/com/android/build/gradle/tasks/BuildAnalyzerTest.kt
+++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/tasks/BuildAnalyzerTest.kt
@@ -16,132 +16,18 @@
package com.android.build.gradle.tasks
-import com.android.build.gradle.internal.coverage.JacocoReportTask
-import com.android.build.gradle.internal.lint.AndroidLintAnalysisTask
-import com.android.build.gradle.internal.lint.AndroidLintCopyReportTask
-import com.android.build.gradle.internal.lint.AndroidLintGlobalTask
-import com.android.build.gradle.internal.lint.AndroidLintTask
-import com.android.build.gradle.internal.lint.AndroidLintTextOutputTask
-import com.android.build.gradle.internal.lint.LintModelWriterTask
-import com.android.build.gradle.internal.pipeline.IncrementalTransformTask
-import com.android.build.gradle.internal.pipeline.NonIncrementalTransformTask
-import com.android.build.gradle.internal.pipeline.StreamBasedTask
-import com.android.build.gradle.internal.pipeline.TransformTask
-import com.android.build.gradle.internal.res.GenerateApiPublicTxtTask
-import com.android.build.gradle.internal.res.GenerateEmptyResourceFilesTask
-import com.android.build.gradle.internal.res.GenerateLibraryRFileTask
-import com.android.build.gradle.internal.res.LinkAndroidResForBundleTask
-import com.android.build.gradle.internal.res.LinkApplicationAndroidResourcesTask
-import com.android.build.gradle.internal.res.ParseLibraryResourcesTask
-import com.android.build.gradle.internal.res.PrivacySandboxSdkLinkAndroidResourcesTask
-import com.android.build.gradle.internal.res.namespaced.CreateNonNamespacedLibraryManifestTask
-import com.android.build.gradle.internal.res.namespaced.GenerateNamespacedLibraryRFilesTask
-import com.android.build.gradle.internal.res.namespaced.LinkLibraryAndroidResourcesTask
-import com.android.build.gradle.internal.res.namespaced.ProcessAndroidAppResourcesTask
-import com.android.build.gradle.internal.res.namespaced.StaticLibraryManifestTask
-import com.android.build.gradle.internal.tasks.AarMetadataTask
-import com.android.build.gradle.internal.tasks.AndroidReportTask
-import com.android.build.gradle.internal.tasks.ApkZipPackagingTask
-import com.android.build.gradle.internal.tasks.AppClasspathCheckTask
-import com.android.build.gradle.internal.tasks.AppMetadataTask
-import com.android.build.gradle.internal.tasks.ApplicationIdWriterTask
-import com.android.build.gradle.internal.tasks.AssetPackManifestGenerationTask
-import com.android.build.gradle.internal.tasks.AssetPackPreBundleTask
+import com.android.build.gradle.internal.tasks.AnalyticsRecordingTask
+import com.android.build.gradle.internal.tasks.AndroidVariantTask
+import com.android.build.gradle.internal.tasks.AppPreBuildTask
+import com.android.build.gradle.internal.tasks.BaseTask
import com.android.build.gradle.internal.tasks.BuildAnalyzer
-import com.android.build.gradle.internal.tasks.BundleLibraryJavaRes
-import com.android.build.gradle.internal.tasks.BundleReportDependenciesTask
-import com.android.build.gradle.internal.tasks.BundleToApkTask
-import com.android.build.gradle.internal.tasks.BundleToStandaloneApkTask
-import com.android.build.gradle.internal.tasks.CheckAarMetadataTask
-import com.android.build.gradle.internal.tasks.CheckDuplicateClassesTask
-import com.android.build.gradle.internal.tasks.CheckJetifierTask
-import com.android.build.gradle.internal.tasks.CheckManifest
-import com.android.build.gradle.internal.tasks.CheckMultiApkLibrariesTask
-import com.android.build.gradle.internal.tasks.CheckProguardFiles
-import com.android.build.gradle.internal.tasks.ClasspathComparisonTask
-import com.android.build.gradle.internal.tasks.CompileArtProfileTask
-import com.android.build.gradle.internal.tasks.CompressAssetsTask
-import com.android.build.gradle.internal.tasks.D8BundleMainDexListTask
-import com.android.build.gradle.internal.tasks.DependencyReportTask
-import com.android.build.gradle.internal.tasks.DesugarLibKeepRulesMergeTask
-import com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestTask
-import com.android.build.gradle.internal.tasks.DeviceSerialTestTask
-import com.android.build.gradle.internal.tasks.DexArchiveBuilderTask
-import com.android.build.gradle.internal.tasks.DexFileDependenciesTask
-import com.android.build.gradle.internal.tasks.DexMergingTask
-import com.android.build.gradle.internal.tasks.ExportConsumerProguardFilesTask
-import com.android.build.gradle.internal.tasks.ExtractApksTask
-import com.android.build.gradle.internal.tasks.ExtractNativeDebugMetadataTask
-import com.android.build.gradle.internal.tasks.ExtractProfilerNativeDependenciesTask
-import com.android.build.gradle.internal.tasks.ExtractProguardFiles
-import com.android.build.gradle.internal.tasks.FeatureDexMergeTask
-import com.android.build.gradle.internal.tasks.FinalizeBundleTask
-import com.android.build.gradle.internal.tasks.GenerateApkDataTask
-import com.android.build.gradle.internal.tasks.GenerateLibraryProguardRulesTask
-import com.android.build.gradle.internal.tasks.InstallVariantTask
-import com.android.build.gradle.internal.tasks.InstallVariantViaBundleTask
-import com.android.build.gradle.internal.tasks.JacocoTask
-import com.android.build.gradle.internal.tasks.L8DexDesugarLibTask
-import com.android.build.gradle.internal.tasks.LibraryJniLibsTask
-import com.android.build.gradle.internal.tasks.LinkManifestForAssetPackTask
-import com.android.build.gradle.internal.tasks.LintCompile
-import com.android.build.gradle.internal.tasks.LintModelMetadataTask
-import com.android.build.gradle.internal.tasks.ListingFileRedirectTask
-import com.android.build.gradle.internal.tasks.ManagedDeviceInstrumentationTestResultAggregationTask
-import com.android.build.gradle.internal.tasks.ManagedDeviceInstrumentationTestTask
-import com.android.build.gradle.internal.tasks.MergeArtProfileTask
-import com.android.build.gradle.internal.tasks.MergeConsumerProguardFilesTask
-import com.android.build.gradle.internal.tasks.MergeJavaResourceTask
-import com.android.build.gradle.internal.tasks.MergeNativeDebugMetadataTask
-import com.android.build.gradle.internal.tasks.MergeNativeLibsTask
-import com.android.build.gradle.internal.tasks.ModuleMetadataWriterTask
-import com.android.build.gradle.internal.tasks.OptimizeResourcesTask
-import com.android.build.gradle.internal.tasks.PackageBundleTask
-import com.android.build.gradle.internal.tasks.PackageForUnitTest
-import com.android.build.gradle.internal.tasks.PackageRenderscriptTask
-import com.android.build.gradle.internal.tasks.ParseIntegrityConfigTask
-import com.android.build.gradle.internal.tasks.PerModuleBundleTask
-import com.android.build.gradle.internal.tasks.PerModuleReportDependenciesTask
-import com.android.build.gradle.internal.tasks.PrepareLintJarForPublish
-import com.android.build.gradle.internal.tasks.ProcessAssetPackManifestTask
-import com.android.build.gradle.internal.tasks.ProcessJavaResTask
-import com.android.build.gradle.internal.tasks.ProguardConfigurableTask
-import com.android.build.gradle.internal.tasks.R8Task
-import com.android.build.gradle.internal.tasks.RecalculateStackFramesTask
-import com.android.build.gradle.internal.tasks.SdkDependencyDataGeneratorTask
-import com.android.build.gradle.internal.tasks.ShrinkResourcesOldShrinkerTask
-import com.android.build.gradle.internal.tasks.SigningConfigVersionsWriterTask
-import com.android.build.gradle.internal.tasks.SigningConfigWriterTask
-import com.android.build.gradle.internal.tasks.SigningReportTask
-import com.android.build.gradle.internal.tasks.SourceSetsTask
-import com.android.build.gradle.internal.tasks.StripDebugSymbolsTask
-import com.android.build.gradle.internal.tasks.TestServerTask
-import com.android.build.gradle.internal.tasks.UninstallTask
-import com.android.build.gradle.internal.tasks.UnsafeOutputsTask
-import com.android.build.gradle.internal.tasks.ValidateSigningTask
-import com.android.build.gradle.internal.tasks.databinding.DataBindingExportFeatureInfoTask
-import com.android.build.gradle.internal.tasks.databinding.DataBindingExportFeatureNamespacesTask
-import com.android.build.gradle.internal.tasks.databinding.DataBindingGenBaseClassesTask
-import com.android.build.gradle.internal.tasks.databinding.DataBindingMergeDependencyArtifactsTask
-import com.android.build.gradle.internal.tasks.databinding.DataBindingTriggerTask
-import com.android.build.gradle.internal.tasks.featuresplit.FeatureNameWriterTask
-import com.android.build.gradle.internal.tasks.featuresplit.FeatureSetMetadataWriterTask
-import com.android.build.gradle.internal.tasks.featuresplit.FeatureSplitDeclarationWriterTask
-import com.android.build.gradle.internal.tasks.featuresplit.PackagedDependenciesWriterTask
-import com.android.build.gradle.internal.tasks.mlkit.GenerateMlModelClass
-import com.android.build.gradle.internal.transforms.LegacyShrinkBundleModuleResourcesTask
-import com.android.build.gradle.internal.transforms.ShrinkAppBundleResourcesTask
-import com.android.build.gradle.internal.transforms.ShrinkResourcesNewShrinkerTask
-import com.android.build.gradle.tasks.factory.AndroidUnitTest
-import com.android.build.gradle.tasks.sync.AbstractVariantModelTask
-import com.android.build.gradle.tasks.sync.AndroidTestVariantModelTask
-import com.android.build.gradle.tasks.sync.ApplicationVariantModelTask
-import com.android.build.gradle.tasks.sync.DynamicFeatureVariantModelTask
-import com.android.build.gradle.tasks.sync.LibraryVariantModelTask
-import com.android.build.gradle.tasks.sync.ModuleVariantModelTask
-import com.android.build.gradle.tasks.sync.TestModuleVariantModelTask
-import com.android.build.gradle.tasks.sync.TestVariantModelTask
-import com.android.build.gradle.tasks.sync.UnitTestVariantModelTask
+import com.android.build.gradle.internal.tasks.GeneratePrivacySandboxSdkRuntimeConfigFile
+import com.android.build.gradle.internal.tasks.NewIncrementalTask
+import com.android.build.gradle.internal.tasks.NonIncrementalGlobalTask
+import com.android.build.gradle.internal.tasks.NonIncrementalTask
+import com.android.build.gradle.internal.tasks.TestPreBuildTask
+import com.android.build.gradle.tasks.sync.AppIdListTask
+import com.android.ide.common.attribution.TaskCategoryLabel
import org.gradle.api.Task
import com.google.common.reflect.ClassPath
import com.google.common.reflect.TypeToken
@@ -152,196 +38,49 @@ import kotlin.test.assertEquals
class BuildAnalyzerTest {
@Test
- fun `all tasks have build analyzer annotations`() {
+ fun `all tasks have build analyzer annotations unless in allow-list`() {
val allTasks = getAllTasks()
- // When annotations for all tasks are added,
- // can just assert missingTasks is empty
- val missingTasks = allTasks.filter {
+ val actualTasksWithoutAnnotations = allTasks.filter {
!it.isAnnotationPresent(BuildAnalyzer::class.java)
}
- val tasksWithAnnotations = allTasks.filter {
+ // Make sure a task was not added twice in allow-list
+ assertEquals(expectedTasksWithoutAnnotations.toSet().size, expectedTasksWithoutAnnotations.size)
+ // Tasks without annotations has to be added into allow-list, otherwise it needs annotation
+ assertThat(actualTasksWithoutAnnotations).containsExactlyElementsIn(expectedTasksWithoutAnnotations)
+ }
+
+ @Test
+ fun `build analyzer annotated tasks does not have unallowed labels`() {
+ val allTasks = getAllTasks()
+ val unallowedLabels = listOf(TaskCategoryLabel.GRADLE,
+ TaskCategoryLabel.MISC, TaskCategoryLabel.UNKNOWN)
+ val tasksWithUnallowedLabels = allTasks.filter {
it.isAnnotationPresent(BuildAnalyzer::class.java)
+ }.filter { clazz ->
+ clazz.getAnnotation(BuildAnalyzer::class.java).taskCategoryLabels.any{ it in unallowedLabels }
}
- // Make sure a task was not added twice in list
- assertEquals(TASKS_WITH_ANNOTATIONS.toSet().size, TASKS_WITH_ANNOTATIONS.size)
- // Make sure tasks without annotation weren't accidentally added in
- assertThat(missingTasks).containsNoneIn(TASKS_WITH_ANNOTATIONS)
- assertThat(tasksWithAnnotations).containsExactlyElementsIn(TASKS_WITH_ANNOTATIONS)
- assertEquals(allTasks.size,missingTasks.size + TASKS_WITH_ANNOTATIONS.size)
+ assertThat(tasksWithUnallowedLabels).isEmpty()
}
- // List of tasks which has BuildAnalyzerAnnotation, added manually
- private val TASKS_WITH_ANNOTATIONS = listOf(
- AidlCompile::class.java,
- JavaPreCompileTask::class.java,
- CompileArtProfileTask::class.java,
- LintCompile::class.java,
- CompileLibraryResourcesTask::class.java,
- RenderscriptCompile::class.java,
- ShaderCompile::class.java,
- AndroidReportTask::class.java,
- AndroidUnitTest::class.java,
- DeviceProviderInstrumentTestTask::class.java,
- JacocoReportTask::class.java,
- TestServerTask::class.java,
- GenerateTestConfig::class.java,
- PackageForUnitTest::class.java,
- JacocoTask::class.java,
- ManagedDeviceInstrumentationTestTask::class.java,
- DeviceSerialTestTask::class.java,
- ManagedDeviceInstrumentationTestResultAggregationTask::class.java,
- CheckManifest::class.java,
- CompatibleScreensManifest::class.java,
- InvokeManifestMerger::class.java,
- ProcessApplicationManifest::class.java,
- ProcessLibraryManifest::class.java,
- ProcessTestManifest::class.java,
- StaticLibraryManifestTask::class.java,
- CreateNonNamespacedLibraryManifestTask::class.java,
- ManifestProcessorTask::class.java,
- AssetPackManifestGenerationTask::class.java,
- ProcessAssetPackManifestTask::class.java,
- LinkManifestForAssetPackTask::class.java,
- ProcessManifestForBundleTask::class.java,
- ProcessManifestForMetadataFeatureTask::class.java,
- ProcessManifestForInstantAppTask::class.java,
- ProcessPackagedManifestTask::class.java,
- ProcessMultiApkApplicationManifest::class.java,
- GenerateManifestJarTask::class.java,
- LinkLibraryAndroidResourcesTask::class.java,
- LinkApplicationAndroidResourcesTask::class.java,
- LinkAndroidResForBundleTask::class.java,
- GenerateResValues::class.java,
- MergeResources::class.java,
- VerifyLibraryResourcesTask::class.java,
- ProcessAndroidAppResourcesTask::class.java,
- GenerateLibraryRFileTask::class.java,
- GenerateNamespacedLibraryRFilesTask::class.java,
- LegacyShrinkBundleModuleResourcesTask::class.java,
- ParseLibraryResourcesTask::class.java,
- ExtractDeepLinksTask::class.java,
- ShrinkResourcesOldShrinkerTask::class.java,
- GenerateEmptyResourceFilesTask::class.java,
- OptimizeResourcesTask::class.java,
- ShrinkAppBundleResourcesTask::class.java,
- ShrinkResourcesNewShrinkerTask::class.java,
- PrivacySandboxSdkLinkAndroidResourcesTask::class.java,
- ExternalNativeBuildJsonTask::class.java,
- ExternalNativeBuildTask::class.java,
- ExternalNativeCleanTask::class.java,
- MergeNativeLibsTask::class.java,
- StripDebugSymbolsTask::class.java,
- LibraryJniLibsTask::class.java,
- ExtractNativeDebugMetadataTask::class.java,
- MergeNativeDebugMetadataTask::class.java,
- PrefabPackageTask::class.java,
- PrefabPackageConfigurationTask::class.java,
- ProcessJavaResTask::class.java,
- BundleLibraryJavaRes::class.java,
- MergeJavaResourceTask::class.java,
- JavaDocGenerationTask::class.java,
- JavaDocJarTask::class.java,
- PackageRenderscriptTask::class.java,
- DexMergingTask::class.java,
- DexFileDependenciesTask::class.java,
- DexArchiveBuilderTask::class.java,
- L8DexDesugarLibTask::class.java,
- D8BundleMainDexListTask::class.java,
- FeatureDexMergeTask::class.java,
- PrivacySandboxSdkDexTask::class.java,
- PrivacySandboxSdkMergeDexTask::class.java,
- MergeArtProfileTask::class.java,
- ProcessLibraryArtProfileTask::class.java,
- PrepareLintJarForPublish::class.java,
- LintModelWriterTask::class.java,
- AndroidLintTask::class.java,
- AndroidLintGlobalTask::class.java,
- AndroidLintCopyReportTask::class.java,
- AndroidLintAnalysisTask::class.java,
- LintModelMetadataTask::class.java,
- AndroidLintTextOutputTask::class.java,
- DataBindingTriggerTask::class.java,
- DataBindingGenBaseClassesTask::class.java,
- DataBindingExportFeatureNamespacesTask::class.java,
- DataBindingExportFeatureInfoTask::class.java,
- DataBindingMergeDependencyArtifactsTask::class.java,
- GenerateApkDataTask::class.java,
- FeatureSplitDeclarationWriterTask::class.java,
- ModuleMetadataWriterTask::class.java,
- FeatureSetMetadataWriterTask::class.java,
- ApplicationIdWriterTask::class.java,
- ParseIntegrityConfigTask::class.java,
- FeatureNameWriterTask::class.java,
- SdkDependencyDataGeneratorTask::class.java,
- AarMetadataTask::class.java,
- CheckAarMetadataTask::class.java,
- GenerateApiPublicTxtTask::class.java,
- AppMetadataTask::class.java,
- SigningConfigVersionsWriterTask::class.java,
- ListingFileRedirectTask::class.java,
- ApplicationVariantModelTask::class.java,
- AbstractVariantModelTask::class.java,
- LibraryVariantModelTask::class.java,
- DynamicFeatureVariantModelTask::class.java,
- AndroidTestVariantModelTask::class.java,
- TestVariantModelTask::class.java,
- UnitTestVariantModelTask::class.java,
- ModuleVariantModelTask::class.java,
- TestModuleVariantModelTask::class.java,
- InstallVariantTask::class.java,
- UninstallTask::class.java,
- InstallVariantViaBundleTask::class.java,
- DependencyReportTask::class.java,
- SigningReportTask::class.java,
- SourceSetsTask::class.java,
- PackagedDependenciesWriterTask::class.java,
- AnalyzeDependenciesTask::class.java,
- ClasspathComparisonTask::class.java,
- UnsafeOutputsTask::class.java,
- PackageApplication::class.java,
- ExtractApksTask::class.java,
- BundleToApkTask::class.java,
- BundleToStandaloneApkTask::class.java,
- SigningConfigWriterTask::class.java,
- ApkZipPackagingTask::class.java,
- BundleAar::class.java,
- FusedLibraryBundleAar::class.java,
- PackageBundleTask::class.java,
- PerModuleBundleTask::class.java,
- FinalizeBundleTask::class.java,
- BundleReportDependenciesTask::class.java,
- PerModuleReportDependenciesTask::class.java,
- AssetPackPreBundleTask::class.java,
- PackagePrivacySandboxSdkBundle::class.java,
- ValidateSigningTask::class.java,
- CheckTestedAppObfuscation::class.java,
- CheckMultiApkLibrariesTask::class.java,
- AppClasspathCheckTask::class.java,
- CheckDuplicateClassesTask::class.java,
- CheckJetifierTask::class.java,
- ExtractProguardFiles::class.java,
- CheckProguardFiles::class.java,
- MergeConsumerProguardFilesTask::class.java,
- GenerateLibraryProguardRulesTask::class.java,
- ProguardConfigurableTask::class.java,
- ExportConsumerProguardFilesTask::class.java,
- R8Task::class.java,
- CompressAssetsTask::class.java,
- GenerateBuildConfig::class.java,
- GenerateMlModelClass::class.java,
- PrivacySandboxSdkManifestGeneratorTask::class.java,
- ExtractAnnotations::class.java,
- MergeSourceSetFolders::class.java,
- StreamBasedTask::class.java,
- TransformTask::class.java,
- RecalculateStackFramesTask::class.java,
- ExtractProfilerNativeDependenciesTask::class.java,
- TransformClassesWithAsmTask::class.java,
- DesugarLibKeepRulesMergeTask::class.java,
- FusedLibraryClassesRewriteTask::class.java,
- IncrementalTransformTask::class.java,
- NonIncrementalTransformTask::class.java,
- ) as List<Class<*>>
+ // Allow-list of tasks that are defined to not have annotations.
+ // Usually due to it being a base task, and hence is implemented by other tasks.
+ // Another reason is that it does not fall into any TaskCategoryLabel,
+ // and the task will not show up in Build Analyzer anyway.
+ private val expectedTasksWithoutAnnotations = listOf(
+ AppPreBuildTask::class.java,
+ TestPreBuildTask::class.java,
+ AndroidVariantTask::class.java,
+ NewIncrementalTask::class.java,
+ NonIncrementalTask::class.java,
+ PackageAndroidArtifact::class.java,
+ BaseTask::class.java,
+ NonIncrementalGlobalTask::class.java,
+ AnalyticsRecordingTask::class.java,
+ BuildPrivacySandboxSdkApks::class.java,
+ GeneratePrivacySandboxAsar::class.java,
+ GeneratePrivacySandboxSdkRuntimeConfigFile::class.java,
+ AppIdListTask::class.java
+ )
private fun getAllTasks(): List<Class<*>> {
val classPath = ClassPath.from(this.javaClass.classLoader)
diff --git a/build-system/gradle-core/src/test/resources/com/android/build/gradle/pseudo-api.txt b/build-system/gradle-core/src/test/resources/com/android/build/gradle/pseudo-api.txt
index 3f0aa7535e..f6a6a89641 100644
--- a/build-system/gradle-core/src/test/resources/com/android/build/gradle/pseudo-api.txt
+++ b/build-system/gradle-core/src/test/resources/com/android/build/gradle/pseudo-api.txt
@@ -1455,7 +1455,7 @@ com.android.build.gradle.internal.dsl.ExternalNativeNdkBuildOptions.setcFlags: v
com.android.build.gradle.internal.dsl.ExternalNativeNdkBuildOptions.targets: void (java.lang.String[])
com.android.build.gradle.internal.dsl.InitWithUtilKt
com.android.build.gradle.internal.dsl.InitWithUtilKt.initExtensions: void (org.gradle.api.plugins.ExtensionAware, org.gradle.api.plugins.ExtensionAware)
-com.android.build.gradle.internal.dsl.InternalApplicationExtension implements com.android.build.api.dsl.ApplicationExtension, com.android.build.gradle.internal.dsl.InternalTestedExtension, com.android.build.gradle.internal.dsl.InternalCommonExtension
+com.android.build.gradle.internal.dsl.InternalApplicationExtension implements com.android.build.api.dsl.ApplicationExtension, com.android.build.gradle.internal.dsl.InternalTestedExtension
com.android.build.gradle.internal.dsl.InternalApplicationExtension.bundle: void (org.gradle.api.Action<com.android.build.gradle.internal.dsl.BundleOptions>)
com.android.build.gradle.internal.dsl.InternalApplicationExtension.dependenciesInfo: void (org.gradle.api.Action<com.android.build.api.dsl.DependenciesInfo>)
com.android.build.gradle.internal.dsl.InternalApplicationExtension.getAssetPacks: java.util.Set<java.lang.String> ()
@@ -1502,8 +1502,8 @@ com.android.build.gradle.internal.dsl.InternalCommonExtension.splits: void (org.
com.android.build.gradle.internal.dsl.InternalCommonExtension.testCoverage: void (org.gradle.api.Action<com.android.build.api.dsl.TestCoverage>)
com.android.build.gradle.internal.dsl.InternalCommonExtension.testOptions: void (org.gradle.api.Action<com.android.build.gradle.internal.dsl.TestOptions>)
com.android.build.gradle.internal.dsl.InternalCommonExtension.viewBinding: void (org.gradle.api.Action<com.android.build.gradle.internal.dsl.ViewBindingOptionsImpl>)
-com.android.build.gradle.internal.dsl.InternalDynamicFeatureExtension implements com.android.build.api.dsl.DynamicFeatureExtension, com.android.build.gradle.internal.dsl.InternalTestedExtension, com.android.build.gradle.internal.dsl.InternalCommonExtension
-com.android.build.gradle.internal.dsl.InternalLibraryExtension implements com.android.build.api.dsl.LibraryExtension, com.android.build.gradle.internal.dsl.InternalTestedExtension, com.android.build.gradle.internal.dsl.InternalCommonExtension
+com.android.build.gradle.internal.dsl.InternalDynamicFeatureExtension implements com.android.build.api.dsl.DynamicFeatureExtension, com.android.build.gradle.internal.dsl.InternalTestedExtension
+com.android.build.gradle.internal.dsl.InternalLibraryExtension implements com.android.build.api.dsl.LibraryExtension, com.android.build.gradle.internal.dsl.InternalTestedExtension
com.android.build.gradle.internal.dsl.InternalLibraryExtension.getAidlPackagedList: java.util.Collection<java.lang.String> ()
com.android.build.gradle.internal.dsl.InternalLibraryExtension.publishing: void (org.gradle.api.Action<com.android.build.api.dsl.LibraryPublishing>)
com.android.build.gradle.internal.dsl.InternalLibraryExtension.setAidlPackagedList: void (java.util.Collection<java.lang.String>)
@@ -1511,7 +1511,7 @@ com.android.build.gradle.internal.dsl.InternalPrivacySandboxSdkExtension impleme
com.android.build.gradle.internal.dsl.InternalPrivacySandboxSdkExtension.bundle: void (org.gradle.api.Action<com.android.build.api.dsl.PrivacySandboxSdkBundle>)
com.android.build.gradle.internal.dsl.InternalSigningConfig implements com.android.build.api.dsl.SigningConfig, com.android.build.api.dsl.ApkSigningConfig, org.gradle.api.Named, com.android.builder.model.SigningConfig
com.android.build.gradle.internal.dsl.InternalTestExtension implements com.android.build.api.dsl.TestExtension, com.android.build.gradle.internal.dsl.InternalCommonExtension
-com.android.build.gradle.internal.dsl.InternalTestedExtension implements com.android.build.api.dsl.TestedExtension
+com.android.build.gradle.internal.dsl.InternalTestedExtension implements com.android.build.api.dsl.TestedExtension, com.android.build.gradle.internal.dsl.InternalCommonExtension
com.android.build.gradle.internal.dsl.InternalTestedExtension.testFixtures: void (org.gradle.api.Action<com.android.build.api.dsl.TestFixtures>)
com.android.build.gradle.internal.dsl.JavaCompileOptions implements com.android.build.gradle.api.JavaCompileOptions, com.android.build.api.dsl.JavaCompileOptions
com.android.build.gradle.internal.dsl.JavaCompileOptions.<init>: com.android.build.gradle.internal.dsl.JavaCompileOptions ()
diff --git a/build-system/integration-test/application/BUILD.bazel b/build-system/integration-test/application/BUILD.bazel
index 023e05c1b5..78657f4a74 100644
--- a/build-system/integration-test/application/BUILD.bazel
+++ b/build-system/integration-test/application/BUILD.bazel
@@ -49,7 +49,7 @@ OLD_SDKS = [
]
PREVIEW_SDKS = [
- "//prebuilts/studio/sdk:platforms/android-Tiramisu_build_only",
+ "//prebuilts/studio/sdk:platforms/android-TiramisuPrivacySandbox_build_only",
]
#keep sorted
diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/AarPublishTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/AarPublishTest.kt
index 552d4b8bca..80e6ad83a0 100644
--- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/AarPublishTest.kt
+++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/AarPublishTest.kt
@@ -16,11 +16,15 @@
package com.android.build.gradle.integration.application
+import com.android.SdkConstants
import com.android.build.gradle.integration.common.fixture.GradleTestProject
import com.android.build.gradle.integration.common.fixture.app.MinimalSubProject
import com.android.build.gradle.integration.common.fixture.app.MultiModuleTestProject
+import com.android.build.gradle.integration.common.fixture.testprojects.PluginType
+import com.android.build.gradle.integration.common.fixture.testprojects.createGradleProject
import com.android.build.gradle.options.BooleanOption
import com.android.utils.FileUtils
+import com.google.wireless.android.sdk.stats.GradleBuildProject
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
@@ -30,18 +34,30 @@ import java.util.zip.ZipFile
/*
* Tests to verify that AARs produced from library modules in build/output/aar are in a state
-* which can be published e.g to public repository like Maven.
+* which can be published
+* e.g. to a public repository like Maven, AAR contains expected file structure.
*/
class AarPublishTest {
@get:Rule
- val project = GradleTestProject.builder().fromTestApp(
- MultiModuleTestProject.builder()
- .subproject(
- ":library", MinimalSubProject.lib("com.example.library")
- .appendToBuild("android.buildTypes.debug.testCoverageEnabled true")
- ).build()
- ).create()
+ val project = createGradleProject {
+ subProject(":library") {
+ plugins.add(PluginType.ANDROID_LIB)
+ android {
+ defaultCompileSdk()
+ namespace = "com.example.library"
+ buildTypes {
+ named("debug") {
+ testCoverageEnabled = true
+ }
+ }
+ addFile("src/main/res/values/strings.xml",
+ "<resources>\n" +
+ "<string name=\"one\">Some string</string>\n" +
+ "</resources>")
+ }
+ }
+ }
@get:Rule
val temporaryDirectory = TemporaryFolder()
@@ -55,7 +71,6 @@ class AarPublishTest {
val libraryPublishedAar =
FileUtils.join(librarySubproject.outputDir, "aar", "library-debug.aar")
val tempTestData = temporaryDirectory.newFolder("testData")
- val buildConfigClasspath = "com/example/library/BuildConfig.class"
val extractedJar = File(tempTestData, "classes.jar")
// Extracts the zipped BuildConfig.class in library-debug.aar/classes.jar to
// the extractedBuildConfigClass temporary file, so it can be later loaded
@@ -81,4 +96,18 @@ class AarPublishTest {
}
}
}
+
+ @Test
+ fun aarContainsAllowedRootDirectories() {
+ project.execute("library:assembleDebug")
+ project.getSubproject(":library").assertThatAar(GradleTestProject.ApkType.DEBUG.buildType) {
+ containsFile("/AndroidManifest.xml")
+ containsFile("/R.txt")
+ containsFile("/classes.jar")
+ containsFile("/res/values/values.xml")
+ containsFile("META-INF/com/android/build/gradle/aar-metadata.properties")
+ // Regression test for b/232117952
+ doesNotContain("/values/")
+ }
+ }
}
diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/CheckAarMetadataTaskTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/CheckAarMetadataTaskTest.kt
index 23e42bac5f..42c028fb5e 100644
--- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/CheckAarMetadataTaskTest.kt
+++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/CheckAarMetadataTaskTest.kt
@@ -424,11 +424,11 @@ class CheckAarMetadataTaskTest {
addAarWithPossiblyInvalidAarMetadataToAppProject(
aarFormatVersion = AarMetadataTask.AAR_FORMAT_VERSION,
aarMetadataVersion = AarMetadataTask.AAR_METADATA_VERSION,
- forceCompileSdkPreview = "Tiramisu"
+ forceCompileSdkPreview = "TiramisuPrivacySandbox"
)
TestFileUtils.appendToFile(
project.getSubproject("app").buildFile,
- "\n\nandroid.compileSdkPreview 'Tiramisu'\n\n"
+ "\n\nandroid.compileSdkPreview 'TiramisuPrivacySandbox'\n\n"
)
val result = project.executor().run(":app:checkDebugAarMetadata")
ScannerSubject.assertThat(result.stdout).contains("BUILD SUCCESSFUL")
@@ -439,7 +439,7 @@ class CheckAarMetadataTaskTest {
addAarWithPossiblyInvalidAarMetadataToAppProject(
aarFormatVersion = AarMetadataTask.AAR_FORMAT_VERSION,
aarMetadataVersion = AarMetadataTask.AAR_METADATA_VERSION,
- forceCompileSdkPreview = "Tiramisu"
+ forceCompileSdkPreview = "TiramisuPrivacySandbox"
)
// Test that build fails with desired error message.
@@ -453,13 +453,13 @@ class CheckAarMetadataTaskTest {
An issue was found when checking AAR metadata:
1. Dependency 'library.aar' requires libraries and applications that
- depend on it to compile against codename "Tiramisu" of the
+ depend on it to compile against codename "TiramisuPrivacySandbox" of the
Android APIs.
:app is currently compiled against $compileSdkHash.
Recommended action: Use a different version of dependency 'library.aar',
- or set compileSdkPreview to "Tiramisu" in your build.gradle
+ or set compileSdkPreview to "TiramisuPrivacySandbox" in your build.gradle
file if you intend to experiment with that preview SDK.
""".trimIndent()
)
diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/DifferentProjectClassLoadersTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/DifferentProjectClassLoadersTest.kt
index d1c79e9849..651e5f9add 100644
--- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/DifferentProjectClassLoadersTest.kt
+++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/DifferentProjectClassLoadersTest.kt
@@ -21,6 +21,7 @@ import com.android.build.gradle.integration.common.fixture.GradleTestProject
import com.android.build.gradle.integration.common.fixture.app.MinimalSubProject
import com.android.build.gradle.integration.common.fixture.app.MultiModuleTestProject
import com.android.build.gradle.integration.common.utils.TestFileUtils
+import com.android.build.gradle.internal.services.LintParallelBuildService
import com.android.build.gradle.options.StringOption
import com.android.ide.common.attribution.AndroidGradlePluginAttributionData
import com.google.common.truth.Truth.assertThat
@@ -65,6 +66,15 @@ class DifferentProjectClassLoadersTest {
project.executor().run("assembleDebug")
}
+ /**
+ * Test lint because we register the [LintParallelBuildService] once instead of registering one
+ * per classloader.
+ */
+ @Test
+ fun testLint() {
+ project.executor().run("lintDebug")
+ }
+
@Test
fun testAttributionFile() {
fun setUpDummyTask(taskName: String): String =
diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/NoCruncherTest.java b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/NoCruncherTest.java
index df401c3cf5..deaaee215a 100644
--- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/NoCruncherTest.java
+++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/NoCruncherTest.java
@@ -20,7 +20,6 @@ import static com.android.testutils.truth.PathSubject.assertThat;
import static com.google.common.truth.Truth.assertThat;
import com.android.annotations.NonNull;
-import com.android.build.gradle.integration.common.fixture.BaseGradleExecutor;
import com.android.build.gradle.integration.common.fixture.GradleTestProject;
import com.android.build.gradle.integration.common.fixture.GradleTestProject.ApkType;
import com.android.build.gradle.integration.common.fixture.TemporaryProjectModification;
@@ -79,7 +78,7 @@ public class NoCruncherTest {
checkResource(ApkType.RELEASE, "drawable/icon.png", true);
}
// QA is debuggable, but inits from release, so the cruncher is default enabled.
- checkResource(ApkType.of("qa", true), "drawable/icon.png", true);
+ checkResource(ApkType.of("qa", false), "drawable/icon.png", true);
});
}
@@ -95,7 +94,7 @@ public class NoCruncherTest {
projectModification.replaceInFile(
"build.gradle", "// crunchPngs false", "crunchPngs false");
noPngCrunch.executor().run("assembleQa");
- checkResource(ApkType.of("qa", true), "drawable/icon.png", false);
+ checkResource(ApkType.of("qa", false), "drawable/icon.png", false);
});
}
diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/ProfileableTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/ProfileableTest.kt
index 808f50e32c..30489aa17c 100644
--- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/ProfileableTest.kt
+++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/ProfileableTest.kt
@@ -16,6 +16,7 @@
package com.android.build.gradle.integration.application
+import com.android.apksig.ApkVerifier
import com.android.build.gradle.integration.common.fixture.DEFAULT_COMPILE_SDK_VERSION
import com.android.build.gradle.integration.common.fixture.GradleTestProject
import com.android.build.gradle.integration.common.fixture.app.MinimalSubProject
@@ -25,6 +26,7 @@ import com.android.build.gradle.integration.common.truth.ScannerSubject
import com.android.build.gradle.integration.common.truth.TruthHelper.assertThat
import com.android.build.gradle.integration.common.utils.SigningHelper
import com.android.build.gradle.integration.common.utils.TestFileUtils
+import com.android.build.gradle.options.BooleanOption
import com.android.build.gradle.options.StringOption
import org.junit.Rule
import org.junit.Test
@@ -50,14 +52,16 @@ class ProfileableTest {
fun `test dsl setting the release build type to be profileable`() {
val app = project.getSubproject(":app")
app.buildFile.appendText("android.buildTypes.release.profileable true")
- project.executor().run("assembleRelease")
- val apkType = GradleTestProject.ApkType.RELEASE_SIGNED
- val apk = project.getSubproject("app").getApk(apkType)
- val verificationResult = SigningHelper.assertApkSignaturesVerify(apk, 30)
+ project.executor()
+ .with(BooleanOption.ENABLE_DEFAULT_DEBUG_SIGNING_CONFIG, true)
+ .run("assembleRelease")
+ val apkSigned =
+ project.getSubproject("app").getApk(GradleTestProject.ApkType.RELEASE_SIGNED)
+ val verificationResult = SigningHelper.assertApkSignaturesVerify(apkSigned, 30)
assertThat(
verificationResult.signerCertificates.first().subjectX500Principal.name
).isEqualTo("C=US,O=Android,CN=Android Debug")
- val manifest = ApkSubject.getManifestContent(apk.file.toAbsolutePath())
+ val manifest = ApkSubject.getManifestContent(apkSigned.file.toAbsolutePath())
assertThat(manifest).containsAtLeastElementsIn(
arrayListOf(
" E: application (line=11)",
@@ -66,6 +70,13 @@ class ProfileableTest {
" A: http://schemas.android.com/apk/res/android:shell(0x01010594)=true"
)
)
+
+ // Test no signing config configured, if the automatic signing config assignment is disabled.
+ project.executor().with(BooleanOption.ENABLE_DEFAULT_DEBUG_SIGNING_CONFIG, false)
+ .run("clean", "assembleRelease")
+ val apkUnsigned =
+ project.getSubproject("app").getApk(GradleTestProject.ApkType.RELEASE)
+ ApkSubject.assertThat(apkUnsigned).doesNotContainApkSigningBlock()
}
@Test
@@ -108,6 +119,7 @@ class ProfileableTest {
val app = project.getSubproject(":app")
project.executor()
.with(StringOption.PROFILING_MODE, "profileable")
+ .with(BooleanOption.ENABLE_DEFAULT_DEBUG_SIGNING_CONFIG, true)
.run("assembleRelease")
checkProjectContainsProfileableInManifest(app, GradleTestProject.ApkType.RELEASE_SIGNED)
}
diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/AarMetadataTaskTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/AarMetadataTaskTest.kt
index 20926ebbdc..f43cf475b2 100644
--- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/AarMetadataTaskTest.kt
+++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/library/AarMetadataTaskTest.kt
@@ -257,7 +257,7 @@ class AarMetadataTaskTest {
project.getSubproject("lib").buildFile.appendText(
"""
android {
- compileSdkPreview 'Tiramisu'
+ compileSdkPreview 'TiramisuPrivacySandbox'
}
""".trimIndent()
)
@@ -271,7 +271,7 @@ class AarMetadataTaskTest {
AarMetadataTask.AAR_METADATA_FILE_NAME
)
PathSubject.assertThat(aarMetadataFile).contains(
- "${FORCE_COMPILE_SDK_PREVIEW_PROPERTY}=Tiramisu"
+ "${FORCE_COMPILE_SDK_PREVIEW_PROPERTY}=TiramisuPrivacySandbox"
)
}
}
diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/manifest/ProcessTestManifestTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/manifest/ProcessTestManifestTest.kt
index 8296f0dadd..7bb456e36e 100644
--- a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/manifest/ProcessTestManifestTest.kt
+++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/manifest/ProcessTestManifestTest.kt
@@ -298,8 +298,8 @@ class ProcessTestManifestTest {
""".trimIndent())
project.file("src/main/AndroidManifest.xml").delete()
FileUtils.createFile(
- project.file("src/main/AndroidManifest.xml"),
- """
+ project.file("src/main/AndroidManifest.xml"),
+ """
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/resources/UserAddedGeneratedResourcesTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/resources/UserAddedGeneratedResourcesTest.kt
new file mode 100644
index 0000000000..dce683c863
--- /dev/null
+++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/resources/UserAddedGeneratedResourcesTest.kt
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.integration.resources
+
+import com.android.build.gradle.integration.common.fixture.GradleTestProject
+import com.android.build.gradle.integration.common.fixture.app.MinimalSubProject
+import com.android.build.gradle.integration.common.fixture.app.MultiModuleTestProject
+import com.android.testutils.truth.PathSubject
+import org.junit.Rule
+import org.junit.Test
+
+class UserAddedGeneratedResourcesTest {
+
+ private val buildSrc = MinimalSubProject.buildSrc().also {
+ it.addFile("src/main/java/TestPlugin.java",
+ // language=java
+ """
+ import org.gradle.api.Action;
+ import org.gradle.api.Plugin;
+ import org.gradle.api.Project;
+ import org.gradle.api.file.Directory;
+ import org.gradle.api.file.ProjectLayout;
+ import org.gradle.api.model.ObjectFactory;
+ import org.gradle.api.provider.Provider;
+ import org.gradle.api.tasks.TaskContainer;
+ import org.gradle.api.tasks.TaskProvider;
+
+ import com.android.build.api.dsl.AndroidSourceSet;
+ import com.android.build.api.variant.AndroidComponentsExtension;
+ import com.android.build.api.variant.Variant;
+
+ import java.util.Arrays;
+
+ @SuppressWarnings({"rawtypes", "UnstableApiUsage"})
+ public class TestPlugin implements Plugin<Project>
+ {
+ public void apply(Project project) {
+
+ final ProjectLayout layout = project.getLayout();
+ final TaskContainer tasks = project.getTasks();
+ final ObjectFactory objects = project.getObjects();
+
+ Action<? super Plugin> action = plugin -> {
+ AndroidComponentsExtension components = project.getExtensions().getByType(AndroidComponentsExtension.class);
+ components.onVariants(components.selector().all(), (Action<? super Variant>) variant -> {
+
+ TaskProvider<MyCopy> copyTask = tasks.register("copyResources" + variant.getName(), MyCopy.class, task -> {
+ task.setDescription("Copy resources into target directory");
+ task.setGroup("Custom");
+ task.getInputFiles().from(
+ project.fileTree(
+ layout.getProjectDirectory().dir("default"),
+ c -> c.include("**/*.xml")));
+ });
+
+ variant.getSources().getRes().addGeneratedSourceDirectory(copyTask, MyCopy::getOutputDirectory);
+ });
+ };
+
+ project.getPlugins().withId("com.android.application", action);
+ }
+ }
+ """.trimIndent())
+
+ it.addFile("src/main/java/MyCopy.java",
+ // language=java
+ """
+ import org.gradle.api.DefaultTask;
+ import org.gradle.api.file.ConfigurableFileCollection;
+ import org.gradle.api.file.DirectoryProperty;
+ import org.gradle.api.file.FileSystemOperations;
+ import org.gradle.api.tasks.InputFiles;
+ import org.gradle.api.tasks.OutputDirectory;
+ import org.gradle.api.tasks.TaskAction;
+
+ import javax.inject.Inject;
+
+ public abstract class MyCopy extends DefaultTask {
+
+ @OutputDirectory
+ public abstract DirectoryProperty getOutputDirectory();
+
+ @InputFiles
+ public abstract ConfigurableFileCollection getInputFiles();
+
+ @Inject
+ public abstract FileSystemOperations getFileSystemOperations();
+
+ @TaskAction
+ public void copy() {
+ getFileSystemOperations().copy( c -> {
+ c.from(getInputFiles());
+ c.into(getOutputDirectory());
+ });
+ }
+ }
+
+ """.trimIndent())
+ }
+
+ private val app = MinimalSubProject.app("com.example.app")
+ .withFile("default/values/ConnectStatus.xml",
+ // language=xml
+ """
+ <?xml version="1.0" encoding="UTF-8"?>
+ <resources>
+ <string name="connect_status_none">Unknown status.</string>
+ </resources>
+ """.trimIndent())
+
+ private val testApp =
+ MultiModuleTestProject.builder()
+ .buildSrcProject(buildSrc)
+ .subproject(":app", app)
+ .build()
+
+ @get:Rule
+ val project = GradleTestProject.builder().fromTestApp(testApp).create()
+
+ @Test
+ fun testGeneratedResourcesArePresentInMergedResources() {
+ val appProject = project.getSubproject(":app")
+ appProject.buildFile.appendText(
+ "apply plugin: TestPlugin"
+ )
+ project.execute(":app:mergeDebugResources")
+
+ val mergedAppValues = appProject.getIntermediateFile(
+ "incremental",
+ "debug",
+ "mergeDebugResources",
+ "merged.dir",
+ "values",
+ "values.xml"
+ )
+
+ // Make sure the merged values in app (big merge) contain both overlayable from app and lib,
+ // as well as their content.
+ PathSubject.assertThat(mergedAppValues).containsAllOf(
+ "<string name=\"connect_status_none\">Unknown status.</string>"
+ )
+ }
+}
diff --git a/build-system/integration-test/connected/BUILD.bazel b/build-system/integration-test/connected/BUILD.bazel
index 902ac418dd..4797701801 100644
--- a/build-system/integration-test/connected/BUILD.bazel
+++ b/build-system/integration-test/connected/BUILD.bazel
@@ -54,7 +54,6 @@ avd(name = "avd")
#keep sorted
TEST_DATA = [
- ":avd",
"//prebuilts/studio/sdk:build-tools/latest",
"//prebuilts/studio/sdk:platform-tools",
"//tools/base/build-system:gradle-distrib",
@@ -81,6 +80,7 @@ TEST_MAVEN_REPOS = [
gradle_connected_test(
name = "AdditionalTestOutputConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/library/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/additionalTestOutput"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -91,6 +91,7 @@ gradle_connected_test(
gradle_connected_test(
name = "AdditionalTestOutputOverrideConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/library/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/additionalTestOutputOverride"],
maven_repo_zips = MAVEN_REPO_ZIPS,
maven_repos = TEST_MAVEN_REPOS,
@@ -100,6 +101,7 @@ gradle_connected_test(
gradle_connected_test(
name = "AndroidTestResourcesConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA,
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -110,6 +112,7 @@ gradle_connected_test(
gradle_connected_test(
name = "AnnotationProcessorConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA,
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -120,6 +123,7 @@ gradle_connected_test(
gradle_connected_test(
name = "ApiConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/library/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/api"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -130,6 +134,7 @@ gradle_connected_test(
gradle_connected_test(
name = "ApplibtestConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/library/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/applibtest"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -140,6 +145,7 @@ gradle_connected_test(
gradle_connected_test(
name = "AttrOrderConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/library/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/attrOrder"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -150,6 +156,7 @@ gradle_connected_test(
gradle_connected_test(
name = "BasicConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/basic"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -160,6 +167,7 @@ gradle_connected_test(
gradle_connected_test(
name = "CmakeJniLibConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/nativebuild/",
+ avd = ":avd",
data = TEST_DATA + [
"//prebuilts/studio/sdk:cmake",
"//prebuilts/studio/sdk:ndk",
@@ -174,6 +182,7 @@ gradle_connected_test(
gradle_connected_test(
name = "ComposeHelloWorldConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/composeHelloWorld"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -186,6 +195,7 @@ gradle_connected_test(
gradle_connected_test(
name = "CoreLibraryDesugarConversionConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA,
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -197,6 +207,7 @@ gradle_connected_test(
gradle_connected_test(
name = "CustomTestedApksTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/testing/",
+ avd = ":avd",
data = TEST_DATA,
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -208,6 +219,7 @@ gradle_connected_test(
gradle_connected_test(
name = "D8DesugaringConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA,
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -218,6 +230,7 @@ gradle_connected_test(
gradle_connected_test(
name = "DataBindingExternalArtifactDependencyConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/databinding/",
+ avd = ":avd",
data = TEST_DATA + [
"//tools/data-binding:integration-test-projects",
"//tools/data-binding:integration-test-projects-support",
@@ -235,6 +248,7 @@ gradle_connected_test(
gradle_connected_test(
name = "DataBindingIntegrationTestAppsConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/databinding/",
+ avd = ":avd",
data = TEST_DATA + [
"//tools/data-binding:integration-test-projects",
"//tools/data-binding:integration-test-projects-support",
@@ -252,6 +266,7 @@ gradle_connected_test(
gradle_connected_test(
name = "DensitySplitConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/densitySplit"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -262,6 +277,7 @@ gradle_connected_test(
gradle_connected_test(
name = "DependenciesConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/dependencies"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -272,6 +288,7 @@ gradle_connected_test(
gradle_connected_test(
name = "DynamicFeatureConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/feature/",
+ avd = ":avd",
data = TEST_DATA,
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -282,6 +299,7 @@ gradle_connected_test(
gradle_connected_test(
name = "FlavoredConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/flavored"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -292,6 +310,7 @@ gradle_connected_test(
gradle_connected_test(
name = "FlavoredlibConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/library/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/flavoredlib"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -302,6 +321,7 @@ gradle_connected_test(
gradle_connected_test(
name = "FlavorlibConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/library/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/flavorlib"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -312,6 +332,7 @@ gradle_connected_test(
gradle_connected_test(
name = "FlavorsConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/flavors"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -322,6 +343,7 @@ gradle_connected_test(
gradle_connected_test(
name = "JacocoConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA,
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -332,6 +354,7 @@ gradle_connected_test(
gradle_connected_test(
name = "JarsInLibrariesConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/library/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/assets"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -343,6 +366,7 @@ gradle_connected_test(
gradle_connected_test(
name = "KotlinAppConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/kotlinApp"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -353,6 +377,7 @@ gradle_connected_test(
gradle_connected_test(
name = "LibMinifyJarDepConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/library/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/libMinifyJarDep"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -363,6 +388,7 @@ gradle_connected_test(
gradle_connected_test(
name = "LibMinifyLibDepConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/library/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/libMinifyLibDep"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -373,6 +399,7 @@ gradle_connected_test(
gradle_connected_test(
name = "LibsTestConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/library/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/libsTest"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -383,6 +410,7 @@ gradle_connected_test(
gradle_connected_test(
name = "LibTestDepConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/library/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/libTestDep"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -393,6 +421,7 @@ gradle_connected_test(
gradle_connected_test(
name = "MigratedConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/migrated"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -403,6 +432,7 @@ gradle_connected_test(
gradle_connected_test(
name = "MinifyConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/minify"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -413,6 +443,7 @@ gradle_connected_test(
gradle_connected_test(
name = "MinifyLibConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/library/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/minifyLib"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -423,6 +454,7 @@ gradle_connected_test(
gradle_connected_test(
name = "MlModelBindingConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA + [
"//tools/base/build-system/integration-test:test-projects/mlModelBinding",
"//prebuilts/tools/common/mlkit/testData",
@@ -436,6 +468,7 @@ gradle_connected_test(
gradle_connected_test(
name = "MultiDexConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/multiDex"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -446,6 +479,7 @@ gradle_connected_test(
gradle_connected_test(
name = "MultiDexWithLibConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/library/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/multiDexWithLib"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -456,6 +490,7 @@ gradle_connected_test(
gradle_connected_test(
name = "MultiProjectConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/library/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/multiproject"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -466,6 +501,7 @@ gradle_connected_test(
gradle_connected_test(
name = "MultiresConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/multires"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -476,6 +512,7 @@ gradle_connected_test(
gradle_connected_test(
name = "NdkConnectedCheckTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/ndk/",
+ avd = ":avd",
data = TEST_DATA + [
"//prebuilts/studio/sdk:cmake",
"//prebuilts/studio/sdk:ndk",
@@ -489,6 +526,7 @@ gradle_connected_test(
gradle_connected_test(
name = "NdkJniLibConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/ndk/",
+ avd = ":avd",
data = TEST_DATA + [
"//prebuilts/studio/sdk:cmake",
"//prebuilts/studio/sdk:ndk",
@@ -503,6 +541,7 @@ gradle_connected_test(
gradle_connected_test(
name = "NdkLibPrebuiltsConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/ndk/",
+ avd = ":avd",
data = TEST_DATA + [
"//prebuilts/studio/sdk:cmake",
"//prebuilts/studio/sdk:ndk",
@@ -517,6 +556,7 @@ gradle_connected_test(
gradle_connected_test(
name = "NdkSanAngelesConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/ndk/",
+ avd = ":avd",
data = TEST_DATA + [
"//prebuilts/studio/sdk:cmake",
"//prebuilts/studio/sdk:ndk",
@@ -531,6 +571,7 @@ gradle_connected_test(
gradle_connected_test(
name = "NoSplitNdkVariantsConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/ndk/",
+ avd = ":avd",
data = TEST_DATA + [
"//prebuilts/studio/sdk:cmake",
"//prebuilts/studio/sdk:ndk",
@@ -544,6 +585,7 @@ gradle_connected_test(
gradle_connected_test(
name = "Overlay1ConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/overlay1"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -554,6 +596,7 @@ gradle_connected_test(
gradle_connected_test(
name = "Overlay2ConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/overlay2"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -564,6 +607,7 @@ gradle_connected_test(
gradle_connected_test(
name = "Overlay3ConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/overlay3"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -574,6 +618,7 @@ gradle_connected_test(
gradle_connected_test(
name = "PkgOverrideConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/pkgOverride"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -584,6 +629,7 @@ gradle_connected_test(
gradle_connected_test(
name = "RenderscriptNdkConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/nativebuild/",
+ avd = ":avd",
data = TEST_DATA + [
"//prebuilts/studio/sdk:cmake",
"//prebuilts/studio/sdk:ndk",
@@ -598,6 +644,7 @@ gradle_connected_test(
gradle_connected_test(
name = "ResValueTypeConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA,
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -608,6 +655,7 @@ gradle_connected_test(
gradle_connected_test(
name = "ShardingConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/testing/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/appWithTests"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -618,6 +666,7 @@ gradle_connected_test(
gradle_connected_test(
name = "SameNamedLibsConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/library/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/sameNamedLibs"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -628,6 +677,7 @@ gradle_connected_test(
gradle_connected_test(
name = "SeparateTestModuleConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/testing/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/separateTestModule"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -638,6 +688,7 @@ gradle_connected_test(
gradle_connected_test(
name = "SeparateTestModuleWithMinifiedAppConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/testing/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/separateTestModuleWithMinifiedApp"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -648,6 +699,7 @@ gradle_connected_test(
gradle_connected_test(
name = "SeparateTestWithAarDependencyConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/testing/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/separateTestModule"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -658,6 +710,7 @@ gradle_connected_test(
gradle_connected_test(
name = "SeparateTestWithMinificationButNoObfuscationConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/testing/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/separateTestWithMinificationButNoObfuscation"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -668,6 +721,7 @@ gradle_connected_test(
gradle_connected_test(
name = "SigningConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA,
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -679,6 +733,7 @@ gradle_connected_test(
gradle_connected_test(
name = "TestingSupportLibraryConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/testing/",
+ avd = ":avd",
data = TEST_DATA,
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -689,6 +744,7 @@ gradle_connected_test(
gradle_connected_test(
name = "TestWithSameDepAsAppConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/dependencies/",
+ avd = ":avd",
data = TEST_DATA,
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -699,6 +755,7 @@ gradle_connected_test(
gradle_connected_test(
name = "UtpConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA + [
"//tools/adt/idea/utp:addGradleAndroidTestListener",
"//tools/base/build-system/integration-test:test-projects/utp",
@@ -714,6 +771,7 @@ gradle_connected_test(
gradle_connected_test(
name = "FailureRetentionConnectedTest",
srcs = "src/test/java/com/android/build/gradle/integration/connected/application/",
+ avd = ":avd",
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/failureRetention"],
flaky = True, # b/148626301 flaky emulator connectivity
maven_repo_zips = MAVEN_REPO_ZIPS,
diff --git a/build-system/integration-test/connected/connected-test.bzl b/build-system/integration-test/connected/connected-test.bzl
index f32ec45109..d874560da9 100644
--- a/build-system/integration-test/connected/connected-test.bzl
+++ b/build-system/integration-test/connected/connected-test.bzl
@@ -1,4 +1,5 @@
load("//tools/base/build-system/integration-test:integration-test.bzl", "single_gradle_integration_test")
+load("//tools/base/bazel:maven.bzl", "maven_repository")
# A gradle connected test
#
@@ -15,18 +16,32 @@ load("//tools/base/build-system/integration-test:integration-test.bzl", "single_
def gradle_connected_test(
name,
srcs,
+ avd,
deps,
data,
maven_repos,
+ maven_artifacts = [],
runtime_deps = [],
tags = [],
timeout = "long",
+ jvm_flags = [],
**kwargs):
+ if avd:
+ emulator_path = "%s/%s" % (native.package_name(), avd[1:])
+ jvm_flags = jvm_flags + ["-DEMULATOR_PATH=%s" % emulator_path]
+ if maven_artifacts:
+ repo_name = name + ".mavenRepo"
+ maven_repository(
+ name = repo_name,
+ artifacts = maven_artifacts,
+ )
+ absolute_path = "//%s:%s" % (native.package_name(), repo_name)
+ maven_repos += [absolute_path]
single_gradle_integration_test(
name = name,
srcs = srcs,
deps = deps,
- data = data,
+ data = data + ([avd] if avd else []),
maven_repos = maven_repos,
runtime_deps = runtime_deps,
tags = tags + [
@@ -34,5 +49,6 @@ def gradle_connected_test(
"no_windows",
],
timeout = timeout,
+ jvm_flags = jvm_flags,
**kwargs
)
diff --git a/build-system/integration-test/connected/src/main/java/com/android/build/gradle/integration/connected/utils/EmulatorUtils.kt b/build-system/integration-test/connected/src/main/java/com/android/build/gradle/integration/connected/utils/EmulatorUtils.kt
index 812aa97c89..d9efdef784 100644
--- a/build-system/integration-test/connected/src/main/java/com/android/build/gradle/integration/connected/utils/EmulatorUtils.kt
+++ b/build-system/integration-test/connected/src/main/java/com/android/build/gradle/integration/connected/utils/EmulatorUtils.kt
@@ -27,7 +27,7 @@ import org.junit.rules.ExternalResource
* <p>The executable is the script that starts and stops emulators and must be used to launch
* the emulator.
*/
-private const val DEVICE = "tools/base/build-system/integration-test/connected/avd"
+private val DEVICE = System.getProperty("EMULATOR_PATH")
/**
* Port at which to open the emulator.
diff --git a/build-system/integration-test/connected/src/test/java/com/android/build/gradle/integration/connected/application/PrivacySandboxSdkConnectedTest.kt b/build-system/integration-test/connected/src/test/java/com/android/build/gradle/integration/connected/application/PrivacySandboxSdkConnectedTest.kt
new file mode 100644
index 0000000000..89bbd33ddd
--- /dev/null
+++ b/build-system/integration-test/connected/src/test/java/com/android/build/gradle/integration/connected/application/PrivacySandboxSdkConnectedTest.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.integration.connected.application
+
+import com.android.build.gradle.integration.common.fixture.GradleTestProject.Companion.builder
+import com.android.build.gradle.integration.connected.utils.getEmulator
+import com.android.ddmlib.AndroidDebugBridge
+import com.android.ddmlib.IDevice
+import org.junit.Before
+import org.junit.ClassRule
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+import java.util.concurrent.TimeUnit
+
+
+/**
+ * Connected tests using UTP test executor.
+ */
+class PrivacySandboxSdkConnectedTest {
+ init {
+ AndroidDebugBridge.init(true)
+ }
+ // private val adb: AndroidDebugBridge by lazy { AndroidDebugBridge.createBridge(10, TimeUnit.SECONDS) }
+ private val adb: AndroidDebugBridge = AndroidDebugBridge.createBridge(10, TimeUnit.SECONDS)
+ private lateinit var device: IDevice
+
+ @get:Rule var project = builder()
+ .fromTestProject("privacySandboxSdk/libraryAndConsumer")
+ .create()
+
+ @Before
+ fun setUp() {
+ // fail fast if no response
+ project.addAdbTimeout();
+ adb.hasInitialDeviceList()
+ assert(adb.devices.size == 1)
+ device = adb.devices[0]
+
+ device.uninstallPackage("com.example.rubidumconsumer")
+ device.uninstallPackage("com.example.rubidumconsumer.test")
+ device.uninstallPackage("com.myrbsdk_10000")
+ }
+
+ @Test
+ fun `connectedAndroidTest task, SDK preinstalled`() {
+ project.execute(":app:buildPrivacySandboxSdkApksForDebug")
+ device.installPackage(
+ project.getSubproject("app").getIntermediateFile(
+ "extracted_apks_from_privacy_sandbox_sdks",
+ "debug",
+ "ads-sdk",
+ "standalone.apk"
+ ).path,
+ /* reinstall */ true
+ )
+ project.execute("connectedAndroidTest")
+ }
+
+ @Test
+ @Ignore // This doesn't work because deployment is not handled yet.
+ fun `connectedAndroidTest task`() {
+ project.execute("connectedAndroidTest")
+ }
+
+ @Test
+ @Ignore // This doesn't work because deployment is not handled yet.
+ fun `install and uninstall works for both SDK and APK`() {
+ project.execute("installDebug")
+ // Verify both APKs are installed here.
+ project.execute("uninstallAll")
+ // Verify both APKs are deleted
+ }
+
+ companion object {
+ @JvmField @ClassRule val emulator = getEmulator()
+ }
+}
diff --git a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/BuildSrcProject.kt b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/BuildSrcProject.kt
new file mode 100644
index 0000000000..7f36186429
--- /dev/null
+++ b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/BuildSrcProject.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * 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 com.android.build.gradle.integration.common.fixture
+
+import java.io.File
+
+/**
+ * Specialization of the [GradleProject] fpr buildSrc project.
+ */
+class BuildSrcProject: GradleProject("buildSrc") {
+
+ override fun containsFullBuildScript(): Boolean = false
+
+ override fun write(projectDir: File, buildScriptContent: String?, projectRepoScript: String) {
+ super.write(projectDir, buildScriptContent, projectRepoScript)
+ val buildFileName =
+ if (sourceFiles.containsKey("build.gradle.kts")) "build.gradle.kts" else "build.gradle"
+ val buildFile = File(projectDir, buildFileName)
+ buildFile.appendText(
+ projectRepoScript
+ )
+ }
+}
diff --git a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/GradleProject.kt b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/GradleProject.kt
index b9f452d08a..f1c4c834fb 100644
--- a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/GradleProject.kt
+++ b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/GradleProject.kt
@@ -16,7 +16,6 @@
package com.android.build.gradle.integration.common.fixture
-import com.android.build.gradle.integration.common.fixture.app.MinimalSubProject
import com.android.build.gradle.integration.common.fixture.app.TestSourceFile
import java.io.File
@@ -46,7 +45,7 @@ abstract class GradleProject(
}
/** Map from a relative path to the corresponding [TestSourceFile] instance. */
- private val sourceFiles: MutableMap<String, TestSourceFile> = mutableMapOf()
+ protected val sourceFiles: MutableMap<String, TestSourceFile> = mutableMapOf()
/** Returns a source file with the specified file path. */
fun getFile(relativePath: String): TestSourceFile {
diff --git a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/app/MinimalSubProject.kt b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/app/MinimalSubProject.kt
index 02172fb7db..4e5c121167 100644
--- a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/app/MinimalSubProject.kt
+++ b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/app/MinimalSubProject.kt
@@ -16,6 +16,7 @@
package com.android.build.gradle.integration.common.fixture.app
+import com.android.build.gradle.integration.common.fixture.BuildSrcProject
import com.android.build.gradle.integration.common.fixture.GradleProject
import com.android.build.gradle.integration.common.fixture.GradleTestProject
import com.android.build.gradle.integration.common.fixture.SUPPORT_LIB_MIN_SDK
@@ -79,6 +80,10 @@ class MinimalSubProject private constructor(
companion object {
+ fun buildSrc(): BuildSrcProject {
+ return BuildSrcProject()
+ }
+
@JvmOverloads
fun app(namespace: String = "com.example.app", projectPath: String = "app"): MinimalSubProject {
return MinimalSubProject(
diff --git a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/app/MultiModuleTestProject.java b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/app/MultiModuleTestProject.java
index 216c018c8f..a79f01989f 100644
--- a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/app/MultiModuleTestProject.java
+++ b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/app/MultiModuleTestProject.java
@@ -4,6 +4,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
+import com.android.build.gradle.integration.common.fixture.BuildSrcProject;
import com.android.build.gradle.integration.common.fixture.GradleProject;
import com.android.build.gradle.integration.common.fixture.TestProject;
import com.google.common.collect.BiMap;
@@ -19,6 +20,7 @@ import java.util.Map;
public class MultiModuleTestProject implements TestProject {
private final ImmutableMap<String, TestProject> subprojects;
+ @Nullable private final BuildSrcProject buildSrcProject;
/**
* Creates a MultiModuleTestProject.
@@ -27,7 +29,14 @@ public class MultiModuleTestProject implements TestProject {
* value.
*/
public MultiModuleTestProject(@NonNull Map<String, ? extends TestProject> subprojects) {
+ this(subprojects, null);
+ }
+
+ public MultiModuleTestProject(
+ @NonNull Map<String, ? extends TestProject> subprojects,
+ @Nullable BuildSrcProject buildSrcProject) {
this.subprojects = ImmutableMap.copyOf(subprojects);
+ this.buildSrcProject = buildSrcProject;
}
/**
@@ -44,6 +53,7 @@ public class MultiModuleTestProject implements TestProject {
builder.put(baseName + i, subproject);
}
subprojects = builder.build();
+ buildSrcProject = null;
}
/** Return the test project with the given project path. */
@@ -68,6 +78,19 @@ public class MultiModuleTestProject implements TestProject {
subproject.write(subprojectDir, null, projectRepoScript);
}
+ if (buildSrcProject != null) {
+ File subprojectDir = new File(projectDir, "buildSrc");
+ if (!subprojectDir.exists()) {
+ subprojectDir.mkdirs();
+ }
+ // buildSrc requires the repo declaration.
+ buildSrcProject.write(
+ subprojectDir,
+ "dependencies { implementation \"com.android.tools.build:gradle-api:"
+ + com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION
+ + "\" }\n",
+ projectRepoScript);
+ }
StringBuilder builder = new StringBuilder();
for (String subprojectName : subprojects.keySet()) {
builder.append("include '").append(subprojectName).append("'\n");
@@ -96,6 +119,22 @@ public class MultiModuleTestProject implements TestProject {
public static class Builder {
private BiMap<String, GradleProject> projects = HashBiMap.create();
+ private BuildSrcProject buildSrcProject = null;
+
+ /**
+ * Adds a buildSrc project to the current test project. Can only be called once.
+ *
+ * @param buildSrcProject the [BuildSrcProject] to use as buildSrc
+ * @return itself.
+ */
+ @NonNull
+ public Builder buildSrcProject(@NonNull BuildSrcProject buildSrcProject) {
+ if (this.buildSrcProject != null) {
+ throw new IllegalStateException("Test project can only have one buildSrc project");
+ }
+ this.buildSrcProject = buildSrcProject;
+ return this;
+ }
@NonNull
public Builder subproject(@NonNull GradleProject testProject) {
@@ -165,7 +204,7 @@ public class MultiModuleTestProject implements TestProject {
@NonNull
public MultiModuleTestProject build() {
- return new MultiModuleTestProject(projects);
+ return new MultiModuleTestProject(projects, buildSrcProject);
}
}
}
diff --git a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/testprojects/TestProjectBuilderImpl.kt b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/testprojects/TestProjectBuilderImpl.kt
index 2a4f0fc9a5..f0d78c1596 100644
--- a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/testprojects/TestProjectBuilderImpl.kt
+++ b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/fixture/testprojects/TestProjectBuilderImpl.kt
@@ -17,7 +17,6 @@
package com.android.build.gradle.integration.common.fixture.testprojects
import com.android.Version
-import com.android.build.gradle.integration.common.fixture.GradleTestProject
import com.android.build.gradle.integration.common.fixture.TestProject
import com.android.testutils.MavenRepoGenerator
import com.android.utils.FileUtils
diff --git a/build-system/integration-test/managed-devices/BUILD.bazel b/build-system/integration-test/managed-devices/BUILD.bazel
index e8d89c99e9..4063427184 100644
--- a/build-system/integration-test/managed-devices/BUILD.bazel
+++ b/build-system/integration-test/managed-devices/BUILD.bazel
@@ -65,6 +65,7 @@ TEST_MAVEN_REPOS = [
gradle_connected_test(
name = "UtpManagedDeviceTest",
srcs = "src/test/java/com/android/build/gradle/integration/manageddevice/application/",
+ avd = None,
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/utp"],
jvm_flags = sdk_jvm_flags,
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -80,6 +81,7 @@ gradle_connected_test(
gradle_connected_test(
name = "SimpleManagedDeviceTest",
srcs = "src/test/java/com/android/build/gradle/integration/manageddevice/application/",
+ avd = None,
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/utp"],
jvm_flags = sdk_jvm_flags,
maven_repo_zips = MAVEN_REPO_ZIPS,
@@ -93,6 +95,7 @@ gradle_connected_test(
gradle_connected_test(
name = "TestApplicationManagedDeviceTest",
srcs = "src/test/java/com/android/build/gradle/integration/manageddevice/application/",
+ avd = None,
data = TEST_DATA + ["//tools/base/build-system/integration-test:test-projects/utp"],
jvm_flags = sdk_jvm_flags,
maven_repo_zips = MAVEN_REPO_ZIPS,
diff --git a/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/nativebuild/CmakeBasicProjectTest.kt b/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/nativebuild/CmakeBasicProjectTest.kt
index 8f5e0ad177..0d31e4aa8e 100644
--- a/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/nativebuild/CmakeBasicProjectTest.kt
+++ b/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/nativebuild/CmakeBasicProjectTest.kt
@@ -17,7 +17,9 @@
package com.android.build.gradle.integration.nativebuild
import com.android.SdkConstants.CURRENT_PLATFORM
+import com.android.SdkConstants.NDK_DEFAULT_VERSION
import com.android.SdkConstants.PLATFORM_WINDOWS
+import com.android.Version
import com.android.build.gradle.integration.common.fixture.GradleBuildResult
import com.android.build.gradle.integration.common.fixture.GradleTestProject
import com.android.build.gradle.integration.common.fixture.GradleTestProject.ApkLocation
@@ -53,11 +55,13 @@ import com.android.build.gradle.internal.core.Abi
import com.android.build.gradle.internal.cxx.attribution.decodeBuildTaskAttributions
import com.android.build.gradle.internal.cxx.configure.CMakeVersion
import com.android.build.gradle.internal.cxx.configure.shouldConfigure
+import com.android.build.gradle.internal.cxx.hashing.sha256Of
import com.android.build.gradle.internal.cxx.io.SynchronizeFile.Outcome.CREATED_HARD_LINK_FROM_SOURCE_TO_DESTINATION
import com.android.build.gradle.internal.cxx.io.decodeSynchronizeFile
import com.android.build.gradle.internal.cxx.json.AndroidBuildGradleJsons
import com.android.build.gradle.internal.cxx.json.AndroidBuildGradleJsons.getNativeBuildMiniConfig
import com.android.build.gradle.internal.cxx.model.compileCommandsJsonBinFile
+import com.android.build.gradle.internal.cxx.model.cxxBuildHashKeyFile
import com.android.build.gradle.internal.cxx.model.jsonGenerationLoggingRecordFile
import com.android.build.gradle.internal.cxx.model.miniConfigFile
import com.android.build.gradle.internal.cxx.model.ninjaBuildFile
@@ -411,6 +415,49 @@ class CmakeBasicProjectTest(
}
@Test
+ fun `ensure hashed output paths are stable`() {
+ Assume.assumeTrue(mode == Mode.CMake && cmakeVersionInDsl != "3.6.0")
+ project.execute("configure${mode.buildFolderTag}Debug[x86_64]")
+ val abi = project.recoverExistingCxxAbiModels().single { it.abi == Abi.X86_64 }
+ val hashKey = abi.cxxBuildHashKeyFile.readText()
+ val hashSegment = abi.cxxBuildHashKeyFile.parentFile.name
+ val hashKeyExpected =
+ """
+ # Values used to calculate the hash in this folder name.
+ # Should not depend on the absolute path of the project itself.
+ # - AGP: ${Version.ANDROID_GRADLE_PLUGIN_VERSION}.
+ # - ${'$'}NDK is the path to NDK $NDK_DEFAULT_VERSION.
+ # - ${'$'}PROJECT is the path to the parent folder of the root Gradle build file.
+ # - ${'$'}ABI is the ABI to be built with. The specific value doesn't contribute to the value of the hash.
+ # - ${'$'}HASH is the hash value computed from this text.
+ # - ${'$'}CMAKE is the path to CMake $cmakeVersionInDsl.
+ # - ${'$'}NINJA is the path to Ninja.
+ -H${'$'}PROJECT
+ -DCMAKE_SYSTEM_NAME=Android
+ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
+ -DCMAKE_SYSTEM_VERSION=16
+ -DANDROID_PLATFORM=android-16
+ -DANDROID_ABI=${'$'}ABI
+ -DCMAKE_ANDROID_ARCH_ABI=${'$'}ABI
+ -DANDROID_NDK=${'$'}NDK
+ -DCMAKE_ANDROID_NDK=${'$'}NDK
+ -DCMAKE_TOOLCHAIN_FILE=${'$'}NDK/build/cmake/android.toolchain.cmake
+ -DCMAKE_MAKE_PROGRAM=${'$'}NINJA
+ -DCMAKE_C_FLAGS=-DTEST_C_FLAG -DTEST_C_FLAG_2
+ -DCMAKE_CXX_FLAGS=-DTEST_CPP_FLAG
+ -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${'$'}PROJECT/build/intermediates/cxx/Debug/${'$'}HASH/obj/${'$'}ABI
+ -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=${'$'}PROJECT/build/intermediates/cxx/Debug/${'$'}HASH/obj/${'$'}ABI
+ -DCMAKE_BUILD_TYPE=Debug
+ -B${'$'}PROJECT/.cxx/Debug/${'$'}HASH/${'$'}ABI
+ -GNinja
+ """.trimIndent()
+ assertThat(hashKey).isEqualTo(hashKeyExpected)
+ val expectedHashSegment = sha256Of(hashKeyExpected, includeGradleVersionInHash = false).substring(0,8)
+ // If the text above passes then the SHA-256 of it should be stable.
+ assertThat(hashSegment).isEqualTo(expectedHashSegment)
+ }
+
+ @Test
fun `ensure CMake arguments have macros expanded`() {
if (mode != Mode.CMake) return // This is a CMake-only test
TestFileUtils.appendToFile(
diff --git a/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/ndk/ModuleToModuleDepsTest.kt b/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/ndk/ModuleToModuleDepsTest.kt
index b0d76e3f3c..ac70ef8940 100644
--- a/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/ndk/ModuleToModuleDepsTest.kt
+++ b/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/ndk/ModuleToModuleDepsTest.kt
@@ -31,9 +31,11 @@ import com.android.build.gradle.integration.ndk.ModuleToModuleDepsTest.BuildSyst
import com.android.build.gradle.internal.core.Abi
import com.android.build.gradle.internal.cxx.configure.CMakeVersion
import com.android.build.gradle.internal.cxx.json.AndroidBuildGradleJsons
+import com.android.build.gradle.internal.cxx.json.readJsonFile
import com.android.build.gradle.internal.cxx.logging.LoggingMessage
import com.android.build.gradle.internal.cxx.logging.decodeLoggingMessage
import com.android.build.gradle.internal.cxx.logging.text
+import com.android.build.gradle.internal.cxx.prefab.ModuleMetadataV1
import com.android.builder.model.v2.ide.SyncIssue
import com.google.common.truth.Truth.assertThat
import org.junit.Assume
@@ -109,11 +111,18 @@ class ModuleToModuleDepsTest(
.dependency(app, lib)
.build()
+ private val appOutputRoot : File get() =
+ if (outputStructureType == OutputStructureType.Normal) project.getSubproject("app").buildDir.parentFile
+ else {
+ // The output folder for lib is at $PROJECT_ROOT/out/lib
+ project.getSubproject("app").buildDir.parentFile.parentFile.resolve("out/app")
+ }
+
private val libOutputRoot : File get() =
if (outputStructureType == OutputStructureType.Normal) project.getSubproject("lib").buildDir.parentFile
else {
// The output folder for lib is at $PROJECT_ROOT/out/lib
- project.getSubproject("lib").buildDir.parentFile.parentFile.parentFile.resolve("out/lib")
+ project.getSubproject("lib").buildDir.parentFile.parentFile.resolve("out/lib")
}
@get:Rule
@@ -172,7 +181,6 @@ class ModuleToModuleDepsTest(
.buildFile
.parentFile
.parentFile
- .parentFile
.absolutePath.replace("\\", "/")
val appStructureStanza = if (outputStructureType == OutputStructureType.Normal) "" else when(appBuildSystem) {
is CMake -> """
@@ -196,6 +204,8 @@ class ModuleToModuleDepsTest(
""".trimIndent()
else -> error("$appBuildSystem")
}
+ val libExportLibrariesStanza =
+ "android.externalNativeBuild.experimentalProperties[\"prefab.foo.exportLibraries\"] = [\"-llog\"]"
project.getSubproject(":app").buildFile.appendText(
"""
@@ -263,6 +273,7 @@ class ModuleToModuleDepsTest(
$libStanza
$libStlStanza
$libStructureStanza
+ $libExportLibrariesStanza
""")
val header =
project.getSubproject(":lib").buildFile.resolveSibling("src/main/cpp/include/foo.h")
@@ -354,7 +365,6 @@ class ModuleToModuleDepsTest(
int callFoo() { return foo(); }
""".trimIndent())
}
-
enableCxxStructuredLogging(project)
}
@@ -470,6 +480,19 @@ class ModuleToModuleDepsTest(
assertThat(libOutput.isFile)
.named("$libOutput")
.isFalse()
+
+ // Check that export libraries informations winds up in the final prefab structure
+ var sawAtleastOneModule = false
+ appOutputRoot.walkTopDown().forEach { file ->
+ if (file.name == "module.json") {
+ val module = readJsonFile<ModuleMetadataV1>(file)
+ assertThat(module.exportLibraries).containsExactly("-llog")
+ sawAtleastOneModule = true
+ }
+ }
+ assertThat(sawAtleastOneModule)
+ .named("Expected at least one Prefab module")
+ .isTrue()
}
@Test
diff --git a/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/ndk/PrefabPublishingTest.kt b/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/ndk/PrefabPublishingTest.kt
index 62bf6eb2de..892d456a1d 100644
--- a/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/ndk/PrefabPublishingTest.kt
+++ b/build-system/integration-test/native/src/test/java/com/android/build/gradle/integration/ndk/PrefabPublishingTest.kt
@@ -212,6 +212,9 @@ class PrefabPublishingTest(
containsFile("prefab/prefab.json")
containsFile("prefab/modules/$gradleModuleName/module.json")
containsFile("prefab/modules/${gradleModuleName}_static/module.json")
+ // Regression test for b/232117952
+ doesNotContain("/modules/$gradleModuleName/")
+ doesNotContain("/modules/$gradleModuleName/include/$gradleModuleName/")
}
}
diff --git a/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/ads-sdk-implementation/build.gradle b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/ads-sdk-implementation/build.gradle
new file mode 100644
index 0000000000..733f73ea4d
--- /dev/null
+++ b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/ads-sdk-implementation/build.gradle
@@ -0,0 +1,22 @@
+plugins {
+ id 'com.android.library'
+}
+
+android {
+ namespace 'com.example.ads_sdk_implementation'
+ compileSdkPreview = 'TiramisuPrivacySandbox'
+
+ defaultConfig {
+ minSdk 33
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+}
+
+dependencies {
+ implementation 'androidx.annotation:annotation:1.2.0-rc01'
+}
diff --git a/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/ads-sdk-implementation/src/main/AndroidManifest.xml b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/ads-sdk-implementation/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..abfbe8f055
--- /dev/null
+++ b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/ads-sdk-implementation/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+ <application></application>
+</manifest> \ No newline at end of file
diff --git a/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/ads-sdk-implementation/src/main/assets/example.txt b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/ads-sdk-implementation/src/main/assets/example.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/ads-sdk-implementation/src/main/assets/example.txt
diff --git a/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/ads-sdk-implementation/src/main/java/com/myrbsdk/MyAdsSdkEntryPoint.java b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/ads-sdk-implementation/src/main/java/com/myrbsdk/MyAdsSdkEntryPoint.java
new file mode 100644
index 0000000000..38e31f8c99
--- /dev/null
+++ b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/ads-sdk-implementation/src/main/java/com/myrbsdk/MyAdsSdkEntryPoint.java
@@ -0,0 +1,44 @@
+package com.myrbsdk;
+
+import android.app.sdksandbox.SandboxedSdkContext;
+import android.app.sdksandbox.SandboxedSdkProvider;
+import android.content.Context;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import androidx.annotation.RequiresApi;
+
+import java.util.concurrent.Executor;
+
+@RequiresApi(api = 34)
+public class MyAdsSdkEntryPoint extends SandboxedSdkProvider {
+
+ @Override
+ public void initSdk(SandboxedSdkContext sandboxedSdkContext, Bundle bundle,
+ Executor executor, InitSdkCallback initSdkCallback) {
+ Log.i("SDK", "initSdk");
+ executor.execute(() -> initSdkCallback.onInitSdkFinished(new Bundle()));
+ }
+
+ @Override
+ public View getView(Context windowContext, Bundle bundle) {
+ Log.i("SDK", "getView");
+
+ LinearLayout layout = new LinearLayout(windowContext);
+ layout.setLayoutParams(new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.MATCH_PARENT,
+ LinearLayout.LayoutParams.MATCH_PARENT
+ ));
+ layout.setBackgroundColor(Color.RED);
+ return layout;
+ }
+
+ @Override
+ public void onDataReceived(Bundle bundle, DataReceivedCallback dataReceivedCallback) {
+ Log.i("SDK", "onDataReceived");
+ }
+}
+
diff --git a/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/ads-sdk/build.gradle b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/ads-sdk/build.gradle
new file mode 100644
index 0000000000..d7f6d1dc30
--- /dev/null
+++ b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/ads-sdk/build.gradle
@@ -0,0 +1,19 @@
+plugins {
+ id 'com.android.privacy-sandbox-sdk'
+}
+
+android {
+ compileSdkPreview 'TiramisuPrivacySandbox'
+ minSdk = 33
+ namespace = "com.example.adssdk"
+
+ bundle {
+ packageName = "com.myrbsdk"
+ sdkProviderClassName = "com.myrbsdk.MyAdsSdkEntryPoint"
+ setVersion(1, 0, 0)
+ }
+}
+
+dependencies {
+ include project(':ads-sdk-implementation')
+}
diff --git a/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/build.gradle b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/build.gradle
new file mode 100644
index 0000000000..a650b29b0f
--- /dev/null
+++ b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/build.gradle
@@ -0,0 +1,38 @@
+plugins {
+ id 'com.android.application'
+ id 'org.jetbrains.kotlin.android'
+}
+
+android {
+ namespace 'com.example.rubidumconsumer'
+ compileSdkPreview = 'TiramisuPrivacySandbox'
+ defaultConfig {
+ applicationId "com.example.rubidumconsumer"
+ minSdk 24
+ targetSdk 34
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+}
+
+dependencies {
+ implementation project(':ads-sdk')
+ implementation 'androidx.appcompat:appcompat:1.4.1'
+
+ // This is implementation because of https://github.com/android/android-test/issues/1412
+ // (or https://issuetracker.google.com/issues/240993946)
+ // It needs to merge the underlying bootstrap activities to the main manifest
+ implementation 'androidx.test.ext:junit:1.1.3'
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+}
diff --git a/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/androidTest/java/com/example/rubidumconsumer/MainActivityTest.kt b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/androidTest/java/com/example/rubidumconsumer/MainActivityTest.kt
new file mode 100644
index 0000000000..4266984229
--- /dev/null
+++ b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/androidTest/java/com/example/rubidumconsumer/MainActivityTest.kt
@@ -0,0 +1,25 @@
+package com.example.rubidumconsumer
+
+import android.graphics.Color
+import androidx.test.ext.junit.rules.ActivityScenarioRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class MainActivityTest {
+
+ @get:Rule var rule = ActivityScenarioRule(MainActivity::class.java)
+
+ @Test
+ fun viewIsUpdatedBySdk() {
+ InstrumentationRegistry.getInstrumentation().apply {
+ waitForIdle {
+ val bitmap = uiAutomation.takeScreenshot()
+ assert(bitmap.getPixel(bitmap.width / 2, bitmap.height / 2) == Color.RED)
+ }
+ }
+ }
+}
diff --git a/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/main/AndroidManifest.xml b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..325b2885f5
--- /dev/null
+++ b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/main/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools">
+
+
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+
+ <application
+ android:label="@string/app_name"
+ android:supportsRtl="true"
+ tools:targetApi="33">
+
+ <activity
+ android:name=".MainActivity"
+ android:exported="true"
+ android:label="@string/app_name"
+ android:theme="@style/Theme.AppCompat">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/main/java/com/example/rubidumconsumer/MainActivity.java b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/main/java/com/example/rubidumconsumer/MainActivity.java
new file mode 100644
index 0000000000..36579a5520
--- /dev/null
+++ b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/main/java/com/example/rubidumconsumer/MainActivity.java
@@ -0,0 +1,62 @@
+package com.example.rubidumconsumer;
+
+import android.annotation.SuppressLint;
+import android.app.sdksandbox.SdkSandboxManager;
+import androidx.appcompat.app.AppCompatActivity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.view.SurfaceControlViewHost;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
+
+@SuppressLint("NewApi")
+public class MainActivity extends AppCompatActivity {
+
+ // Needs to be the package name of the SDK as defined in the SdkModulesConfig.pb.json when building the SDK
+ static final String SDK_PACKAGE_NAME = "com.myrbsdk";
+
+ private SdkSandboxManager sdkSandboxManager;
+
+ private RemoteSdkCallbackImpl callback;
+ private SurfaceView renderedView;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ renderedView = findViewById(R.id.rendered_view);
+ sdkSandboxManager = getApplicationContext().getSystemService(
+ SdkSandboxManager.class);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ renderedView.setVisibility(View.INVISIBLE);
+ callback = new RemoteSdkCallbackImpl(this);
+ sdkSandboxManager.loadSdk(SDK_PACKAGE_NAME, new Bundle(), Runnable::run, callback);
+ }
+
+ void requestSurfacePackage() {
+ final WindowMetrics metrics = getApplicationContext().getSystemService(
+ WindowManager.class).getCurrentWindowMetrics();
+
+ sdkSandboxManager.requestSurfacePackage(
+ SDK_PACKAGE_NAME, getDisplay().getDisplayId(),
+ metrics.getBounds().width(),
+ metrics.getBounds().height(),
+ new Bundle(),
+ Runnable::run,
+ callback);
+ }
+
+ void renderSurfaceView(SurfaceControlViewHost.SurfacePackage surfacePackage) {
+ new Handler(Looper.getMainLooper()).post(() -> {
+ renderedView.setChildSurfacePackage(surfacePackage);
+ renderedView.setVisibility(View.VISIBLE);
+ });
+ }
+}
diff --git a/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/main/java/com/example/rubidumconsumer/RemoteSdkCallbackImpl.java b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/main/java/com/example/rubidumconsumer/RemoteSdkCallbackImpl.java
new file mode 100644
index 0000000000..76e87ef10b
--- /dev/null
+++ b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/main/java/com/example/rubidumconsumer/RemoteSdkCallbackImpl.java
@@ -0,0 +1,43 @@
+package com.example.rubidumconsumer;
+
+import android.annotation.SuppressLint;
+import android.app.sdksandbox.SdkSandboxManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.SurfaceControlViewHost;
+import androidx.annotation.NonNull;
+
+@SuppressLint("NewApi")
+public class RemoteSdkCallbackImpl implements SdkSandboxManager.LoadSdkCallback, SdkSandboxManager.RequestSurfacePackageCallback {
+
+
+ RemoteSdkCallbackImpl(MainActivity mainActivity) {
+ this.mainActivity = mainActivity;
+ }
+
+ private MainActivity mainActivity;
+
+ @Override
+ public void onLoadSdkSuccess(Bundle bundle) {
+ Log.i("App", "onLoadSdkSuccess");
+ mainActivity.requestSurfacePackage();
+ }
+
+ @Override
+ public void onLoadSdkFailure(int errorCode, String errorMessage) {
+ Log.i("App", String.format("onLoadSdkFailure. Error code: %d, Error message: %s",errorCode, errorMessage));
+ }
+
+ @Override
+ public void onSurfacePackageReady(@NonNull SurfaceControlViewHost.SurfacePackage surfacePackage,
+ int i, @NonNull Bundle bundle) {
+ Log.i("App", "onSurfacePackageReady");
+ mainActivity.renderSurfaceView(surfacePackage);
+ }
+
+ @Override
+ public void onSurfacePackageError(int errorCode, String errorMessage) {
+ Log.i("App", "onSurfacePackageError");
+ }
+}
+
diff --git a/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/main/res/layout/activity_main.xml b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000000..1b878ac32a
--- /dev/null
+++ b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".MainActivity">
+ <SurfaceView
+ android:id="@+id/rendered_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+</LinearLayout>
diff --git a/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/main/res/values/strings.xml b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000000..cbaab5ba60
--- /dev/null
+++ b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+ <string name="app_name">RubidumConsumer</string>
+</resources> \ No newline at end of file
diff --git a/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/build.gradle b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/build.gradle
new file mode 100644
index 0000000000..a5a7957e08
--- /dev/null
+++ b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/build.gradle
@@ -0,0 +1,11 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+apply from: "../commonHeader.gradle"
+
+buildscript {
+ apply from: "../commonHeader.gradle" // for $kotlinVersion
+ apply from: "../commonBuildScript.gradle"
+
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$rootProject.kotlinVersion"
+ }
+}
diff --git a/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/gradle.properties b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/gradle.properties
new file mode 100644
index 0000000000..da3a59093e
--- /dev/null
+++ b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/gradle.properties
@@ -0,0 +1,2 @@
+android.useAndroidX=true
+android.experimental.privacysandboxsdk.enable=true
diff --git a/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/settings.gradle b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/settings.gradle
new file mode 100644
index 0000000000..288816bd9e
--- /dev/null
+++ b/build-system/integration-test/test-projects/privacySandboxSdk/libraryAndConsumer/settings.gradle
@@ -0,0 +1,5 @@
+apply from: "../commonLocalRepo.gradle", to: pluginManagement
+
+include ':app'
+include ':ads-sdk-implementation'
+include ':ads-sdk'
diff --git a/ddmlib/src/main/java/com/android/ddmlib/internal/DeviceClientMonitorTask.java b/ddmlib/src/main/java/com/android/ddmlib/internal/DeviceClientMonitorTask.java
index 96a60802f7..1333b7be5a 100644
--- a/ddmlib/src/main/java/com/android/ddmlib/internal/DeviceClientMonitorTask.java
+++ b/ddmlib/src/main/java/com/android/ddmlib/internal/DeviceClientMonitorTask.java
@@ -731,6 +731,17 @@ class DeviceClientMonitorTask implements Runnable {
private class CmdlineFileProcessor extends Processor {
+ // CmdlineFileProcessor is peculiar since contrary to TrackServiceProcessor it tap into a
+ // source that does not prefix its message with their size (it runs a bash command). Also
+ // the source does not send several messages, it returns a single message made fo the whole
+ // update of the bash command.
+ //
+ // To be compliant with the parseMessage/onMessage system, it always return false on
+ // parseMessage() until the Processor is closed. After that parseMessage returns true once
+ // and then false each subsequent calls.
+
+ private boolean messageReceived = false;
+
private final int mPid;
private int mRetryCount; // The number of attempts left to read the cmdline file.
@@ -752,10 +763,11 @@ class DeviceClientMonitorTask implements Runnable {
@Override
protected Optional<ByteBuffer> parseMessage() {
- if (mSocketConnected) {
+ if (mSocketConnected || messageReceived) {
return Optional.empty();
}
+ messageReceived = true;
return Optional.of(ByteBuffer.wrap(mStream.buf(), 0, mStream.size()));
}
@@ -797,6 +809,7 @@ class DeviceClientMonitorTask implements Runnable {
message.remaining(),
AdbHelper.DEFAULT_CHARSET);
+ message.position(message.remaining());
name = name.trim();
if (name.isEmpty()) {
return;
diff --git a/ddmlib/src/test/java/com/android/ddmlib/testing/FakeAdbRule.kt b/ddmlib/src/test/java/com/android/ddmlib/testing/FakeAdbRule.kt
index ad666e453c..816ed66e40 100644
--- a/ddmlib/src/test/java/com/android/ddmlib/testing/FakeAdbRule.kt
+++ b/ddmlib/src/test/java/com/android/ddmlib/testing/FakeAdbRule.kt
@@ -101,6 +101,7 @@ class FakeAdbRule : ExternalResource() {
release: String,
sdk: String,
abi: String = "x86_64",
+ properties: Map<String, String> = emptyMap(),
hostConnectionType: DeviceState.HostConnectionType = DeviceState.HostConnectionType.USB,
avdName: String? = null,
avdPath: String? = null
@@ -110,7 +111,16 @@ class FakeAdbRule : ExternalResource() {
if (avdName != null && avdPath != null) {
EmulatorConsole.registerConsoleForTest(deviceId, consoleFactory(avdName, avdPath))
}
- val device = fakeAdbServer.connectDevice(deviceId, manufacturer, model, release, sdk, abi, hostConnectionType).get()
+ val deviceFuture = fakeAdbServer.connectDevice(
+ deviceId,
+ manufacturer,
+ model,
+ release,
+ sdk,
+ abi,
+ properties,
+ hostConnectionType)
+ val device = deviceFuture.get()
device.deviceStatus = DeviceState.DeviceStatus.ONLINE
assertThat(startLatch.await(30, TimeUnit.SECONDS)).isTrue()
return device
diff --git a/deploy/agent/runtime/android.sdktools.deployer.deployer-runtime-support.iml b/deploy/agent/runtime/android.sdktools.deployer.deployer-runtime-support.iml
index 2e2c1fb27a..2e515c3dc7 100644
--- a/deploy/agent/runtime/android.sdktools.deployer.deployer-runtime-support.iml
+++ b/deploy/agent/runtime/android.sdktools.deployer.deployer-runtime-support.iml
@@ -6,27 +6,21 @@
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/main/kotlin" isTestSource="false" />
+ <excludeFolder url="file://$MODULE_DIR$/src/main/java/com/android/tools/deploy/liveedit/superclasses" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
+
<orderEntry type="module-library">
<library>
<CLASSES>
- <root url="jar://$MODULE_DIR$/lib/kotlin-eval4j.jar!/" />
- </CLASSES>
- <JAVADOC />
- <SOURCES />
- </library>
- </orderEntry>
- <orderEntry type="module-library">
- <library>
- <CLASSES>
- <root url="jar://$MODULE_DIR$/lib/kotlin-stdlib.jar!/" />
+ <root url="jar://$MODULE_DIR$/lib/deploy_asm4.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
+
<orderEntry type="module-library">
<library>
<CLASSES>
@@ -77,7 +71,20 @@
<SOURCES />
</library>
</orderEntry>
- <orderEntry type="library" scope="TEST" name="mockito" level="project" />
+ <orderEntry type="module-library" scope="TEST">
+ <library name="mockito-junit-jupiter" type="repository">
+ <properties maven-id="org.mockito:mockito-junit-jupiter:3.12.4" />
+ <CLASSES>
+ <root url="jar://$MAVEN_REPOSITORY$/org/mockito/mockito-junit-jupiter/3.12.4/mockito-junit-jupiter-3.12.4.jar!/" />
+ <root url="jar://$MAVEN_REPOSITORY$/org/mockito/mockito-core/3.12.4/mockito-core-3.12.4.jar!/" />
+ </CLASSES>
+ <JAVADOC>
+ <root url="jar://$MAVEN_REPOSITORY$/org/mockito/mockito-junit-jupiter/3.12.4/mockito-junit-jupiter-3.12.4-javadoc.jar!/" />
+ <root url="jar://$MAVEN_REPOSITORY$/org/mockito/mockito-core/3.12.4/mockito-core-3.12.4-javadoc.jar!/" />
+ </JAVADOC>
+ <SOURCES />
+ </library>
+ </orderEntry>
<orderEntry type="library" scope="TEST" name="studio-sdk" level="project" />
</component>
-</module> \ No newline at end of file
+</module>
diff --git a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DefaultProvisionerPlugin.kt b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DefaultProvisionerPlugin.kt
index 35c1593a7c..cc3bac4154 100644
--- a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DefaultProvisionerPlugin.kt
+++ b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DefaultProvisionerPlugin.kt
@@ -17,13 +17,9 @@ package com.android.sdklib.deviceprovisioner
import com.android.adblib.ConnectedDevice
import com.android.adblib.deviceProperties
-import com.android.adblib.scope
-import kotlinx.coroutines.CancellationException
-import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.launch
/**
* Plugin which provides handles for devices when no other plugin claims them. This will offer a
diff --git a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProperties.kt b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProperties.kt
index 19a6f0fd14..601f554bff 100644
--- a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProperties.kt
+++ b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProperties.kt
@@ -16,7 +16,6 @@
package com.android.sdklib.deviceprovisioner
import com.android.sdklib.AndroidVersion
-import com.android.sdklib.AndroidVersion.AndroidVersionException
import com.android.sdklib.devices.Abi
/**
@@ -26,56 +25,62 @@ import com.android.sdklib.devices.Abi
*/
interface DeviceProperties {
- val model: String?
- val manufacturer: String?
- val apiLevel: AndroidVersion
- val abi: Abi?
+ val model: String?
+ val manufacturer: String?
+ val abi: Abi?
+ /** The Android API level. May include a codename if not a release version. */
+ val androidVersion: AndroidVersion
+ /** The user-visible version of Android, like "7.1" or "11". */
+ val androidRelease: String?
- open class Builder {
+ /**
+ * A string ideally unique to the device instance (e.g. serial number or emulator console port),
+ * used for disambiguating this device from others with similar properties.
+ */
+ val disambiguator: String?
- var manufacturer: String? = null
- var model: String? = null
- var apiLevel = AndroidVersion.DEFAULT
- var abi: Abi? = null
+ open class Builder {
- fun readCommonProperties(properties: Map<String, String>) {
- manufacturer =
- properties["ro.product.manufacturer"]
- ?: properties["ro.manufacturer"]
- model =
- properties["ro.product.model"]
- ?: properties["ro.model"]
- apiLevel =
- properties["ro.build.version.sdk"]?.let {
- try {
- AndroidVersion(it)
- } catch (e: AndroidVersionException) {
- null
- }
- } ?: AndroidVersion.DEFAULT
- abi = properties["ro.product.cpu.abi"]?.let { Abi.getEnum(it) }
- }
+ var manufacturer: String? = null
+ var model: String? = null
+ var abi: Abi? = null
+ var androidVersion = AndroidVersion.DEFAULT
+ var androidRelease: String? = null
+ var disambiguator: String? = null
- fun buildBase(): DeviceProperties = Impl(manufacturer, model, apiLevel, abi)
+ fun readCommonProperties(properties: Map<String, String>) {
+ manufacturer = properties["ro.product.manufacturer"] ?: properties["ro.manufacturer"]
+ model = properties["ro.product.model"] ?: properties["ro.model"]
+ androidVersion =
+ properties["ro.build.version.sdk"]?.let { it.toIntOrNull() }?.let { sdk ->
+ AndroidVersion(sdk, properties["ro.build.version.codename"])
+ }
+ ?: AndroidVersion.DEFAULT
+ abi = properties["ro.product.cpu.abi"]?.let { Abi.getEnum(it) }
+ androidRelease = properties["ro.build.version.release"]
}
- class Impl(
- override val manufacturer: String?,
- override val model: String?,
- override val apiLevel: AndroidVersion,
- override val abi: Abi?
- ) : DeviceProperties
+ fun buildBase(): DeviceProperties =
+ Impl(manufacturer, model, androidVersion, abi, androidRelease, disambiguator)
+ }
- /**
- * Default implementation of device title; may be overridden.
- */
- fun title(): String =
+ class Impl(
+ override val manufacturer: String?,
+ override val model: String?,
+ override val androidVersion: AndroidVersion,
+ override val abi: Abi?,
+ override val androidRelease: String?,
+ override val disambiguator: String?
+ ) : DeviceProperties
+
+ /** Default implementation of device title; may be overridden. */
+ fun title(): String =
+ when {
+ manufacturer.isNullOrBlank() -> model ?: "Unknown"
+ else ->
when {
- manufacturer.isNullOrBlank() ->
- model ?: "Unknown"
- else -> when {
- model.isNullOrBlank() -> "$manufacturer Device"
- else -> "$manufacturer $model"
- }
+ model.isNullOrBlank() -> "$manufacturer Device"
+ else -> "$manufacturer $model"
}
+ }
}
diff --git a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProvisioner.kt b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProvisioner.kt
index bb47ecb1e9..eb0c983377 100644
--- a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProvisioner.kt
+++ b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProvisioner.kt
@@ -66,7 +66,9 @@ private constructor(
// We want to update whenever the ConnectedDevicesTracker updates, or when one of the
// devices' deviceInfoFlow updates (to know when the device comes online, since it will
// often appear initially in an offline state, and we ignore offline devices).
- adbSession.connectedDevicesTracker.connectedDevices
+ adbSession
+ .connectedDevicesTracker
+ .connectedDevices
.flatMapLatest { devices ->
combine(devices.map { device -> device.deviceInfoFlow.map { Pair(device, it) } }) {
it.mapNotNull { (device, info) ->
diff --git a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProvisionerPlugin.kt b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProvisionerPlugin.kt
index b3c56e1dcc..cec13a9925 100644
--- a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProvisionerPlugin.kt
+++ b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceProvisionerPlugin.kt
@@ -24,9 +24,7 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
-/**
- * A component of [DeviceProvisioner] responsible for a particular class of device.
- */
+/** A component of [DeviceProvisioner] responsible for a particular class of device. */
interface DeviceProvisionerPlugin {
/**
@@ -56,28 +54,20 @@ interface DeviceProvisionerPlugin {
val templates: StateFlow<List<DeviceTemplate>>
get() = MutableStateFlow(emptyList<DeviceTemplate>()).asStateFlow()
- /**
- * A [DeviceAction] that creates a device, typically based on input from the user.
- */
+ /** A [DeviceAction] that creates a device, typically based on input from the user. */
val createDeviceAction: CreateDeviceAction?
get() = null
- /**
- * A [DeviceAction] that creates a template, typically based on input from the user.
- */
+ /** A [DeviceAction] that creates a template, typically based on input from the user. */
val createDeviceTemplateAction: CreateDeviceTemplateAction?
get() = null
}
-/**
- * On device disconnection, runs the given block in the [AdbSession] scope.
- */
+/** On device disconnection, runs the given block in the [AdbSession] scope. */
fun ConnectedDevice.invokeOnDisconnection(block: suspend () -> Unit) {
scope.coroutineContext[Job]?.invokeOnCompletion {
// Run the block in the AdbSession scope, since this CompletionHandler must
// be fast, non-blocking, and thread-safe, and not throw exceptions.
- session.scope.launch {
- block()
- }
+ session.scope.launch { block() }
}
}
diff --git a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceState.kt b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceState.kt
index 42b04859b1..e05320e2af 100644
--- a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceState.kt
+++ b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceState.kt
@@ -17,8 +17,8 @@ package com.android.sdklib.deviceprovisioner
import com.android.adblib.ConnectedDevice
import com.google.common.base.Stopwatch
-import kotlinx.coroutines.Job
import java.time.Duration
+import kotlinx.coroutines.Job
/**
* Identifies the state of a provisionable device with respect to ADB: disconnected, connecting,
diff --git a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceTemplate.kt b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceTemplate.kt
index b297b8f3f2..ad0f34ab0b 100644
--- a/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceTemplate.kt
+++ b/device-provisioner/src/main/com/android/sdklib/deviceprovisioner/DeviceTemplate.kt
@@ -16,14 +16,14 @@
package com.android.sdklib.deviceprovisioner
/**
- * A DeviceTemplate contains the information necessary to activate / lease a device
- * from a provisioner. In contrast to a DeviceHandle, it does not refer to a specific device:
- * each activation produces a different device.
+ * A DeviceTemplate contains the information necessary to activate / lease a device from a
+ * provisioner. In contrast to a DeviceHandle, it does not refer to a specific device: each
+ * activation produces a different device.
*/
interface DeviceTemplate {
- val displayName: String
+ val displayName: String
- val activationAction: ActivationAction
+ val activationAction: ActivationAction
- val editAction: EditTemplateAction
+ val editAction: EditTemplateAction?
}
diff --git a/device-provisioner/src/test/com/android/sdklib/deviceprovisioner/DeviceProvisionerTest.kt b/device-provisioner/src/test/com/android/sdklib/deviceprovisioner/DeviceProvisionerTest.kt
index 4b09d83506..74af6d1ef3 100644
--- a/device-provisioner/src/test/com/android/sdklib/deviceprovisioner/DeviceProvisionerTest.kt
+++ b/device-provisioner/src/test/com/android/sdklib/deviceprovisioner/DeviceProvisionerTest.kt
@@ -199,8 +199,8 @@ class DeviceProvisionerTest {
/**
* Receives messages on this channel until one is received that does not cause an [AssertionError]
- * in the supplied block. This should be used within a withTimeout() block. If timeout occurs, throws
- * a new AssertionError with the last received error as a cause, if one was received.
+ * in the supplied block. This should be used within a withTimeout() block. If timeout occurs,
+ * throws a new AssertionError with the last received error as a cause, if one was received.
*/
suspend fun <T, R> Channel<T>.receiveUntilPassing(block: (T) -> R): R {
var lastError: AssertionError? = null
diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/DeviceState.java b/fakeadbserver/src/main/java/com/android/fakeadbserver/DeviceState.java
index 649120cc39..ca92f065f3 100644
--- a/fakeadbserver/src/main/java/com/android/fakeadbserver/DeviceState.java
+++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/DeviceState.java
@@ -32,6 +32,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.TreeMap;
import java.util.Vector;
import java.util.stream.Collectors;
@@ -69,6 +70,8 @@ public class DeviceState {
private final String mCpuAbi;
+ private final Map<String, String> mProperties;
+
private DeviceStatus mDeviceStatus;
private final ServiceManager mServiceManager;
@@ -90,6 +93,7 @@ public class DeviceState {
@NonNull String release,
@NonNull String sdk,
@NonNull String cpuAbi,
+ @NonNull Map<String, String> properties,
@NonNull HostConnectionType hostConnectionType,
int transportId) {
mServer = server;
@@ -100,6 +104,7 @@ public class DeviceState {
mBuildVersionSdk = sdk;
mCpuAbi = cpuAbi;
mFeatures = initFeatures(sdk);
+ mProperties = combinedProperties(manufacturer, model, release, sdk, cpuAbi, properties);
mHostConnectionType = hostConnectionType;
myTransportId = transportId;
mDeviceStatus = DeviceStatus.OFFLINE;
@@ -115,6 +120,7 @@ public class DeviceState {
config.getBuildVersionRelease(),
config.getBuildVersionSdk(),
config.getCpuAbi(),
+ config.getProperties(),
config.getHostConnectionType(),
transportId);
config.getFiles().forEach(fileState -> mFiles.put(fileState.getPath(), fileState));
@@ -165,6 +171,10 @@ public class DeviceState {
}
}
+ public Map<String, String> getProperties() {
+ return mProperties;
+ }
+
@NonNull
public DeviceStatus getDeviceStatus() {
return mDeviceStatus;
@@ -354,6 +364,7 @@ public class DeviceState {
mBuildVersionRelease,
mBuildVersionSdk,
mCpuAbi,
+ mProperties,
mDeviceStatus);
}
@@ -416,6 +427,22 @@ public class DeviceState {
return (List<String>) mAbbLogs.clone();
}
+ private static Map<String, String> combinedProperties(
+ @NonNull String manufacturer,
+ @NonNull String model,
+ @NonNull String release,
+ @NonNull String sdk,
+ @NonNull String cpuAbi,
+ @NonNull Map<String, String> properties) {
+ Map<String, String> combined = new TreeMap<>(properties);
+ combined.put("ro.product.manufacturer", manufacturer);
+ combined.put("ro.product.model", model);
+ combined.put("ro.build.version.release", release);
+ combined.put("ro.build.version.sdk", sdk);
+ combined.put("ro.product.cpu.abi", cpuAbi);
+ return combined;
+ }
+
/**
* The state of a device.
*/
diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/FakeAdbServer.java b/fakeadbserver/src/main/java/com/android/fakeadbserver/FakeAdbServer.java
index a7a8ddd397..0fb881c997 100644
--- a/fakeadbserver/src/main/java/com/android/fakeadbserver/FakeAdbServer.java
+++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/FakeAdbServer.java
@@ -249,7 +249,7 @@ public final class FakeAdbServer implements AutoCloseable {
* for handlers that inherit from {@link CommandHandler}. The purpose of the hub is to propagate
* server events to existing connections with the server.
*
- * <p>For example, if {@link #connectDevice(String, String, String, String, String,
+ * <p>For example, if {@link #connectDevice(String, String, String, String, String, Map,
* DeviceState.HostConnectionType)} is called, an event will be sent through the {@link
* DeviceStateChangeHub} to all open connections waiting on host:track-devices messages.
*/
@@ -267,6 +267,7 @@ public final class FakeAdbServer implements AutoCloseable {
* @param release is the Android OS version of the device
* @param sdk is the SDK version of the device
* @param cpuAbi is the ABI of the device CPU
+ * @param properties is the device properties
* @param hostConnectionType is the simulated connection type to the device @return the future
* @return a future to allow synchronization of the side effects of the call
*/
@@ -277,6 +278,7 @@ public final class FakeAdbServer implements AutoCloseable {
@NonNull String release,
@NonNull String sdk,
@NonNull String cpuAbi,
+ @NonNull Map<String, String> properties,
@NonNull DeviceState.HostConnectionType hostConnectionType) {
DeviceState device =
new DeviceState(
@@ -287,6 +289,7 @@ public final class FakeAdbServer implements AutoCloseable {
release,
sdk,
cpuAbi,
+ properties,
hostConnectionType,
newTransportId());
if (mConnectionHandlerTask == null) {
@@ -318,6 +321,7 @@ public final class FakeAdbServer implements AutoCloseable {
release,
sdk,
"x86_64",
+ Collections.emptyMap(),
hostConnectionType);
}
diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/FakeAdbServerConfig.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/FakeAdbServerConfig.kt
index 89f1438748..0bd94089dc 100644
--- a/fakeadbserver/src/main/java/com/android/fakeadbserver/FakeAdbServerConfig.kt
+++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/FakeAdbServerConfig.kt
@@ -50,5 +50,6 @@ class DeviceStateConfig(
val buildVersionRelease: String,
val buildVersionSdk: String,
val cpuAbi: String,
+ val properties: Map<String, String>,
var deviceStatus: DeviceState.DeviceStatus,
)
diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/execcommandhandlers/GetPropExecCommandHandler.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/execcommandhandlers/GetPropExecCommandHandler.kt
index 45c733c9c4..701f89ae26 100644
--- a/fakeadbserver/src/main/java/com/android/fakeadbserver/execcommandhandlers/GetPropExecCommandHandler.kt
+++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/execcommandhandlers/GetPropExecCommandHandler.kt
@@ -30,16 +30,13 @@ class GetPropExecCommandHandler : SimpleExecHandler("getprop") {
) {
val stream = responseSocket.getOutputStream()
writeOkay(stream) // Send ok first.
- val builder = """
- # This is some build info
- # This is more build info
-
- [ro.product.manufacturer]: [${device.manufacturer}]
- [ro.product.model]: [${device.model}]
- [ro.build.version.release]: [${device.buildVersionRelease}]
- [ro.build.version.sdk]: [${device.buildVersionSdk}]
-
- """.trimIndent()
- stream.write(builder.toByteArray(Charsets.UTF_8))
+ val buf = StringBuilder()
+ buf.append("# This is some build info\n")
+ buf.append("# This is more build info\n")
+ buf.append("\n")
+ for (entry in device.properties) {
+ buf.append("[${entry.key}]: [${entry.value}]\n")
+ }
+ stream.write(buf.toString().toByteArray(Charsets.UTF_8))
}
}
diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/GetPropCommandHandler.java b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/GetPropCommandHandler.java
index 316d3fabc8..6fe13babf0 100644
--- a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/GetPropCommandHandler.java
+++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellcommandhandlers/GetPropCommandHandler.java
@@ -25,6 +25,7 @@ import com.google.common.base.Charsets;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
+import java.util.Map;
/** shell:getprop gets the device properties of the specified device. */
public class GetPropCommandHandler extends SimpleShellHandler {
@@ -42,25 +43,18 @@ public class GetPropCommandHandler extends SimpleShellHandler {
try {
OutputStream stream = responseSocket.getOutputStream();
CommandHandler.writeOkay(stream); // Send ok first.
- String builder =
- "# This is some build info\n"
- + "# This is more build info\n\n"
- + "[ro.product.cpu.abi]: ["
- + device.getCpuAbi()
- + "]\n"
- + "[ro.product.manufacturer]: ["
- + device.getManufacturer()
- + "]\n"
- + "[ro.product.model]: ["
- + device.getModel()
- + "]\n"
- + "[ro.build.version.release]: ["
- + device.getBuildVersionRelease()
- + "]\n"
- + "[ro.build.version.sdk]: ["
- + device.getBuildVersionSdk()
- + "]\n";
- stream.write(builder.getBytes(Charsets.UTF_8));
+ StringBuilder buf = new StringBuilder();
+ buf.append("# This is some build info\n");
+ buf.append("# This is more build info\n");
+ buf.append("\n");
+ for (Map.Entry<String, String> entry : device.getProperties().entrySet()) {
+ buf.append('[');
+ buf.append(entry.getKey());
+ buf.append("]: [");
+ buf.append(entry.getValue());
+ buf.append("]\n");
+ }
+ stream.write(buf.toString().getBytes(Charsets.UTF_8));
} catch (IOException ignored) {
}
}
diff --git a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellv2commandhandlers/GetPropV2CommandHandler.kt b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellv2commandhandlers/GetPropV2CommandHandler.kt
index 477e3652c9..2e092a44fa 100644
--- a/fakeadbserver/src/main/java/com/android/fakeadbserver/shellv2commandhandlers/GetPropV2CommandHandler.kt
+++ b/fakeadbserver/src/main/java/com/android/fakeadbserver/shellv2commandhandlers/GetPropV2CommandHandler.kt
@@ -34,17 +34,14 @@ class GetPropV2CommandHandler : SimpleShellV2Handler("getprop") {
) {
protocol.writeOkay()
- val builder = """
- # This is some build info
- # This is more build info
-
- [ro.product.manufacturer]: [${device.manufacturer}]
- [ro.product.model]: [${device.model}]
- [ro.build.version.release]: [${device.buildVersionRelease}]
- [ro.build.version.sdk]: [${device.buildVersionSdk}]
-
- """.trimIndent()
- protocol.writeStdout(builder.toByteArray(Charsets.UTF_8))
+ val buf = StringBuilder()
+ buf.append("# This is some build info\n")
+ buf.append("# This is more build info\n")
+ buf.append("\n")
+ for (entry in device.properties) {
+ buf.append("[${entry.key}]: [${entry.value}]\n")
+ }
+ protocol.writeStdout(buf.toString().toByteArray(Charsets.UTF_8))
protocol.writeExitCode(0)
}
}
diff --git a/gmaven/src/test/resources/com/android/tools/test/gmaven-aars.txt b/gmaven/src/test/resources/com/android/tools/test/gmaven-aars.txt
index 9886730e33..2f2fe602c3 100644
--- a/gmaven/src/test/resources/com/android/tools/test/gmaven-aars.txt
+++ b/gmaven/src/test/resources/com/android/tools/test/gmaven-aars.txt
@@ -17,7 +17,6 @@ androidx/databinding/databinding-adapters
res/
res/values/
res/values/values.xml
- values/
androidx/databinding/databinding-ktx
AndroidManifest.xml
@@ -44,7 +43,6 @@ androidx/databinding/databinding-runtime
res/
res/values/
res/values/values.xml
- values/
androidx/databinding/viewbinding
AndroidManifest.xml
@@ -77,7 +75,6 @@ com/android/databinding/adapters
res/
res/values/
res/values/values.xml
- values/
com/android/databinding/library
AndroidManifest.xml
@@ -95,7 +92,6 @@ com/android/databinding/library
res/
res/values/
res/values/values.xml
- values/
com/android/databinding/viewbinding
AndroidManifest.xml
diff --git a/gmaven/src/test/resources/com/android/tools/test/gmaven-jars.txt b/gmaven/src/test/resources/com/android/tools/test/gmaven-jars.txt
index 21918747bb..1576336dd5 100644
--- a/gmaven/src/test/resources/com/android/tools/test/gmaven-jars.txt
+++ b/gmaven/src/test/resources/com/android/tools/test/gmaven-jars.txt
@@ -420,6 +420,7 @@ com/android/tools/build/gradle
com/android/build/gradle/internal/component/legacy/
com/android/build/gradle/internal/core/
com/android/build/gradle/internal/core/dsl/
+ com/android/build/gradle/internal/core/dsl/impl/
com/android/build/gradle/internal/coverage/
com/android/build/gradle/internal/crash/
com/android/build/gradle/internal/cxx/
diff --git a/lint/cli/src/main/java/com/android/tools/lint/LintFixPerformer.kt b/lint/cli/src/main/java/com/android/tools/lint/LintFixPerformer.kt
index de7a0ff56f..3c175d2f48 100644
--- a/lint/cli/src/main/java/com/android/tools/lint/LintFixPerformer.kt
+++ b/lint/cli/src/main/java/com/android/tools/lint/LintFixPerformer.kt
@@ -740,7 +740,7 @@ open class LintFixPerformer constructor(
if (to == -1) {
to = line.length
}
- imported.add(line.substring("package ".length, to).trim { it <= ' ' } + ".")
+ imported.add(line.substring("package ".length, to).trim() + ".")
} else if (line.startsWith("import ")) {
var from = "import ".length
if (line.startsWith("static ", from)) {
@@ -753,7 +753,7 @@ open class LintFixPerformer constructor(
if (line[to - 1] == '*') {
to--
}
- imported.add(line.substring(from, to).trim { it <= ' ' })
+ imported.add(line.substring(from, to).trim())
}
}
for (full in imported) {
@@ -766,7 +766,7 @@ open class LintFixPerformer constructor(
}
clz = clz.substring(0, index + 1)
}
- replacement = replacement.replace(clz, "")
+ replacement = removePackage(replacement, clz)
}
}
}
@@ -807,6 +807,53 @@ open class LintFixPerformer constructor(
return true
}
+ /**
+ * Given a package [prefix] and a Java/Kotlin source fragment, removes the
+ * package prefix from any fully qualified references with that package
+ * prefix. The reason we can't just use [String.replace] is that we only
+ * want to replace prefixes in the same package, not in any sub packages.
+ *
+ * For example, given the package prefix `p1.p2`, for the source
+ * string `p1.p2.p3.Class1, `p1.p2.Class2`, this method will return
+ * `p1.p2.p3.Class1, Class2`.
+ */
+ private fun removePackage(source: String, prefix: String): String {
+ if (prefix.isEmpty()) {
+ return source
+ }
+
+ // Checks whether the symbol starting at offset [next] references
+ // the [prefix] package and not potentially some subpackage of it
+ fun isPackageMatchAt(next: Int): Boolean {
+ var i = next + prefix.length
+ while (i < source.length) {
+ val c = source[i++]
+ if (c == '.') {
+ return false
+ } else if (!c.isJavaIdentifierPart()) {
+ return true
+ }
+ }
+ return true
+ }
+
+ val sb = StringBuilder()
+ var index = 0
+ while (true) {
+ val next = source.indexOf(prefix, index)
+ sb.append(source.substring(index, if (next == -1) source.length else next))
+ if (next == -1) {
+ break
+ }
+ index = next + prefix.length
+ if ((index == source.length || !source[index].isUpperCase()) && !isPackageMatchAt(next)) {
+ sb.append(source.substring(next, index))
+ }
+ }
+
+ return sb.toString()
+ }
+
fun computeEdits(incident: Incident, lintFix: LintFix): List<PendingEditFile> {
val fileMap = mutableMapOf<File, PendingEditFile>()
registerFix(fileMap, incident, lintFix)
diff --git a/lint/cli/src/main/java/com/android/tools/lint/UastEnvironment.kt b/lint/cli/src/main/java/com/android/tools/lint/UastEnvironment.kt
index f0842f116d..6c251ce9c4 100644
--- a/lint/cli/src/main/java/com/android/tools/lint/UastEnvironment.kt
+++ b/lint/cli/src/main/java/com/android/tools/lint/UastEnvironment.kt
@@ -129,7 +129,7 @@ interface UastEnvironment {
fun create(
config: Configuration,
): UastEnvironment {
- return when(config) {
+ return when (config) {
is FirUastEnvironment.Configuration ->
FirUastEnvironment.create(config)
else ->
diff --git a/lint/cli/src/main/java/com/android/tools/lint/gradle/GroovyGradleVisitor.java b/lint/cli/src/main/java/com/android/tools/lint/gradle/GroovyGradleVisitor.java
index e9d09f853c..35fb93caea 100644
--- a/lint/cli/src/main/java/com/android/tools/lint/gradle/GroovyGradleVisitor.java
+++ b/lint/cli/src/main/java/com/android/tools/lint/gradle/GroovyGradleVisitor.java
@@ -20,6 +20,7 @@ import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.tools.lint.checks.GradleDetector;
import com.android.tools.lint.client.api.GradleVisitor;
+import com.android.tools.lint.client.api.LintClient;
import com.android.tools.lint.detector.api.Context;
import com.android.tools.lint.detector.api.DefaultPosition;
import com.android.tools.lint.detector.api.GradleContext;
@@ -55,6 +56,11 @@ public class GroovyGradleVisitor extends GradleVisitor {
@NonNull GradleContext context, @NonNull List<? extends GradleScanner> detectors) {
try {
visitQuietly(context, detectors);
+ } catch (AssertionError e) {
+ // Test infrastructure checks
+ if (LintClient.isUnitTest()) {
+ throw e;
+ }
} catch (Throwable t) {
// else: ignore
// Parsing the build script can involve class loading that we sometimes can't
diff --git a/lint/libs/lint-api/src/main/java/com/android/tools/lint/client/api/JarFileIssueRegistry.kt b/lint/libs/lint-api/src/main/java/com/android/tools/lint/client/api/JarFileIssueRegistry.kt
index 482361ec65..271b31d6c8 100644
--- a/lint/libs/lint-api/src/main/java/com/android/tools/lint/client/api/JarFileIssueRegistry.kt
+++ b/lint/libs/lint-api/src/main/java/com/android/tools/lint/client/api/JarFileIssueRegistry.kt
@@ -331,16 +331,6 @@ The Lint API version currently running is $CURRENT_API (${describeApi(CURRENT_AP
}
recordRejectedIssues(issues)
return null
- } else if (verifier.hasPackageConflict()) {
- if (reportErrors(driver)) {
- val message = getPackagingConflictMessage(className, verifier)
- LintClient.report(
- client = client, issue = OBSOLETE_LINT_CHECK,
- message = message, file = jarFile, project = currentProject, driver = driver
- )
- }
- recordRejectedIssues(issues)
- return null
}
// Not returning here: try to run the checks
} else {
@@ -393,16 +383,6 @@ The Lint API version currently running is $CURRENT_API (${describeApi(CURRENT_AP
}
recordRejectedIssues(issues)
return null
- } else if (verifier.hasPackageConflict()) {
- if (reportErrors(driver)) {
- val message = getPackagingConflictMessage(className, verifier)
- LintClient.report(
- client = client, issue = OBSOLETE_LINT_CHECK,
- message = message, file = jarFile, project = currentProject, driver = driver
- )
- }
- recordRejectedIssues(issues)
- return null
}
}
} catch (e: Throwable) {
@@ -485,33 +465,6 @@ The Lint API version currently running is $CURRENT_API (${describeApi(CURRENT_AP
issues.forEach { rejectedIssues.add(it.id) }
}
- private fun getPackagingConflictMessage(className: String, verifier: LintJarVerifier): String {
- return """
-Lint found an issue registry (`$className`)
-which contains code in some of lint's reserved packages.
-
-This is usually because the lint jar has accidentally
-packed in libraries that are part of lint's API surface,
-such as the Kotlin standard library (`kotlin.*`), or
-some of the Android tooling libraries (`com.android.*`)
-including lint's own API jars, or some of the third party
-libraries that lint depends on, such as UAST.
-If you need these and cannot rely on the ones provided
-in lint's runtime environment, consider `jarjar`ing your
-own versions.
-
-A second reason is one where you've accidentally placed
-your own detector code into one of these package
-namespaces, since they are pretty broad (`com.android.*`).
-For Android specifically, you can place them under
-`com.android.internal.*` which is explicitly allowed.
-
-The first bundled package that is part of lint's API
-surface namespace is:
-${verifier.describeFirstPackagedDependency()}
-""".trim()
- }
-
private fun getVendor(
client: LintClient,
registry: IssueRegistry,
diff --git a/lint/libs/lint-api/src/main/java/com/android/tools/lint/client/api/LintDriver.kt b/lint/libs/lint-api/src/main/java/com/android/tools/lint/client/api/LintDriver.kt
index fb8796dc3c..be66a6c772 100644
--- a/lint/libs/lint-api/src/main/java/com/android/tools/lint/client/api/LintDriver.kt
+++ b/lint/libs/lint-api/src/main/java/com/android/tools/lint/client/api/LintDriver.kt
@@ -3429,7 +3429,7 @@ class LintDriver(
names: Collection<String>?
) {
var message = "Issue `${issue.id}` is not allowed to be suppressed"
- if (names?.isNotEmpty() == true) {
+ if (names?.isNotEmpty() == true && context !is XmlContext) {
message += " (but can be with ${
formatList(
names.map { "`@$it`" }.toList(),
@@ -3489,6 +3489,12 @@ class LintDriver(
}
}
+ val customSuppressNames = if (!allowSuppress) {
+ issue.suppressNames?.toSet()
+ } else {
+ null
+ }
+
var currentNode = node
if (currentNode is Attr) {
currentNode = currentNode.ownerElement
@@ -3501,9 +3507,27 @@ class LintDriver(
if (element.hasAttributeNS(TOOLS_URI, ATTR_IGNORE)) {
val ignore = element.getAttributeNS(TOOLS_URI, ATTR_IGNORE)
if (isSuppressed(issue, ignore)) {
+ if (customSuppressNames != null && context != null) {
+ flagInvalidSuppress(
+ context, issue, context.getLocation(currentNode),
+ currentNode, issue.suppressNames
+ )
+ return false
+ }
+ return true
+ }
+ if (customSuppressNames != null && isSuppressed(customSuppressNames, ignore)) {
return true
}
- } else if (checkComments && context!!.isSuppressedWithComment(currentNode, issue)) {
+ } else if (checkComments && context != null && context.isSuppressedWithComment(currentNode, issue)) {
+ if (customSuppressNames != null) {
+ flagInvalidSuppress(
+ context, issue, context.getLocation(currentNode),
+ currentNode, issue.suppressNames
+ )
+ return false
+ }
+
return true
}
}
@@ -3959,6 +3983,30 @@ class LintDriver(
return false
}
+ private fun isSuppressed(issueIds: Collection<String>, string: String): Boolean {
+ return issueIds.any { isSuppressed(it, string) }
+ }
+
+ private fun isSuppressed(issueId: String, string: String): Boolean {
+ if (string.isEmpty()) {
+ return false
+ }
+
+ if (string.indexOf(',') == -1) {
+ if (matches(issueId, string)) {
+ return true
+ }
+ } else {
+ for (id in Splitter.on(',').trimResults().split(string)) {
+ if (matches(issueId, id)) {
+ return true
+ }
+ }
+ }
+
+ return false
+ }
+
/**
* Returns true if the given AST modifier has a suppress
* annotation for the given issue (which can be null to check
diff --git a/lint/libs/lint-api/src/main/java/com/android/tools/lint/client/api/LintJarVerifier.kt b/lint/libs/lint-api/src/main/java/com/android/tools/lint/client/api/LintJarVerifier.kt
index a9e5acd4d4..d64a91ea8f 100644
--- a/lint/libs/lint-api/src/main/java/com/android/tools/lint/client/api/LintJarVerifier.kt
+++ b/lint/libs/lint-api/src/main/java/com/android/tools/lint/client/api/LintJarVerifier.kt
@@ -51,23 +51,14 @@ class LintJarVerifier(jarFile: File) : ClassVisitor(ASM9) {
* we want to check for validity?
*/
private fun isRelevantApi(internal: String): Boolean {
+ val relevant = internal.startsWith("com/android/") ||
+ // Imported APIs
+ internal.startsWith("org/jetbrains/uast") ||
+ internal.startsWith("org/jetbrains/kotlin") ||
+ internal.startsWith("com/intellij")
// Libraries unlikely to change: org.w3c.dom, org.objectweb.asm, org.xmlpull, etc.
- if (internal.startsWith("com/android/") &&
- // Reserved for various Android-internal checks such as CallingIdentityTokenDetector in AOSP
- !internal.startsWith("com/android/internal/") &&
- // We have a few clashes with this namespace which are not part of
- // the API surface; remove these
- !internal.startsWith("com/android/tools/lint/checks/studio/") &&
- !internal.startsWith("com/android/tools/lint/checks/infrastructure/")
- ) {
- return true
- }
- // Imported APIs
- return internal.startsWith("org/jetbrains/uast") ||
- internal.startsWith("org/jetbrains/kotlin/psi") ||
- internal.startsWith("org/jetbrains/kotlin/asJava") ||
- internal.startsWith("com/intellij/psi")
+ return relevant && !bundledClasses.contains(internal)
}
/**
@@ -79,14 +70,6 @@ class LintJarVerifier(jarFile: File) : ClassVisitor(ASM9) {
return incompatibleReference == null
}
- /**
- * Returns true if the lint jar contains classes that conflict with
- * (or are repackaging) lint's own API surface.
- */
- fun hasPackageConflict(): Boolean {
- return packageConflict != null
- }
-
fun getVerificationThrowable(): Throwable? = verifyProblem
/**
@@ -97,39 +80,38 @@ class LintJarVerifier(jarFile: File) : ClassVisitor(ASM9) {
// Scans through the bytecode for all the classes in lint.jar, and
// checks any class, method or field reference accessing the Lint API
// and makes sure that API is found in the bytecode
+ val classes = mutableMapOf<String, ByteArray>()
JarFile(lintJar).use { jar ->
jar.entries().also { entries ->
- var firstInDir = true
while (entries.hasMoreElements()) {
(entries.nextElement() as java.util.jar.JarEntry).also { entry ->
val directory = entry.isDirectory
val name = entry.name
- if (directory) {
- firstInDir = true
- } else if (name.endsWith(DOT_CLASS)) {
- if (firstInDir) {
- if (packageConflict == null) {
- val packageOwner = name.substring(0, name.lastIndexOf('/') + 1)
- if (isRelevantApi(packageOwner)) {
- packageConflict = packageOwner
- }
- }
- firstInDir = false
- }
- currentClassFile = name
+ if (!directory && name.endsWith(DOT_CLASS)) {
jar.getInputStream(entry).use { stream ->
val bytes = ByteStreams.toByteArray(stream)
- val reader = ClassReader(bytes)
- reader.accept(this, SKIP_DEBUG or SKIP_FRAMES)
- if (incompatibleReference != null) {
- return
- }
+ classes[name] = bytes
}
}
}
}
}
}
+
+ classes.forEach { (name, _) ->
+ // Note that jar file internal names always use forward slash, not File.separator
+ // so we can compute the internal name by just dropping the .class suffix
+ bundledClasses.add(name.removeSuffix(DOT_CLASS))
+ }
+
+ for ((name, bytes) in classes) {
+ currentClassFile = name
+ val reader = ClassReader(bytes)
+ reader.accept(this, SKIP_DEBUG or SKIP_FRAMES)
+ if (incompatibleReference != null) {
+ return
+ }
+ }
}
/** Returns a message describing the incompatibility */
@@ -170,9 +152,6 @@ class LintJarVerifier(jarFile: File) : ClassVisitor(ASM9) {
return incompatibleReferencer!! // should only be called if incompatibleReference is non null
}
- fun describeFirstPackagedDependency(): String =
- packageConflict?.replace('/', '.')?.removeSuffix(".") ?: "None"
-
/**
* An exception thrown if there is some other verification problem
* (invalid class file etc)
@@ -182,15 +161,15 @@ class LintJarVerifier(jarFile: File) : ClassVisitor(ASM9) {
/** The internal name of the invalid reference. */
private var incompatibleReference: String? = null
+ /** The internal names of the classes in the Jar file */
+ private val bundledClasses: MutableSet<String> = mutableSetOf()
+
/**
* The class file containing the reference to
* [incompatibleReference]
*/
private var incompatibleReferencer: String? = null
- /** The first conflicting package found */
- private var packageConflict: String? = null
-
private val methodVisitor = object : MethodVisitor(ASM9) {
override fun visitMethodInsn(
opcode: Int,
diff --git a/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/UastLintUtils.kt b/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/UastLintUtils.kt
index b87a702441..c65691c8a7 100644
--- a/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/UastLintUtils.kt
+++ b/lint/libs/lint-api/src/main/java/com/android/tools/lint/detector/api/UastLintUtils.kt
@@ -29,6 +29,7 @@ import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiModifier
import com.intellij.psi.PsiParameter
import com.intellij.psi.PsiVariable
+import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.uast.UAnnotation
@@ -493,6 +494,16 @@ fun UElement.isBelow(parent: UElement, strict: Boolean = false): Boolean {
}
/**
+ * Returns true if [this] element is a child or indirect child of the
+ * given [parent]. If [strict] is false, this method will return true
+ * when [parent] is the same as [this].
+ */
+fun PsiElement?.isBelow(parent: PsiElement, strict: Boolean = false): Boolean {
+ this ?: return false
+ return PsiTreeUtil.isAncestor(parent, this, strict)
+}
+
+/**
* Like [UFile.accept], but in the case of multi-file classes (where
* multiple source files containing top level declarations are annotated
* with `@JvmMultifileClass`, all naming the same target class) the
diff --git a/lint/libs/lint-api/src/main/java/com/android/tools/lint/helpers/DefaultUastParser.kt b/lint/libs/lint-api/src/main/java/com/android/tools/lint/helpers/DefaultUastParser.kt
index aa8c58818d..ec0a0fbeef 100644
--- a/lint/libs/lint-api/src/main/java/com/android/tools/lint/helpers/DefaultUastParser.kt
+++ b/lint/libs/lint-api/src/main/java/com/android/tools/lint/helpers/DefaultUastParser.kt
@@ -137,7 +137,9 @@ open class DefaultUastParser(
if (psiFile is PsiPlainTextFile) { // plain text: file too large to process with PSI
if (!warnedAboutLargeFiles) {
warnedAboutLargeFiles = true
- val max = FileUtilRt.getUserFileSizeLimit()
+ // default user file size limit = 2500 KiB
+ // default user content load limit = 20000 KiB
+ val max = max(FileUtilRt.getUserFileSizeLimit(), FileUtilRt.getUserContentLoadLimit()) / 1024
val size = file.length() / 1024
val sizeRoundedUp = 2.0.pow(ceil(log10(size.toDouble()) / log10(2.0) + 0.2)).toInt()
context.report(
diff --git a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/CheckResultDetector.kt b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/CheckResultDetector.kt
index ad72c0bcbd..4173191ee1 100644
--- a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/CheckResultDetector.kt
+++ b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/CheckResultDetector.kt
@@ -30,6 +30,7 @@ import com.android.tools.lint.detector.api.SourceCodeScanner
import com.android.tools.lint.detector.api.UImplicitCallExpression
import com.android.tools.lint.detector.api.UastLintUtils.Companion.getAnnotationStringValue
import com.android.tools.lint.detector.api.findSelector
+import com.android.tools.lint.detector.api.isBelow
import com.android.tools.lint.detector.api.isJava
import com.android.tools.lint.detector.api.isKotlin
import com.android.tools.lint.detector.api.nextStatement
@@ -313,11 +314,15 @@ class CheckResultDetector : AbstractAnnotationDetector(), SourceCodeScanner {
curr = curr.uastParent ?: return true
}
- @Suppress("RedundantIf")
if (curr is UBlockExpression) {
- if (curr.sourcePsi is PsiSynchronizedStatement) {
- return false
+ val sourcePsi = curr.sourcePsi
+ if (sourcePsi is PsiSynchronizedStatement) {
+ val lock = sourcePsi.lockExpression
+ if (lock != null && element.sourcePsi.isBelow(lock)) {
+ return false
+ }
}
+
// In Java, it's apparent when an expression is unused:
// the parent is a block expression. However, in Kotlin it's
// much trickier: values can flow through blocks and up through
@@ -342,7 +347,7 @@ class CheckResultDetector : AbstractAnnotationDetector(), SourceCodeScanner {
// It's the last child: see if the parent is unused
val parent = skipParenthesizedExprUp(curr.uastParent)
- if (parent is ULambdaExpression && isKotlin(curr.sourcePsi)) {
+ if (parent is ULambdaExpression && isKotlin(sourcePsi)) {
val expressionType = parent.getExpressionType()?.canonicalText
if (expressionType != null &&
expressionType.startsWith("kotlin.jvm.functions.Function") &&
@@ -357,7 +362,7 @@ class CheckResultDetector : AbstractAnnotationDetector(), SourceCodeScanner {
return false
}
- if (isJava(curr.sourcePsi)) {
+ if (isJava(sourcePsi)) {
// In Java there's no implicit passing to the parent
return true
}
diff --git a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/DeprecationDetector.kt b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/DeprecationDetector.kt
index 92b974986d..5ab0ff488c 100644
--- a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/DeprecationDetector.kt
+++ b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/DeprecationDetector.kt
@@ -108,8 +108,9 @@ class DeprecationDetector : ResourceXmlDetector(), SourceCodeScanner {
return listOf(ABSOLUTE_LAYOUT, TAG_USES_PERMISSION_SDK_M)
}
- override fun getApplicableAttributes(): Collection<String>? {
+ override fun getApplicableAttributes(): Collection<String> {
return listOf(
+ ATTR_USER_SHARED_ID,
// TODO: fill_parent is deprecated as of API 8.
// We could warn about it, but it will probably be very noisy
// and make people disable the deprecation check; let's focus on
@@ -158,6 +159,16 @@ class DeprecationDetector : ResourceXmlDetector(), SourceCodeScanner {
val fix: String
var minSdk = 1
when (name) {
+ ATTR_USER_SHARED_ID -> {
+ if (!attribute.ownerElement.hasAttributeNS(ANDROID_URI, ATTR_SHARED_USER_MAX_SDK_VERSION)) {
+ fix = "Consider removing `$ATTR_USER_SHARED_ID` for new users by adding " +
+ "`android:sharedUserMaxSdkVersion=\"32\"` to your manifest. " +
+ "See https://developer.android.com/guide/topics/manifest/manifest-element for details."
+ val addFix = fix().set(ANDROID_URI, ATTR_SHARED_USER_MAX_SDK_VERSION, "32").build()
+ context.report(ISSUE, attribute, context.getLocation(attribute), fix, addFix)
+ }
+ return
+ }
ATTR_PERMISSION -> {
if (TAG_SERVICE == attribute.ownerElement.tagName &&
CHOOSER_TARGET_SERVICE_PERM == attribute.value
@@ -302,6 +313,9 @@ class DeprecationDetector : ResourceXmlDetector(), SourceCodeScanner {
private const val APP_ACTIONS_MIGRATION_URL =
"https://developers.google.com/assistant/app/legacy/migration-guide"
+ private const val ATTR_USER_SHARED_ID = "sharedUserId"
+ private const val ATTR_SHARED_USER_MAX_SDK_VERSION = "sharedUserMaxSdkVersion"
+
/** Usage of deprecated views or attributes. */
@JvmField
val ISSUE = create(
diff --git a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/GooglePlaySdkIndex.kt b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/GooglePlaySdkIndex.kt
index 584942531c..ab3bcd51e4 100644
--- a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/GooglePlaySdkIndex.kt
+++ b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/GooglePlaySdkIndex.kt
@@ -49,6 +49,7 @@ abstract class GooglePlaySdkIndex(cacheDir: Path? = null) : NetworkCache(
const val VIEW_DETAILS_MESSAGE = "View details in Google Play SDK Index"
}
+ private lateinit var lastReadResult: ReadDataResult
private var initialized: Boolean = false
private var status: GooglePlaySdkIndexStatus = GooglePlaySdkIndexStatus.NOT_READY
private val libraryToSdk = HashMap<String, LibraryToSdk>()
@@ -66,6 +67,25 @@ abstract class GooglePlaySdkIndex(cacheDir: Path? = null) : NetworkCache(
initialize(null)
}
+ private fun readIndexData(readFunction: () -> InputStream?): ReadDataResult {
+ var readDataErrorType = ReadDataErrorType.DATA_FUNCTION_EXCEPTION
+ try {
+ val rawData = readFunction.invoke()
+ if (rawData != null) {
+ readDataErrorType = ReadDataErrorType.GZIP_EXCEPTION
+ val gzipData = GZIPInputStream(rawData)
+ readDataErrorType = ReadDataErrorType.INDEX_PARSE_EXCEPTION
+ val index = Index.parseFrom(gzipData)
+ readDataErrorType = if (index != null) ReadDataErrorType.NO_ERROR else ReadDataErrorType.INDEX_PARSE_NULL_ERROR
+ return ReadDataResult(index, readDataErrorType, exception = null)
+ }
+ }
+ catch (exception: Exception) {
+ return ReadDataResult(index = null, readDataErrorType, exception)
+ }
+ return ReadDataResult(index = null, readDataErrorType = ReadDataErrorType.DATA_FUNCTION_NULL_ERROR, exception = null)
+ }
+
@VisibleForTesting
fun initialize(overriddenData: InputStream? = null) {
synchronized(this) {
@@ -76,27 +96,45 @@ abstract class GooglePlaySdkIndex(cacheDir: Path? = null) : NetworkCache(
status = GooglePlaySdkIndexStatus.NOT_READY
}
var index: Index? = null
+ val indexDataSource: DataSourceType
// Read from cache/network
if (overriddenData != null) {
// Do not check for exceptions, calling from a test
+ lastReadSourceType = DataSourceType.TEST_DATA
+ indexDataSource = lastReadSourceType
index = Index.parseFrom(overriddenData)
- } else {
- try {
- index = Index.parseFrom(GZIPInputStream(findData(GOOGLE_PLAY_SDK_INDEX_SNAPSHOT_FILE)))
- } catch (exception: Exception) {
- val message = if (exception.message.isNullOrEmpty()) exception.toString() else exception.message
- logCachingError(message)
- try {
- index = Index.parseFrom(GZIPInputStream(readDefaultData(GOOGLE_PLAY_SDK_INDEX_SNAPSHOT_RESOURCE)))
- } catch (defaultException: Exception) {
- logErrorInDefaultData(defaultException.message)
+ }
+ else {
+ lastReadResult = readIndexData { findData(GOOGLE_PLAY_SDK_INDEX_SNAPSHOT_FILE) }
+ if (lastReadResult.index != null) {
+ // Using data from cache
+ indexDataSource = lastReadSourceType
+ index = lastReadResult.index
+ }
+ else {
+ if (lastReadSourceType != DataSourceType.DEFAULT_DATA) {
+ lastReadSourceType = DataSourceType.UNKNOWN_SOURCE
+ val offlineResult = readIndexData {
+ readDefaultData(GOOGLE_PLAY_SDK_INDEX_SNAPSHOT_RESOURCE)
+ }
+ if (offlineResult.index != null) {
+ indexDataSource = DataSourceType.DEFAULT_DATA
+ index = offlineResult.index
+ } else {
+ indexDataSource = DataSourceType.UNKNOWN_SOURCE
+ logErrorInDefaultData(offlineResult)
+ }
+ }
+ else {
+ indexDataSource = DataSourceType.UNKNOWN_SOURCE
+ logErrorInDefaultData(lastReadResult)
}
}
}
if (index != null) {
setMaps(index)
status = GooglePlaySdkIndexStatus.READY
- logIndexLoadedCorrectly()
+ logIndexLoadedCorrectly(indexDataSource)
}
}
@@ -259,10 +297,13 @@ abstract class GooglePlaySdkIndex(cacheDir: Path? = null) : NetworkCache(
}
override fun readDefaultData(relative: String): InputStream? {
- if (GOOGLE_PLAY_SDK_INDEX_SNAPSHOT_RESOURCE == relative) {
- return GooglePlaySdkIndex::class.java.getResourceAsStream("/$GOOGLE_PLAY_SDK_INDEX_SNAPSHOT_RESOURCE")
+ // This function is called only if there were errors while reading the cached data, log that error if the previous source was known
+ if (lastReadSourceType != DataSourceType.UNKNOWN_SOURCE) {
+ // Log reason for not being able to use cached file
+ logCachingError(lastReadResult, lastReadSourceType)
}
- return null
+ // We only have a single file, return it no matter what relative string is used
+ return GooglePlaySdkIndex::class.java.getResourceAsStream("/$GOOGLE_PLAY_SDK_INDEX_SNAPSHOT_RESOURCE")
}
/**
@@ -325,12 +366,31 @@ abstract class GooglePlaySdkIndex(cacheDir: Path? = null) : NetworkCache(
protected open fun logOutdated(groupId: String, artifactId: String, versionString: String, file: File?) {
}
- protected open fun logCachingError(message: String?) {
+ protected open fun logCachingError(readResult: ReadDataResult, dataSourceType: DataSourceType) {
+ }
+
+ protected open fun logErrorInDefaultData(readResult: ReadDataResult) {
}
- protected open fun logErrorInDefaultData(message: String?) {
+ protected open fun logIndexLoadedCorrectly(dataSourceType: DataSourceType) {
}
- protected open fun logIndexLoadedCorrectly() {
+ protected enum class ReadDataErrorType {
+ NO_ERROR,
+ // Function used to get the data caused an exception
+ DATA_FUNCTION_EXCEPTION,
+ // Function used to get the data returned null
+ DATA_FUNCTION_NULL_ERROR,
+ // There was an exception while decompressing the raw data
+ GZIP_EXCEPTION,
+ // Exception while parsing decompressed data
+ INDEX_PARSE_EXCEPTION,
+ // Resulted Index was null after parsing
+ INDEX_PARSE_NULL_ERROR,;
}
+
+ protected class ReadDataResult(val index: Index?, val readDataErrorType: ReadDataErrorType, val exception: Exception?)
+
+ @VisibleForTesting
+ fun getLastReadSource() = lastReadSourceType
}
diff --git a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/GradleDetector.kt b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/GradleDetector.kt
index 40afd231ce..992e9d6b32 100644
--- a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/GradleDetector.kt
+++ b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/GradleDetector.kt
@@ -1061,7 +1061,13 @@ open class GradleDetector : Detector(), GradleScanner {
if (newerVersion != null && version > GradleVersion(0, 0, 0) && newerVersion > version) {
val versionString = newerVersion.toString()
- val message = getNewerVersionAvailableMessage(dependency, versionString, null)
+ val message = if (dependency.groupId == "androidx.slidingpanelayout" && dependency.artifactId == "slidingpanelayout") {
+ "Upgrade `androidx.slidingpanelayout` for keyboard and mouse support"
+ } else if (dependency.groupId == "androidx.compose.foundation" && dependency.artifactId == "foundation") {
+ "Upgrade `androidx.compose.foundation` for keyboard and mouse support"
+ } else {
+ getNewerVersionAvailableMessage(dependency, versionString, null)
+ }
val fix = if (!isResolved) getUpdateDependencyFix(revision, versionString) else null
report(context, cookie, issue, message, fix)
}
diff --git a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/PluralsDetector.kt b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/PluralsDetector.kt
index 402aebe6f1..0accd2f927 100644
--- a/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/PluralsDetector.kt
+++ b/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/PluralsDetector.kt
@@ -24,6 +24,7 @@ import com.android.tools.lint.checks.PluralsDatabase.Quantity
import com.android.tools.lint.checks.TranslationDetector.Companion.getLanguageDescription
import com.android.tools.lint.detector.api.Category
import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Incident
import com.android.tools.lint.detector.api.Issue.Companion.create
import com.android.tools.lint.detector.api.ResourceXmlDetector
import com.android.tools.lint.detector.api.Scope
@@ -121,21 +122,24 @@ class PluralsDetector : ResourceXmlDetector() {
if (!missing.isEmpty()) {
val examplesLookup = PluralExamplesLookup.getInstance()
val withExamples = missing.map { form ->
- val example = examplesLookup.findExample(language, form.name)
- form to example?.formattedWithNumber()
- }.map { (form, example) ->
+ val example = examplesLookup.findExample(language, form.name)?.formattedWithNumber()
if (example != null) {
"`${form.name}` (e.g. \"$example\")"
} else {
"`${form.name}`"
}
}
+ val languageDescription = getLanguageDescription(language)
val message = if (withExamples.size == 1) {
- "For locale ${getLanguageDescription(language)} the following quantity should also be defined: ${withExamples.single()}"
+ "For locale $languageDescription the following quantity should also be defined: ${withExamples.single()}"
} else {
- "For locale ${getLanguageDescription(language)} the following quantities should also be defined: ${withExamples.joinToString(", ")}"
+ "For locale $languageDescription the following quantities should also be defined: ${withExamples.joinToString(", ")}"
}
- context.report(MISSING, element, context.getLocation(element), message)
+ val incident = Incident(MISSING, element, context.getLocation(element), message)
+ if (NEW_PLURAL_FORMS.containsKey(language) && missing.singleOrNull() == NEW_PLURAL_FORMS[language]) {
+ incident.overrideSeverity(Severity.WARNING)
+ }
+ context.report(incident)
}
// Look for irrelevant
@@ -157,6 +161,15 @@ class PluralsDetector : ResourceXmlDetector() {
)
/**
+ * For these languages and plural forms, issue a warning as opposed to an error, since they have been recently
+ * added in the database. Will be removed once [PluralsDatabase] has a diff table for handling successive versions
+ * of the ICU database (i.e. version 40 and above).
+ */
+ private val NEW_PLURAL_FORMS = mapOf(
+ "fr" to Quantity.many
+ )
+
+ /**
* This locale should define a quantity string for the given
* quantity
*/
diff --git a/lint/libs/lint-checks/src/main/resources/sdk-index-offline-snapshot.proto.gz b/lint/libs/lint-checks/src/main/resources/sdk-index-offline-snapshot.proto.gz
index 9c3268f0f6..5844c15531 100644
--- a/lint/libs/lint-checks/src/main/resources/sdk-index-offline-snapshot.proto.gz
+++ b/lint/libs/lint-checks/src/main/resources/sdk-index-offline-snapshot.proto.gz
Binary files differ
diff --git a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/LintFixPerformerTest.kt b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/LintFixPerformerTest.kt
index f21c954e12..b17d9dfb29 100644
--- a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/LintFixPerformerTest.kt
+++ b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/LintFixPerformerTest.kt
@@ -42,7 +42,8 @@ class LintFixPerformerTest : TestCase() {
vararg fixes: LintFix,
expected: String,
expectedOutput: String? = null,
- expectedFailure: String? = null
+ expectedFailure: String? = null,
+ includeMarkers: Boolean = false
) {
val client = TestLintClient()
for (fix in fixes) {
@@ -51,7 +52,7 @@ class LintFixPerformerTest : TestCase() {
var after: String = source
var output = ""
val printStatistics = expectedOutput != null
- val performer = object : LintFixPerformer(client, printStatistics) {
+ val performer = object : LintFixPerformer(client, printStatistics, includeMarkers = includeMarkers) {
override fun writeFile(pendingFile: PendingEditFile, contents: String) {
after = contents
}
@@ -408,4 +409,47 @@ class LintFixPerformerTest : TestCase() {
sorted.toString()
)
}
+
+ fun testShortenNames() {
+ // Regression test for b/https://issuetracker.google.com/241573146
+ val file = File("Test.java")
+ @Language("java")
+ val source =
+ """
+ package test.pkg;
+ import android.graphics.drawable.Drawable;
+ import android.graphics.Outline;
+
+ class Test {
+ static void getOutline() {
+ }
+ }
+ """.trimIndent()
+
+ val range = Location.create(file, source, 0, source.length)
+ val fix =
+ fix().replace()
+ .text("()")
+ .with("(android.graphics.drawable.Drawable drawable, android.graphics.Outline outline)")
+ .shortenNames()
+ .autoFix()
+ .range(range)
+ .build()
+ check(
+ file, source, fix,
+ expected =
+ """
+ package test.pkg;
+ import android.graphics.drawable.Drawable;
+ import android.graphics.Outline;
+
+ class Test {
+ static void getOutline(Drawable drawable, Outline outline) {
+ }
+ }
+ """,
+ expectedOutput = "Applied 1 edits across 1 files for this fix: Replace with (android.graphics.drawable.Drawable drawable, android.graphics.Outline outline)",
+ includeMarkers = true
+ )
+ }
}
diff --git a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/CheckResultDetectorTest.kt b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/CheckResultDetectorTest.kt
index 8dc665c58f..314c3be162 100644
--- a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/CheckResultDetectorTest.kt
+++ b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/CheckResultDetectorTest.kt
@@ -1656,7 +1656,7 @@ class CheckResultDetectorTest : AbstractCheckTest() {
public Object getLock() { return Api.class; }
public void test() {
synchronized (getLock()) {
- println("Test");
+ System.out.println("Test");
}
}
}
@@ -1675,6 +1675,47 @@ class CheckResultDetectorTest : AbstractCheckTest() {
).run().expectClean()
}
+ fun testSynchronizedUnused() {
+ // 242305422: CheckResultDetector allows unused results in Java synchronized expressions.
+ lint().files(
+ java(
+ """
+ import androidx.annotation.CheckResult;
+ public class Api {
+ @CheckResult
+ public Object getLock() { return Api.class; }
+ public void test() {
+ synchronized (getLock()) {
+ getLock(); // ERROR
+ System.out.println("test");
+ }
+ }
+ }
+ """
+ ).indented(),
+ kotlin(
+ """
+ class Api2 : Api() {
+ fun test2() {
+ synchronized(getLock()) { getLock(); println("test") } // ERROR
+ }
+ }
+ """
+ ).indented(),
+ SUPPORT_ANNOTATIONS_JAR
+ ).run().expect(
+ """
+ src/Api.java:7: Warning: The result of getLock is not used [CheckResult]
+ getLock(); // ERROR
+ ~~~~~~~~~
+ src/Api2.kt:3: Warning: The result of getLock is not used [CheckResult]
+ synchronized(getLock()) { getLock(); println("test") } // ERROR
+ ~~~~~~~~~
+ 0 errors, 2 warnings
+ """
+ )
+ }
+
fun testKotlinTest() {
lint().files(
kotlin(
diff --git a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/DeprecationDetectorTest.kt b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/DeprecationDetectorTest.kt
index 3bd0495236..03a64dc7af 100644
--- a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/DeprecationDetectorTest.kt
+++ b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/DeprecationDetectorTest.kt
@@ -460,4 +460,42 @@ class DeprecationDetectorTest : AbstractCheckTest() {
"""
)
}
+
+ fun testSharedUserId() {
+ // Regression test for issue 233388117
+ lint().files(
+ manifest(
+ """
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.pkg"
+ android:sharedUserId="0"
+ android:sharedUserMaxSdkVersion="32">
+ </manifest>
+ """
+ ).indented(),
+ manifest(
+ """
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.pkg"
+ android:sharedUserId="0">
+ </manifest>
+ """
+ ).to("../app/AndroidManifest.xml")
+ ).run().expect(
+ """
+ AndroidManifest.xml:4: Warning: Consider removing sharedUserId for new users by adding android:sharedUserMaxSdkVersion="32" to your manifest. See https://developer.android.com/guide/topics/manifest/manifest-element for details. [Deprecated]
+ android:sharedUserId="0">
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ 0 errors, 1 warnings
+ """
+ ).expectFixDiffs(
+ """
+ Fix for AndroidManifest.xml line 4: Set sharedUserMaxSdkVersion="32":
+ @@ -4 +4
+ - android:sharedUserId="0" >
+ + android:sharedUserId="0"
+ + android:sharedUserMaxSdkVersion="32" >
+ """
+ )
+ }
}
diff --git a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/GooglePlaySdkIndexTest.kt b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/GooglePlaySdkIndexTest.kt
index 950fd8af68..561f888c40 100644
--- a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/GooglePlaySdkIndexTest.kt
+++ b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/GooglePlaySdkIndexTest.kt
@@ -15,6 +15,7 @@
*/
package com.android.tools.lint.checks
+import com.android.ide.common.repository.NetworkCache
import com.android.tools.lint.detector.api.LintFix
import com.google.common.truth.Truth.assertThat
import org.junit.Assert.fail
@@ -150,6 +151,7 @@ class GooglePlaySdkIndexTest {
}
}
index.initialize(ByteArrayInputStream(proto.toByteArray()))
+ assertThat(index.getLastReadSource()).isEqualTo(NetworkCache.DataSourceType.TEST_DATA)
}
@Test
@@ -235,6 +237,21 @@ class GooglePlaySdkIndexTest {
}
}
+ @Test
+ fun `offline snapshot can be used correctly`() {
+ val offlineIndex = object : GooglePlaySdkIndex() {
+ override fun readUrlData(url: String, timeout: Int): ByteArray? {
+ return null
+ }
+
+ override fun error(throwable: Throwable, message: String?) {
+ }
+ }
+ offlineIndex.initialize()
+ assertThat(offlineIndex.isReady()).isTrue()
+ assertThat(offlineIndex.getLastReadSource()).isEqualTo(NetworkCache.DataSourceType.DEFAULT_DATA)
+ }
+
private fun hasOutdatedIssues(): Boolean {
for (sdk in proto.sdksList) {
for (library in sdk.librariesList) {
diff --git a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/GradleDetectorTest.kt b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/GradleDetectorTest.kt
index 57a147320c..844ed42e15 100644
--- a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/GradleDetectorTest.kt
+++ b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/GradleDetectorTest.kt
@@ -507,7 +507,6 @@ class GradleDetectorTest : AbstractCheckTest() {
"""
)
}
-
fun testSnapshots() {
// Regression test for b/183137869:
// Gradle special-cases the SNAPSHOT version; make sure we don't offer updates to/from it except
@@ -1083,6 +1082,51 @@ class GradleDetectorTest : AbstractCheckTest() {
).issues(DEPENDENCY).run().expect(expected)
}
+ fun testLargeScreenIncorrectDependencies() {
+ val expected = "build.gradle:9: Warning: Upgrade androidx.slidingpanelayout for keyboard and mouse support [GradleDependency]\n" +
+ " compile 'androidx.slidingpanelayout:slidingpanelayout:1.1.0'\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "build.gradle:10: Warning: Upgrade androidx.compose.foundation for keyboard and mouse support [GradleDependency]\n" +
+ " compile 'androidx.compose.foundation:foundation:1.1.1'\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 2 warnings"
+ lint().files(
+ gradle(
+ "" +
+ "apply plugin: 'com.android.application'\n" +
+ "\n" +
+ "android {\n" +
+ " compileSdkVersion 21\n" +
+ " buildToolsVersion \"21.1.2\"\n" +
+ "}\n" +
+ "\n" +
+ "dependencies {\n" +
+ " compile 'androidx.slidingpanelayout:slidingpanelayout:1.1.0'\n" +
+ " compile 'androidx.compose.foundation:foundation:1.1.1'\n" +
+ "}\n"
+ )
+ ).issues(DEPENDENCY).run().expect(expected)
+ }
+
+ fun testLargeScreenCorrectDependencies() {
+ lint().files(
+ gradle(
+ "" +
+ "apply plugin: 'com.android.application'\n" +
+ "\n" +
+ "android {\n" +
+ " compileSdkVersion 21\n" +
+ " buildToolsVersion \"21.1.2\"\n" +
+ "}\n" +
+ "\n" +
+ "dependencies {\n" +
+ " compile 'androidx.slidingpanelayout:slidingpanelayout:1.2'\n" +
+ " compile 'androidx.compose.foundation:foundation:1.2.1'\n" +
+ "}\n"
+ )
+ ).issues(DEPENDENCY).run().expectClean()
+ }
+
fun testDependenciesMinSdkVersion() {
lint().files(
gradle(
@@ -4443,7 +4487,9 @@ class GradleDetectorTest : AbstractCheckTest() {
// SDK distributed via Maven
"caches/modules-2/files-2.1/com.android.support/recyclerview-v7/26.0.0/sample",
- "caches/modules-2/files-2.1/com.google.firebase/firebase-messaging/11.0.0/sample"
+ "caches/modules-2/files-2.1/com.google.firebase/firebase-messaging/11.0.0/sample",
+ "caches/modules-2/files-2.1/androidx.slidingpanelayout/slidingpanelayout/1.2.0/sample",
+ "caches/modules-2/files-2.1/androidx.compose.foundation/foundation/1.2.1/sample"
)
)
}
@@ -4464,6 +4510,8 @@ class GradleDetectorTest : AbstractCheckTest() {
<com.google.android.gms/>
<com.google.android.support/>
<androidx.core/>
+ <androidx.slidingpanelayout/>
+ <androidx.compose/>
</metadata>
""".trimIndent()
)
@@ -4540,6 +4588,24 @@ class GradleDetectorTest : AbstractCheckTest() {
</androidx.core>
""".trimIndent()
)
+ task.networkData(
+ "https://maven.google.com/androidx/slidingpanelayout/group-index.xml",
+ """
+ <?xml version="1.0" encoding="UTF-8"?>
+ <androidx.slidingpanelayout>
+ <slidingpanelayout versions="1.1.0", "1.2.0"/>
+ </androidx.slidingpanelayout>
+ """.trimIndent()
+ )
+ task.networkData(
+ "https://maven.google.com/androidx/compose/foundation/group-index.xml",
+ """
+ <?xml version="1.0" encoding="UTF-8"?>
+ <androidx.compose.foundation>
+ <foundation versions="1.1.0", "1.2.0"/>
+ </androidx.compose.foundation>
+ """.trimIndent()
+ )
// Similarly set up the expected SDK Index network output from dl.google.com to
// ensure stable SDK library suggestions in the tests
diff --git a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/PluralsDetectorTest.java b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/PluralsDetectorTest.java
index 043815a9f1..e6eec9a303 100644
--- a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/PluralsDetectorTest.java
+++ b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/PluralsDetectorTest.java
@@ -42,10 +42,10 @@ public class PluralsDetectorTest extends AbstractCheckTest {
public void test2() {
String expected =
""
- + "res/values-fr/plurals.xml:3: Error: For locale \"fr\" (French) the following quantity should also be defined: many (e.g. \"1000000 de jours\") [MissingQuantity]\n"
+ + "res/values-cs/plurals3.xml:3: Error: For locale \"cs\" (Czech) the following quantities should also be defined: few (e.g. \"2 dny\"), many (e.g. \"10.0 dne\") [MissingQuantity]\n"
+ " <plurals name=\"draft\">\n"
+ " ^\n"
- + "res/values-cs/plurals3.xml:3: Error: For locale \"cs\" (Czech) the following quantities should also be defined: few (e.g. \"2 dny\"), many (e.g. \"10.0 dne\") [MissingQuantity]\n"
+ + "res/values-fr/plurals.xml:3: Warning: For locale \"fr\" (French) the following quantity should also be defined: many (e.g. \"1000000 de jours\") [MissingQuantity]\n"
+ " <plurals name=\"draft\">\n"
+ " ^\n"
+ "res/values-zh-rCN/plurals3.xml:3: Warning: For language \"zh\" (Chinese) the following quantities are not relevant: one [UnusedQuantity]\n"
@@ -54,7 +54,7 @@ public class PluralsDetectorTest extends AbstractCheckTest {
+ "res/values-zh-rCN/plurals3.xml:7: Warning: For language \"zh\" (Chinese) the following quantities are not relevant: one [UnusedQuantity]\n"
+ " <plurals name=\"title_day_dialog_content\">\n"
+ " ^\n"
- + "2 errors, 2 warnings\n";
+ + "1 errors, 3 warnings";
lint().files(
xml(
"res/values-zh-rCN/plurals3.xml",
@@ -176,6 +176,47 @@ public class PluralsDetectorTest extends AbstractCheckTest {
.expectClean();
}
+ public void testFrenchMany() {
+ lint().files(
+ xml(
+ "res/values-fr/plurals.xml",
+ ""
+ + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ + "<resources>\n"
+ + " <plurals name=\"draft\">\n"
+ + " <item quantity=\"one\">\"brouillon\"</item>\n"
+ + " <item quantity=\"other\">\"brouillons\"</item>\n"
+ + " </plurals>\n"
+ + "</resources>\n"))
+ .issues(PluralsDetector.MISSING)
+ .run()
+ .expect(
+ "res/values-fr/plurals.xml:3: Warning: For locale \"fr\" (French) the following quantity should also be defined: many (e.g. \"1000000 de jours\") [MissingQuantity]\n"
+ + " <plurals name=\"draft\">\n"
+ + " ^\n"
+ + "0 errors, 1 warnings");
+ }
+
+ public void testFrenchOtherAndMany() {
+ lint().files(
+ xml(
+ "res/values-fr/plurals.xml",
+ ""
+ + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ + "<resources>\n"
+ + " <plurals name=\"draft\">\n"
+ + " <item quantity=\"one\">\"brouillon\"</item>\n"
+ + " </plurals>\n"
+ + "</resources>\n"))
+ .issues(PluralsDetector.MISSING)
+ .run()
+ .expect(
+ "res/values-fr/plurals.xml:3: Warning: For locale \"fr\" (French) the following quantity should also be defined: many (e.g. \"1000000 de jours\") [MissingQuantity]\n"
+ + " <plurals name=\"draft\">\n"
+ + " ^\n"
+ + "0 errors, 1 warnings");
+ }
+
public void testImpliedQuantity() {
String expected =
""
diff --git a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/SdCardDetectorTest.java b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/SdCardDetectorTest.java
index 300c7d6352..4835a81c18 100644
--- a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/SdCardDetectorTest.java
+++ b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/SdCardDetectorTest.java
@@ -16,7 +16,9 @@
package com.android.tools.lint.checks;
+import com.android.tools.lint.checks.infrastructure.TestMode;
import com.android.tools.lint.detector.api.Detector;
+import com.intellij.openapi.util.io.FileUtilRt;
import org.intellij.lang.annotations.Language;
@SuppressWarnings({"javadoc", "ClassNameDiffersFromFileName"})
@@ -545,8 +547,10 @@ public class SdCardDetectorTest extends AbstractCheckTest {
// We've recently removed the large file limit (look for PersistentFSConstants)
public void testLargeFiles() {
- int max = 2600 * 1024;
- StringBuilder large = new StringBuilder(max + 100); // default is 2500
+ // default user file size limit = 2500 KiB
+ // default user content load limit = 20000 KiB
+ int max = Math.max(FileUtilRt.getUserFileSizeLimit(), FileUtilRt.getUserContentLoadLimit());
+ StringBuilder large = new StringBuilder(max + 100);
large.append("package test.pkg;\nclass VeryLarge {\n");
for (int i = 0; i < max; i++) {
large.append(' ');
@@ -559,24 +563,23 @@ public class SdCardDetectorTest extends AbstractCheckTest {
lint().files(java("src/test/pkg/VeryLarge.java", javaSource))
.allowSystemErrors(true)
.allowCompilationErrors()
+ .testModes(TestMode.DEFAULT)
.run()
- /* We've recently removed the large file limit (look for PersistentFSConstants
- references)
- .expect("src/test/pkg/VeryLarge.java: Error: Source file too large for lint to " +
- "process (2600KB); the current max size is 2560000KB. You can increase " +
- "the limit by setting this system property: " +
- "idea.max.intellisense.filesize=4096 (or even higher) [LintError]\n" +
- "1 errors, 0 warnings\n");
- */
- .expectClean();
+ .expect(
+ "src/test/pkg/VeryLarge.java: Error: Source file too large for lint to "
+ + "process (20480KB); the current max size is 20480KB. You can increase "
+ + "the limit by setting this system property: "
+ + "idea.max.intellisense.filesize=32768 (or even higher) [LintError]\n"
+ + "1 errors, 0 warnings\n");
// Bump up the file limit and make sure it no longer complains!
- String prev = System.getProperty("idea.max.intellisense.filesize");
+ String prev = System.getProperty(IDEA_MAX_INTELLISENSE_FILESIZE);
try {
- System.setProperty(IDEA_MAX_INTELLISENSE_FILESIZE, "4096");
+ System.setProperty(IDEA_MAX_INTELLISENSE_FILESIZE, Integer.toString(max + 1024));
lint().files(java("src/test/pkg/VeryLarge.java", javaSource))
.allowSystemErrors(true)
.allowCompilationErrors()
+ .testModes(TestMode.DEFAULT)
.run()
.expectClean();
} finally {
diff --git a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/infrastructure/SuppressLintTest.kt b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/infrastructure/SuppressLintTest.kt
index 79ef3d4724..f094418f73 100644
--- a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/infrastructure/SuppressLintTest.kt
+++ b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/infrastructure/SuppressLintTest.kt
@@ -30,10 +30,14 @@ import com.android.tools.lint.detector.api.Issue
import com.android.tools.lint.detector.api.JavaContext
import com.android.tools.lint.detector.api.Scope
import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import com.android.tools.lint.detector.api.XmlContext
+import com.android.tools.lint.detector.api.XmlScanner
import com.intellij.psi.PsiMethod
import org.jetbrains.uast.UCallExpression
import org.jetbrains.uast.UImportStatement
import org.junit.Test
+import org.w3c.dom.Attr
/**
* Checks that some lint checks cannot be suppressed with the normal
@@ -95,6 +99,7 @@ class SuppressLintTest {
import forbidden;
@MyOwnAnnotation
class Test {
+ @SuppressWarnings("InfiniteRecursion")
public void forbidden() {
forbidden();
}
@@ -191,6 +196,80 @@ class SuppressLintTest {
}
@Test
+ fun checkForbiddenSuppressWithXmlIgnore() {
+ lint()
+ .allowCompilationErrors()
+ .files(
+ xml(
+ "res/layout/main.xml",
+ """
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ xmlns:tools="http://schemas.android.com/tools"
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <androidx.compose.ui.platform.ComposeView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:forbidden="true"
+ tools:ignore="_SecureIssue"/>
+ </LinearLayout>
+ """
+ ).indented()
+ )
+ .issues(MySecurityDetector.TEST_ISSUE)
+ .sdkHome(TestUtils.getSdk().toFile())
+ .run()
+ .expect(
+ """
+ res/layout/main.xml:7: Error: Issue _SecureIssue is not allowed to be suppressed [LintError]
+ <androidx.compose.ui.platform.ComposeView
+ ^
+ res/layout/main.xml:10: Warning: Some error message here [_SecureIssue]
+ android:forbidden="true"
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ 1 errors, 1 warnings
+ """
+ )
+ }
+
+ @Test
+ fun checkForbiddenSuppressWithXmlComment() {
+ lint()
+ .allowCompilationErrors()
+ .files(
+ xml(
+ "res/layout/main.xml",
+ """
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <!--suppress _SecureIssue -->
+ <androidx.compose.ui.platform.ComposeView android:forbidden="true"/>
+ </LinearLayout>
+ """
+ ).indented()
+ )
+ .issues(MySecurityDetector.TEST_ISSUE)
+ .sdkHome(TestUtils.getSdk().toFile())
+ .run()
+ .expect(
+ """
+ res/layout/main.xml:7: Error: Issue _SecureIssue is not allowed to be suppressed [LintError]
+ <androidx.compose.ui.platform.ComposeView android:forbidden="true"/>
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ res/layout/main.xml:7: Warning: Some error message here [_SecureIssue]
+ <androidx.compose.ui.platform.ComposeView android:forbidden="true"/>
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ 1 errors, 1 warnings
+ """
+ )
+ }
+
+ @Test
fun checkForbiddenSuppressWithLintXml() {
lint()
.allowCompilationErrors()
@@ -451,7 +530,7 @@ class SuppressLintTest {
// Sample detector which just flags calls to a method called "forbidden"
@SuppressWarnings("ALL")
- class MySecurityDetector : Detector(), Detector.UastScanner {
+ class MySecurityDetector : Detector(), SourceCodeScanner, XmlScanner {
override fun getApplicableUastTypes() = listOf(UImportStatement::class.java)
override fun getApplicableMethodNames(): List<String> {
@@ -483,6 +562,15 @@ class SuppressLintTest {
}
}
+ override fun getApplicableAttributes(): Collection<String> = listOf("forbidden")
+
+ override fun visitAttribute(context: XmlContext, attribute: Attr) {
+ val message = "Some error message here"
+ val location = context.getLocation(attribute)
+ context.report(TEST_ISSUE, attribute, location, message)
+ context.report(TEST_ISSUE_NEVER_SUPPRESSIBLE, attribute, location, message)
+ }
+
companion object {
@Suppress("SpellCheckingInspection")
@JvmField
@@ -494,7 +582,7 @@ class SuppressLintTest {
suppressAnnotations = listOf("foo.bar.MyOwnAnnotation"),
implementation = Implementation(
MySecurityDetector::class.java,
- Scope.JAVA_FILE_SCOPE
+ Scope.JAVA_AND_RESOURCE_FILES
)
)
@@ -510,7 +598,7 @@ class SuppressLintTest {
suppressAnnotations = emptyList(),
implementation = Implementation(
MySecurityDetector::class.java,
- Scope.JAVA_FILE_SCOPE
+ Scope.JAVA_AND_RESOURCE_FILES
)
)
}
diff --git a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/client/api/JarFileIssueRegistryTest.kt b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/client/api/JarFileIssueRegistryTest.kt
index a965ce2d17..da2cff9467 100644
--- a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/client/api/JarFileIssueRegistryTest.kt
+++ b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/client/api/JarFileIssueRegistryTest.kt
@@ -441,32 +441,7 @@ class JarFileIssueRegistryTest : AbstractCheckTest() {
.allowObsoleteLintChecks(false)
.issueIds("MyIssueId")
.run()
- .expectContains(
- """
- lint.jar: Warning: Lint found an issue registry (test.pkg.MyIssueRegistry)
- which contains code in some of lint's reserved packages.
-
- This is usually because the lint jar has accidentally
- packed in libraries that are part of lint's API surface,
- such as the Kotlin standard library (kotlin.*), or
- some of the Android tooling libraries (com.android.*)
- including lint's own API jars, or some of the third party
- libraries that lint depends on, such as UAST.
- If you need these and cannot rely on the ones provided
- in lint's runtime environment, consider `jarjar`ing your
- own versions.
-
- A second reason is one where you've accidentally placed
- your own detector code into one of these package
- namespaces, since they are pretty broad (com.android.*).
- For Android specifically, you can place them under
- com.android.internal.* which is explicitly allowed.
-
- The first bundled package that is part of lint's API
- surface namespace is:
- com.android.something [ObsoleteLintCustomCheck]
- 0 errors, 1 warnings"""
- )
+ .expectClean()
}
fun testNewerLintBroken() {
diff --git a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/client/api/LintJarVerifierTest.kt b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/client/api/LintJarVerifierTest.kt
index 15dbfdd67e..bea7987aa1 100644
--- a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/client/api/LintJarVerifierTest.kt
+++ b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/client/api/LintJarVerifierTest.kt
@@ -138,48 +138,6 @@ class LintJarVerifierTest {
}
@Test
- fun testPackagedDeps() {
- val projects = lint().files(
- compiled(
- "lint.jar",
- kotlin(
- """
- package com.android.lint.mycheck
-
- // Not implementing real lint APIs here, just
- // including data in a suspicious package
- class MyDetector
- """
- ).indented(),
- 0x6db3a5a1,
- """
- META-INF/main.kotlin_module:
- H4sIAAAAAAAAAGNgYGBmYGBgBGJWKM2gxKDFAABNj30wGAAAAA==
- """,
- """
- com/android/lint/mycheck/MyDetector.class:
- H4sIAAAAAAAAAI1Ru0oDQRQ9d2I2ukYT3/GBjQhq4arYKYIPhEBUUEmTarI7
- mEmyM7A7Ee3yLf6BlWAhwdKPEu/GgK1THM5juI+Zr+/3DwCHWCNshDYOpIkS
- q6Ogq40L4uewpcJOcPV8oZwKnU0KIEK5LR9l0JXmIbhpttkvIEfwjrXR7oSQ
- 29quF5GH52MMBcKYa+mUsFn7R/0jwkytYx3HwZVyMpJOsifixxyPSRnkCdRh
- 60lnao9ZtE9YH/R9X1SEL8rMBv3KoH8g9ugs//niibLIbh0QV8DUX7PdjuPp
- zm2kCKWaNuq6FzdVci+bXXZmazaU3bpMdKZHpn9ne0moLnUmlm97xulY1XWq
- OT01xjrptDUp9iF4+ezwtNlbMC6xCoaal9h5w/grE4EKo/drYpmxOOIT8If5
- yhAXsTr8J8IkZ8UGclVMVTHNiFIG5SpmMNsApZjDPOcp/BQLKbwfJ1hjDeQB
- AAA=
- """
- )
- ).createProjects(temporaryFolder.newFolder())
-
- assertEquals(1, projects.size)
- val jar = File(projects[0], "lint.jar")
- assertTrue(jar.isFile)
- val verifier = LintJarVerifier(jar)
- assertTrue(verifier.hasPackageConflict())
- assertEquals("com.android.lint.mycheck", verifier.describeFirstPackagedDependency())
- }
-
- @Test
fun checkMavenJars() {
// This test downloads ALL the AAR files on maven.google.com and verifies
// any lint.jar files found within!
diff --git a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/detector/api/VersionChecksTest.kt b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/detector/api/VersionChecksTest.kt
index 40ee02922d..a2a1fe0625 100644
--- a/lint/libs/lint-tests/src/test/java/com/android/tools/lint/detector/api/VersionChecksTest.kt
+++ b/lint/libs/lint-tests/src/test/java/com/android/tools/lint/detector/api/VersionChecksTest.kt
@@ -2321,10 +2321,10 @@ class VersionChecksTest : AbstractCheckTest() {
import android.os.Build.VERSION_CODES.N
import android.text.Html
- fun String.fromHtm() : String
+ fun String.fromHtml() : String
{
return when {
- false, SDK_INT >= N -> Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY)
+ SDK_INT >= N -> Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY)
else -> Html.fromHtml(this)
}.toString()
}"""
@@ -2332,6 +2332,48 @@ class VersionChecksTest : AbstractCheckTest() {
).run().expectClean()
}
+ fun testKotlinWhenStatement_logicalOperatorsWithConstants() {
+ // Regression test for
+ // 242479753: false positives when logical operators and constants are combined
+ lint().files(
+ manifest().minSdk(4),
+ kotlin(
+ """
+ import android.os.Build.VERSION.SDK_INT
+ import android.os.Build.VERSION_CODES.N
+ import android.text.Html
+
+ fun String.fromHtml() : String
+ {
+ return when {
+ false || SDK_INT >= N -> Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY)
+ true || SDK_INT >= N -> Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY)
+ false && SDK_INT >= N -> Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY)
+ true && SDK_INT >= N -> Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY)
+ else -> Html.fromHtml(this)
+ }.toString()
+ }"""
+ ).indented()
+ ).run().expect(
+ """
+ src/test.kt:8: Warning: Field requires API level 24 (current min is 4): android.text.Html#FROM_HTML_MODE_LEGACY [InlinedApi]
+ false || SDK_INT >= N -> Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ src/test.kt:9: Warning: Field requires API level 24 (current min is 4): android.text.Html#FROM_HTML_MODE_LEGACY [InlinedApi]
+ true || SDK_INT >= N -> Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ src/test.kt:8: Error: Call requires API level 24 (current min is 4): android.text.Html#fromHtml [NewApi]
+ false || SDK_INT >= N -> Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY)
+ ~~~~~~~~
+ src/test.kt:9: Error: Call requires API level 24 (current min is 4): android.text.Html#fromHtml [NewApi]
+ true || SDK_INT >= N -> Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY)
+ ~~~~~~~~
+ 2 errors, 2 warnings
+ """
+ )
+ //.expectClean() // Should be same as [testKotlinWhenStatement]
+ }
+
fun testKotlinWhenStatement2() {
// Regression test for issue 69661204
lint().files(
diff --git a/sdk-common/src/main/java/com/android/ide/common/attribution/TaskCategoryLabel.kt b/sdk-common/src/main/java/com/android/ide/common/attribution/TaskCategoryLabel.kt
index 93e478e5e6..451b812316 100644
--- a/sdk-common/src/main/java/com/android/ide/common/attribution/TaskCategoryLabel.kt
+++ b/sdk-common/src/main/java/com/android/ide/common/attribution/TaskCategoryLabel.kt
@@ -38,6 +38,7 @@ enum class TaskCategoryLabel {
JAVA_RESOURCES,
// Tasks that involve Java docs
JAVA_DOC,
+ KOTLIN,
// Tasks that invovle AIDL
AIDL,
// Tasks involving Renderscript framework
@@ -62,8 +63,11 @@ enum class TaskCategoryLabel {
DEPLOYMENT,
// Tasks that helps/gives information to the user
HELP,
+ // Task related to packaging APKs
APK_PACKAGING,
+ // Tasks related to packaging AARs
AAR_PACKAGING,
+ // Tasks related to packaging bundles
BUNDLE_PACKAGING,
// Tasks that involve the optimization of the project
OPTIMIZATION,
@@ -71,4 +75,16 @@ enum class TaskCategoryLabel {
SOURCE_GENERATION,
// Tasks that process sources
SOURCE_PROCESSING,
+ // Tasks related to packaging artifacts
+ ZIPPING,
+ LINKING,
+ MERGING,
+ FUSING,
+ // org.gradle tasks - No tasks in AGP should have this annotation label
+ GRADLE,
+ // Various tasks that do not fall into any other category
+ // No tasks in AGP should have this annotation label
+ MISC,
+ // Other TP plugins - No task in AGP should have this annotation label
+ UNKNOWN
}
diff --git a/sdk-common/src/main/java/com/android/ide/common/repository/GradleVersion.java b/sdk-common/src/main/java/com/android/ide/common/repository/GradleVersion.java
index d0750fa8d8..be7db5039a 100644
--- a/sdk-common/src/main/java/com/android/ide/common/repository/GradleVersion.java
+++ b/sdk-common/src/main/java/com/android/ide/common/repository/GradleVersion.java
@@ -29,18 +29,26 @@ import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.jetbrains.annotations.NotNull;
/**
- * Supports versions in the given formats: <ul> <li>major (e.g. 1)</li> <li>major.minor (e.g.
- * 1.0)</li> <li>major.minor.micro (e.g. 1.1.1)</li> </ul> A version can also be a "preview" (e.g.
- * 1-alpha1, 1.0.0-rc2) or an unreleased version (or "snapshot") (e.g. 1-SNAPSHOT,
- * 1.0.0-alpha1-SNAPSHOT).
+ * Supports versions in the given formats:
+ *
+ * <ul>
+ * <li>major (e.g. 1)
+ * <li>major.minor (e.g. 1.0)
+ * <li>major.minor.micro (e.g. 1.1.1)
+ * </ul>
+ *
+ * A version can also be a "previewType" (e.g. 1-alpha1, 1.0.0-rc2) or an unreleased version (or
+ * "snapshot") (e.g. 1-SNAPSHOT, 1.0.0-alpha1-SNAPSHOT).
*/
public class GradleVersion implements Comparable<GradleVersion>, Serializable {
private static final String PLUS = "+";
- private static final Pattern PREVIEW_PATTERN = Pattern.compile("([a-zA-z]+)[\\-]?([\\d]+)?(-\\d+)?");
-
+ // TODO(b/242691473): This pattern is not inclusive for all the possible versions.
+ private static final Pattern PREVIEW_AND_SNAPSHOT_PATTERN =
+ Pattern.compile("([a-zA-z]+)[\\-]?([\\d]+)?[\\-]?(\\d+)?[\\-]?([a-zA-z]+)?");
private final String mRawValue;
@NonNull
@@ -59,10 +67,41 @@ public class GradleVersion implements Comparable<GradleVersion>, Serializable {
private final boolean mSnapshot;
- @NonNull
- private final List<VersionSegment> mAdditionalSegments;
+ @NonNull private final List<VersionSegment> mAdditionalSegments;
+
+ private final VersionQualifiers mQualifiers;
- private final String mQualifiers;
+ private static class VersionQualifiers {
+ @NotNull String previewType;
+
+ int preview;
+
+ // TODO(b/242691473): We could have multiple additional previewType types and should
+ // consider all of them eventually.
+ int additionalPreviewType;
+
+ @Nullable String previewChannel;
+
+ private VersionQualifiers(
+ @NotNull String previewType,
+ int preview,
+ int additionalPreviewType,
+ @Nullable String previewChannel) {
+ this.previewType = previewType;
+ this.preview = preview;
+ this.additionalPreviewType = additionalPreviewType;
+ this.previewChannel = previewChannel;
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ return previewType
+ + ((preview != 0) ? "-" + preview : "")
+ + ((additionalPreviewType != 0) ? "-" + additionalPreviewType : "")
+ + ((!isNullOrEmpty(previewChannel)) ? "-" + previewChannel : "");
+ }
+ }
/**
* Parses the given version. This method does the same as {@link #parse(String)}, but it does
@@ -93,12 +132,45 @@ public class GradleVersion implements Comparable<GradleVersion>, Serializable {
@NonNull
public static GradleVersion parse(@NonNull String value) {
String version = value;
- String qualifiers = null;
+ VersionQualifiers qualifiers = null;
char dash = '-';
int dashIndex = value.indexOf(dash);
if (dashIndex != -1) {
if (dashIndex < value.length() - 1) {
- qualifiers = value.substring(dashIndex + 1);
+ String qualifiersText = value.substring(dashIndex + 1);
+ String qualifierName = null;
+ int qualifierValue = 0;
+ int additionalQualifierValue = 0;
+ String qualifierChannel = null;
+ Matcher matcher = PREVIEW_AND_SNAPSHOT_PATTERN.matcher(qualifiersText);
+ if (matcher.matches()) {
+ qualifierName = matcher.group(1);
+ if (matcher.groupCount() >= 2) {
+ String group = matcher.group(2);
+ if (!isNullOrEmpty(group)) {
+ qualifierValue = Integer.parseInt(group);
+ }
+ String group3 = matcher.group(3);
+ if (!isNullOrEmpty(group3)) {
+ additionalQualifierValue = Integer.parseInt(group3);
+ }
+ String group4 = matcher.group(4);
+ if (!isNullOrEmpty(group4)) {
+ qualifierChannel = group4;
+ }
+ }
+ }
+ if (!isNullOrEmpty(qualifierName)
+ || qualifierValue != 0
+ || additionalQualifierValue != 0
+ || !isNullOrEmpty(qualifierChannel)) {
+ qualifiers =
+ new VersionQualifiers(
+ qualifierName,
+ qualifierValue,
+ additionalQualifierValue,
+ qualifierChannel);
+ }
}
version = value.substring(0, dashIndex);
}
@@ -124,39 +196,25 @@ public class GradleVersion implements Comparable<GradleVersion>, Serializable {
additionalSegments.addAll(parsedVersionSegments.subList(3, segmentCount));
}
- int preview = 0;
- String previewType = null;
boolean snapshot = false;
if (qualifiers != null) {
- if (isSnapshotQualifier(qualifiers)) {
+ if (isSnapshotQualifier(qualifiers.toString())) {
snapshot = true;
qualifiers = null;
- }
- else {
- // find and remove "SNAPSHOT" at the end of the qualifiers.
- int lastDashIndex = qualifiers.lastIndexOf(dash);
- if (lastDashIndex != -1) {
- String mayBeSnapshot = qualifiers.substring(lastDashIndex + 1);
- if (isSnapshotQualifier(mayBeSnapshot)) {
- snapshot = true;
- qualifiers = qualifiers.substring(0, lastDashIndex);
- }
- }
- }
- if (!isNullOrEmpty(qualifiers)) {
- Matcher matcher = PREVIEW_PATTERN.matcher(qualifiers);
- if (matcher.matches()) {
- previewType = matcher.group(1);
- if (matcher.groupCount() >= 2) {
- String group = matcher.group(2);
- if (!isNullOrEmpty(group)) {
- preview = Integer.parseInt(group);
- }
- }
- }
+ } else if (!isNullOrEmpty(qualifiers.previewChannel)
+ && isSnapshotQualifier(qualifiers.previewChannel)) {
+ snapshot = true;
+ qualifiers.previewChannel = null;
}
}
+
+ int preview = (qualifiers != null) ? qualifiers.preview : 0;
+ String previewType =
+ (qualifiers != null)
+ ? qualifiers.previewType
+ : null; // PreviewType is never null
+
return new GradleVersion(value, majorSegment, minorSegment, microSegment,
additionalSegments, preview, previewType, snapshot, qualifiers);
}
@@ -235,7 +293,8 @@ public class GradleVersion implements Comparable<GradleVersion>, Serializable {
Collections.emptyList(), 0, null, false, null);
}
- private GradleVersion(@NonNull String rawValue,
+ private GradleVersion(
+ @NonNull String rawValue,
@NonNull VersionSegment majorSegment,
@Nullable VersionSegment minorSegment,
@Nullable VersionSegment microSegment,
@@ -243,7 +302,7 @@ public class GradleVersion implements Comparable<GradleVersion>, Serializable {
int preview,
@Nullable String previewType,
boolean snapshot,
- String qualifiers) {
+ VersionQualifiers qualifiers) {
mRawValue = rawValue;
mMajorSegment = majorSegment;
mMinorSegment = minorSegment;
@@ -342,28 +401,37 @@ public class GradleVersion implements Comparable<GradleVersion>, Serializable {
delta = mSnapshot == version.mSnapshot ? 0 : (mSnapshot ? -1 : 1);
} else if (version.mQualifiers == null) {
return -1;
- } else if (mQualifiers.startsWith("dev") && version.mQualifiers.startsWith("dev")) {
- delta = mQualifiers.compareTo(version.mQualifiers);
- } else if (mQualifiers.startsWith("dev") || version.mQualifiers.startsWith("dev")) {
- delta = mQualifiers.startsWith("dev") ? -1 : 1;
+ } else if (mQualifiers.previewType.equals("dev")
+ && version.mQualifiers.previewType.equals("dev")) {
+ delta = mQualifiers.preview - version.mQualifiers.preview;
+ } else if (mQualifiers.previewType.equals("dev")
+ || version.mQualifiers.previewType.equals("dev")) {
+ delta = mQualifiers.previewType.equals("dev") ? -1 : 1;
+ } else if (mQualifiers.previewType.equals(version.mQualifiers.previewType)) {
+ delta = mQualifiers.preview - version.mQualifiers.preview;
+ if (delta == 0) {
+ delta =
+ mQualifiers.additionalPreviewType
+ - version.mQualifiers.additionalPreviewType;
+ }
} else {
- delta = mQualifiers.compareTo(version.mQualifiers);
+ // TODO(b/242691473): Fix previewType comparison.
+ delta = mQualifiers.previewType.compareTo(version.mQualifiers.previewType);
}
}
return delta;
}
/**
- * Is this {@linkplain GradleVersion} at least as high as the given
- * major, minor, micro version?
+ * Is this {@linkplain GradleVersion} at least as high as the given major, minor, micro version?
*/
public boolean isAtLeast(int major, int minor, int micro) {
return isAtLeast(major, minor, micro, null, 0, false);
}
/**
- * Is this {@linkplain GradleVersion} at least as high as the given
- * major, minor, micro version? Any preview suffixes are ignored.
+ * Is this {@linkplain GradleVersion} at least as high as the given major, minor, micro version?
+ * Any previewType suffixes are ignored.
*/
public boolean isAtLeastIncludingPreviews(int major, int minor, int micro) {
return isAtLeast(major, minor, micro, "", 0, false);
diff --git a/sdk-common/src/main/java/com/android/ide/common/repository/NetworkCache.kt b/sdk-common/src/main/java/com/android/ide/common/repository/NetworkCache.kt
index c819d49c67..0999f2f3bd 100644
--- a/sdk-common/src/main/java/com/android/ide/common/repository/NetworkCache.kt
+++ b/sdk-common/src/main/java/com/android/ide/common/repository/NetworkCache.kt
@@ -50,6 +50,7 @@ abstract class NetworkCache constructor(
* */
private val networkEnabled: Boolean = true
) {
+ protected var lastReadSourceType: DataSourceType = DataSourceType.UNKNOWN_SOURCE
/** Reads the given query URL in, with the given time out, and returns the bytes found. */
@Slow
@@ -66,7 +67,7 @@ abstract class NetworkCache constructor(
protected open fun findData(relative: String): InputStream? {
if (cacheDir != null) {
synchronized(cacheDir) {
- val file = cacheDir.resolve(if (relative.isNotEmpty()) relative else cacheKey)
+ val file = cacheDir.resolve(relative.ifEmpty { cacheKey })
try {
val lastModified = CancellableFileIo.getLastModifiedTime(file).toMillis()
val now = System.currentTimeMillis()
@@ -78,6 +79,15 @@ abstract class NetworkCache constructor(
// - Outside the "cache expiry interval" if a network connection is allowed we always try to download the
// latest version (code bellow). If a network connection is not allowed, we assume the cache only exists
// because it was (or will be) updated on a background task where a network connection is allowed.
+ lastReadSourceType = if (lastModified != 0L) {
+ if (now - lastModified > expiryMs) {
+ DataSourceType.CACHE_FILE_EXPIRED_NO_NETWORK
+ } else {
+ DataSourceType.CACHE_FILE_RECENT
+ }
+ } else {
+ DataSourceType.CACHE_FILE_EXPIRED_UNKNOWN
+ }
return CancellableFileIo.newInputStream(file)
}
} catch (ignore: NoSuchFileException) {
@@ -85,6 +95,7 @@ abstract class NetworkCache constructor(
if (networkEnabled) {
try {
+ lastReadSourceType = DataSourceType.CACHE_FILE_NEW
val data = readUrlData("$baseUrl$relative", networkTimeoutMs)
if (data != null) {
file.parent?.let { Files.createDirectories(it) }
@@ -97,8 +108,9 @@ abstract class NetworkCache constructor(
throw e
}
catch (e: Throwable) {
- // timeouts etc: fall through to use "expired" data, if available, otherwise use the Builtin index
+ // timeouts etc.: fall through to use "expired" data, if available, otherwise use the Builtin index
try {
+ lastReadSourceType = DataSourceType.CACHE_FILE_EXPIRED_NETWORK_ERROR
return CancellableFileIo.newInputStream(file)
} catch (ignore: NoSuchFileException) {
}
@@ -108,6 +120,27 @@ abstract class NetworkCache constructor(
}
// Fallback: Builtin index, used for offline scenarios etc
- return readDefaultData(relative)
+ val result = readDefaultData(relative)
+ // Assign after reading, so it can be used inside readDefaultData for logging purposes
+ lastReadSourceType = DataSourceType.DEFAULT_DATA
+ return result
+ }
+
+ enum class DataSourceType {
+ UNKNOWN_SOURCE,
+ // Test data, not to be used in production
+ TEST_DATA,
+ // Cache file is too old but no network is available
+ CACHE_FILE_EXPIRED_NO_NETWORK,
+ // Cache file is too old, network is available but was not able to update
+ CACHE_FILE_EXPIRED_NETWORK_ERROR,
+ // Cache file exist but cannot tell if too old
+ CACHE_FILE_EXPIRED_UNKNOWN,
+ // Cache file exists and has not expired
+ CACHE_FILE_RECENT,
+ // Cache file and was just downloaded
+ CACHE_FILE_NEW,
+ // Default data was used
+ DEFAULT_DATA,
}
}
diff --git a/sdk-common/src/main/java/com/android/ide/common/resources/AbstractResourceRepository.java b/sdk-common/src/main/java/com/android/ide/common/resources/AbstractResourceRepository.java
index b246ff315a..959002ad14 100644
--- a/sdk-common/src/main/java/com/android/ide/common/resources/AbstractResourceRepository.java
+++ b/sdk-common/src/main/java/com/android/ide/common/resources/AbstractResourceRepository.java
@@ -55,7 +55,7 @@ public abstract class AbstractResourceRepository implements ResourceRepository {
@NonNull String resourceName) {
ListMultimap<String, ResourceItem> map = getResourcesInternal(namespace, resourceType);
List<ResourceItem> items = map.get(resourceName);
- return items == null ? ImmutableList.of() : ImmutableList.copyOf(items);
+ return items.isEmpty() ? ImmutableList.of() : ImmutableList.copyOf(items);
}
@Override
@@ -93,7 +93,7 @@ public abstract class AbstractResourceRepository implements ResourceRepository {
@NonNull String resourceName) {
ListMultimap<String, ResourceItem> map = getResourcesInternal(namespace, resourceType);
List<ResourceItem> items = map.get(resourceName);
- return items != null && !items.isEmpty();
+ return !items.isEmpty();
}
@Override
diff --git a/sdk-common/src/test/java/com/android/ide/common/repository/GradleCoordinateTest.java b/sdk-common/src/test/java/com/android/ide/common/repository/GradleCoordinateTest.java
index afda23849b..e12f92d889 100644
--- a/sdk-common/src/test/java/com/android/ide/common/repository/GradleCoordinateTest.java
+++ b/sdk-common/src/test/java/com/android/ide/common/repository/GradleCoordinateTest.java
@@ -425,4 +425,4 @@ public class GradleCoordinateTest extends BaseTestCase {
test = new GradleCoordinate("a.b.c", "foo", 1);
assertTrue(actual.matches(test));
}
-} \ No newline at end of file
+}
diff --git a/sdk-common/src/test/java/com/android/ide/common/repository/GradleVersionTest.java b/sdk-common/src/test/java/com/android/ide/common/repository/GradleVersionTest.java
index 2212b01c23..96d0f06e9b 100644
--- a/sdk-common/src/test/java/com/android/ide/common/repository/GradleVersionTest.java
+++ b/sdk-common/src/test/java/com/android/ide/common/repository/GradleVersionTest.java
@@ -367,6 +367,7 @@ public class GradleVersionTest {
assertTrue(GradleVersion.parse("1.0.0-alpha9-1").compareTo("1.0.0-alpha9-2") < 0);
assertTrue(GradleVersion.parse("1.0.0-rc1").compareTo("1.0.0-alpha2") > 0);
assertTrue(GradleVersion.parse("2.0.0-alpha1").compareTo("1.0.0-alpha1") > 0);
+ assertTrue(GradleVersion.parse("2.0.0-alpha08").compareTo("2.0.0-alpha6") > 0);
// A pure -dev version is larger than a "numbered" preview. So if a piece of DSL was added
// in alpha3, projects for 3.0.0-dev will use it.
diff --git a/testutils/src/main/java/com/android/testutils/TestUtils.java b/testutils/src/main/java/com/android/testutils/TestUtils.java
index 8457db92ae..60639022d3 100644
--- a/testutils/src/main/java/com/android/testutils/TestUtils.java
+++ b/testutils/src/main/java/com/android/testutils/TestUtils.java
@@ -216,6 +216,16 @@ public class TestUtils {
return getWorkspaceRoot().resolve(relativePath);
}
+ /** Gets the path to a specific Bazel workspace. */
+ @NonNull
+ public static Path getWorkspaceRoot(@NonNull String workspaceName) throws IOException {
+ String pathToParent = runningFromBazel() ? ".." : "bazel-out/../../../external";
+ // Canonicalize to get rid of the ".."s or symlinks.
+ Path canonicalPath =
+ resolveWorkspacePathUnchecked(pathToParent).toFile().getCanonicalFile().toPath();
+ return canonicalPath.resolve(workspaceName);
+ }
+
/** Returns true if the file exists in the workspace. */
public static boolean workspaceFileExists(@NonNull String path) {
return Files.exists(getWorkspaceRoot().resolve(path));
diff --git a/utp/android-device-provider-gradle-proto/BUILD b/utp/android-device-provider-gradle-proto/BUILD
index 1fdfa119f9..63ec88ee5b 100644
--- a/utp/android-device-provider-gradle-proto/BUILD
+++ b/utp/android-device-provider-gradle-proto/BUILD
@@ -1,4 +1,4 @@
-load("//tools/base/bazel:proto.bzl", "java_proto_library", "maven_proto_library")
+load("//tools/base/bazel:proto.bzl", "android_java_proto_library", "maven_proto_library")
load("//tools/base/common:version.bzl", "BASE_VERSION")
maven_proto_library(
@@ -12,10 +12,9 @@ maven_proto_library(
visibility = ["//visibility:public"],
)
-java_proto_library(
- name = "studio.android-device-provider-gradle-proto",
+android_java_proto_library(
+ name = "libstudio.android-device-provider-gradle-proto",
srcs = glob(["*.proto"]),
- proto_java_runtime_library = ["@maven//:com.google.protobuf.protobuf-java"],
resource_strip_prefix = "tools/base/utp/android-device-provider-gradle-proto",
visibility = ["//visibility:public"],
)
diff --git a/utp/android-test-plugin-host-device-info-proto/BUILD b/utp/android-test-plugin-host-device-info-proto/BUILD
index 4621973b6b..82107d0c5a 100644
--- a/utp/android-test-plugin-host-device-info-proto/BUILD
+++ b/utp/android-test-plugin-host-device-info-proto/BUILD
@@ -1,4 +1,4 @@
-load("//tools/base/bazel:proto.bzl", "java_proto_library", "maven_proto_library")
+load("//tools/base/bazel:proto.bzl", "android_java_proto_library", "maven_proto_library")
load("//tools/base/common:version.bzl", "BASE_VERSION")
maven_proto_library(
@@ -11,9 +11,8 @@ maven_proto_library(
visibility = ["//visibility:public"],
)
-java_proto_library(
- name = "studio.android-test-plugin-host-device-info-proto",
+android_java_proto_library(
+ name = "libstudio.android-test-plugin-host-device-info-proto",
srcs = glob(["src/main/proto/*.proto"]),
- proto_java_runtime_library = ["@maven//:com.google.protobuf.protobuf-java"],
visibility = ["//visibility:public"],
)
diff --git a/utp/android-test-plugin-host-retention-proto/BUILD b/utp/android-test-plugin-host-retention-proto/BUILD
index 40d08872df..cb65301328 100644
--- a/utp/android-test-plugin-host-retention-proto/BUILD
+++ b/utp/android-test-plugin-host-retention-proto/BUILD
@@ -1,4 +1,4 @@
-load("//tools/base/bazel:proto.bzl", "java_proto_library", "maven_proto_library")
+load("//tools/base/bazel:proto.bzl", "android_java_proto_library", "maven_proto_library")
load("//tools/base/common:version.bzl", "BASE_VERSION")
maven_proto_library(
@@ -15,9 +15,8 @@ maven_proto_library(
visibility = ["//visibility:public"],
)
-java_proto_library(
- name = "studio.android-test-plugin-host-retention-proto",
+android_java_proto_library(
+ name = "libstudio.android-test-plugin-host-retention-proto",
srcs = glob(["src/main/proto/*.proto"]),
- proto_java_runtime_library = ["@maven//:com.google.protobuf.protobuf-java"],
visibility = ["//visibility:public"],
)
diff --git a/utp/android-test-plugin-result-listener-gradle-proto/BUILD b/utp/android-test-plugin-result-listener-gradle-proto/BUILD
index d209772a22..71a7239a80 100644
--- a/utp/android-test-plugin-result-listener-gradle-proto/BUILD
+++ b/utp/android-test-plugin-result-listener-gradle-proto/BUILD
@@ -1,4 +1,4 @@
-load("//tools/base/bazel:proto.bzl", "java_proto_library", "maven_proto_library")
+load("//tools/base/bazel:proto.bzl", "android_java_proto_library", "maven_proto_library")
load("//tools/base/common:version.bzl", "BASE_VERSION")
maven_proto_library(
@@ -22,9 +22,8 @@ maven_proto_library(
)
# Android Studio only needs protobuf message without gRPC services.
-java_proto_library(
- name = "studio.android-test-plugin-result-listener-gradle-proto",
+android_java_proto_library(
+ name = "libstudio.android-test-plugin-result-listener-gradle-proto",
srcs = glob(["src/main/proto/*.proto"]),
- proto_java_runtime_library = ["@maven//:com.google.protobuf.protobuf-java"],
visibility = ["//visibility:public"],
)