Merge "Add isSubmatchSupported to check if MatchInfo#getSubmatch works." into androidx-main
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/interoperability/InteropArchitecture.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/interoperability/InteropArchitecture.kt
index 67043c8..e660af9 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/interoperability/InteropArchitecture.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/interoperability/InteropArchitecture.kt
@@ -29,8 +29,6 @@
 import android.util.AttributeSet
 import android.widget.LinearLayout
 import android.widget.TextView
-import androidx.activity.OnBackPressedCallback
-import androidx.activity.OnBackPressedDispatcher
 import androidx.activity.compose.setContent
 import androidx.appcompat.app.AppCompatActivity
 import androidx.compose.foundation.layout.Column
@@ -38,13 +36,11 @@
 import androidx.compose.material.Text
 import androidx.compose.material.TextField
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.SideEffect
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.livedata.observeAsState
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberUpdatedState
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.platform.ComposeView
 import androidx.lifecycle.LiveData
@@ -126,41 +122,20 @@
 
 private object InteropArchitectureSnippet3 {
     @Composable
-    fun BackHandler(
-        enabled: Boolean,
-        backDispatcher: OnBackPressedDispatcher,
-        onBack: () -> Unit
-    ) {
-
-        // Safely update the current `onBack` lambda when a new one is provided
-        val currentOnBack by rememberUpdatedState(onBack)
-
-        // Remember in Composition a back callback that calls the `onBack` lambda
-        val backCallback = remember {
-            // Always intercept back events. See the SideEffect for a more complete version
-            object : OnBackPressedCallback(true) {
-                override fun handleOnBackPressed() {
-                    currentOnBack()
-                }
-            }
+    fun rememberAnalytics(user: User): FirebaseAnalytics {
+        val analytics: FirebaseAnalytics = remember {
+            // START - DO NOT COPY IN CODE SNIPPET
+            FirebaseAnalytics()
+            // END - DO NOT COPY IN CODE SNIPPET, just use /* ... */
         }
 
-        // On every successful composition, update the callback with the `enabled` value
-        // to tell `backCallback` whether back events should be intercepted or not
+        // On every successful composition, update FirebaseAnalytics with
+        // the userType from the current User, ensuring that future analytics
+        // events have this metadata attached
         SideEffect {
-            backCallback.isEnabled = enabled
+            analytics.setUserProperty("userType", user.userType)
         }
-
-        // If `backDispatcher` changes, dispose and reset the effect
-        DisposableEffect(backDispatcher) {
-            // Add callback to the backDispatcher
-            backDispatcher.addCallback(backCallback)
-
-            // When the effect leaves the Composition, remove the callback
-            onDispose {
-                backCallback.remove()
-            }
-        }
+        return analytics
     }
 }
 
@@ -215,3 +190,8 @@
         return GreetingViewModel(userId) as T
     }
 }
+
+private class User(val userType: String = "user")
+private class FirebaseAnalytics {
+    fun setUserProperty(name: String, value: String) {}
+}
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/sideeffects/SideEffects.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/sideeffects/SideEffects.kt
index 98c63c6..d5a5c46 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/sideeffects/SideEffects.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/sideeffects/SideEffects.kt
@@ -21,8 +21,6 @@
 
 package androidx.compose.integration.docs.sideeffects
 
-import androidx.activity.OnBackPressedCallback
-import androidx.activity.OnBackPressedDispatcher
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.fillMaxSize
@@ -49,12 +47,23 @@
 import androidx.compose.runtime.rememberUpdatedState
 import androidx.compose.runtime.snapshotFlow
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalLifecycleOwner
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleEventObserver
+import androidx.lifecycle.LifecycleOwner
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.launch
+import kotlin.Boolean
+import kotlin.Exception
+import kotlin.Long
+import kotlin.Nothing
+import kotlin.String
+import kotlin.Suppress
+import kotlin.Unit
 import kotlin.random.Random
 
 /**
@@ -142,61 +151,56 @@
 
 private object SideEffectsSnippet4 {
     @Composable
-    fun BackHandler(backDispatcher: OnBackPressedDispatcher, onBack: () -> Unit) {
+    fun HomeScreen(
+        lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
+        onStart: () -> Unit, // Send the 'started' analytics event
+        onStop: () -> Unit // Send the 'stopped' analytics event
+    ) {
+        // Safely update the current lambdas when a new one is provided
+        val currentOnStart by rememberUpdatedState(onStart)
+        val currentOnStop by rememberUpdatedState(onStop)
 
-        // Safely update the current `onBack` lambda when a new one is provided
-        val currentOnBack by rememberUpdatedState(onBack)
-
-        // Remember in Composition a back callback that calls the `onBack` lambda
-        val backCallback = remember {
-            // Always intercept back events. See the SideEffect for a more complete version
-            object : OnBackPressedCallback(true) {
-                override fun handleOnBackPressed() {
-                    currentOnBack()
+        // If `lifecycleOwner` changes, dispose and reset the effect
+        DisposableEffect(lifecycleOwner) {
+            // Create an observer that triggers our remembered callbacks
+            // for sending analytics events
+            val observer = LifecycleEventObserver { _, event ->
+                if (event == Lifecycle.Event.ON_START) {
+                    currentOnStart()
+                } else if (event == Lifecycle.Event.ON_STOP) {
+                    currentOnStop()
                 }
             }
-        }
 
-        // If `backDispatcher` changes, dispose and reset the effect
-        DisposableEffect(backDispatcher) {
-            // Add callback to the backDispatcher
-            backDispatcher.addCallback(backCallback)
+            // Add the observer to the lifecycle
+            lifecycleOwner.lifecycle.addObserver(observer)
 
-            // When the effect leaves the Composition, remove the callback
+            // When the effect leaves the Composition, remove the observer
             onDispose {
-                backCallback.remove()
+                lifecycleOwner.lifecycle.removeObserver(observer)
             }
         }
+
+        /* Home screen content */
     }
 }
 
 private object SideEffectsSnippet5 {
     @Composable
-    fun BackHandler(
-        backDispatcher: OnBackPressedDispatcher,
-        enabled: Boolean = true, // Whether back events should be intercepted or not
-        onBack: () -> Unit
-    ) {
-        // START - DO NOT COPY IN CODE SNIPPET
-        val currentOnBack by rememberUpdatedState(onBack)
-
-        val backCallback = remember {
-            // Always intercept back events. See the SideEffect for a more complete version
-            object : OnBackPressedCallback(true) {
-                override fun handleOnBackPressed() {
-                    currentOnBack()
-                }
-            }
+    fun rememberAnalytics(user: User): FirebaseAnalytics {
+        val analytics: FirebaseAnalytics = remember {
+            // START - DO NOT COPY IN CODE SNIPPET
+            FirebaseAnalytics()
+            // END - DO NOT COPY IN CODE SNIPPET, just use /* ... */
         }
-        // END - DO NOT COPY IN CODE SNIPPET, just use /* ... */
 
-        // On every successful composition, update the callback with the `enabled` value
-        // to tell `backCallback` whether back events should be intercepted or not
+        // On every successful composition, update FirebaseAnalytics with
+        // the userType from the current User, ensuring that future analytics
+        // events have this metadata attached
         SideEffect {
-            backCallback.isEnabled = enabled
+            analytics.setUserProperty("userType", user.userType)
         }
-
-        /* Rest of the code */
+        return analytics
     }
 }
 
@@ -269,24 +273,29 @@
 
 private object SideEffectsSnippet9 {
     @Composable
-    fun BackHandler(backDispatcher: OnBackPressedDispatcher, onBack: () -> Unit) {
-        // START - DO NOT COPY IN CODE SNIPPET
-        val currentOnBack by rememberUpdatedState(onBack)
+    fun HomeScreen(
+        lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
+        onStart: () -> Unit, // Send the 'started' analytics event
+        onStop: () -> Unit // Send the 'stopped' analytics event
+    ) {
+        // These values never change in Composition
+        val currentOnStart by rememberUpdatedState(onStart)
+        val currentOnStop by rememberUpdatedState(onStop)
 
-        val backCallback = remember {
-            // Always intercept back events. See the SideEffect for a more complete version
-            object : OnBackPressedCallback(true) {
-                override fun handleOnBackPressed() {
-                    currentOnBack()
+        DisposableEffect(lifecycleOwner) {
+            val observer = LifecycleEventObserver { _, event ->
+                // START - DO NOT COPY IN CODE SNIPPET
+                if (event == Lifecycle.Event.ON_START) {
+                    currentOnStart()
+                } else if (event == Lifecycle.Event.ON_STOP) {
+                    currentOnStop()
                 }
+                // END - DO NOT COPY IN CODE SNIPPET, just use /* ... */
             }
-        }
-        // END - DO NOT COPY IN CODE SNIPPET, just use /* ... */
 
-        DisposableEffect(backDispatcher) {
-            backDispatcher.addCallback(backCallback)
+            lifecycleOwner.lifecycle.addObserver(observer)
             onDispose {
-                backCallback.remove()
+                lifecycleOwner.lifecycle.removeObserver(observer)
             }
         }
     }
@@ -315,13 +324,17 @@
     fun load(url: String): Image? = if (Random.nextInt() == 0) Image() else null // Avoid warnings
 }
 
+private class FirebaseAnalytics {
+    fun setUserProperty(name: String, value: String) {}
+}
+
 private sealed class Result {
     data class Success(val data: T) : Result()
     object Loading : Result()
     object Error : Result()
 }
 
-private class User
+private class User(val userType: String = "user")
 private class Weather
 private class Greeting(val name: String)
 private fun prepareGreeting(user: User, weather: Weather) = Greeting("haha")