Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 30a88ce5 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Consolidate setViewTreeOnBackPressedDispatcherOwner calls" into main

parents dbf27628 5dea64fc
Loading
Loading
Loading
Loading
+65 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui

import android.view.View
import androidx.activity.OnBackPressedDispatcher
import androidx.activity.OnBackPressedDispatcherOwner
import androidx.activity.setViewTreeOnBackPressedDispatcherOwner
import androidx.lifecycle.Lifecycle
import com.android.systemui.scene.shared.flag.SceneContainerFlag

/**
 * Attaches a [OnBackPressedDispatcherOwner] to a [View] to prevent a [IllegalStateException].
 *
 * When [SceneContainerFlag] is enabled this is usually not needed for child [ComposeView]s because
 * it is sufficient to attach it to the root container. However, when [SceneContainerFlag] is
 * disabled, this function needs to be called for each [ComposeView] or one of its ancestors. Needs
 * to be called within [repeatOnLifeCycle] as follows:
 * ```
 * ComposeView(context).apply {
 *     repeatWhenAttached {
 *         repeatOnLifecycle(Lifecycle.State.CREATED) {
 *             initOnBackPressedDispatcherOwner(this@repeatWhenAttached.lifecycle)
 *             setContent {
 *                 PlatformTheme { YourComposable() }
 *             }
 *         }
 *     }
 * }
 * ```
 *
 * Make sure to call [setContent] within the same [repeatOnLifeCycle] block and after this init
 * otherwise a composition might happen before and cause a crash.
 *
 * @param lifecycle The lifecycle of the view.
 * @param force Whether the dispatcher should be set up regardless of any flag checks.
 */
fun View.initOnBackPressedDispatcherOwner(lifecycle: Lifecycle, force: Boolean = false) {
    if (!SceneContainerFlag.isEnabled || force) {
        setViewTreeOnBackPressedDispatcherOwner(
            object : OnBackPressedDispatcherOwner {
                override val onBackPressedDispatcher =
                    OnBackPressedDispatcher().apply {
                        setOnBackInvokedDispatcher(viewRootImpl.onBackInvokedDispatcher)
                    }

                override val lifecycle: Lifecycle = lifecycle
            }
        )
    }
}
+2 −21
Original line number Diff line number Diff line
@@ -18,10 +18,6 @@ package com.android.systemui.notifications.ui.composable.row

import android.content.Context
import android.graphics.drawable.Drawable
import android.view.View
import androidx.activity.OnBackPressedDispatcher
import androidx.activity.OnBackPressedDispatcherOwner
import androidx.activity.setViewTreeOnBackPressedDispatcherOwner
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
@@ -55,8 +51,8 @@ import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.SceneTransitionLayout
import com.android.compose.theme.PlatformTheme
import com.android.compose.ui.graphics.painter.rememberDrawablePainter
import com.android.systemui.initOnBackPressedDispatcherOwner
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.statusbar.notification.row.ui.viewmodel.BundleHeaderViewModel

object BundleHeader {
@@ -77,7 +73,7 @@ fun createComposeView(viewModel: BundleHeaderViewModel, context: Context): Compo
    return ComposeView(context).apply {
        repeatWhenAttached {
            repeatOnLifecycle(Lifecycle.State.CREATED) {
                initOnBackPressureDispatcherOwner(this@repeatWhenAttached.lifecycle)
                initOnBackPressedDispatcherOwner(this@repeatWhenAttached.lifecycle)
                setContent {
                    // TODO(b/399588047): Check if we can init PlatformTheme once instead of once
                    //  per ComposeView
@@ -88,21 +84,6 @@ fun createComposeView(viewModel: BundleHeaderViewModel, context: Context): Compo
    }
}

private fun View.initOnBackPressureDispatcherOwner(lifecycle: Lifecycle) {
    if (!SceneContainerFlag.isEnabled) {
        setViewTreeOnBackPressedDispatcherOwner(
            object : OnBackPressedDispatcherOwner {
                override val onBackPressedDispatcher =
                    OnBackPressedDispatcher().apply {
                        setOnBackInvokedDispatcher(viewRootImpl.onBackInvokedDispatcher)
                    }

                override val lifecycle: Lifecycle = lifecycle
            }
        )
    }
}

@Composable
fun BundleHeader(viewModel: BundleHeaderViewModel, modifier: Modifier = Modifier) {
    Box(modifier) {
+2 −21
Original line number Diff line number Diff line
@@ -19,10 +19,6 @@
package com.android.systemui.notifications.ui.composable.row

import android.content.Context
import android.view.View
import androidx.activity.OnBackPressedDispatcher
import androidx.activity.OnBackPressedDispatcherOwner
import androidx.activity.setViewTreeOnBackPressedDispatcherOwner
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@@ -54,35 +50,20 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.internal.R
import com.android.systemui.initOnBackPressedDispatcherOwner
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.statusbar.notification.row.ui.viewmodel.BundleHeaderGutsViewModel

fun createBundleHeaderGutsComposeView(context: Context): ComposeView {
    return ComposeView(context).apply {
        repeatWhenAttached {
            repeatOnLifecycle(Lifecycle.State.CREATED) {
                initOnBackPressureDispatcherOwner(this@repeatWhenAttached.lifecycle)
                initOnBackPressedDispatcherOwner(this@repeatWhenAttached.lifecycle)
            }
        }
    }
}

private fun View.initOnBackPressureDispatcherOwner(lifecycle: Lifecycle) {
    if (!SceneContainerFlag.isEnabled) {
        setViewTreeOnBackPressedDispatcherOwner(
            object : OnBackPressedDispatcherOwner {
                override val onBackPressedDispatcher =
                    OnBackPressedDispatcher().apply {
                        setOnBackInvokedDispatcher(viewRootImpl.onBackInvokedDispatcher)
                    }

                override val lifecycle: Lifecycle = lifecycle
            }
        )
    }
}

@Composable
fun BundleHeaderGuts(viewModel: BundleHeaderGutsViewModel, modifier: Modifier = Modifier) {
    Column(modifier.padding(horizontal = 16.dp)) {
+4 −15
Original line number Diff line number Diff line
@@ -33,9 +33,6 @@ import android.view.View.VISIBLE
import android.view.ViewGroup
import android.view.ViewGroup.OnHierarchyChangeListener
import android.view.WindowInsets
import androidx.activity.OnBackPressedDispatcher
import androidx.activity.OnBackPressedDispatcherOwner
import androidx.activity.setViewTreeOnBackPressedDispatcherOwner
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.app.tracing.coroutines.launchTraced as launch
@@ -50,6 +47,7 @@ import com.android.systemui.common.ui.view.onApplyWindowInsets
import com.android.systemui.common.ui.view.onLayoutChanged
import com.android.systemui.common.ui.view.onTouchListener
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor
import com.android.systemui.initOnBackPressedDispatcherOwner
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.ui.view.layout.sections.AodPromotedNotificationSection
import com.android.systemui.keyguard.ui.viewmodel.BurnInParameters
@@ -229,18 +227,9 @@ object KeyguardRootViewBinder {
            view.repeatWhenAttached {
                repeatOnLifecycle(Lifecycle.State.CREATED) {
                    if (SceneContainerFlag.isEnabled) {
                        view.setViewTreeOnBackPressedDispatcherOwner(
                            object : OnBackPressedDispatcherOwner {
                                override val onBackPressedDispatcher =
                                    OnBackPressedDispatcher().apply {
                                        setOnBackInvokedDispatcher(
                                            view.viewRootImpl.onBackInvokedDispatcher
                                        )
                                    }

                                override val lifecycle: Lifecycle =
                                    this@repeatWhenAttached.lifecycle
                            }
                        view.initOnBackPressedDispatcherOwner(
                            this@repeatWhenAttached.lifecycle,
                            force = true,
                        )
                    }
                    launch {
+2 −17
Original line number Diff line number Diff line
@@ -31,9 +31,6 @@ import android.view.View
import android.view.ViewConfiguration
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.activity.OnBackPressedDispatcher
import androidx.activity.OnBackPressedDispatcherOwner
import androidx.activity.setViewTreeOnBackPressedDispatcherOwner
import androidx.annotation.VisibleForTesting
import androidx.compose.animation.core.tween
import androidx.compose.foundation.ScrollState
@@ -57,7 +54,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
@@ -120,6 +116,7 @@ import com.android.systemui.compose.modifiers.sysUiResTagContainer
import com.android.systemui.compose.modifiers.sysuiResTag
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dump.DumpManager
import com.android.systemui.initOnBackPressedDispatcherOwner
import com.android.systemui.keyboard.shortcut.ui.composable.InteractionsConfig
import com.android.systemui.keyboard.shortcut.ui.composable.ProvideShortcutHelperIndication
import com.android.systemui.lifecycle.repeatWhenAttached
@@ -222,19 +219,7 @@ constructor(
                id = R.id.quick_settings_container
                repeatWhenAttached {
                    repeatOnLifecycle(Lifecycle.State.CREATED) {
                        setViewTreeOnBackPressedDispatcherOwner(
                            object : OnBackPressedDispatcherOwner {
                                override val onBackPressedDispatcher =
                                    OnBackPressedDispatcher().apply {
                                        setOnBackInvokedDispatcher(
                                            it.viewRootImpl.onBackInvokedDispatcher
                                        )
                                    }

                                override val lifecycle: Lifecycle =
                                    this@repeatWhenAttached.lifecycle
                            }
                        )
                        initOnBackPressedDispatcherOwner(this@repeatWhenAttached.lifecycle)
                        setContent {
                            this@QSFragmentCompose.Content(Modifier.sysUiResTagContainer())
                        }
Loading