Merge "Revert^2 "Runtime micro-optimizations"" into androidx-main
diff --git a/activity/activity-compose-lint/src/main/java/androidx/activity/compose/lint/ActivityComposeIssueRegistry.kt b/activity/activity-compose-lint/src/main/java/androidx/activity/compose/lint/ActivityComposeIssueRegistry.kt
index 5eb0a32..586ba0c 100644
--- a/activity/activity-compose-lint/src/main/java/androidx/activity/compose/lint/ActivityComposeIssueRegistry.kt
+++ b/activity/activity-compose-lint/src/main/java/androidx/activity/compose/lint/ActivityComposeIssueRegistry.kt
@@ -31,7 +31,8 @@
         get() =
             listOf(
                 ActivityResultLaunchDetector.LaunchDuringComposition,
-                CollectProgressDetector.NoCollectCallFound
+                CollectProgressDetector.NoCollectCallFound,
+                LocalContextCastIssueDetector.ContextCastToActivity
             )
 
     override val vendor =
diff --git a/activity/activity-compose-lint/src/main/java/androidx/activity/compose/lint/LocalContextCastIssueDetector.kt b/activity/activity-compose-lint/src/main/java/androidx/activity/compose/lint/LocalContextCastIssueDetector.kt
new file mode 100644
index 0000000..fa22ec7
--- /dev/null
+++ b/activity/activity-compose-lint/src/main/java/androidx/activity/compose/lint/LocalContextCastIssueDetector.kt
@@ -0,0 +1,94 @@
+/*
+ * 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.activity.compose.lint
+
+import androidx.compose.lint.Name
+import androidx.compose.lint.Package
+import androidx.compose.lint.inheritsFrom
+import com.android.tools.lint.client.api.UElementHandler
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+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.intellij.psi.PsiClassOwner
+import java.util.EnumSet
+import org.jetbrains.uast.UBinaryExpressionWithType
+import org.jetbrains.uast.UQualifiedReferenceExpression
+import org.jetbrains.uast.tryResolveNamed
+import org.jetbrains.uast.util.isTypeCast
+
+class LocalContextCastIssueDetector : Detector(), SourceCodeScanner {
+    private val activityType = Name(Package("android.app"), "Activity")
+    private val contextType = Name(Package("android.content"), "Context")
+
+    override fun getApplicableUastTypes() = listOf(UBinaryExpressionWithType::class.java)
+
+    override fun createUastHandler(context: JavaContext) =
+        object : UElementHandler() {
+            override fun visitBinaryExpressionWithType(node: UBinaryExpressionWithType) {
+                // Cast expression
+                if (node.isTypeCast()) {
+                    // RHS is Activity
+                    if (node.type.inheritsFrom(activityType)) {
+                        // LHS is Context
+                        if (node.operand.getExpressionType()?.inheritsFrom(contextType) == true) {
+                            // Check to see if LHS is a call to LocalContext.current - the receiver
+                            // will be LocalContext
+                            val resolvedReceiver =
+                                (node.operand as? UQualifiedReferenceExpression)
+                                    ?.receiver
+                                    ?.tryResolveNamed() ?: return
+                            if (
+                                resolvedReceiver.name == "LocalContext" &&
+                                    (resolvedReceiver.containingFile as? PsiClassOwner)
+                                        ?.packageName == "androidx.compose.ui.platform"
+                            ) {
+                                context.report(
+                                    ContextCastToActivity,
+                                    node,
+                                    context.getNameLocation(node),
+                                    DESCRIPTION
+                                )
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+    companion object {
+        private const val DESCRIPTION =
+            "LocalContext should not be cast to Activity, use LocalActivity instead"
+        val ContextCastToActivity =
+            Issue.create(
+                "ContextCastToActivity",
+                DESCRIPTION,
+                "Casting Context to Activity is an error as Contexts are not always Activities. Use LocalActivity instead",
+                Category.CORRECTNESS,
+                3,
+                Severity.ERROR,
+                Implementation(
+                    LocalContextCastIssueDetector::class.java,
+                    EnumSet.of(Scope.JAVA_FILE, Scope.TEST_SOURCES)
+                )
+            )
+    }
+}
diff --git a/activity/activity-compose-lint/src/test/java/androidx/activity/compose/lint/LocalContextCastIssueDetectorTest.kt b/activity/activity-compose-lint/src/test/java/androidx/activity/compose/lint/LocalContextCastIssueDetectorTest.kt
new file mode 100644
index 0000000..fe8da96
--- /dev/null
+++ b/activity/activity-compose-lint/src/test/java/androidx/activity/compose/lint/LocalContextCastIssueDetectorTest.kt
@@ -0,0 +1,221 @@
+/*
+ * 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.activity.compose.lint
+
+import androidx.compose.lint.test.Stubs
+import androidx.compose.lint.test.bytecodeStub
+import com.android.tools.lint.checks.infrastructure.LintDetectorTest
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class LocalContextCastIssueDetectorTest : LintDetectorTest() {
+    override fun getDetector(): Detector = LocalContextCastIssueDetector()
+
+    override fun getIssues(): MutableList =
+        mutableListOf(LocalContextCastIssueDetector.ContextCastToActivity)
+
+    val LocalActivityStub =
+        bytecodeStub(
+            "LocalActivity.kt",
+            "androidx/activity/compose",
+            0xfc1de7e2,
+            """
+            package androidx.activity.compose
+
+            import android.app.Activity
+            import androidx.compose.runtime.compositionLocalOf
+
+            val LocalActivity = compositionLocalOf()
+        """
+                .trimIndent(),
+            """
+                META-INF/main.kotlin_module:
+                H4sIAAAAAAAA/2XLTQrCMBAF4BFBcFwUAoKCK5dS4hmKy7r0AiGNMJA/kqnU
+                2xticOPAbN77HgCsAWBVfgvtsMej8lMKNC1SaaYX8Vvq4GLIRnT3oJUdWjwy
+                Sjz8dEMyzZ7JGSFuNSCm4Ouu+Cue/vxMMlrFz5Cc6IZvW30ugz3uipNmUS5a
+                IzYPk3nkM1zgA8GrRwe+AAAA
+                """,
+            """
+                androidx/activity/compose/LocalActivityKt.class:
+                H4sIAAAAAAAA/61STW/TQBB967itY9I2LdCPlM+0QAJSN0UgJFJVqipVskgT
+                RFEvPW1sN9o0sSt7HZVbfgu/gI8L4oAijvwoxKyTgJrCpcKSd2fezns7Mzs/
+                fn79BuAZHjOUReBFofTOuXCV7En1jrth9yyMfV4LXdHZHaGv1AwYQ74teoJ3
+                RNDijWbbdwnNENry1YVohhelcu239FgxSgIluz5/HYU96Ylmx99LT6SSYZAK
+                VBkaV2Nuj0lcnJ3xcSLVHVJcr4VRi7d91YyEDGIugiBUQjNjXg9VPenoe2cn
+                Knh+pfxzyMLOwsA1Bmvb7chAqh2GTKl8xPDkn4qTOrrd8wwFdwJvnGx4/olI
+                OoqhXaqdhopu4O1el58kgTssaX9kVapObfK5qld7lRwWsGgjj+sMB//5dRbG
+                VRz4SnhCCcKMbi9DE8r0ktULGNipNgw6PJfaqpDlbTFsDvpz9qBvGyvG8LeM
+                4nJ+0C9Yi+aiUTEq7Pv7aYsiCqaVyZua9ZRh6e8J0SxfGIPNU2p09lC2AqGS
+                yGdYezOs1Ql6MpZU6e6fYWIw90KPguZrMvDrSbfpR291NxjswzCJXH9famd1
+                pHF0SQFbNDlmWm5BDxJ5G7po3MQD2qcJt1J/FVPkZfCQvFuE6s/8hNyHlPto
+                FKvXIX/mAt/CLObI1uwi0v7CZib7ghufkft4ScNAKVVZR5n2l4Qu0f3Lx8g4
+                WHGw6lC2aw4lctvBHdw9BotxD/ePMRUjG8OOUYy1Pf0LK8v1wXoEAAA=
+                """
+        )
+
+    val LocalContextStub =
+        bytecodeStub(
+            "AndroidLocals.kt",
+            "androidx/compose/ui/platform",
+            0xac8d2426,
+            """
+            package androidx.compose.ui.platform
+
+            import android.content.Context
+            import androidx.compose.runtime.staticCompositionLocalOf
+
+            val LocalContext = staticCompositionLocalOf()
+           """,
+            """
+                META-INF/main.kotlin_module:
+                H4sIAAAAAAAA/2NgYGBmYGBgBGJOBijg0uOSSMxLKcrPTKnQS87PLcgvTtUr
+                Ks0rycxNFRJyBgtklmTm5/nkJyfmeJdw6XPJYKgvzdQryEksScsvyhXid4TI
+                gtUXAzWIcnED1emlViTmFuSkCrGFpBaXeJcoMWgxAACzjsPdkAAAAA==
+                """,
+            """
+                androidx/compose/ui/platform/AndroidLocalsKt.class:
+                H4sIAAAAAAAA/61Ty07bQBQ94xhw3JQE+oBAHxRoG9oKh6pVpQYhISQkq+Eh
+                qNiwmthONMGZQfY4Ysm39Av62FRdVKjLflTVO05QBYgNqiV77uucuWfm+vef
+                Hz8BvMELhldchokS4YkXqN6xSiMvE95xzHVbJT1vfZBsqoDH6Qc9BsZQ6fI+
+                92IuO95OqxsFFC0wlDuRzss2lNTRiWZ4V1tqXiFPMqlFL/J2E9UXIW/F0Uae
+                EVoomeMbDHs3Q66egwhDPUjtDXtprBHpQlMlHa8b6VbChUw9LqXS3IBTb1vp
+                7Sw2W5cuanh7IwUlFOEWYeEWg7MaxEIKvcZQqC0dMLy8lvEyjznvMsNcatoM
+                Lmd32oth1OZZTG12a80jpWkfr9vvee1MBgNdm0Or3vCbl2+tcbPbKWECky4q
+                uMOw+/9vaeJcyFakecg1p5jV6xdoXJn5FM0HDOzIGBYlT4Sx6mSFKwzLZ6fj
+                7tmpa01bg9ex5qcqZ6czzqQ9adWtOvv1adShihnbKVRsg3rNUL22Jxr3C//A
+                8hEdd3FfdCTXWRIxzO4NFPuyL1JBetf/zRWDvaFCKio3hYy2s14rSj6aM2Fw
+                91WWBNGmME51yHFwhQErNEV2rnjGDBV5i0Y37uEpraMUd3K/ihHyCnhG3gOK
+                msf+itLnHPt8WAuMDfFjF/AObmOcbIOeR37EcJnNvuPuN5S+XOGwUMtZFrBE
+                63uK3qf9pw5R8DHto+pTt7M+NfLQxyM8PgRLMYcnhxhJUUzhpphPjT36F/cv
+                7rmKBAAA
+                """
+        )
+
+    val ContextStub =
+        bytecodeStub(
+            "Context.kt",
+            "android/content",
+            0x7e746f3f,
+            """
+            package android.content
+
+            class Context()
+        """
+                .trimIndent(),
+            """
+                META-INF/main.kotlin_module:
+                H4sIAAAAAAAA/2NgYGBmYGBgBGJOBijg0uOSSMxLKcrPTKnQS87PLcgvTtUr
+                Ks0rycxNFRJyBgtklmTm5/nkJyfmeJdw6XPJYKgvzdQryEksScsvyhXid4TI
+                gtUXAzWIcnED1emlViTmFuSkCrGFpBaXeJcoMWgxAACzjsPdkAAAAA==
+                """,
+            """
+                android/content/Context.class:
+                H4sIAAAAAAAA/3VRy04CMRQ9twODjigPH4CvtbpwgLjTmCiJCQlqooYNq8JM
+                tDw6CVMIS77FP3Bl4sIQl36U8XZk6+b0PO5tb9vvn49PAGc4IJSkDsaRCvxe
+                pE2ojd+w68xkQIR8X06lP5T62b/v9sMeuw7BvVBamUuCc3TcziIN10MKGULK
+                vKiYUGn9s+c5odAaRGaotH8bGhlII9kTo6nD45CFVQsg0ID9mbKqyiyoEQ4X
+                c88TZeGJPLPFvLyY10WVrtNfr67IC1tVJ9vrLY87HRieqREFISHXUjq8m4y6
+                4fhJdofsFFtRTw7bcqysXpreYzQZ98IbZUXlYaKNGoVtFStOr7SOjDQq0jFq
+                EHzl5aj2BRjLrPxEA+mTd6y8MRGoMLqJ6WCXMftXgFV4Sb6XYAn7yY8Q1jjL
+                duA0sd7ERhM55Jmi0EQRmx1QjC1scx7Di7ETw/0FYlRJz84BAAA=
+                """
+        )
+
+    @Test
+    fun errors() {
+        lint()
+            .files(
+                kotlin(
+                    """
+                package com.example
+
+                import android.app.Activity
+                import androidx.compose.runtime.Composable
+                import androidx.compose.ui.platform.LocalContext
+
+                class MyActivity: Activity()
+
+                @Composable
+                fun Test() {
+                    val activity: Activity = LocalContext.current as Activity
+                    val activity2 = LocalContext.current as? Activity
+                    val activity3 = LocalContext.current as? MyActivity
+                }
+            """
+                        .trimIndent()
+                ),
+                Stubs.Composable,
+                Stubs.CompositionLocal,
+                LocalContextStub,
+                ContextStub
+            )
+            .run()
+            .expect(
+                """
+                src/com/example/MyActivity.kt:11: Error: LocalContext should not be cast to Activity, use LocalActivity instead [ContextCastToActivity]
+                    val activity: Activity = LocalContext.current as Activity
+                                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+                src/com/example/MyActivity.kt:12: Error: LocalContext should not be cast to Activity, use LocalActivity instead [ContextCastToActivity]
+                    val activity2 = LocalContext.current as? Activity
+                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+                src/com/example/MyActivity.kt:13: Error: LocalContext should not be cast to Activity, use LocalActivity instead [ContextCastToActivity]
+                    val activity3 = LocalContext.current as? MyActivity
+                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+                3 errors, 0 warnings
+            """
+                    .trimIndent()
+            )
+    }
+
+    @Test
+    fun clean() {
+        lint()
+            .files(
+                kotlin(
+                    """
+                package com.example
+
+                import android.app.Activity
+                import androidx.activity.ComponentActivity
+                import androidx.activity.compose.LocalActivity
+                import androidx.compose.runtime.Composable
+                import androidx.compose.ui.platform.LocalContext
+                
+                @Composable
+                fun Test() {
+                    val context = LocalContext.current
+                    val activity: Activity = LocalActivity.current as Activity
+                    val activity2 = LocalContext.current as ComponentActivity
+                }
+                """
+                        .trimIndent()
+                ),
+                Stubs.Composable,
+                Stubs.CompositionLocal,
+                LocalActivityStub,
+                LocalContextStub,
+                ContextStub,
+                COMPONENT_ACTIVITY
+            )
+            .run()
+            .expectClean()
+    }
+}
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2DeviceCloser.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2DeviceCloser.kt
index a6081aa..2da4d5f 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2DeviceCloser.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2DeviceCloser.kt
@@ -96,9 +96,15 @@
                 Log.debug { "Empty capture session quirk completed" }
             }
         }
-        Threading.runBlockingChecked(threads.backgroundDispatcher, 5000L) {
+        Threading.runBlockingCheckedOrNull(threads.backgroundDispatcher, CAMERA_CLOSE_TIMEOUT_MS) {
             cameraDevice.closeWithTrace()
         }
+            ?: run {
+                Log.error {
+                    "Camera device close timed out after ${CAMERA_CLOSE_TIMEOUT_MS}ms. " +
+                        "The camera is likely in a bad state."
+                }
+            }
         if (camera2Quirks.shouldWaitForCameraDeviceOnClosed(cameraId)) {
             Log.debug { "Waiting for OnClosed from $cameraId" }
             if (androidCameraState.awaitCameraDeviceClosed(timeoutMillis = 5000)) {
@@ -158,4 +164,8 @@
         }
         sessionConfigured.await()
     }
+
+    companion object {
+        const val CAMERA_CLOSE_TIMEOUT_MS = 8_000L // 8s
+    }
 }
diff --git a/compose/lint/common-test/src/main/java/androidx/compose/lint/test/Stubs.kt b/compose/lint/common-test/src/main/java/androidx/compose/lint/test/Stubs.kt
index d01e748..96a6a6a 100644
--- a/compose/lint/common-test/src/main/java/androidx/compose/lint/test/Stubs.kt
+++ b/compose/lint/common-test/src/main/java/androidx/compose/lint/test/Stubs.kt
@@ -1460,6 +1460,143 @@
         RlEikLgj4eZ2WcKWWJFYlaj8BpHq1rYeAwAA
         """
         )
+
+    val CompositionLocal =
+        bytecodeStub(
+            filename = "CompositionLocal.kt",
+            filepath = "androidx/compose/runtime",
+            checksum = 0xa5bf3022,
+            """
+            package androidx.compose.runtime
+
+            sealed class CompositionLocal constructor(defaultFactory: (() -> T)? = null) {
+                val stubValue: T = defaultFactory!!.invoke()
+
+                inline val current: T
+                    @Composable get() = stubValue
+            }
+
+            abstract class ProvidableCompositionLocal internal constructor(
+                defaultFactory: (() -> T)?
+            ) : CompositionLocal(defaultFactory)
+
+            internal class DynamicProvidableCompositionLocal constructor(
+                defaultFactory: (() -> T)?
+            ) : ProvidableCompositionLocal(defaultFactory)
+
+            internal class StaticProvidableCompositionLocal(
+                defaultFactory: (() -> T)?
+            ) : ProvidableCompositionLocal(defaultFactory)
+
+            fun  compositionLocalOf(
+                defaultFactory: (() -> T)? = null
+            ): ProvidableCompositionLocal = DynamicProvidableCompositionLocal(defaultFactory)
+
+            fun  staticCompositionLocalOf(
+                defaultFactory: (() -> T)? = null
+            ): ProvidableCompositionLocal = StaticProvidableCompositionLocal(defaultFactory)
+        """,
+            """
+                META-INF/main.kotlin_module:
+                H4sIAAAAAAAA/2NgYGBmYGBgBGJOBijg0uOSSMxLKcrPTKnQS87PLcgvTtUr
+                Ks0rycxNFRJyBgtklmTm5/nkJyfmeJdw6XPJYKgvzdQryEksScsvyhXid4TI
+                gtUXAzWIcnED1emlViTmFuSkCrGFpBaXeJcoMWgxAACzjsPdkAAAAA==
+                """,
+            """
+                androidx/compose/runtime/CompositionLocal.class:
+                H4sIAAAAAAAA/5VUXW/bVBh+juPEiZu2brKOfmylZdnIBzRZ2UZZQseWUQhK
+                O0ijSKgXyHXc7jSJPfnY0biZKm74DdzyC5gEFLhA1bjjR017j5N2XVsUJkvn
+                nPfxe573eT/sf1/+9TeAW/iKIWc6bc/l7adFy+09cYVd9ALH5z27WA1t7nPX
+                qbuW2dXAGLKV5t36vtk3i13T2Ss+2tm3Lb+8dh5iMM5iGlSGWIU73F9juJat
+                d1y/y53ifr9X3A0cS0YSxfXhqVTOtUjeKK9Kodksr4W+kWyulUQMCR1R6AwL
+                p25yx7c9x+wWa47vcUdwS2hIMiStx7bV2XT9zaDbZZjOns9Ekk5gUsc4jDdJ
+                L5CjIUU5cqfvdmyGS9nceb4kLmF6DGlcZkgIP9hpmd2AnFMXuc5gNgEFcwyq
+                /5gLhkL9fzeMejDRtnfNoOuvm5bvet8zLI4qOkNjZGNq9Ysq+3AQqkq+vhfI
+                eBum17G9sDffjCR9W07Z6SWdavMedXHP9rdeVzKazdFQMOgEVwPPsx2f4fqo
+                wpk7XZsqnsG0ZM0yTGZ4ZjdzmoPVZFRNvv+AIZ2xXuv6rhcKY1h+u0RobEOt
+                U8fXNmzfbJu+SZjS60foO2VyScgFJKFD+FMurRKd2jcZnh0dzOjKjKIfHeiK
+                QYvcyVTimtzjd2aODvJq/OjAYCtKSXkwG1dTRlwxInN6Sk0pq3SdldQXP8cU
+                I9pIGbE5Ca3+86NCUGxOjWtGvJE2EiFMkE5BxgjWjfiLHxhLShUrJKzJpL7U
+                cR6nR0qzjit4+7+78LXn9nlbduGCQU6fxZY7xJbY4nuO6QceNV2tum3aJuvc
+                sTeD3o7tNSWXVCT9W6bHpT0Ex7d80+psmE+G9nxjoKLm9LngBN13HNc3wyGl
+                QdpyA8+y17l0nR26ts45qks0GNGwTSn55dL+gCwFJUIVOTm0Vgl5hAidgHT+
+                EGP5wrd/YOpPvMPwG+afhxce0joB2WSVnijRqficrMuDa7iCq3Ic6LSAd0/C
+                xOn/FMMi2dXw9x6hW8DkFfXZT4iyer7ADnFtEGCd1ghYPIykh6wqRUxgSn4A
+                Q5lFOW+0R/O/Yv6XE2GxARgKSg7PA0EDGdeJ5AaRREKSMnlIei1Syf+O3Js0
+                pPkkL1m6PAohoXaG8Iuh//tAmOPSMMdVeiurFMsXDvHh87D0km9xgJ7UKTas
+                kzwtU17y1oA7gi/D/T5qtDfI5ybpWNlGpIaParhVw23coSM+rlG0T7bBBO6i
+                vI1xgasCFYFPBRYE1gQ0gXsCNwSmBWYEMgKzAp+9AtxYnCVtBwAA
+                """,
+            """
+                androidx/compose/runtime/CompositionLocalKt.class:
+                H4sIAAAAAAAA/51UW08TQRT+ZntfCpSi0gsoQlUuyhYQVKgkBkNsKJdIgzE8
+                TbcLmV52ye62gRfD3/Bf+KbRxPTZH2U8sy1RiwXTlzNn5nzznW/PObM/fn79
+                DuApnjPMc7NsW6J8pulW/dRyDM1umK6oG9qmtxeusMyCpfPathsCY4hVeJNr
+                NW6eaHuliqHTqY8hrneh944Z3s0UqpZbE6ZWada144apy7CjbXW87PpsoWf6
+                fdtqijIv1YxuIesMZ7niWqFbyPrGTfly88Xi+kZ/WXPeVYbpgmWfaBXDLdlc
+                EDk3Tcvl7US7lrvbqEmBmetQBJEZCLbWU8jrc5PXhd5bTwgqQzAnTOFukKqb
+                S30YRRSDKgYwxLDcRwVCiDEMlY1j3qi5W1x3LfucYfKmxAypq8OR6dAwVG5U
+                nr/a6f7mJooAgioU3GFIOLIdejdGju2LntwH3p3rKpRUkZL1nexFf/nhUSTa
+                WiYYRi4rsGO4vMxdTjVT6k0fvVEmTUQaMLCqdBQKngnpZckrLzKUWxcxtXWh
+                KglFVcKKt7YuUpkYmXDcH1feKFk25Q8TTFmKhZWYL6W2jxMs6ydc4D9gMtcS
+                w0qfL5YV6Sdx+Z1/DsdoN3ihSlPh37TKBsNwQZjGbqNeMuyiJJYcEnPIbSH3
+                ncPIgTgxuduwyU+/bcvJm03hCAq/+v306F12R/e5zeuGa9h/wQap03p1h592
+                EqgHVsPWjS0hN8kOx+EVfixSQ/2yWWSTctpo1Wi3Ch/1D4h+w8D7uc8YbmHk
+                k+wlsmSDXixJtwnRxiGOUVqXPEwIyx1U2PttAyEqKCJALIJbuE1+O4kCORaD
+                af+Hjwiw7bkvGGtnWSFLCsJeuiEPNUaECSIco8SJfwlNSaHpfwid6E/o+LVC
+                7/YUmibCcSJMU3jVAy3gGa0vie0e1XjyCL487ucxlcc0Mnk8wMM8HmHmCMzB
+                LOaOEHQQcDDv4LGDuIMnDhK/AIiJIGwEBwAA
+                """,
+            """
+                androidx/compose/runtime/DynamicProvidableCompositionLocal.class:
+                H4sIAAAAAAAA/51S308TQRD+9lpaOKG0RRDwByhoBBKvoCaG1iaKITSp2EjT
+                F562dwtuudszd3sNvPVv8T/wycQH0/joH2WcbUtEE9KEl5lvZr/5dmZ2f/3+
+                /gPACzxh2OXKi0LpnTtuGHwOY+FEidIyEM67C8UD6TaisCs93vbF3oAgtQxV
+                PXS5nwVjaFSau/UO73LH5+rU+dDuCFeXq/VrZa/XqzSb5WqZ4fkNarNIM2Qq
+                UkldZVh7Wj8LtS+V0+kGzkmiXEOMnf0RKpU3Wgwb41iVrUFHhrteD6NTpyN0
+                O+KSOFypUPMh/zDxfdNTeRoZZG1MwGZI608yZqhcv4ix+6VV5DxxwhNf73NX
+                h9EFw+q4wRgKl5T3QnOPa045K+im6MWZMVPGgIGdUf5cmqhEyNtmOOj3ira1
+                aNn93r9ust9b7Pc20+TzbGeymC5aB6xkvZ0v5vKpZdvEr4jCSumfXzJWfsLo
+                7dAVTYaXN/kK1HLxcoyrs839T3x2pmnXe6EnGGbrUonDJGiLqGlEjYbhtHgk
+                TTxKTh3JU8V1EhFe/zhspaa6MpZ03OARD4QW0Zu/D8xgH4VJ5Ip9aeqXRjWt
+                YcUVIrZh0euP1ms+A1JYoahKeYt8ZnPrG259JWRhlaw9yBaoZhYPCS0MWZjG
+                zEAlgxydMDwaVExijXzWSE8RSI3SKawP/AM8Jv+aTvMkWDhGqoZiDXM13MY8
+                QSzUcAeLx2AxlrB8jEyMmRh3Y9yLkYtxP0b2D5OoO78aBAAA
+                """,
+            """
+                androidx/compose/runtime/ProvidableCompositionLocal.class:
+                H4sIAAAAAAAA/41SXU9TQRA9e1vacsFSikLBLxBEgcRbURNjK0YxjTUFURpe
+                eNr2Lrjt7V6zd2+Db/0t/gOfTHwwjY/+KONsWyKSEHzZmT1z5szszP76/f0H
+                gMe4x/CIK1+H0j/xmmHnUxgJT8fKyI7w9nTYlT5vBGJ7EJFGhqoWNnmQBmOo
+                lOvPai3e5V7A1bH3rtESTVPaql2od16lXK+XtkoMa/+dkUaSIVWWSpothuX7
+                tXZoAqm8VrfjHcWqaYmRVxl5xdLaAalfxipvDPqw3JVaqI+9ljANzSVxuFKh
+                4UP+bhwEdhbU8PtLC5+NS2WEVjzwXosjHgdmm6hGx00T6h2u20JT6Umk4LoY
+                wwRD0nyUEcOTiwd58WKouaw/LFPhtsJnhsXLmmWYPqXsCMN9bjhhTqeboD/C
+                7DFuDzCwNuEn0t6K5PkPGd72e3nXKThuv/evyawW+r31ZKbfy7HNTD6Zd96w
+                ovNqjoB8NpdYcC30tN8rsGLy55eUkxuziptUpM6w8f+/iFrNn7Z/9k0z54kP
+                2oaGux36gmGqJpXYjTsNoet2jlbDcg64lvY+Asf35bHiJtbkr3wYNlBVXRlJ
+                Cu9xzTuCdvvy7y9hcPfDWDdFRdr8+VHOwTDjDDG5BIfWPRorbT+NBBbp9oKs
+                Qza9vsG+YfIruQ6W6HQH8BWiTuAOebNDGiHZgUwaU8iR1PIgI4MVi1ntcXIS
+                IziBuwN7G6tkn1N0mrrIHyJRxUwVV6u4hllyMVdFAfOHYBEWcP0QqQjZCDci
+                3IwwFeFWhPQfROtXvEUEAAA=
+                """,
+            """
+                androidx/compose/runtime/StaticProvidableCompositionLocal.class:
+                H4sIAAAAAAAA/51SXW8SQRQ9s1A+1pZSkNrWj1aLxraJS6smKkiiTZqSYG2E
+                8MLTsDvFgWXX7M6S+sZv8R/4ZOKDIT76o4x3gMZqQpr05d5z75x75t478+v3
+                9x8AnuERw0vuOYEvnXPL9gef/FBYQeQpORBWQ3El7dPAH0qHd1xxODmXSvpe
+                3be5mwRjOK00X9V7fMgtl3td632nJ2xVrtbnqs7XqzSb5WqZ4ek1apOIMyQq
+                0pOqyrD9uN73lSs9qzccWGeRZ2tiaB3NUKm802LYuYpV2Zt0pLnFuh90rZ5Q
+                nYBL4nDP8/V6NP8kcl3dU3kRCSRNLMBkiKuPMmQoz1/EVeulTWQcccYjVx1x
+                W/nBZ4atq+ZiWLmgvBOKO1xxyhmDYYzem2mT1gYMrE/5c6mjEiFnn+F4PMqZ
+                xpphjkf/utR4tDYe7cbJZ9lBKhfPGcesZLwt5DLZ2Iap4xdEYaX4zy8JI7ug
+                9Q7oiibD8+v8BGo5dzHG5dny/xOf9BWt+tB3BMNyXXriJBp0RNDUolpDc1o8
+                kDqeJdMN2fW4igLCxQ/TVmreUIaSjk95wAdCieDN3/dlMBt+FNjiSOr69VlN
+                a1pxiYh9GPT4s/Xqv4AYNimqUt4gn9jd+4YbXwkZ2CJrTrIFqsnjPqHVKQuL
+                WJqoJJDBMik9mFSksE0+qaXTBGKzdAzFib+Hh+Rf02mWBFfaiNWQqyFfw00U
+                CGK1hltYa4OFWMdGG4kQSyFuh7gTIhPibojkH2XEsYYYBAAA
+                """
+        )
 }
 
 /**
diff --git a/compose/runtime/runtime-lint/src/test/java/androidx/compose/runtime/lint/CompositionLocalNamingDetectorTest.kt b/compose/runtime/runtime-lint/src/test/java/androidx/compose/runtime/lint/CompositionLocalNamingDetectorTest.kt
index 233445e..c4fdde3 100644
--- a/compose/runtime/runtime-lint/src/test/java/androidx/compose/runtime/lint/CompositionLocalNamingDetectorTest.kt
+++ b/compose/runtime/runtime-lint/src/test/java/androidx/compose/runtime/lint/CompositionLocalNamingDetectorTest.kt
@@ -18,7 +18,7 @@
 
 package androidx.compose.runtime.lint
 
-import androidx.compose.lint.test.bytecodeStub
+import androidx.compose.lint.test.Stubs
 import com.android.tools.lint.checks.infrastructure.LintDetectorTest
 import com.android.tools.lint.detector.api.Detector
 import com.android.tools.lint.detector.api.Issue
@@ -35,132 +35,6 @@
     override fun getIssues(): MutableList =
         mutableListOf(CompositionLocalNamingDetector.CompositionLocalNaming)
 
-    // Simplified CompositionLocal.kt stubs
-    private val compositionLocalStub =
-        bytecodeStub(
-            filename = "CompositionLocal.kt",
-            filepath = "androidx/compose/runtime",
-            checksum = 0xeda1836e,
-            """
-            package androidx.compose.runtime
-
-            sealed class CompositionLocal constructor(defaultFactory: (() -> T)? = null)
-
-            abstract class ProvidableCompositionLocal internal constructor(
-                defaultFactory: (() -> T)?
-            ) : CompositionLocal(defaultFactory)
-
-            internal class DynamicProvidableCompositionLocal constructor(
-                defaultFactory: (() -> T)?
-            ) : ProvidableCompositionLocal(defaultFactory)
-
-            internal class StaticProvidableCompositionLocal(
-                defaultFactory: (() -> T)?
-            ) : ProvidableCompositionLocal(defaultFactory)
-
-            fun  compositionLocalOf(
-                defaultFactory: (() -> T)? = null
-            ): ProvidableCompositionLocal = DynamicProvidableCompositionLocal(defaultFactory)
-
-            fun  staticCompositionLocalOf(
-                defaultFactory: (() -> T)? = null
-            ): ProvidableCompositionLocal = StaticProvidableCompositionLocal(defaultFactory)
-        """,
-            """
-        META-INF/main.kotlin_module:
-        H4sIAAAAAAAA/2NgYGBmYGBgBGJOBijg0uOSSMxLKcrPTKnQS87PLcgvTtUr
-        Ks0rycxNFRJyBgtklmTm5/nkJyfmeJdwqXHJ4FKvl5afL8QWklpc4l2ixKDF
-        AAAiXiK7cAAAAA==
-        """,
-            """
-        androidx/compose/runtime/CompositionLocal.class:
-        H4sIAAAAAAAA/5VTS08TURT+7nT6YOQxFMWCqCCofShTiRoUQlQMSZMiCk03
-        LMxlZsBL2xkyc9vgxjT+C7f+A1YkLkzD0h9lPHdalKCksjmv+51zvjPnzI+f
-        374DeAyLIcc9J/CFc2jZfuPAD10raHpSNFxrNfKFFL5X9m1eT4IxZJcrz8v7
-        vMWtOvf2rI2dfdeWSyt/hxjM87EkdIbEsvCEXGGYzZZrvqwLz9pvNazdpmer
-        TqG11rOKS7kq0euHWi5UKksrETaWzVUHkcCAgTgMBl1+ECFDofzfIxLrYcfd
-        5c26XOO29IOPDNP9aDJs9h2ldBYgPOkGHq9br7utVgkrg6bqt86DmhtE07zr
-        W/SyNdW3GTWgIa2spLKuMozN2X+w7xsRmGH+csUZRk8T1l3JHS45xbRGK0Z3
-        xpQYUAIMrEbxQ6G8IlnOI4aNTnvc0DKa0WkbmklC6Z6b0VJPM512Xk912iZb
-        0Iraq4mUnjZTmhmbNNJ6WlvstDOsqJ98TWhm/OQzYwlVdoE6VZhqmD4ldnZj
-        Ty6+ibeB3xIO36m7/7iOsfOx+ZqkQ1v1HZdhpCw8902zseMGFZWveitMlQdC
-        +b3gwJbY87hsBmQPbUlu19b5Qe/N2PKbge2uCeVMbHYpVUUo6PWl5/mSR0eg
-        z9Du4uqDIkYWLZNklrxnNLBGOp4/xpUjMjTkSCYoDOjIkxzvAjCIoahAHMMY
-        ofdChE6Z9IvCJF+VK1J5nfTIlP7pC+KsnC+wY4x1Cz+IurPU2Q5R9mgve5FA
-        as+JfOEY146i9SsG093obwaJHgNljeN6lNVlE8PDSN/HPOkXhMkQ34ltxEqY
-        LOFGCVO4SSZulXAb09tgIWZwZxvJEEMhZkPMhRgOcTdUkXu/AG89zFz4BAAA
-        """,
-            """
-        androidx/compose/runtime/CompositionLocalKt.class:
-        H4sIAAAAAAAA/51UW08TQRT+ZntfCpSiUIoXhKpclC0gqLSSGAyxoVwiDcbw
-        NN0uZHrZJbvbBl4Mf8N/4ZtGE9Nnf5TxzLZELZSavpw5M+eb73x7zpn9+evb
-        DwDP8IJhgZsl2xKlM023aqeWY2h23XRFzdA2vb1whWXmLZ1Xt90QGEOszBtc
-        q3LzRNsrlg2dTn0Mcb0DvXfM8H42X7HcqjC1cqOmHddNXYYdbavtpTNz+a7p
-        922rIUq8WDU6hWQYzrKF9XynkMxGr3zZhUIhs9Ff1qx3lWEmb9knWtlwizYX
-        RM5N03J5K9Gu5e7Wq1Jg6iYUQWQGgq13FfLm3OQ1oXfXE4LKEMwKU7gbpKp3
-        qQ+jiGJQxQCGGFb6qEAIMYahknHM61V3i+uuZZ8zTPVKzJC8OhypNg1Duafy
-        3NVO9zc3UQQQVKFgjCHhyHbonRg5ti+7ch94d26q0ISKpKzvVDf6yw+PItHS
-        cpdh5LICO4bLS9zlVDOl1vDRG2XSRKQBA6tIR6HgmZBemrzSEkOpeRFTmxeq
-        klBUJax4a/MimYqRCcf9ceWtkmbT/jDBlOVYWIn5kmrrOMHSfsIF/gMmcy0z
-        rPb5YlmBfhKX3/n3cIx2ghcrNBX+TatkMAznhWns1mtFwy5IYskhMYfcFnLf
-        PowciBOTu3Wb/Ml3LTk5syEcQeHXf54evcvO6D63ec1wDfsf2CB1Wq/s8NN2
-        AvXAqtu6sSXkZqLNcXiFH0vUUL9sFtkJOW20arRbg4/6B0S/Y+DD/BcMNzHy
-        WfYSabJBL3aLbhOihUMco7Que5gQVtqosPfbBkJUUESAWISu3Sa/lUSBHIvB
-        Sf/HTwiw7fmvGG9lWSVLCsJeuiEPFSfCUSKMk9DEdUKTUujkNUIT/Qm9c6PQ
-        e12FjhHhOBGOUXjNAy3iOa2viO0+1XjqCL4cHuQwncMMUjk8xKMcHmP2CMzB
-        HOaPEHQQcLDg4ImDuIOnDhK/AezqFjcEBwAA
-        """,
-            """
-        androidx/compose/runtime/DynamicProvidableCompositionLocal.class:
-        H4sIAAAAAAAA/51SXU8TQRQ9sy0tXaGUIljwAxQ0AolbUBNDaxPFEJpUJNLw
-        wtN0d6jT7s6a3dkG3vpb/Ac+mfhgGh/9UcY7bYloQkh4mXvumXPP3Lkzv35/
-        /wHgBZ4w7HDlRaH0zhw3DD6HsXCiRGkZCOfdueKBdA+jsCc93vLF7lAgtQxV
-        I3S5nwVjOKw2dxod3uOOz1Xb+dDqCFdXao0rba/2qzablVqF4fkNarNIM2Sq
-        UkldY1h92uiG2pfK6fQC5zRRrhHGzt4YlSvrxwzr16mqm8OOjHatEUZtpyN0
-        K+KSNFypUPOR/iDxfdNTZQoZZG1MwGZI608yZqhePYhr50ujyHvilCe+3uOu
-        DqNzhpXrLsYweyF5LzT3uObEWUEvRS/OzJIzCxhYl/gzabIyIW+LYX/QL9pW
-        ybIH/X/D5KBfGvQ30hQLbHuymC5a+6xsvZ0v5gupJdvkr0jCyumfXzJWYcL4
-        bdMRTYaXN/kK1HLx4hqX7zb3v/BZV9Osd0NPMMw0pBIHSdASUdOYGg+jOeaR
-        NPmYzB3JtuI6iQivfRy1Ulc9GUvaPuQRD4QW0Zu/D8xgH4VJ5Io9aeoXxzXH
-        o4pLQmzBotcfj9d8BqSwTFmNeItiZmPzG259JWRhhVZ7yE6ZH4OHhBZGKmKm
-        hy4Z5DFDTo+GFZNYpZg11jkCqTGdwtowPsBjiq9pt0CGsydI1VGsY66O25gn
-        iIU67qB0AhZjEUsnyMSYjnE3xr0Y+Rj3Y2T/AJbWL04aBAAA
-        """,
-            """
-        androidx/compose/runtime/ProvidableCompositionLocal.class:
-        H4sIAAAAAAAA/41SXU9TQRA9e1vacsVSikLBLxBEgcRbURNjK0YxjTUFURpe
-        eNr2Lrjt7V6zd2+Db/0t/gOfTHwwjY/+KONsWyKSEHjZmT1z5szszP7+8+Mn
-        gCe4z/CYK1+H0j/2mmHncxgJT8fKyI7wdnXYlT5vBGJrEJFGhqoWNnmQBmOo
-        lOvPay3e5V7A1ZH3vtESTVParJ2rd1alXK+XNksMq5fOSCPJkCpLJc0mw9KD
-        Wjs0gVReq9vxDmPVtMTIq4y8Yml1n9QvYpXXB31Y7nIt1EdeS5iG5pI4XKnQ
-        8CF/Jw4COwtq+MOFhU/HpTJCKx54b8QhjwOzRVSj46YJ9TbXbaGp9ARScF2M
-        4QpD0nySEcPT8wd5/mKouaw/LFPhtsIXhoWLmmWYOqFsC8N9bjhhTqeboD/C
-        7DFuDzCwNuHH0t6K5PmPGN71e3nXKThuv/e/yawU+r21ZKbfy7GNTD6Zd96y
-        ovN6loB8NpeYdy30rN8rsGLy19eUkxuzihtUpM6wfvlfRK3mT9o//abps8SH
-        bUPD3Qp9wTBZk0rsxJ2G0HU7R6thOftcS3sfgeN78khxE2vylz8OG6iqrowk
-        hXe55h1Bu33175cwuHthrJuiIm3+3Chnf5hxiphchEPrHo2Vtp9GAgt0e0nW
-        IZteW2ffMfGNXAeLdLoDOEPUFO6SNzOk4SqyA5k0JpEjqaVBRgbLFrPa4+Qk
-        RnAC9wb2DlbIvqDoFHWRP0CiiukqrlVxHTPkYraKAuYOwCLM48YBUhGyEW5G
-        uBVhMsLtCOm/jQDw8EUEAAA=
-        """,
-            """
-        androidx/compose/runtime/StaticProvidableCompositionLocal.class:
-        H4sIAAAAAAAA/51SXW8SQRQ9s1A+1pZSaiutH60WjW0Tl1ZNVJBEmzQlwUqE
-        8MLTsDvFgWXX7M6S+sZv8R/4ZOKDIT76o4x3gMZqQpr0Ze65Z849c+fO/Pr9
-        /QeAZ3jE8JJ7TuBL59yy/cEnPxRWEHlKDoTVUFxJux74Q+nwjiuOJvtSSd+r
-        +TZ3k2AM9XLzVa3Hh9xyude13nd6wlalSm2u63y/crNZqpQYnl6jNok4Q6Is
-        PakqDDuPa31fudKzesOBdRZ5thaG1vEMFUu7LYbdq1Tl/UlHWluo+UHX6gnV
-        CbgkDfc8X49H608j19U9lRaRQNLEAkyGuPooQ4bS/EFcNV6aRMYRZzxy1TG3
-        lR98Zti+6l4MKxeSd0JxhytOnDEYxui9mV7SegED6xN/LnVWJOQcMJyMRznT
-        yBvmePRvSI1H+fFoL04xyw5TuXjOOGFF4+1aLpONbZo6f0ESVoz//JIwsgva
-        75COaDI8v85PoJZzF9e4fLfV/4VP+opGfeQ7gmG5Jj1xGg06ImhqU+2hNS0e
-        SJ3PyHRDdj2uooBw4cO0lao3lKGk7ToP+EAoEbz5+74MZsOPAlscS12/Matp
-        TSsuCXEAgx5/Nl79FxDDFmUV4g2Kib39b7jxlZCBbVrNCZulmgzuE1qfqrCI
-        pYlLgvhlcnowqUhhh2JSW6cJxGZ0DIVJvIeHFF/TrjZcaSNWRa6K1SpuYo0g
-        1qu4hXwbLMQGNttIhFgKcTvEnRCZEHdDJP8AhWEFiBgEAAA=
-        """
-        )
-
     @Test
     fun noLocalPrefix() {
         lint()
@@ -187,7 +61,7 @@
                 }
             """
                 ),
-                compositionLocalStub
+                Stubs.CompositionLocal
             )
             .run()
             .expect(
@@ -229,7 +103,7 @@
                 }
             """
                 ),
-                compositionLocalStub
+                Stubs.CompositionLocal
             )
             .run()
             .expectClean()
diff --git a/compose/ui/ui-lint/src/test/java/androidx/compose/ui/lint/SuspiciousCompositionLocalModifierReadDetectorTest.kt b/compose/ui/ui-lint/src/test/java/androidx/compose/ui/lint/SuspiciousCompositionLocalModifierReadDetectorTest.kt
index f4c3192..3b1f2d1 100644
--- a/compose/ui/ui-lint/src/test/java/androidx/compose/ui/lint/SuspiciousCompositionLocalModifierReadDetectorTest.kt
+++ b/compose/ui/ui-lint/src/test/java/androidx/compose/ui/lint/SuspiciousCompositionLocalModifierReadDetectorTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.ui.lint
 
+import androidx.compose.lint.test.Stubs
 import androidx.compose.ui.lint.SuspiciousCompositionLocalModifierReadDetector.Companion.SuspiciousCompositionLocalModifierRead
 import com.android.tools.lint.checks.infrastructure.LintDetectorTest
 import com.android.tools.lint.detector.api.Detector
@@ -64,29 +65,6 @@
         """
         )
 
-    private val CompositionLocalStub =
-        kotlin(
-            """
-            package androidx.compose.runtime
-
-            import java.lang.RuntimeException
-
-            class CompositionLocal(defaultFactory: () -> T)
-
-            class ProvidedValue internal constructor(
-                val compositionLocal: CompositionLocal,
-                val value: T,
-                val canOverride: Boolean
-            )
-
-            fun  compositionLocalOf(defaultFactory: () -> T): CompositionLocal =
-                throw RuntimeException("Not implemented in lint stubs.")
-
-            fun  staticCompositionLocalOf(defaultFactory: () -> T): CompositionLocal =
-                throw RuntimeException("Not implemented in lint stubs.")
-        """
-        )
-
     @Test
     fun testCompositionLocalReadInModifierAttachAndDetach() {
         lint()
@@ -116,7 +94,7 @@
                 }
             """
                 ),
-                CompositionLocalStub,
+                Stubs.CompositionLocal,
                 CompositionLocalConsumerModifierStub,
                 ModifierNodeStub
             )
@@ -167,7 +145,7 @@
                 }
             """
                 ),
-                CompositionLocalStub,
+                Stubs.CompositionLocal,
                 CompositionLocalConsumerModifierStub,
                 ModifierNodeStub
             )
@@ -201,7 +179,7 @@
                 }
             """
                 ),
-                CompositionLocalStub,
+                Stubs.CompositionLocal,
                 CompositionLocalConsumerModifierStub,
                 ModifierNodeStub
             )
@@ -243,7 +221,7 @@
                 }
             """
                 ),
-                CompositionLocalStub,
+                Stubs.CompositionLocal,
                 CompositionLocalConsumerModifierStub,
                 ModifierNodeStub
             )
@@ -275,7 +253,7 @@
                 }
             """
                 ),
-                CompositionLocalStub,
+                Stubs.CompositionLocal,
                 CompositionLocalConsumerModifierStub,
                 ModifierNodeStub
             )
@@ -319,7 +297,7 @@
                 }
             """
                 ),
-                CompositionLocalStub,
+                Stubs.CompositionLocal,
                 CompositionLocalConsumerModifierStub,
                 ModifierNodeStub
             )
diff --git a/constraintlayout/constraintlayout-compose/integration-tests/demos/src/main/java/androidx/constraintlayout/compose/demos/AllDemos.kt b/constraintlayout/constraintlayout-compose/integration-tests/demos/src/main/java/androidx/constraintlayout/compose/demos/AllDemos.kt
index d3330d3..74ee699 100644
--- a/constraintlayout/constraintlayout-compose/integration-tests/demos/src/main/java/androidx/constraintlayout/compose/demos/AllDemos.kt
+++ b/constraintlayout/constraintlayout-compose/integration-tests/demos/src/main/java/androidx/constraintlayout/compose/demos/AllDemos.kt
@@ -16,8 +16,8 @@
 
 package androidx.constraintlayout.compose.demos
 
-import android.app.Activity
 import androidx.activity.compose.BackHandler
+import androidx.activity.compose.LocalActivity
 import androidx.compose.foundation.background
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.layout.Arrangement
@@ -46,7 +46,6 @@
 import androidx.compose.ui.draw.clip
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.graphicsLayer
-import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
@@ -159,7 +158,7 @@
         }
     }
 
-    val activity = LocalContext.current as? Activity
+    val activity = LocalActivity.current
     // If there's a demo being displayed, return to demo list, otherwise, exit app
     BackHandler {
         if (displayedDemoIndex >= 0) {
diff --git a/libraryversions.toml b/libraryversions.toml
index 99b1bb5c..00fd408 100644
--- a/libraryversions.toml
+++ b/libraryversions.toml
@@ -7,7 +7,7 @@
 ARCH_CORE = "2.3.0-alpha01"
 ASYNCLAYOUTINFLATER = "1.1.0-alpha02"
 AUTOFILL = "1.3.0-beta01"
-BENCHMARK = "1.4.0-alpha03"
+BENCHMARK = "1.4.0-alpha04"
 BIOMETRIC = "1.4.0-alpha02"
 BLUETOOTH = "1.0.0-alpha02"
 BROWSER = "1.9.0-alpha01"
@@ -19,12 +19,12 @@
 CAMERA_VIEWFINDER = "1.4.0-alpha09"
 CARDVIEW = "1.1.0-alpha01"
 CAR_APP = "1.7.0-beta02"
-COLLECTION = "1.5.0-alpha04"
-COMPOSE = "1.8.0-alpha04"
+COLLECTION = "1.5.0-alpha05"
+COMPOSE = "1.8.0-alpha05"
 COMPOSE_MATERIAL3 = "1.4.0-alpha02"
 COMPOSE_MATERIAL3_ADAPTIVE = "1.1.0-alpha05"
 COMPOSE_MATERIAL3_COMMON = "1.0.0-alpha01"
-COMPOSE_RUNTIME = "1.8.0-alpha04"
+COMPOSE_RUNTIME = "1.8.0-alpha05"
 CONSTRAINTLAYOUT = "2.2.0-beta01"
 CONSTRAINTLAYOUT_COMPOSE = "1.1.0-beta01"
 CONSTRAINTLAYOUT_CORE = "1.1.0-beta01"
@@ -91,7 +91,7 @@
 LEANBACK_TAB = "1.1.0-beta01"
 LEGACY = "1.1.0-alpha01"
 LIBYUV = "0.1.0-dev01"
-LIFECYCLE = "2.9.0-alpha05"
+LIFECYCLE = "2.9.0-alpha06"
 LIFECYCLE_EXTENSIONS = "2.2.0"
 LINT = "1.0.0-alpha02"
 LOADER = "1.2.0-alpha01"
@@ -117,9 +117,9 @@
 RECYCLERVIEW_SELECTION = "1.2.0-alpha02"
 REMOTECALLBACK = "1.0.0-alpha02"
 RESOURCEINSPECTION = "1.1.0-alpha01"
-ROOM = "2.7.0-alpha10"
+ROOM = "2.7.0-alpha11"
 SAFEPARCEL = "1.0.0-alpha01"
-SAVEDSTATE = "1.3.0-alpha03"
+SAVEDSTATE = "1.3.0-alpha04"
 SECURITY = "1.1.0-alpha07"
 SECURITY_APP_AUTHENTICATOR = "1.0.0-rc01"
 SECURITY_APP_AUTHENTICATOR_TESTING = "1.0.0-rc01"
@@ -133,7 +133,7 @@
 SLICE_BUILDERS_KTX = "1.0.0-alpha09"
 SLICE_REMOTECALLBACK = "1.0.0-alpha01"
 SLIDINGPANELAYOUT = "1.3.0-alpha01"
-SQLITE = "2.5.0-alpha10"
+SQLITE = "2.5.0-alpha11"
 SQLITE_INSPECTOR = "2.1.0-alpha01"
 STABLE_AIDL = "1.0.0-alpha01"
 STARTUP = "1.2.0-rc01"
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/ext/xelement_ext.kt b/room/room-compiler/src/main/kotlin/androidx/room/ext/xelement_ext.kt
index 28f9f0c..bf4537a 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/ext/xelement_ext.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/ext/xelement_ext.kt
@@ -16,8 +16,10 @@
 
 package androidx.room.ext
 
+import androidx.room.compiler.processing.XConstructorElement
 import androidx.room.compiler.processing.XElement
 import androidx.room.compiler.processing.XExecutableParameterElement
+import androidx.room.compiler.processing.XFieldElement
 import androidx.room.compiler.processing.XTypeElement
 import kotlin.contracts.contract
 
@@ -26,7 +28,7 @@
     return this.hasAnnotation(androidx.room.Entity::class)
 }
 
-fun XTypeElement.getValueClassUnderlyingElement(): XExecutableParameterElement {
+fun XTypeElement.getValueClassUnderlyingInfo(): ValueClassInfo {
     check(this.isValueClass()) {
         "Can't get value class property, type element '$this' is not a value class"
     }
@@ -34,12 +36,21 @@
     // * Primary constructor is required for value class
     // * Value class must have exactly one primary constructor parameter
     // * Value class primary constructor must only have final read-only (val) property parameter
-    return checkNotNull(this.findPrimaryConstructor()) {
+    val constructor =
+        checkNotNull(this.findPrimaryConstructor()) {
             "Couldn't find primary constructor for value class."
         }
-        .parameters
-        .single()
+    val param = constructor.parameters.first()
+    val field = getDeclaredFields().first { it.name == param.name }
+    return ValueClassInfo(constructor, param, field)
 }
 
+/** Store information about the underlying value property of a Kotlin value class */
+class ValueClassInfo(
+    val constructor: XConstructorElement,
+    val parameter: XExecutableParameterElement,
+    val field: XFieldElement,
+)
+
 /** Suffix of the Kotlin synthetic class created interface method implementations. */
 const val DEFAULT_IMPLS_CLASS_NAME = "DefaultImpls"
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
index 798bfeb..86c5e95 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
@@ -28,7 +28,7 @@
 import androidx.room.ext.CollectionTypeNames.LONG_SPARSE_ARRAY
 import androidx.room.ext.CommonTypeNames
 import androidx.room.ext.GuavaTypeNames
-import androidx.room.ext.getValueClassUnderlyingElement
+import androidx.room.ext.getValueClassUnderlyingInfo
 import androidx.room.ext.isByteBuffer
 import androidx.room.ext.isEntityElement
 import androidx.room.ext.isNotByte
@@ -377,12 +377,15 @@
         val typeElement = type.typeElement
         if (typeElement?.isValueClass() == true) {
             // Extract the type value of the Value class element
-            val underlyingProperty = typeElement.getValueClassUnderlyingElement()
+            val underlyingInfo = typeElement.getValueClassUnderlyingInfo()
+            if (underlyingInfo.constructor.isPrivate() || underlyingInfo.field.getter == null) {
+                return null
+            }
             val underlyingTypeColumnAdapter =
                 findColumnTypeAdapter(
                     // Find an adapter for the non-null underlying type, nullability will be handled
                     // by the value class adapter.
-                    out = underlyingProperty.asMemberOf(type).makeNonNullable(),
+                    out = underlyingInfo.parameter.asMemberOf(type).makeNonNullable(),
                     affinity = affinity,
                     skipDefaultConverter = false
                 ) ?: return null
@@ -391,7 +394,7 @@
                 valueTypeColumnAdapter = underlyingTypeColumnAdapter,
                 affinity = underlyingTypeColumnAdapter.typeAffinity,
                 out = type,
-                valuePropertyName = underlyingProperty.name
+                valuePropertyName = underlyingInfo.parameter.name
             )
         }
         return when {
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/ext/ElementExtTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/ext/ElementExtTest.kt
index 1e314bf..db835d4 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/ext/ElementExtTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/ext/ElementExtTest.kt
@@ -24,7 +24,7 @@
 import androidx.room.compiler.processing.util.Source
 import androidx.room.compiler.processing.util.XTestInvocation
 import androidx.room.compiler.processing.util.compileFiles
-import androidx.room.runKspTestWithK1
+import androidx.room.compiler.processing.util.runKspTest
 import androidx.room.runProcessorTestWithK1
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -225,25 +225,44 @@
                 """
             package foo
             class Subject {
-              fun makeULong(): ULong {
-                TODO()
-              }
+              fun uLongFunction(): ULong = TODO()
+              fun durationFunction(): kotlin.time.Duration = TODO()
             }
             """
                     .trimIndent()
             )
-        runKspTestWithK1(
+        runKspTest(
             sources = listOf(src),
             config =
                 XProcessingEnvConfig.DEFAULT.copy(excludeMethodsWithInvalidJvmSourceNames = false)
         ) { invocation ->
             val subject = invocation.processingEnv.requireTypeElement("foo.Subject")
-            val returnType =
-                subject.getDeclaredMethods().single { it.name == "makeULong" }.returnType
-            val prop = checkNotNull(returnType.typeElement).getValueClassUnderlyingElement()
-            assertThat(prop.name).isEqualTo("data")
-            assertThat(prop.type)
-                .isEqualTo(invocation.processingEnv.requireType(XTypeName.PRIMITIVE_LONG))
+            subject
+                .getDeclaredMethods()
+                .first { it.name == "uLongFunction" }
+                .let { uLongFunction ->
+                    val returnType = uLongFunction.returnType
+                    val info = checkNotNull(returnType.typeElement).getValueClassUnderlyingInfo()
+                    assertThat(info.parameter.name).isEqualTo("data")
+                    assertThat(info.field.name).isEqualTo("data")
+                    assertThat(info.parameter.type)
+                        .isEqualTo(invocation.processingEnv.requireType(XTypeName.PRIMITIVE_LONG))
+                    assertThat(info.field.type)
+                        .isEqualTo(invocation.processingEnv.requireType(XTypeName.PRIMITIVE_LONG))
+                }
+            subject
+                .getDeclaredMethods()
+                .first { it.name == "durationFunction" }
+                .let { durationFunction ->
+                    val returnType = durationFunction.returnType
+                    val info = checkNotNull(returnType.typeElement).getValueClassUnderlyingInfo()
+                    assertThat(info.parameter.name).isEqualTo("rawValue")
+                    assertThat(info.field.name).isEqualTo("rawValue")
+                    assertThat(info.parameter.type)
+                        .isEqualTo(invocation.processingEnv.requireType(XTypeName.PRIMITIVE_LONG))
+                    assertThat(info.field.type)
+                        .isEqualTo(invocation.processingEnv.requireType(XTypeName.PRIMITIVE_LONG))
+                }
         }
     }
 
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
index 29cbd79..d43a813 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
@@ -30,6 +30,7 @@
 import androidx.room.compiler.processing.util.Source
 import androidx.room.compiler.processing.util.XTestInvocation
 import androidx.room.compiler.processing.util.compileFiles
+import androidx.room.compiler.processing.util.runKspTest
 import androidx.room.compiler.processing.util.runProcessorTest
 import androidx.room.ext.CommonTypeNames
 import androidx.room.ext.GuavaUtilConcurrentTypeNames
@@ -195,7 +196,6 @@
             Source.java(
                 "foo.bar.Fruit",
                 """ package foo.bar;
-                import androidx.room.*;
                 enum Fruit {
                     APPLE,
                     BANANA,
@@ -222,7 +222,6 @@
             Source.kotlin(
                 "Foo.kt",
                 """
-            import androidx.room.*
             @JvmInline
             value class IntValueClass(val data: Int)
             @JvmInline
@@ -282,7 +281,6 @@
             Source.kotlin(
                 "Foo.kt",
                 """
-            import androidx.room.*
             @JvmInline
             value class Foo(val value : Int) {
                 val double
@@ -292,15 +290,78 @@
                     .trimIndent()
             )
 
-        runProcessorTestWithK1(sources = listOf(source)) { invocation ->
-            TypeAdapterStore.create(
-                context = invocation.context,
-                builtInConverterFlags = BuiltInConverterFlags.DEFAULT
-            )
+        runKspTest(sources = listOf(source)) { invocation ->
+            val store =
+                TypeAdapterStore.create(
+                    context = invocation.context,
+                    builtInConverterFlags = BuiltInConverterFlags.DEFAULT
+                )
             val typeElement = invocation.processingEnv.requireTypeElement("Foo")
-            assertThat(typeElement.getDeclaredFields()).hasSize(1)
-            assertThat(typeElement.getDeclaredFields().single().type.asTypeName())
-                .isEqualTo(PRIMITIVE_INT)
+            val result =
+                store.findColumnTypeAdapter(
+                    out = typeElement.type,
+                    affinity = null,
+                    skipDefaultConverter = false
+                )
+            assertThat(result).isInstanceOf()
+        }
+    }
+
+    @Test
+    fun testValueClassWithPrivateVal() {
+        val source =
+            Source.kotlin(
+                "Foo.kt",
+                """
+            @JvmInline
+            value class Foo(private val value : Int)
+            """
+                    .trimIndent()
+            )
+
+        runKspTest(sources = listOf(source)) { invocation ->
+            val store =
+                TypeAdapterStore.create(
+                    context = invocation.context,
+                    builtInConverterFlags = BuiltInConverterFlags.DEFAULT
+                )
+            val typeElement = invocation.processingEnv.requireTypeElement("Foo")
+            val result =
+                store.findColumnTypeAdapter(
+                    out = typeElement.type,
+                    affinity = null,
+                    skipDefaultConverter = false
+                )
+            assertThat(result).isNull()
+        }
+    }
+
+    @Test
+    fun testValueClassWithPrivateConstructor() {
+        val source =
+            Source.kotlin(
+                "Foo.kt",
+                """
+            @JvmInline
+            value class Foo private constructor(val value : Int)
+            """
+                    .trimIndent()
+            )
+
+        runKspTest(sources = listOf(source)) { invocation ->
+            val store =
+                TypeAdapterStore.create(
+                    context = invocation.context,
+                    builtInConverterFlags = BuiltInConverterFlags.DEFAULT
+                )
+            val typeElement = invocation.processingEnv.requireTypeElement("Foo")
+            val result =
+                store.findColumnTypeAdapter(
+                    out = typeElement.type,
+                    affinity = null,
+                    skipDefaultConverter = false
+                )
+            assertThat(result).isNull()
         }
     }