Add samples' source jars as published artifacts to sampling libraries

This does not yet work with KMP libraries.
This does not yet support libraries with multiple sample projects.

Bug: 295155220
Test: changes in the published project/group zips
Change-Id: I8105e1c301e7b2448b5fd3c0c7924ac6076628b2
diff --git a/activity/activity-compose/build.gradle b/activity/activity-compose/build.gradle
index 257bb1c..1fad276 100644
--- a/activity/activity-compose/build.gradle
+++ b/activity/activity-compose/build.gradle
@@ -51,8 +51,6 @@
 
     lintChecks(projectOrArtifact(":activity:activity-compose-lint"))
     lintPublish(projectOrArtifact(":activity:activity-compose-lint"))
-
-    samples(projectOrArtifact(":activity:activity-compose:activity-compose-samples"))
 }
 
 androidx {
@@ -62,6 +60,7 @@
     description = "Compose integration with Activity"
     runApiTasks = new RunApiTasks.Yes()
     metalavaK2UastEnabled = true
+    samples(projectOrArtifact(":activity:activity-compose:activity-compose-samples"))
 }
 
 android {
diff --git a/appactions/builtintypes/builtintypes/build.gradle b/appactions/builtintypes/builtintypes/build.gradle
index 22a77b0..04d7a42 100644
--- a/appactions/builtintypes/builtintypes/build.gradle
+++ b/appactions/builtintypes/builtintypes/build.gradle
@@ -39,8 +39,6 @@
 
     testImplementation(libs.junit)
     testImplementation(libs.truth)
-
-    samples(project(":appactions:builtintypes:builtintypes:builtintypes-samples"))
 }
 
 kapt {
@@ -68,4 +66,5 @@
     inceptionYear = "2023"
     description = "This library exposes a core set of data types based on schema.org definitions."
     metalavaK2UastEnabled = true
+    samples(project(":appactions:builtintypes:builtintypes:builtintypes-samples"))
 }
diff --git a/biometric/biometric-ktx/build.gradle b/biometric/biometric-ktx/build.gradle
index 809c1ba..7ce4886 100644
--- a/biometric/biometric-ktx/build.gradle
+++ b/biometric/biometric-ktx/build.gradle
@@ -33,8 +33,6 @@
     api(libs.kotlinStdlib)
     api(libs.kotlinCoroutinesCore)
     api(project(":biometric:biometric"))
-
-    samples(project(":biometric:biometric-ktx-samples"))
 }
 
 androidx {
@@ -43,6 +41,7 @@
     inceptionYear = "2020"
     description = "Kotlin extensions for the Biometric Library."
     metalavaK2UastEnabled = true
+    samples(project(":biometric:biometric-ktx-samples"))
 }
 
 android {
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXExtension.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXExtension.kt
index bc564a2..0574cbc 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXExtension.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXExtension.kt
@@ -27,6 +27,7 @@
 import org.gradle.api.plugins.ExtensionContainer
 import org.gradle.api.provider.Property
 import org.gradle.api.provider.Provider
+import org.gradle.api.tasks.TaskProvider
 import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
 
 /** Extension for [AndroidXImplPlugin] that's responsible for holding configuration options. */
@@ -39,6 +40,8 @@
     val libraryGroupsByGroupId: Map<String, LibraryGroup>
     val overrideLibraryGroupsByProjectPath: Map<String, LibraryGroup>
 
+    var copySampleSourceJarsTask: TaskProvider<LazyInputsCopyTask>? = null
+
     val mavenGroup: LibraryGroup?
 
     val listProjectsService: Provider<ListProjectsService>
@@ -449,6 +452,12 @@
     companion object {
         const val DEFAULT_UNSPECIFIED_VERSION = "unspecified"
     }
+
+    /**
+     * Used to register a project that will be providing documentation samples for this project.
+     * Can only be called once so only one samples library can exist per library b/318840087.
+     */
+    fun samples(samplesProject: Project) = registerSamplesLibrary(samplesProject)
 }
 
 class License {
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
index 02d35dd..5792385 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
@@ -125,8 +125,6 @@
                 project
             )
 
-        project.configurations.create("samples")
-
         project.tasks.register(BUILD_ON_SERVER_TASK, DefaultTask::class.java)
         // Perform different actions based on which plugins have been applied to the project.
         // Many of the actions overlap, ex. API tracking.
@@ -493,7 +491,7 @@
                 }
             }
             project.configureKmp()
-            project.configureSourceJarForMultiplatform()
+            project.configureSourceJarForMultiplatform(androidXExtension)
 
             // Disable any source JAR task(s) added by KotlinMultiplatformPlugin.
             // https://youtrack.jetbrains.com/issue/KT-55881
@@ -683,7 +681,7 @@
         }
 
         project.configurePublicResourcesStub(libraryExtension)
-        project.configureSourceJarForAndroid(libraryExtension)
+        project.configureSourceJarForAndroid(libraryExtension, androidXExtension)
         project.configureVersionFileWriter(libraryAndroidComponentsExtension, androidXExtension)
         project.configureJavaCompilationWarnings(androidXExtension)
 
@@ -743,7 +741,7 @@
                 }
             }
             if (!project.plugins.hasPlugin(KotlinBasePluginWrapper::class.java)) {
-                project.configureSourceJarForJava()
+                project.configureSourceJarForJava(androidXExtension)
             }
         }
 
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/Samples.kt b/buildSrc/private/src/main/kotlin/androidx/build/Samples.kt
new file mode 100644
index 0000000..716af2a
--- /dev/null
+++ b/buildSrc/private/src/main/kotlin/androidx/build/Samples.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2024 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 androidx.build
+
+import org.gradle.api.DefaultTask
+import org.gradle.api.Project
+import org.gradle.api.artifacts.Configuration
+import org.gradle.api.attributes.Category
+import org.gradle.api.attributes.DocsType
+import org.gradle.api.attributes.LibraryElements
+import org.gradle.api.attributes.Usage
+import org.gradle.api.file.ConfigurableFileCollection
+import org.gradle.api.file.RegularFileProperty
+import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.OutputFile
+import org.gradle.api.tasks.PathSensitive
+import org.gradle.api.tasks.PathSensitivity
+import org.gradle.api.tasks.TaskAction
+import org.gradle.kotlin.dsl.named
+import org.gradle.work.DisableCachingByDefault
+
+/**
+ * Used to register a project that will be providing documentation samples for this project.
+ * Can only be called once so only one samples library can exist per library b/318840087.
+ */
+fun AndroidXExtension.registerSamplesLibrary(samplesProject: Project) {
+    fun Configuration.setResolveSources() {
+        // While a sample library can have more dependencies than the library it has samples
+        // for, in Studio sample code is not executable or inspectable, so we don't need them.
+        isTransitive = false
+        isCanBeConsumed = false
+        attributes {
+            it.attribute(
+                Usage.USAGE_ATTRIBUTE,
+                project.objects.named<Usage>(Usage.JAVA_RUNTIME)
+            )
+            it.attribute(
+                Category.CATEGORY_ATTRIBUTE,
+                project.objects.named<Category>(Category.DOCUMENTATION)
+            )
+            it.attribute(
+                DocsType.DOCS_TYPE_ATTRIBUTE,
+                project.objects.named<DocsType>(DocsType.SOURCES)
+            )
+            it.attribute(
+                LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE,
+                project.objects.named<LibraryElements>(LibraryElements.JAR)
+            )
+        }
+    }
+
+    val samplesConfiguration = project.configurations.findByName("samples")
+        ?: project.configurations.create("samples") {
+            it.setResolveSources()
+            it.isVisible = false
+            it.isCanBeConsumed = false
+            it.isCanBeResolved = true
+        }
+    project.dependencies.add("samples", samplesProject)
+
+    copySampleSourceJarsTask =
+        project.tasks.register("copySampleSourceJars", LazyInputsCopyTask::class.java) {
+            it.inputJars.from(samplesConfiguration.incoming.artifactView { }.files)
+            // This file will be renamed later by `publish`. We can't know the proper name before
+            // this tasks's dependencies are known after configuration is finished.
+            it.destinationDir.set(project.layout.buildDirectory.file("samples_sources.jar"))
+        }
+}
+
+/**
+ * This is necessary because we need to delay artifact resolution until after configuration.
+ * If one sample is used by multiple libraries (e.g. paging-samples) it is copied several times.
+ * This is to avoid caching failures. There should be a better way that avoids needing this.
+ */
+@DisableCachingByDefault(because = "caching large output files is more expensive than copying")
+abstract class LazyInputsCopyTask : DefaultTask() {
+    @get:[InputFiles PathSensitive(value = PathSensitivity.RELATIVE)]
+    abstract val inputJars: ConfigurableFileCollection
+    @get:OutputFile
+    abstract val destinationDir: RegularFileProperty
+
+    @TaskAction
+    fun copyAction() {
+        inputJars.files.single().copyTo(destinationDir.get().asFile, overwrite = true)
+    }
+}
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/SourceJarTaskHelper.kt b/buildSrc/private/src/main/kotlin/androidx/build/SourceJarTaskHelper.kt
index 5dcc7c7..5b07bc0 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/SourceJarTaskHelper.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/SourceJarTaskHelper.kt
@@ -46,7 +46,10 @@
 import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
 
 /** Sets up a source jar task for an Android library project. */
-fun Project.configureSourceJarForAndroid(libraryExtension: LibraryExtension) {
+fun Project.configureSourceJarForAndroid(
+    libraryExtension: LibraryExtension,
+    androidXExtension: AndroidXExtension
+) {
     libraryExtension.defaultPublishVariant { variant ->
         val sourceJar =
             tasks.register(
@@ -61,7 +64,7 @@
                 // otherwise.
                 it.duplicatesStrategy = DuplicatesStrategy.FAIL
             }
-        registerSourcesVariant(sourceJar)
+        registerSourcesVariant(sourceJar, androidXExtension)
 
         // b/272214715
         configurations.whenObjectAdded {
@@ -107,7 +110,7 @@
 }
 
 /** Sets up a source jar task for a Java library project. */
-fun Project.configureSourceJarForJava() {
+fun Project.configureSourceJarForJava(androidXExtension: AndroidXExtension) {
     val sourceJar =
         tasks.register("sourceJar", Jar::class.java) { task ->
             task.archiveClassifier.set("sources")
@@ -134,7 +137,7 @@
                 }
             }
         }
-    registerSourcesVariant(sourceJar)
+    registerSourcesVariant(sourceJar, androidXExtension)
 
     val disableNames =
         setOf(
@@ -143,7 +146,7 @@
     disableUnusedSourceJarTasks(disableNames)
 }
 
-fun Project.configureSourceJarForMultiplatform() {
+fun Project.configureSourceJarForMultiplatform(androidXExtension: AndroidXExtension) {
     val kmpExtension =
         multiplatformExtension
             ?: throw GradleException(
@@ -173,7 +176,7 @@
                 }
             task.metaInf.from(metadataFile)
         }
-    registerMultiplatformSourcesVariant(sourceJar)
+    registerMultiplatformSourcesVariant(sourceJar, androidXExtension)
     val disableNames =
         setOf(
             "kotlinSourcesJar",
@@ -192,18 +195,23 @@
 internal val Project.multiplatformUsage
     get() = objects.named<Usage>("androidx-multiplatform-docs")
 
-private fun Project.registerMultiplatformSourcesVariant(sourceJar: TaskProvider<Jar>) {
-    registerSourcesVariant("androidxSourcesElements", sourceJar, multiplatformUsage)
-}
+private fun Project.registerMultiplatformSourcesVariant(
+    sourceJar: TaskProvider<Jar>,
+    androidXExtension: AndroidXExtension
+) = registerSourcesVariant(
+    "androidxSourcesElements", sourceJar, multiplatformUsage, androidXExtension)
 
-private fun Project.registerSourcesVariant(sourceJar: TaskProvider<Jar>) {
-    registerSourcesVariant("sourcesElements", sourceJar, objects.named(Usage.JAVA_RUNTIME))
-}
+private fun Project.registerSourcesVariant(
+    sourceJar: TaskProvider<Jar>,
+    androidXExtension: AndroidXExtension
+) = registerSourcesVariant(
+        "sourcesElements", sourceJar, objects.named(Usage.JAVA_RUNTIME), androidXExtension)
 
 private fun Project.registerSourcesVariant(
     configurationName: String,
     sourceJar: TaskProvider<Jar>,
-    usage: Usage
+    usage: Usage,
+    androidXExtension: AndroidXExtension
 ) {
     configurations.create(configurationName) { gradleVariant ->
         gradleVariant.isVisible = false
@@ -222,7 +230,13 @@
             objects.named<DocsType>(DocsType.SOURCES)
         )
         gradleVariant.outgoing.artifact(sourceJar)
-
+        androidXExtension.copySampleSourceJarsTask?.let { sampleSourceJarCopyTask ->
+            gradleVariant.outgoing.artifact(sampleSourceJarCopyTask) {
+                // The only place where this name is load-bearing is when we filter these out in our
+                // AndroidXDocsImplPlugin.configureUnzipJvmSourcesTasks
+                it.classifier = "samples-sources"
+            }
+        }
         registerAsComponentForPublishing(gradleVariant)
     }
 }
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/docs/AndroidXDocsImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/docs/AndroidXDocsImplPlugin.kt
index 7ee1196..f77b8c8 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/docs/AndroidXDocsImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/docs/AndroidXDocsImplPlugin.kt
@@ -231,7 +231,9 @@
             task.into(destinationDirectory)
             task.from(
                 sources.elements.map { jars ->
-                    jars.map { jar ->
+                    // Now that we publish sample jars, they can get confused with normal source
+                    // jars. We want to handle sample jars separately, so filter by the name.
+                    jars.filter { "samples" !in it.toString() }.map { jar ->
                         localVar.zipTree(jar).matching { it.exclude("**/META-INF/MANIFEST.MF") }
                     }
                 }
diff --git a/camera/camera-viewfinder-core/build.gradle b/camera/camera-viewfinder-core/build.gradle
index 7577a8b..b47ad6b 100644
--- a/camera/camera-viewfinder-core/build.gradle
+++ b/camera/camera-viewfinder-core/build.gradle
@@ -42,7 +42,6 @@
     implementation("androidx.test.espresso:espresso-idling-resource:3.1.0")
     implementation(libs.kotlinCoroutinesCore)
     implementation(libs.kotlinCoroutinesAndroid)
-    samples(project(":camera:camera-viewfinder-core:camera-viewfinder-core-samples"))
 
     annotationProcessor(libs.autoValue)
 }
@@ -58,4 +57,5 @@
     inceptionYear = "2023"
     description = "Core dependencies for ViewFinder"
     metalavaK2UastEnabled = true
+    samples(project(":camera:camera-viewfinder-core:camera-viewfinder-core-samples"))
 }
diff --git a/compose/runtime/runtime-livedata/build.gradle b/compose/runtime/runtime-livedata/build.gradle
index 58fc8ee..1dcfaa9 100644
--- a/compose/runtime/runtime-livedata/build.gradle
+++ b/compose/runtime/runtime-livedata/build.gradle
@@ -46,8 +46,6 @@
     androidTestImplementation(libs.testRunner)
     androidTestImplementation(libs.junit)
     androidTestImplementation(libs.truth)
-
-    samples(projectOrArtifact(":compose:runtime:runtime-livedata:runtime-livedata-samples"))
 }
 
 androidx {
@@ -57,6 +55,7 @@
     description = "Compose integration with LiveData"
     legacyDisableKotlinStrictApiMode = true
     metalavaK2UastEnabled = true
+    samples(projectOrArtifact(":compose:runtime:runtime-livedata:runtime-livedata-samples"))
 }
 
 android {
diff --git a/compose/runtime/runtime-rxjava2/build.gradle b/compose/runtime/runtime-rxjava2/build.gradle
index b0df134e..9187fa9 100644
--- a/compose/runtime/runtime-rxjava2/build.gradle
+++ b/compose/runtime/runtime-rxjava2/build.gradle
@@ -43,8 +43,6 @@
     androidTestImplementation(libs.testRunner)
     androidTestImplementation(libs.junit)
     androidTestImplementation(libs.truth)
-
-    samples(projectOrArtifact(":compose:runtime:runtime-rxjava2:runtime-rxjava2-samples"))
 }
 
 androidx {
@@ -54,6 +52,7 @@
     description = "Compose integration with RxJava 2"
     legacyDisableKotlinStrictApiMode = true
     metalavaK2UastEnabled = true
+    samples(projectOrArtifact(":compose:runtime:runtime-rxjava2:runtime-rxjava2-samples"))
 }
 
 android {
diff --git a/compose/runtime/runtime-rxjava3/build.gradle b/compose/runtime/runtime-rxjava3/build.gradle
index 73a9189..63a9aa5 100644
--- a/compose/runtime/runtime-rxjava3/build.gradle
+++ b/compose/runtime/runtime-rxjava3/build.gradle
@@ -43,8 +43,6 @@
     androidTestImplementation(libs.testRunner)
     androidTestImplementation(libs.junit)
     androidTestImplementation(libs.truth)
-
-    samples(projectOrArtifact(":compose:runtime:runtime-rxjava3:runtime-rxjava3-samples"))
 }
 
 androidx {
@@ -54,6 +52,7 @@
     description = "Compose integration with RxJava 3"
     legacyDisableKotlinStrictApiMode = true
     metalavaK2UastEnabled = true
+    samples(projectOrArtifact(":compose:runtime:runtime-rxjava3:runtime-rxjava3-samples"))
 }
 
 android {
diff --git a/compose/runtime/runtime-saveable/build.gradle b/compose/runtime/runtime-saveable/build.gradle
index 155e1d1..d4fa60e 100644
--- a/compose/runtime/runtime-saveable/build.gradle
+++ b/compose/runtime/runtime-saveable/build.gradle
@@ -111,7 +111,6 @@
 }
 
 dependencies {
-    samples(projectOrArtifact(":compose:runtime:runtime-saveable:runtime-saveable-samples"))
     lintPublish(project(":compose:runtime:runtime-saveable-lint"))
 }
 
@@ -121,6 +120,7 @@
     inceptionYear = "2020"
     description = "Compose components that allow saving and restoring the local ui state"
     legacyDisableKotlinStrictApiMode = true
+    samples(projectOrArtifact(":compose:runtime:runtime-saveable:runtime-saveable-samples"))
 }
 
 android {
diff --git a/compose/runtime/runtime/build.gradle b/compose/runtime/runtime/build.gradle
index bd9fafc..aaad0b5 100644
--- a/compose/runtime/runtime/build.gradle
+++ b/compose/runtime/runtime/build.gradle
@@ -119,7 +119,6 @@
 dependencies {
     lintChecks(projectOrArtifact(":compose:runtime:runtime-lint"))
     lintPublish(projectOrArtifact(":compose:runtime:runtime-lint"))
-    samples(projectOrArtifact(":compose:runtime:runtime:runtime-samples"))
 }
 
 android {
@@ -135,4 +134,5 @@
     inceptionYear = "2019"
     description = "Tree composition support for code generated by the Compose compiler plugin and corresponding public API"
     legacyDisableKotlinStrictApiMode = true
+    samples(projectOrArtifact(":compose:runtime:runtime:runtime-samples"))
 }
diff --git a/compose/ui/ui-unit/build.gradle b/compose/ui/ui-unit/build.gradle
index 5d03e7c..5a61cdb 100644
--- a/compose/ui/ui-unit/build.gradle
+++ b/compose/ui/ui-unit/build.gradle
@@ -108,16 +108,13 @@
     }
 }
 
-dependencies {
-    samples(projectOrArtifact(":compose:ui:ui-unit:ui-unit-samples"))
-}
-
 androidx {
     name = "Compose Unit"
     type = LibraryType.PUBLISHED_LIBRARY
     inceptionYear = "2020"
     description = "Compose classes for simple units"
     legacyDisableKotlinStrictApiMode = true
+    samples(projectOrArtifact(":compose:ui:ui-unit:ui-unit-samples"))
 }
 
 android {
diff --git a/compose/ui/ui-viewbinding/build.gradle b/compose/ui/ui-viewbinding/build.gradle
index 1d07dab..bbb555f 100644
--- a/compose/ui/ui-viewbinding/build.gradle
+++ b/compose/ui/ui-viewbinding/build.gradle
@@ -46,8 +46,6 @@
     androidTestImplementation(libs.testRunner)
     androidTestImplementation(libs.junit)
     androidTestImplementation(libs.truth)
-
-    samples(project(":compose:ui:ui-viewbinding:ui-viewbinding-samples"))
 }
 
 androidx {
@@ -57,6 +55,7 @@
     description = "Compose integration with ViewBinding"
     legacyDisableKotlinStrictApiMode = true
     metalavaK2UastEnabled = true
+    samples(project(":compose:ui:ui-viewbinding:ui-viewbinding-samples"))
 }
 
 android {
diff --git a/core/core-performance/build.gradle b/core/core-performance/build.gradle
index 23d7a9a..59364f1 100644
--- a/core/core-performance/build.gradle
+++ b/core/core-performance/build.gradle
@@ -41,8 +41,6 @@
     testImplementation(libs.truth)
     testImplementation(libs.robolectric)
     testImplementation(project(":core:core-performance-testing"))
-
-    samples(project(":core:core-performance:core-performance-samples"))
 }
 
 androidx {
@@ -52,6 +50,7 @@
     inceptionYear = "2021"
     description = "This library makes it easy for developers to make UI and feature choices based on Android Performance Class level for GMS devices."
     metalavaK2UastEnabled = true
+    samples(project(":core:core-performance:core-performance-samples"))
 }
 
 android {
diff --git a/core/core-splashscreen/build.gradle b/core/core-splashscreen/build.gradle
index c3d875b..1ccac49 100644
--- a/core/core-splashscreen/build.gradle
+++ b/core/core-splashscreen/build.gradle
@@ -49,8 +49,6 @@
     androidTestImplementation(libs.truth)
     androidTestImplementation(projectOrArtifact(":appcompat:appcompat"))
     androidTestImplementation(project(":test:screenshot:screenshot"))
-
-    samples("androidx.core.core-splashscreen:core-splashscreen-samples:1.0.0-rc01")
 }
 
 androidx {
diff --git a/core/core-splashscreen/samples/build.gradle b/core/core-splashscreen/samples/build.gradle
index b2a88c8..e057f24 100644
--- a/core/core-splashscreen/samples/build.gradle
+++ b/core/core-splashscreen/samples/build.gradle
@@ -44,13 +44,4 @@
     implementation(projectOrArtifact(":appcompat:appcompat"))
     implementation projectOrArtifact(":annotation:annotation")
     implementation(projectOrArtifact(":interpolator:interpolator"))
-    compileOnly(project(":annotation:annotation-sampled"))
-}
-
-androidx {
-    name = "Splashscreen Samples"
-    type = LibraryType.SAMPLES
-    mavenVersion = LibraryVersions.CORE_SPLASHSCREEN
-    inceptionYear = "2021"
-    description = "Sample for the AndoridX Splashscreen library"
 }
diff --git a/core/core-splashscreen/samples/lint-baseline.xml b/core/core-splashscreen/samples/lint-baseline.xml
new file mode 100644
index 0000000..b2f77ab
--- /dev/null
+++ b/core/core-splashscreen/samples/lint-baseline.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.3.0-alpha10" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0-alpha10)" variant="all" version="8.3.0-alpha10">
+
+    <issue
+        id="NewApi"
+        message="`android:enforceNavigationBarContrast` requires API level 29 (current min is 21)"
+        errorLine1="        &lt;item name=&quot;android:enforceNavigationBarContrast&quot;>true&lt;/item>"
+        errorLine2="              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/res/values/styles.xml"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="`android:windowLightNavigationBar` requires API level 27 (current min is 21)"
+        errorLine1="        &lt;item name=&quot;android:windowLightNavigationBar&quot;>true&lt;/item>"
+        errorLine2="              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/res/values/styles.xml"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="`android:windowLightStatusBar` requires API level 23 (current min is 21)"
+        errorLine1="        &lt;item name=&quot;android:windowLightStatusBar&quot;>true&lt;/item>"
+        errorLine2="              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/res/values/styles.xml"/>
+    </issue>
+
+</issues>
diff --git a/core/core-splashscreen/samples/src/main/java/androidx/core/splashscreen/sample/SplashScreenSampleActivity.kt b/core/core-splashscreen/samples/src/main/java/androidx/core/splashscreen/sample/SplashScreenSampleActivity.kt
index 2ad3db5..79a7c1c 100644
--- a/core/core-splashscreen/samples/src/main/java/androidx/core/splashscreen/sample/SplashScreenSampleActivity.kt
+++ b/core/core-splashscreen/samples/src/main/java/androidx/core/splashscreen/sample/SplashScreenSampleActivity.kt
@@ -26,7 +26,6 @@
 import android.view.animation.DecelerateInterpolator
 import android.widget.Button
 import android.widget.LinearLayout
-import androidx.annotation.RequiresApi
 import androidx.appcompat.app.AppCompatActivity
 import androidx.core.animation.doOnEnd
 import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
@@ -35,7 +34,6 @@
 import androidx.core.view.postDelayed
 import androidx.interpolator.view.animation.FastOutLinearInInterpolator
 
-@RequiresApi(21)
 class SplashScreenSampleActivity : AppCompatActivity() {
 
     private var appReady = false
diff --git a/core/core-splashscreen/samples/src/main/res/values/styles.xml b/core/core-splashscreen/samples/src/main/res/values/styles.xml
index 549060b..cc5ad43 100644
--- a/core/core-splashscreen/samples/src/main/res/values/styles.xml
+++ b/core/core-splashscreen/samples/src/main/res/values/styles.xml
@@ -13,7 +13,6 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-
 <resources>
 
     <style name="Theme.App" parent="Theme.AppCompat.DayNight.NoActionBar">
diff --git a/core/haptics/haptics/build.gradle b/core/haptics/haptics/build.gradle
index aaaa2c4..f71ef50 100644
--- a/core/haptics/haptics/build.gradle
+++ b/core/haptics/haptics/build.gradle
@@ -36,7 +36,6 @@
     implementation(projectOrArtifact(":annotation:annotation"))
     implementation(projectOrArtifact(":core:core"))
     implementation(projectOrArtifact(":media:media"))
-    samples(project(":core:haptics:haptics-samples"))
 
     androidTestImplementation(libs.testCore)
     androidTestImplementation(libs.testRunner)
@@ -54,4 +53,5 @@
     description = "Core Haptics Libraries to help navigate different device and Android SDK " +
             "functionalities and create reliable haptic effects across all of Android."
     metalavaK2UastEnabled = true
+    samples(project(":core:haptics:haptics-samples"))
 }
diff --git a/credentials/credentials/build.gradle b/credentials/credentials/build.gradle
index 6e32da8..d267a0f 100644
--- a/credentials/credentials/build.gradle
+++ b/credentials/credentials/build.gradle
@@ -33,7 +33,6 @@
     api("androidx.annotation:annotation:1.5.0")
     api(libs.kotlinStdlib)
     implementation(libs.kotlinCoroutinesCore)
-    samples(project(":credentials:credentials-samples"))
 
     androidTestImplementation("androidx.activity:activity:1.2.0")
     androidTestImplementation(libs.junit)
@@ -63,4 +62,5 @@
     inceptionYear = "2022"
     description = "Android Credentials Library"
     metalavaK2UastEnabled = true
+    samples(project(":credentials:credentials-samples"))
 }
diff --git a/development/build_log_simplifier/messages.ignore b/development/build_log_simplifier/messages.ignore
index 256f54e..bbcd343 100644
--- a/development/build_log_simplifier/messages.ignore
+++ b/development/build_log_simplifier/messages.ignore
@@ -499,6 +499,11 @@
 WARN: .*\/unzippedMultiplatformSources\/commonJvmMain\/androidx\/datastore\/core\/Serializer\.kt:[0-9]+ Missing @param tag for parameter `output` in DFunction writeTo
 WARN: .*\/unzippedMultiplatformSources\/nonJvmMain\/androidx\/annotation\/RestrictTo\.nonJvm\.kt:UnknownLine Link does not resolve for @throws kotlin\.IllegalArgumentException in DFunction valueOf\. Is it from a package that the containing file does not import\? Are docs inherited by an un-documented override function, but the exception class is not in scope in the inheriting class\? The general fix for these is to fully qualify the exception name, e\.g\. `@throws java\.io\.IOException under some conditions`\.
 WARN: File location could not be determined\. Failed to resolve See <a href="https:\/\/developer\.android\.com\/training\/transitions">Transition API Guide<\/a> in DPackage androidx\.transition
+# Task docs-*:unzipJvmSources
+# paging and wear have multiple libraries depending on the same samples library, which can cause the samples library to be unzipped multiple times
+Encountered duplicate path "androidx/paging/samples/.*
+Encountered duplicate path "androidx/wear/compose/material/samples/.*
+Encountered duplicate path "androidx/wear/watchface/samples/.*
 # > Task :compose:ui:ui-tooling:processDebugAndroidTestManifest
 \$SUPPORT/compose/ui/ui\-tooling/src/androidInstrumentedTest/AndroidManifest\.xml:[0-9]+:[0-9]+\-[0-9]+:[0-9]+ Warning:
 # ./gradlew tasks warns as we have warnings present
diff --git a/emoji2/emoji2-emojipicker/build.gradle b/emoji2/emoji2-emojipicker/build.gradle
index f160015..e59722e 100644
--- a/emoji2/emoji2-emojipicker/build.gradle
+++ b/emoji2/emoji2-emojipicker/build.gradle
@@ -46,8 +46,6 @@
     androidTestImplementation(libs.testRules)
     androidTestImplementation(project(":test:screenshot:screenshot"))
     androidTestImplementation(project(":internal-testutils-runtime"))
-
-    samples(project(":emoji2:emoji2-emojipicker:emoji2-emojipicker-samples"))
 }
 
 
diff --git a/emoji2/emoji2-emojipicker/samples/build.gradle b/emoji2/emoji2-emojipicker/samples/build.gradle
index 01d6e1e..c438f60 100644
--- a/emoji2/emoji2-emojipicker/samples/build.gradle
+++ b/emoji2/emoji2-emojipicker/samples/build.gradle
@@ -34,9 +34,3 @@
     }
     namespace "androidx.emoji2.emojipicker.samples"
 }
-androidx {
-    name = "androidx.emoji2:emoji2-emojipicker-samples"
-    type = LibraryType.SAMPLES
-    inceptionYear = "2022"
-    description = "Contains the sample code for the APIs in the androidx.emoji2:emoji2-emojipicker library"
-}
\ No newline at end of file
diff --git a/glance/glance-appwidget-testing/build.gradle b/glance/glance-appwidget-testing/build.gradle
index 97bf0fc..cd6ff3c 100644
--- a/glance/glance-appwidget-testing/build.gradle
+++ b/glance/glance-appwidget-testing/build.gradle
@@ -45,8 +45,6 @@
     testImplementation(libs.testCore)
     testImplementation(libs.testRunner)
     testImplementation(libs.truth)
-
-    samples(projectOrArtifact(":glance:glance-appwidget-testing:glance-appwidget-testing-samples"))
 }
 
 android {
@@ -68,4 +66,5 @@
     targetsJavaConsumers = false
     inceptionYear = "2023"
     description = "This library provides APIs for developers to use for testing their appWidget specific Glance composables."
+    samples(projectOrArtifact(":glance:glance-appwidget-testing:glance-appwidget-testing-samples"))
 }
diff --git a/glance/glance-appwidget/build.gradle b/glance/glance-appwidget/build.gradle
index ca03f23..de7d996 100644
--- a/glance/glance-appwidget/build.gradle
+++ b/glance/glance-appwidget/build.gradle
@@ -92,8 +92,6 @@
     androidTestImplementation(libs.testRunner)
     androidTestImplementation(libs.truth)
     androidTestImplementation(libs.kotlinReflect)
-
-    samples(projectOrArtifact(":glance:glance-appwidget:glance-appwidget-samples"))
 }
 
 android {
@@ -124,6 +122,7 @@
     description = "Glance-appwidgets allows developers to build layouts for Android AppWidgets " +
             "using a Jetpack Compose-style API."
     targetsJavaConsumers = false
+    samples(projectOrArtifact(":glance:glance-appwidget:glance-appwidget-samples"))
 }
 
 LayoutGeneratorTask.registerLayoutGenerator(
diff --git a/graphics/graphics-core/build.gradle b/graphics/graphics-core/build.gradle
index 5841931..bc917ea 100644
--- a/graphics/graphics-core/build.gradle
+++ b/graphics/graphics-core/build.gradle
@@ -42,8 +42,6 @@
     androidTestImplementation("androidx.lifecycle:lifecycle-common:2.5.0-alpha01")
     androidTestImplementation("androidx.test:core:1.4.0@aar")
     androidTestImplementation(project(":core:core"))
-
-    samples(project(":graphics:graphics-core:graphics-core-samples"))
 }
 
 android {
@@ -78,4 +76,5 @@
     inceptionYear = "2021"
     description = "Leverage graphics facilities across multiple Android platform releases"
     metalavaK2UastEnabled = true
+    samples(project(":graphics:graphics-core:graphics-core-samples"))
 }
diff --git a/health/connect/connect-client/build.gradle b/health/connect/connect-client/build.gradle
index d72c003..a62c6d2 100644
--- a/health/connect/connect-client/build.gradle
+++ b/health/connect/connect-client/build.gradle
@@ -72,8 +72,6 @@
     androidTestImplementation(libs.kotlinTest)
     androidTestImplementation(libs.junit)
     androidTestImplementation(libs.truth)
-
-    samples(project(":health:connect:connect-client-samples"))
 }
 
 android {
@@ -96,4 +94,5 @@
     inceptionYear = "2022"
     description = "read or write user's health and fitness records."
     metalavaK2UastEnabled = true
+    samples(project(":health:connect:connect-client-samples"))
 }
diff --git a/hilt/hilt-navigation-compose/build.gradle b/hilt/hilt-navigation-compose/build.gradle
index 7f7b4a3..5383e0d 100644
--- a/hilt/hilt-navigation-compose/build.gradle
+++ b/hilt/hilt-navigation-compose/build.gradle
@@ -64,8 +64,6 @@
     androidTestImplementation(projectOrArtifact(":lifecycle:lifecycle-livedata-core"))
     androidTestImplementation(projectOrArtifact(":lifecycle:lifecycle-viewmodel"))
     androidTestImplementation(projectOrArtifact(":lifecycle:lifecycle-viewmodel-savedstate"))
-
-    samples(projectOrArtifact(":hilt:hilt-navigation-compose-samples"))
 }
 
 hilt {
@@ -81,4 +79,5 @@
     runApiTasks = new RunApiTasks.Yes()
     legacyDisableKotlinStrictApiMode = true
     metalavaK2UastEnabled = true
+    samples(projectOrArtifact(":hilt:hilt-navigation-compose-samples"))
 }
diff --git a/lifecycle/lifecycle-runtime-compose/build.gradle b/lifecycle/lifecycle-runtime-compose/build.gradle
index 24b4513..173eee3 100644
--- a/lifecycle/lifecycle-runtime-compose/build.gradle
+++ b/lifecycle/lifecycle-runtime-compose/build.gradle
@@ -47,8 +47,6 @@
     androidTestImplementation(libs.testRunner)
     androidTestImplementation(libs.junit)
     androidTestImplementation(libs.truth)
-
-    samples(projectOrArtifact(":lifecycle:lifecycle-runtime-compose:lifecycle-runtime-compose-samples"))
 }
 
 androidx {
@@ -58,6 +56,7 @@
     description = "Compose integration with Lifecycle"
     runApiTasks = new RunApiTasks.Yes()
     metalavaK2UastEnabled = true
+    samples(projectOrArtifact(":lifecycle:lifecycle-runtime-compose:lifecycle-runtime-compose-samples"))
 }
 
 android {
diff --git a/lifecycle/lifecycle-viewmodel-compose/build.gradle b/lifecycle/lifecycle-viewmodel-compose/build.gradle
index 4b06506..404e68f 100644
--- a/lifecycle/lifecycle-viewmodel-compose/build.gradle
+++ b/lifecycle/lifecycle-viewmodel-compose/build.gradle
@@ -60,8 +60,6 @@
     androidTestImplementation projectOrArtifact(":lifecycle:lifecycle-viewmodel-savedstate")
     androidTestImplementation projectOrArtifact(":activity:activity-compose")
     androidTestImplementation(projectOrArtifact(":lifecycle:lifecycle-runtime-testing"))
-
-    samples(projectOrArtifact(":lifecycle:lifecycle-viewmodel-compose:lifecycle-viewmodel-compose-samples"))
 }
 
 androidx {
@@ -71,6 +69,7 @@
     description = "Compose integration with Lifecycle ViewModel"
     runApiTasks = new RunApiTasks.Yes()
     metalavaK2UastEnabled = true
+    samples(projectOrArtifact(":lifecycle:lifecycle-viewmodel-compose:lifecycle-viewmodel-compose-samples"))
 }
 
 android {
diff --git a/navigation/navigation-compose/build.gradle b/navigation/navigation-compose/build.gradle
index f06ef99..ddb1ccc 100644
--- a/navigation/navigation-compose/build.gradle
+++ b/navigation/navigation-compose/build.gradle
@@ -64,8 +64,6 @@
 
     lintChecks(projectOrArtifact(":navigation:navigation-compose-lint"))
     lintPublish(projectOrArtifact(":navigation:navigation-compose-lint"))
-
-    samples(projectOrArtifact(":navigation:navigation-compose:navigation-compose-samples"))
 }
 
 androidx {
@@ -75,6 +73,7 @@
     description = "Compose integration with Navigation"
     runApiTasks = new RunApiTasks.Yes()
     legacyDisableKotlinStrictApiMode = true
+    samples(projectOrArtifact(":navigation:navigation-compose:navigation-compose-samples"))
 }
 
 android {
diff --git a/paging/paging-common/build.gradle b/paging/paging-common/build.gradle
index e04b47e..91110be 100644
--- a/paging/paging-common/build.gradle
+++ b/paging/paging-common/build.gradle
@@ -146,17 +146,12 @@
     }
 }
 
-// top level declaration because the KGP sourceSets declaration used by androidXMultiplatform
-// does not support constraints or samples configurations yet
-dependencies {
-    samples(project(":paging:paging-samples"))
-}
-
 androidx {
     name = "Paging-Common"
     publish = Publish.SNAPSHOT_AND_RELEASE
     inceptionYear = "2017"
     description = "Android Paging-Common"
+    samples(project(":paging:paging-samples"))
 }
 
 android {
diff --git a/paging/paging-compose/build.gradle b/paging/paging-compose/build.gradle
index 3502bf0..7810e16 100644
--- a/paging/paging-compose/build.gradle
+++ b/paging/paging-compose/build.gradle
@@ -77,10 +77,6 @@
     }
 }
 
-dependencies {
-    samples(projectOrArtifact(":paging:paging-compose:paging-compose-samples"))
-}
-
 androidx {
     name = "Paging-Compose"
     publish = Publish.SNAPSHOT_AND_RELEASE
@@ -88,6 +84,7 @@
     description = "Compose integration with Paging"
     runApiTasks = new RunApiTasks.Yes()
     legacyDisableKotlinStrictApiMode = true
+    samples(project(":paging:paging-compose:paging-compose-samples"))
 }
 
 android {
diff --git a/paging/paging-guava/build.gradle b/paging/paging-guava/build.gradle
index b1e4aeb..f335511 100644
--- a/paging/paging-guava/build.gradle
+++ b/paging/paging-guava/build.gradle
@@ -41,8 +41,6 @@
     testImplementation(libs.junit)
     testImplementation(libs.kotlinTest)
     testImplementation(libs.kotlinCoroutinesTest)
-
-    samples(project(":paging:paging-samples"))
 }
 
 androidx {
@@ -52,6 +50,7 @@
     description = "Android Paging Guava"
     legacyDisableKotlinStrictApiMode = true
     metalavaK2UastEnabled = true
+    samples(project(":paging:paging-samples"))
 }
 
 android {
diff --git a/paging/paging-runtime/build.gradle b/paging/paging-runtime/build.gradle
index 3f58721..3f072d0 100644
--- a/paging/paging-runtime/build.gradle
+++ b/paging/paging-runtime/build.gradle
@@ -63,8 +63,6 @@
     androidTestImplementation(libs.kotlinCoroutinesTest)
     androidTestImplementation(libs.junit)
     androidTestImplementation(libs.multidex)
-
-    samples(project(":paging:paging-samples"))
 }
 
 androidx {
@@ -74,4 +72,5 @@
     description = "Android Paging-Runtime"
     legacyDisableKotlinStrictApiMode = true
     metalavaK2UastEnabled = true
+    samples(project(":paging:paging-samples"))
 }
diff --git a/paging/paging-rxjava2/build.gradle b/paging/paging-rxjava2/build.gradle
index 3f6f4db..7f7949f 100644
--- a/paging/paging-rxjava2/build.gradle
+++ b/paging/paging-rxjava2/build.gradle
@@ -49,8 +49,6 @@
     androidTestImplementation(libs.testCore)
     androidTestImplementation(libs.testRunner)
     androidTestImplementation("androidx.arch.core:core-testing:2.2.0")
-
-    samples(project(":paging:paging-samples"))
 }
 
 androidx {
@@ -60,6 +58,7 @@
     description = "Android Paging-RXJava2"
     legacyDisableKotlinStrictApiMode = true
     metalavaK2UastEnabled = true
+    samples(project(":paging:paging-samples"))
 }
 
 android {
diff --git a/tv/tv-material/build.gradle b/tv/tv-material/build.gradle
index 95c3c1b..c055bc9 100644
--- a/tv/tv-material/build.gradle
+++ b/tv/tv-material/build.gradle
@@ -51,8 +51,6 @@
     androidTestImplementation(project(":test:screenshot:screenshot"))
     androidTestImplementation(project(":compose:material:material-icons-core"))
     androidTestImplementation(libs.testRunner)
-
-    samples(project(":tv:tv-samples"))
 }
 
 android {
@@ -70,4 +68,5 @@
     inceptionYear = "2022"
     description = "build TV applications using controls that adhere to Material Design Language."
     targetsJavaConsumers = false
+    samples(project(":tv:tv-samples"))
 }
diff --git a/wear/compose/compose-foundation/build.gradle b/wear/compose/compose-foundation/build.gradle
index 9625da5..12ec0fb 100644
--- a/wear/compose/compose-foundation/build.gradle
+++ b/wear/compose/compose-foundation/build.gradle
@@ -54,8 +54,6 @@
     androidTestImplementation(libs.testRunner)
     androidTestImplementation(libs.kotlinTest)
     androidTestImplementation(libs.truth)
-
-    samples(project(":wear:compose:compose-foundation-samples"))
 }
 
 android {
@@ -82,4 +80,5 @@
             "functionality to support wearable specific devices sizes, shapes and navigation " +
             "gestures. It builds upon the Jetpack Compose libraries."
     targetsJavaConsumers = false
+    samples(project(":wear:compose:compose-foundation-samples"))
 }
diff --git a/wear/compose/compose-material/build.gradle b/wear/compose/compose-material/build.gradle
index d5cc186..b7f87f3 100644
--- a/wear/compose/compose-material/build.gradle
+++ b/wear/compose/compose-material/build.gradle
@@ -57,8 +57,6 @@
     testImplementation(libs.testRules)
     testImplementation(libs.testRunner)
     testImplementation(libs.junit)
-
-    samples(project(":wear:compose:compose-material-samples"))
 }
 
 android {
@@ -87,4 +85,5 @@
             "Material Design UX guidelines and specifications. It builds upon the Jetpack Compose" +
             " libraries."
     targetsJavaConsumers = false
+    samples(project(":wear:compose:compose-material-samples"))
 }
diff --git a/wear/compose/compose-material3/build.gradle b/wear/compose/compose-material3/build.gradle
index 6114059..ed1edab 100644
--- a/wear/compose/compose-material3/build.gradle
+++ b/wear/compose/compose-material3/build.gradle
@@ -58,8 +58,6 @@
     testImplementation(libs.testRules)
     testImplementation(libs.testRunner)
     testImplementation(libs.junit)
-
-    samples(project(":wear:compose:compose-material-samples"))
 }
 
 android {
@@ -89,6 +87,7 @@
             "implement Wear Material 3 Design UX guidelines and specifications. It builds upon " +
             "the Jetpack Compose libraries."
     targetsJavaConsumers = false
+    samples(project(":wear:compose:compose-material-samples"))
 }
 
 tasks.withType(KotlinCompile).configureEach {
diff --git a/wear/compose/compose-navigation/build.gradle b/wear/compose/compose-navigation/build.gradle
index 653dcf4..02f0362 100644
--- a/wear/compose/compose-navigation/build.gradle
+++ b/wear/compose/compose-navigation/build.gradle
@@ -53,8 +53,6 @@
     androidTestImplementation(libs.truth)
     androidTestImplementation("androidx.lifecycle:lifecycle-runtime-testing:2.6.0")
     androidTestImplementation("androidx.navigation:navigation-testing:2.6.0")
-
-    samples(project(":wear:compose:compose-navigation-samples"))
 }
 
 android {
@@ -79,5 +77,6 @@
             "It builds upon the Jetpack Compose libraries."
     targetsJavaConsumers = false
     metalavaK2UastEnabled = true
+    samples(project(":wear:compose:compose-navigation-samples"))
 }
 
diff --git a/wear/compose/compose-ui-tooling/build.gradle b/wear/compose/compose-ui-tooling/build.gradle
index 799209c..63d6d89 100644
--- a/wear/compose/compose-ui-tooling/build.gradle
+++ b/wear/compose/compose-ui-tooling/build.gradle
@@ -36,8 +36,6 @@
     implementation(libs.kotlinStdlibCommon)
     implementation(project(":compose:ui:ui-tooling-preview"))
     implementation("androidx.wear:wear-tooling-preview:1.0.0")
-
-    samples(project(":wear:compose:compose-material-samples"))
 }
 
 android {
@@ -50,4 +48,5 @@
     inceptionYear = "2023"
     description = "Tools for Wear Composable"
     metalavaK2UastEnabled = true
+    samples(project(":wear:compose:compose-material-samples"))
 }
diff --git a/wear/watchface/watchface-editor/build.gradle b/wear/watchface/watchface-editor/build.gradle
index 8b69535..758d219 100644
--- a/wear/watchface/watchface-editor/build.gradle
+++ b/wear/watchface/watchface-editor/build.gradle
@@ -54,8 +54,6 @@
     androidTestImplementation(libs.kotlinCoroutinesTest)
     androidTestImplementation(libs.kotlinTest)
     androidTestImplementation(libs.truth)
-
-    samples(project(":wear:watchface:watchface-samples"))
 }
 
 android {
@@ -71,4 +69,5 @@
     inceptionYear = "2020"
     description = "Classes for building Android Wear watchface editors"
     metalavaK2UastEnabled = true
+    samples(project(":wear:watchface:watchface-samples"))
 }
diff --git a/wear/watchface/watchface/build.gradle b/wear/watchface/watchface/build.gradle
index 218c5a5..c9d2805 100644
--- a/wear/watchface/watchface/build.gradle
+++ b/wear/watchface/watchface/build.gradle
@@ -62,8 +62,6 @@
     testImplementation(libs.robolectric)
     testImplementation(libs.truth)
     testImplementation(libs.kotlinTest)
-
-    samples(project(":wear:watchface:watchface-samples"))
 }
 
 android {
@@ -85,4 +83,5 @@
     inceptionYear = "2020"
     description = "Android Wear Watchface"
     metalavaK2UastEnabled = true
+    samples(project(":wear:watchface:watchface-samples"))
 }
diff --git a/wear/wear-input/build.gradle b/wear/wear-input/build.gradle
index 29b0e3c..2f02755 100644
--- a/wear/wear-input/build.gradle
+++ b/wear/wear-input/build.gradle
@@ -43,8 +43,6 @@
 
     compileOnly(fileTree(dir: "../wear_stubs", include: ["com.google.android.wearable-stubs.jar"]))
     compileOnly(project(":annotation:annotation-sampled"))
-
-    samples(project(":wear:wear-input-samples"))
 }
 
 android {
@@ -64,4 +62,5 @@
     inceptionYear = "2020"
     description = "Android Wear Support Input"
     metalavaK2UastEnabled = true
+    samples(project(":wear:wear-input-samples"))
 }
diff --git a/wear/wear-phone-interactions/build.gradle b/wear/wear-phone-interactions/build.gradle
index 1d4c223..ea92bd1 100644
--- a/wear/wear-phone-interactions/build.gradle
+++ b/wear/wear-phone-interactions/build.gradle
@@ -50,8 +50,6 @@
     // Includes the wear-sdk jar
     compileOnly files("../../wear/wear_sdk/wear-sdk.jar")
     testImplementation(files("../../wear/wear_sdk/wear-sdk.jar"))
-
-    samples(project(":wear:wear-phone-interactions-samples"))
 }
 
 android {
@@ -80,4 +78,5 @@
     inceptionYear = "2021"
     description = "Android Wear Phone Interactions"
     metalavaK2UastEnabled = true
+    samples(project(":wear:wear-phone-interactions-samples"))
 }
diff --git a/wear/wear-remote-interactions/build.gradle b/wear/wear-remote-interactions/build.gradle
index 0c21be6..aae2d70 100644
--- a/wear/wear-remote-interactions/build.gradle
+++ b/wear/wear-remote-interactions/build.gradle
@@ -58,7 +58,6 @@
     // Includes the wear-sdk jar
     compileOnly files("../../wear/wear_sdk/wear-sdk.jar")
     testImplementation(files("../../wear/wear_sdk/wear-sdk.jar"))
-    samples(project(":wear:wear-remote-interactions-samples"))
 }
 
 android {
@@ -78,4 +77,5 @@
     inceptionYear = "2020"
     description = "Android Wear Remote Interactions"
     metalavaK2UastEnabled = true
+    samples(project(":wear:wear-remote-interactions-samples"))
 }