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

Commit 70636dd7 authored by Lucas Dupin's avatar Lucas Dupin Committed by Android (Google) Code Review
Browse files

Merge "Increase taskbar height when Ambient Cue is enabled." into main

parents dec3d136 baeb6cca
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1266,4 +1266,7 @@

    <!-- Default height of desktop view header for freeform tasks on launch. -->
    <dimen name="desktop_view_default_header_height">40dp</dimen>

    <!-- Default height of taskbar for Launcher.   -->
    <dimen name="taskbar_stashed_size">24dp</dimen>
</resources>
+73 −1
Original line number Diff line number Diff line
@@ -50,10 +50,12 @@ import com.android.systemui.kosmos.backgroundScope
import com.android.systemui.kosmos.collectLastValue
import com.android.systemui.kosmos.runCurrent
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.navigationbar.NavigationModeController
import com.android.systemui.navigationbar.NavigationModeController.ModeChangedListener
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.shade.data.repository.fakeFocusedDisplayRepository
import com.android.systemui.shared.settings.data.repository.secureSettingsRepository
import com.android.systemui.shared.system.taskStackChangeListeners
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
@@ -95,13 +97,19 @@ class AmbientCueRepositoryTest : SysuiTestCase() {
            executor = kosmos.fakeExecutor,
            applicationContext = kosmos.testableContext,
            taskStackChangeListeners = kosmos.taskStackChangeListeners,
            backgroundDispatcher = kosmos.testDispatcher,
            secureSettingsRepository = kosmos.secureSettingsRepository,
        )

    @Test
    fun isRootViewAttached_whenHasActionsAndNotDeactivatedAndTaskIdMatch_true() =
    fun isRootViewAttached_whenHasActionsAndNotDeactivatedAndTaskIdMatchAndEnabled_true() =
        kosmos.runTest {
            val actions by collectLastValue(underTest.actions)
            val isRootViewAttached by collectLastValue(underTest.isRootViewAttached)
            secureSettingsRepository.setInt(
                AmbientCueRepositoryImpl.AMBIENT_CUE_SETTING,
                AmbientCueRepositoryImpl.OPTED_IN,
            )
            runCurrent()
            verify(smartSpaceSession)
                .addOnTargetsAvailableListener(any(), onTargetsAvailableListenerCaptor.capture())
@@ -121,6 +129,10 @@ class AmbientCueRepositoryTest : SysuiTestCase() {
        kosmos.runTest {
            val actions by collectLastValue(underTest.actions)
            val isRootViewAttached by collectLastValue(underTest.isRootViewAttached)
            secureSettingsRepository.setInt(
                AmbientCueRepositoryImpl.AMBIENT_CUE_SETTING,
                AmbientCueRepositoryImpl.OPTED_IN,
            )
            runCurrent()
            verify(smartSpaceSession)
                .addOnTargetsAvailableListener(any(), onTargetsAvailableListenerCaptor.capture())
@@ -138,6 +150,10 @@ class AmbientCueRepositoryTest : SysuiTestCase() {
        kosmos.runTest {
            val actions by collectLastValue(underTest.actions)
            val isRootViewAttached by collectLastValue(underTest.isRootViewAttached)
            secureSettingsRepository.setInt(
                AmbientCueRepositoryImpl.AMBIENT_CUE_SETTING,
                AmbientCueRepositoryImpl.OPTED_IN,
            )
            runCurrent()
            verify(smartSpaceSession)
                .addOnTargetsAvailableListener(any(), onTargetsAvailableListenerCaptor.capture())
@@ -158,6 +174,10 @@ class AmbientCueRepositoryTest : SysuiTestCase() {
        kosmos.runTest {
            val actions by collectLastValue(underTest.actions)
            val isRootViewAttached by collectLastValue(underTest.isRootViewAttached)
            secureSettingsRepository.setInt(
                AmbientCueRepositoryImpl.AMBIENT_CUE_SETTING,
                AmbientCueRepositoryImpl.OPTED_IN,
            )
            runCurrent()
            verify(smartSpaceSession)
                .addOnTargetsAvailableListener(any(), onTargetsAvailableListenerCaptor.capture())
@@ -172,6 +192,29 @@ class AmbientCueRepositoryTest : SysuiTestCase() {
            assertThat(isRootViewAttached).isFalse()
        }

    @Test
    fun isRootViewAttached_ambientCueDisabled_false() =
        kosmos.runTest {
            val actions by collectLastValue(underTest.actions)
            val isRootViewAttached by collectLastValue(underTest.isRootViewAttached)
            runCurrent()
            verify(smartSpaceSession)
                .addOnTargetsAvailableListener(any(), onTargetsAvailableListenerCaptor.capture())
            taskStackChangeListeners.listenerImpl.onTaskMovedToFront(
                RunningTaskInfo().apply { taskId = TASK_ID }
            )
            advanceTimeBy(DEBOUNCE_DELAY_MS)
            onTargetsAvailableListenerCaptor.firstValue.onTargetsAvailable(listOf(autofillTarget))
            advanceUntilIdle()

            secureSettingsRepository.setInt(
                AmbientCueRepositoryImpl.AMBIENT_CUE_SETTING,
                AmbientCueRepositoryImpl.OPTED_OUT,
            )

            assertThat(isRootViewAttached).isFalse()
        }

    @Test
    fun actions_whenHasSmartSpaceAction() =
        kosmos.runTest {
@@ -327,6 +370,35 @@ class AmbientCueRepositoryTest : SysuiTestCase() {
            assertThat(isTaskBarVisible).isFalse()
        }

    @Test
    fun isAmbientCueEnabled_spoonBarOptIn_true() =
        kosmos.runTest {
            val isAmbientCueEnabled by collectLastValue(underTest.isAmbientCueEnabled)

            secureSettingsRepository.setInt(
                AmbientCueRepositoryImpl.AMBIENT_CUE_SETTING,
                AmbientCueRepositoryImpl.OPTED_IN,
            )
            runCurrent()

            assertThat(isAmbientCueEnabled).isTrue()
        }

    @Test
    fun isAmbientCueEnabled_spoonBarOptOut_false() {
        kosmos.runTest {
            val isAmbientCueEnabled by collectLastValue(underTest.isAmbientCueEnabled)

            secureSettingsRepository.setInt(
                AmbientCueRepositoryImpl.AMBIENT_CUE_SETTING,
                AmbientCueRepositoryImpl.OPTED_OUT,
            )
            runCurrent()

            assertThat(isAmbientCueEnabled).isFalse()
        }
    }

    companion object {

        private const val TITLE_1 = "title 1"
+59 −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.ambientcue.ui.startable

import android.os.UserHandle
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.ambientcue.data.repository.ambientCueRepository
import com.android.systemui.ambientcue.data.repository.fake
import com.android.systemui.ambientcue.ui.startable.AmbientCueCoreStartable.Companion.AMBIENT_CUE_OVERLAY_PACKAGE
import com.android.systemui.kosmos.runCurrent
import com.android.systemui.kosmos.runTest
import com.android.systemui.testKosmos
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.verify

@RunWith(AndroidJUnit4::class)
@SmallTest
class AmbientCueCoreStartableTest : SysuiTestCase() {
    private val kosmos = testKosmos()

    @Test
    fun isAmbientCueEnabled_setFalse_disableOverlay() =
        kosmos.runTest {
            ambientCueCoreStartable.start()
            ambientCueRepository.fake.setAmbientCueEnabled(false)
            runCurrent()

            verify(mockOverlayManager)
                .setEnabled(AMBIENT_CUE_OVERLAY_PACKAGE, false, UserHandle.SYSTEM)
        }

    @Test
    fun isAmbientCueEnabled_setTrue_enableOverlay() =
        kosmos.runTest {
            ambientCueCoreStartable.start()
            ambientCueRepository.fake.setAmbientCueEnabled(true)
            runCurrent()

            verify(mockOverlayManager)
                .setEnabled(AMBIENT_CUE_OVERLAY_PACKAGE, true, UserHandle.SYSTEM)
        }
}
+27 −2
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import com.android.systemui.dump.DumpManager
import com.android.systemui.navigationbar.NavigationModeController
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.res.R
import com.android.systemui.shared.settings.data.repository.SecureSettingsRepository
import com.android.systemui.shared.system.QuickStepContract
import com.android.systemui.shared.system.TaskStackChangeListener
import com.android.systemui.shared.system.TaskStackChangeListeners
@@ -51,6 +52,7 @@ import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import java.io.PrintWriter
import java.util.concurrent.Executor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.channels.awaitClose
@@ -61,6 +63,7 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
@@ -90,6 +93,9 @@ interface AmbientCueRepository {
    val isGestureNav: StateFlow<Boolean>

    val recentsButtonPosition: StateFlow<Rect?>

    /* If AmbientCue is enabled. */
    val isAmbientCueEnabled: StateFlow<Boolean>
}

@SysUISingleton
@@ -106,6 +112,8 @@ constructor(
    @Application applicationContext: Context,
    launcherProxyService: LauncherProxyService,
    private val taskStackChangeListeners: TaskStackChangeListeners,
    @Background backgroundDispatcher: CoroutineDispatcher,
    secureSettingsRepository: SecureSettingsRepository,
) : AmbientCueRepository, Dumpable {

    init {
@@ -293,12 +301,25 @@ constructor(

    val targetTaskId: MutableStateFlow<Int> = MutableStateFlow(INVALID_TASK_ID)

    override val isAmbientCueEnabled: StateFlow<Boolean> =
        secureSettingsRepository
            .intSetting(name = AMBIENT_CUE_SETTING, 0)
            .map { it == OPTED_IN }
            .flowOn(backgroundDispatcher)
            .stateIn(
                scope = backgroundScope,
                started = SharingStarted.WhileSubscribed(),
                initialValue = false,
            )

    override val isRootViewAttached: StateFlow<Boolean> =
        combine(isDeactivated, globallyFocusedTaskId, actions) {
        combine(isDeactivated, globallyFocusedTaskId, actions, isAmbientCueEnabled) {
                isDeactivated,
                globallyFocusedTaskId,
                actions ->
                actions,
                isAmbientCueEnabled ->
                actions.isNotEmpty() &&
                    isAmbientCueEnabled &&
                    !isDeactivated &&
                    globallyFocusedTaskId == targetTaskId.value
            }
@@ -318,6 +339,7 @@ constructor(
        pw.println("isTaskBarVisible: ${isTaskBarVisible.value}")
        pw.println("isGestureNav: ${isGestureNav.value}")
        pw.println("actions: ${actions.value}")
        pw.println("isAmbientCueEnabled: ${isAmbientCueEnabled.value}")
    }

    companion object {
@@ -334,6 +356,9 @@ constructor(
        private const val TAG = "AmbientCueRepository"
        private const val DEBUG = false
        private const val INVALID_TASK_ID = ActivityTaskManager.INVALID_TASK_ID
        @VisibleForTesting const val AMBIENT_CUE_SETTING = "spoonBarOptedIn"
        @VisibleForTesting const val OPTED_IN = 0x10
        @VisibleForTesting const val OPTED_OUT = 0x01
        const val DEBOUNCE_DELAY_MS = 100L
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ constructor(
    val isGestureNav: StateFlow<Boolean> = repository.isGestureNav
    val recentsButtonPosition: StateFlow<Rect?> = repository.recentsButtonPosition
    val isTaskBarVisible: StateFlow<Boolean> = repository.isTaskBarVisible
    val isAmbientCueEnabled: StateFlow<Boolean> = repository.isAmbientCueEnabled

    fun setDeactivated(isDeactivated: Boolean) {
        repository.isDeactivated.update { isDeactivated }
Loading