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

Commit 5501c883 authored by Brad Hinegardner's avatar Brad Hinegardner
Browse files

Fix crash loop related to ambient indication with keyguardBottomAreaRefactor flag

Bug: 290652751
Fixes: 305176847
Test: atest DefaultKeyguardBlueprintTest
Test: manual - flip flag on, ensure crash loop does not happen
Change-Id: Id243b93494024791586d8752bb73c6b0de2a61d2
parent 75dd2c79
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ import com.android.systemui.flags.FlagsModule;
import com.android.systemui.keyboard.KeyboardModule;
import com.android.systemui.keyevent.data.repository.KeyEventRepositoryModule;
import com.android.systemui.keyguard.ui.view.layout.blueprints.KeyguardBlueprintModule;
import com.android.systemui.keyguard.ui.view.layout.sections.KeyguardSectionsModule;
import com.android.systemui.log.dagger.LogModule;
import com.android.systemui.log.dagger.MonitorLog;
import com.android.systemui.log.table.TableLogBuffer;
@@ -189,6 +190,7 @@ import javax.inject.Named;
        KeyEventRepositoryModule.class,
        KeyboardModule.class,
        KeyguardBlueprintModule.class,
        KeyguardSectionsModule.class,
        LetterboxModule.class,
        LogModule.class,
        MediaProjectionModule.class,
+0 −128
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.keyguard.ui.binder

import android.view.View
import android.view.ViewGroup
import android.view.ViewPropertyAnimator
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.res.R
import com.android.systemui.keyguard.ui.viewmodel.KeyguardAmbientIndicationViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch

object KeyguardAmbientIndicationAreaViewBinder {
    /**
     * Defines interface for an object that acts as the binding between the view and its view-model.
     *
     * Users of the [KeyguardBottomAreaViewBinder] class should use this to control the binder after
     * it is bound.
     */
    interface Binding {
        /**
         * Returns a collection of [ViewPropertyAnimator] instances that can be used to animate the
         * indication areas.
         */
        fun getIndicationAreaAnimators(): List<ViewPropertyAnimator>

        /** Notifies that device configuration has changed. */
        fun onConfigurationChanged()

        /** Destroys this binding, releases resources, and cancels any coroutines. */
        fun destroy()
    }

    @OptIn(ExperimentalCoroutinesApi::class)
    fun bind(
        view: ViewGroup,
        viewModel: KeyguardAmbientIndicationViewModel,
        keyguardRootViewModel: KeyguardRootViewModel,
    ): Binding {
        val ambientIndicationArea: View? = view.findViewById(R.id.ambient_indication_container)
        val configurationBasedDimensions = MutableStateFlow(loadFromResources(view))

        val disposableHandle =
            view.repeatWhenAttached {
                repeatOnLifecycle(Lifecycle.State.STARTED) {
                    launch {
                        keyguardRootViewModel.alpha.collect { alpha ->
                            ambientIndicationArea?.apply {
                                this.importantForAccessibility =
                                    if (alpha == 0f) {
                                        View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
                                    } else {
                                        View.IMPORTANT_FOR_ACCESSIBILITY_AUTO
                                    }
                                this.alpha = alpha
                            }
                        }
                    }

                    launch {
                        viewModel.indicationAreaTranslationX.collect { translationX ->
                            ambientIndicationArea?.translationX = translationX
                        }
                    }

                    launch {
                        configurationBasedDimensions
                            .map { it.defaultBurnInPreventionYOffsetPx }
                            .flatMapLatest { defaultBurnInOffsetY ->
                                viewModel.indicationAreaTranslationY(defaultBurnInOffsetY)
                            }
                            .collect { translationY ->
                                ambientIndicationArea?.translationY = translationY
                            }
                    }

                }
            }


        return object : Binding {
            override fun getIndicationAreaAnimators(): List<ViewPropertyAnimator> {
                return listOf(ambientIndicationArea).mapNotNull { it?.animate() }
            }

            override fun onConfigurationChanged() {
                configurationBasedDimensions.value = loadFromResources(view)
            }

            override fun destroy() {
                disposableHandle.dispose()
            }
        }
    }

    private fun loadFromResources(view: View): ConfigurationBasedDimensions {
        return ConfigurationBasedDimensions(
            defaultBurnInPreventionYOffsetPx =
                view.resources.getDimensionPixelOffset(R.dimen.default_burn_in_prevention_offset),
        )
    }

    private data class ConfigurationBasedDimensions(
        val defaultBurnInPreventionYOffsetPx: Int,
    )
}
 No newline at end of file
+10 −4
Original line number Diff line number Diff line
@@ -20,10 +20,10 @@ package com.android.systemui.keyguard.ui.view.layout.blueprints
import com.android.systemui.communal.ui.view.layout.sections.CommunalTutorialIndicatorSection
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
import com.android.systemui.keyguard.shared.model.KeyguardSection
import com.android.systemui.keyguard.ui.view.layout.items.ClockSection
import com.android.systemui.keyguard.ui.view.layout.sections.AodBurnInSection
import com.android.systemui.keyguard.ui.view.layout.sections.AodNotificationIconsSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultAmbientIndicationAreaSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultDeviceEntryIconSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultIndicationAreaSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultNotificationStackScrollLayoutSection
@@ -31,8 +31,13 @@ import com.android.systemui.keyguard.ui.view.layout.sections.DefaultSettingsPopu
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultShortcutsSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultStatusBarSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultStatusViewSection
import com.android.systemui.keyguard.ui.view.layout.sections.KeyguardSectionsModule.Companion.KEYGUARD_AMBIENT_INDICATION_AREA_SECTION
import com.android.systemui.keyguard.ui.view.layout.sections.SmartspaceSection
import com.android.systemui.keyguard.ui.view.layout.sections.SplitShadeGuidelines
import java.util.Optional
import javax.inject.Inject
import javax.inject.Named
import kotlin.jvm.optionals.getOrNull

/**
 * Positions elements of the lockscreen to the default position.
@@ -47,7 +52,8 @@ constructor(
    defaultIndicationAreaSection: DefaultIndicationAreaSection,
    defaultDeviceEntryIconSection: DefaultDeviceEntryIconSection,
    defaultShortcutsSection: DefaultShortcutsSection,
    defaultAmbientIndicationAreaSection: DefaultAmbientIndicationAreaSection,
    @Named(KEYGUARD_AMBIENT_INDICATION_AREA_SECTION)
    defaultAmbientIndicationAreaSection: Optional<KeyguardSection>,
    defaultSettingsPopupMenuSection: DefaultSettingsPopupMenuSection,
    defaultStatusViewSection: DefaultStatusViewSection,
    defaultStatusBarSection: DefaultStatusBarSection,
@@ -61,11 +67,11 @@ constructor(
    override val id: String = DEFAULT

    override val sections =
        listOf(
        listOfNotNull(
            defaultIndicationAreaSection,
            defaultDeviceEntryIconSection,
            defaultShortcutsSection,
            defaultAmbientIndicationAreaSection,
            defaultAmbientIndicationAreaSection.getOrNull(),
            defaultSettingsPopupMenuSection,
            defaultStatusViewSection,
            defaultStatusBarSection,
+9 −4
Original line number Diff line number Diff line
@@ -19,18 +19,22 @@ package com.android.systemui.keyguard.ui.view.layout.blueprints

import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
import com.android.systemui.keyguard.shared.model.KeyguardSection
import com.android.systemui.keyguard.ui.view.layout.sections.AlignShortcutsToUdfpsSection
import com.android.systemui.keyguard.ui.view.layout.sections.AodBurnInSection
import com.android.systemui.keyguard.ui.view.layout.sections.AodNotificationIconsSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultAmbientIndicationAreaSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultDeviceEntryIconSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultIndicationAreaSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultNotificationStackScrollLayoutSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultSettingsPopupMenuSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultStatusBarSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultStatusViewSection
import com.android.systemui.keyguard.ui.view.layout.sections.KeyguardSectionsModule
import com.android.systemui.keyguard.ui.view.layout.sections.SplitShadeGuidelines
import com.android.systemui.util.kotlin.getOrNull
import java.util.Optional
import javax.inject.Inject
import javax.inject.Named

/** Vertically aligns the shortcuts with the udfps. */
@SysUISingleton
@@ -39,7 +43,8 @@ class ShortcutsBesideUdfpsKeyguardBlueprint
constructor(
    defaultIndicationAreaSection: DefaultIndicationAreaSection,
    defaultDeviceEntryIconSection: DefaultDeviceEntryIconSection,
    defaultAmbientIndicationAreaSection: DefaultAmbientIndicationAreaSection,
    @Named(KeyguardSectionsModule.KEYGUARD_AMBIENT_INDICATION_AREA_SECTION)
    defaultAmbientIndicationAreaSection: Optional<KeyguardSection>,
    defaultSettingsPopupMenuSection: DefaultSettingsPopupMenuSection,
    alignShortcutsToUdfpsSection: AlignShortcutsToUdfpsSection,
    defaultStatusViewSection: DefaultStatusViewSection,
@@ -52,10 +57,10 @@ constructor(
    override val id: String = SHORTCUTS_BESIDE_UDFPS

    override val sections =
        listOf(
        listOfNotNull(
            defaultIndicationAreaSection,
            defaultDeviceEntryIconSection,
            defaultAmbientIndicationAreaSection,
            defaultAmbientIndicationAreaSection.getOrNull(),
            defaultSettingsPopupMenuSection,
            alignShortcutsToUdfpsSection,
            defaultStatusViewSection,
+9 −4
Original line number Diff line number Diff line
@@ -20,18 +20,22 @@ package com.android.systemui.keyguard.ui.view.layout.blueprints
import com.android.systemui.communal.ui.view.layout.sections.CommunalTutorialIndicatorSection
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
import com.android.systemui.keyguard.shared.model.KeyguardSection
import com.android.systemui.keyguard.ui.view.layout.sections.AodBurnInSection
import com.android.systemui.keyguard.ui.view.layout.sections.AodNotificationIconsSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultAmbientIndicationAreaSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultDeviceEntryIconSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultIndicationAreaSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultSettingsPopupMenuSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultShortcutsSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultStatusBarSection
import com.android.systemui.keyguard.ui.view.layout.sections.DefaultStatusViewSection
import com.android.systemui.keyguard.ui.view.layout.sections.KeyguardSectionsModule
import com.android.systemui.keyguard.ui.view.layout.sections.SplitShadeGuidelines
import com.android.systemui.keyguard.ui.view.layout.sections.SplitShadeNotificationStackScrollLayoutSection
import com.android.systemui.util.kotlin.getOrNull
import java.util.Optional
import javax.inject.Inject
import javax.inject.Named

/**
 * Split-shade layout, mostly used for larger devices like foldables and tablets when in landscape
@@ -45,7 +49,8 @@ constructor(
    defaultIndicationAreaSection: DefaultIndicationAreaSection,
    defaultDeviceEntryIconSection: DefaultDeviceEntryIconSection,
    defaultShortcutsSection: DefaultShortcutsSection,
    defaultAmbientIndicationAreaSection: DefaultAmbientIndicationAreaSection,
    @Named(KeyguardSectionsModule.KEYGUARD_AMBIENT_INDICATION_AREA_SECTION)
    defaultAmbientIndicationAreaSection: Optional<KeyguardSection>,
    defaultSettingsPopupMenuSection: DefaultSettingsPopupMenuSection,
    defaultStatusViewSection: DefaultStatusViewSection,
    defaultStatusBarSection: DefaultStatusBarSection,
@@ -58,11 +63,11 @@ constructor(
    override val id: String = ID

    override val sections =
        listOf(
        listOfNotNull(
            defaultIndicationAreaSection,
            defaultDeviceEntryIconSection,
            defaultShortcutsSection,
            defaultAmbientIndicationAreaSection,
            defaultAmbientIndicationAreaSection.getOrNull(),
            defaultSettingsPopupMenuSection,
            defaultStatusViewSection,
            defaultStatusBarSection,
Loading