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

Commit 2e7ed2b3 authored by Caitlin Cassidy's avatar Caitlin Cassidy Committed by Automerger Merge Worker
Browse files

Merge "[Ongoing Call] Add an option to disable tapping the chip while in...

Merge "[Ongoing Call] Add an option to disable tapping the chip while in immersive mode." into sc-v2-dev am: 6db6e348 am: 18ef55cd

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15997907

Change-Id: I54a62a6d74469c5df2090860702704f24cfdf6c7
parents 7f191e5a 18ef55cd
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -53,6 +53,8 @@

    <bool name="flag_ongoing_call_in_immersive">false</bool>

    <bool name="flag_ongoing_call_in_immersive_chip_tap">true</bool>

    <bool name="flag_smartspace">false</bool>

    <bool name="flag_smartspace_deduping">true</bool>
+5 −0
Original line number Diff line number Diff line
@@ -128,6 +128,11 @@ public class FeatureFlags {
                && mFlagReader.isEnabled(R.bool.flag_ongoing_call_in_immersive);
    }

    public boolean isOngoingCallInImmersiveChipTapEnabled() {
        return isOngoingCallInImmersiveEnabled()
                && mFlagReader.isEnabled(R.bool.flag_ongoing_call_in_immersive_chip_tap);
    }

    public boolean isSmartspaceEnabled() {
        return mFlagReader.isEnabled(R.bool.flag_smartspace);
    }
+4 −3
Original line number Diff line number Diff line
@@ -257,7 +257,8 @@ public interface StatusBarDependenciesModule {
            OngoingCallLogger logger,
            DumpManager dumpManager,
            StatusBarWindowController statusBarWindowController,
            SwipeStatusBarAwayGestureHandler swipeStatusBarAwayGestureHandler) {
            SwipeStatusBarAwayGestureHandler swipeStatusBarAwayGestureHandler,
            StatusBarStateController statusBarStateController) {
        Optional<StatusBarWindowController> windowController =
                featureFlags.isOngoingCallInImmersiveEnabled()
                        ? Optional.of(statusBarWindowController)
@@ -277,8 +278,8 @@ public interface StatusBarDependenciesModule {
                        logger,
                        dumpManager,
                        windowController,
                        gestureHandler
                );
                        gestureHandler,
                        statusBarStateController);
        ongoingCallController.init();
        return ongoingCallController;
    }
+45 −23
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
@@ -61,8 +62,10 @@ class OngoingCallController @Inject constructor(
    private val dumpManager: DumpManager,
    private val statusBarWindowController: Optional<StatusBarWindowController>,
    private val swipeStatusBarAwayGestureHandler: Optional<SwipeStatusBarAwayGestureHandler>,
    private val statusBarStateController: StatusBarStateController,
) : CallbackController<OngoingCallListener>, Dumpable {

    private var isFullscreen: Boolean = false
    /** Non-null if there's an active call notification. */
    private var callNotificationInfo: CallNotificationInfo? = null
    /** True if the application managing the call is visible to the user. */
@@ -124,6 +127,7 @@ class OngoingCallController @Inject constructor(
        dumpManager.registerDumpable(this)
        if (featureFlags.isOngoingCallStatusBarChipEnabled) {
            notifCollection.addCollectionListener(notifListener)
            statusBarStateController.addCallback(statusBarStateListener)
        }
    }

@@ -177,10 +181,8 @@ class OngoingCallController @Inject constructor(

        val currentChipView = chipView
        val timeView = currentChipView?.getTimeView()
        val backgroundView =
            currentChipView?.findViewById<View>(R.id.ongoing_call_chip_background)

        if (currentChipView != null && timeView != null && backgroundView != null) {
        if (currentChipView != null && timeView != null) {
            if (currentCallNotificationInfo.hasValidStartTime()) {
                timeView.setShouldHideText(false)
                timeView.base = currentCallNotificationInfo.callStartTime -
@@ -191,19 +193,8 @@ class OngoingCallController @Inject constructor(
                timeView.setShouldHideText(true)
                timeView.stop()
            }
            updateChipClickListener()

            currentCallNotificationInfo.intent?.let { intent ->
                currentChipView.setOnClickListener {
                    logger.logChipClicked()
                    activityStarter.postStartActivityDismissingKeyguard(
                            intent,
                            0,
                            ActivityLaunchAnimator.Controller.fromView(
                                    backgroundView,
                                    InteractionJankMonitor.CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP)
                    )
                }
            }
            setUpUidObserver(currentCallNotificationInfo)
            if (!currentCallNotificationInfo.statusBarSwipedAway) {
                statusBarWindowController.ifPresent {
@@ -227,6 +218,30 @@ class OngoingCallController @Inject constructor(
        }
    }

    private fun updateChipClickListener() {
        if (callNotificationInfo == null) { return }
        if (isFullscreen && !featureFlags.isOngoingCallInImmersiveChipTapEnabled) {
            chipView?.setOnClickListener(null)
        } else {
            val currentChipView = chipView
            val backgroundView =
                currentChipView?.findViewById<View>(R.id.ongoing_call_chip_background)
            val intent = callNotificationInfo?.intent
            if (currentChipView != null && backgroundView != null && intent != null) {
                currentChipView.setOnClickListener {
                    logger.logChipClicked()
                    activityStarter.postStartActivityDismissingKeyguard(
                        intent,
                        0,
                        ActivityLaunchAnimator.Controller.fromView(
                            backgroundView,
                            InteractionJankMonitor.CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP)
                    )
                }
            }
        }
    }

    /**
     * Sets up an [IUidObserver] to monitor the status of the application managing the ongoing call.
     */
@@ -315,6 +330,13 @@ class OngoingCallController @Inject constructor(
       }
   }

    private val statusBarStateListener = object : StatusBarStateController.StateListener {
        override fun onFullscreenStateChanged(isFullscreen: Boolean) {
            this@OngoingCallController.isFullscreen = isFullscreen
            updateChipClickListener()
        }
    }

    private data class CallNotificationInfo(
        val key: String,
        val callStartTime: Long,
+64 −4
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
@@ -82,11 +83,13 @@ class OngoingCallControllerTest : SysuiTestCase() {
    private lateinit var controller: OngoingCallController
    private lateinit var notifCollectionListener: NotifCollectionListener

    @Mock private lateinit var mockFeatureFlags: FeatureFlags
    @Mock private lateinit var mockSwipeStatusBarAwayGestureHandler: SwipeStatusBarAwayGestureHandler
    @Mock private lateinit var mockOngoingCallListener: OngoingCallListener
    @Mock private lateinit var mockActivityStarter: ActivityStarter
    @Mock private lateinit var mockIActivityManager: IActivityManager
    @Mock private lateinit var mockStatusBarWindowController: StatusBarWindowController
    @Mock private lateinit var mockStatusBarStateController: StatusBarStateController

    private lateinit var chipView: View

@@ -98,13 +101,12 @@ class OngoingCallControllerTest : SysuiTestCase() {
        }

        MockitoAnnotations.initMocks(this)
        val featureFlags = mock(FeatureFlags::class.java)
        `when`(featureFlags.isOngoingCallStatusBarChipEnabled).thenReturn(true)
        `when`(mockFeatureFlags.isOngoingCallStatusBarChipEnabled).thenReturn(true)
        val notificationCollection = mock(CommonNotifCollection::class.java)

        controller = OngoingCallController(
                notificationCollection,
                featureFlags,
                mockFeatureFlags,
                clock,
                mockActivityStarter,
                mainExecutor,
@@ -113,6 +115,7 @@ class OngoingCallControllerTest : SysuiTestCase() {
                DumpManager(),
                Optional.of(mockStatusBarWindowController),
                Optional.of(mockSwipeStatusBarAwayGestureHandler),
                mockStatusBarStateController,
            )
        controller.init()
        controller.addCallback(mockOngoingCallListener)
@@ -455,6 +458,56 @@ class OngoingCallControllerTest : SysuiTestCase() {
    // Other tests for notifyChipVisibilityChanged are in [OngoingCallLogger], since
    // [OngoingCallController.notifyChipVisibilityChanged] just delegates to that class.

    @Test
    fun callNotificationAdded_chipIsClickable() {
        notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())

        assertThat(chipView.hasOnClickListeners()).isTrue()
    }

    @Test
    fun fullscreenIsTrue_thenCallNotificationAdded_chipNotClickable() {
        `when`(mockFeatureFlags.isOngoingCallInImmersiveChipTapEnabled).thenReturn(false)

        getStateListener().onFullscreenStateChanged(/* isFullscreen= */ true)
        notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())

        assertThat(chipView.hasOnClickListeners()).isFalse()
    }

    @Test
    fun callNotificationAdded_thenFullscreenIsTrue_chipNotClickable() {
        `when`(mockFeatureFlags.isOngoingCallInImmersiveChipTapEnabled).thenReturn(false)

        notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
        getStateListener().onFullscreenStateChanged(/* isFullscreen= */ true)

        assertThat(chipView.hasOnClickListeners()).isFalse()
    }

    @Test
    fun fullscreenChangesToFalse_chipClickable() {
        `when`(mockFeatureFlags.isOngoingCallInImmersiveChipTapEnabled).thenReturn(false)

        notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
        // First, update to true
        getStateListener().onFullscreenStateChanged(/* isFullscreen= */ true)
        // Then, update to false
        getStateListener().onFullscreenStateChanged(/* isFullscreen= */ false)

        assertThat(chipView.hasOnClickListeners()).isTrue()
    }

    @Test
    fun fullscreenIsTrue_butChipClickInImmersiveEnabled_chipClickable() {
        `when`(mockFeatureFlags.isOngoingCallInImmersiveChipTapEnabled).thenReturn(true)

        notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
        getStateListener().onFullscreenStateChanged(/* isFullscreen= */ true)

        assertThat(chipView.hasOnClickListeners()).isTrue()
    }

    private fun createOngoingCallNotifEntry() = createCallNotifEntry(ongoingCallStyle)

    private fun createScreeningCallNotifEntry() = createCallNotifEntry(screeningCallStyle)
@@ -479,6 +532,13 @@ class OngoingCallControllerTest : SysuiTestCase() {
    }

    private fun createNotCallNotifEntry() = NotificationEntryBuilder().build()

    private fun getStateListener(): StatusBarStateController.StateListener {
        val statusBarStateListenerCaptor = ArgumentCaptor.forClass(
            StatusBarStateController.StateListener::class.java)
        verify(mockStatusBarStateController).addCallback(statusBarStateListenerCaptor.capture())
        return statusBarStateListenerCaptor.value!!
    }
}

private val person = Person.Builder().setName("name").build()