Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt +75 −7 Original line number Diff line number Diff line Loading @@ -588,15 +588,26 @@ class CallChipViewModelTest(flags: FlagsParameterization) : SysuiTestCase() { assertThat(latest!!.transitionManager!!.controllerFactory).isEqualTo(factory) assertThat(latest!!.transitionManager!!.hideChipForTransition).isFalse() // Trigger a launch transition [InCall(isAppVisible=false) -> InCall(isAppVisible=true), // NoTransition]. // Trigger a launch transition [InCall(isAppVisible=false), NoTransition -> // LaunchRequested]. val clickBehavior = (latest as OngoingActivityChipModel.Active).clickBehavior as OngoingActivityChipModel.ClickBehavior.ExpandAction clickBehavior.onClick(expandable) assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active::class.java) assertThat((latest as OngoingActivityChipModel.Active).isHidden).isFalse() assertThat(latest!!.transitionManager!!.controllerFactory).isEqualTo(factory) assertThat(latest!!.transitionManager!!.hideChipForTransition).isFalse() // System reacts to the tap [InCall(isAppVisible=false) -> InCall(isAppVisible=true), // LaunchRequested]. kosmos.activityManagerRepository.fake.setIsAppVisible(NOTIFICATION_UID, true) assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active::class.java) assertThat((latest as OngoingActivityChipModel.Active).isHidden).isFalse() assertThat(latest!!.transitionManager!!.controllerFactory).isEqualTo(factory) assertThat(latest!!.transitionManager!!.hideChipForTransition).isFalse() // Request the return transition [InCall(isAppVisible=true), NoTransition -> // Request the launch transition [InCall(isAppVisible=true), NoTransition -> // LaunchRequested]. controller = factory.createController(forLaunch = true) assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active::class.java) Loading @@ -604,7 +615,7 @@ class CallChipViewModelTest(flags: FlagsParameterization) : SysuiTestCase() { assertThat(latest!!.transitionManager!!.controllerFactory).isEqualTo(factory) assertThat(latest!!.transitionManager!!.hideChipForTransition).isFalse() // Start the return transition [InCall(isAppVisible=true), LaunchRequested -> // Start the launch transition [InCall(isAppVisible=true), LaunchRequested -> // Launching]. controller.onTransitionAnimationStart(isExpandingFullyAbove = false) assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active::class.java) Loading @@ -612,10 +623,10 @@ class CallChipViewModelTest(flags: FlagsParameterization) : SysuiTestCase() { assertThat(latest!!.transitionManager!!.controllerFactory).isEqualTo(factory) assertThat(latest!!.transitionManager!!.hideChipForTransition).isFalse() // End the return transition [InCall(isAppVisible=true), Launching -> NoTransition]. controller.onTransitionAnimationStart(isExpandingFullyAbove = false) // End the launch transition [InCall(isAppVisible=true), Launching -> NoTransition]. controller.onTransitionAnimationEnd(isExpandingFullyAbove = false) assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active::class.java) assertThat((latest as OngoingActivityChipModel.Active).isHidden).isFalse() assertThat((latest as OngoingActivityChipModel.Active).isHidden).isTrue() assertThat(latest!!.transitionManager!!.controllerFactory).isEqualTo(factory) assertThat(latest!!.transitionManager!!.hideChipForTransition).isFalse() Loading @@ -638,6 +649,63 @@ class CallChipViewModelTest(flags: FlagsParameterization) : SysuiTestCase() { assertThat(latest!!.transitionManager!!.controllerFactory).isNull() } @Test @EnableFlags(StatusBarChipsReturnAnimations.FLAG_NAME) @EnableChipsModernization fun chipWithReturnAnimation_updatesCorrectly_whenAppIsLaunchedAndClosedWithoutAnimation() = kosmos.runTest { val pendingIntent = mock<PendingIntent>() val intent = mock<Intent>() whenever(pendingIntent.intent).thenReturn(intent) val component = mock<ComponentName>() whenever(intent.component).thenReturn(component) val expandable = mock<Expandable>() val activityController = mock<ActivityTransitionAnimator.Controller>() whenever( expandable.activityTransitionController( anyOrNull(), anyOrNull(), any(), anyOrNull(), any(), ) ) .thenReturn(activityController) val latest by collectLastValue(underTest.chip) // Start off with a call with visible app. addOngoingCallState( key = NOTIFICATION_KEY, startTimeMs = 345, contentIntent = pendingIntent, uid = NOTIFICATION_UID, isAppVisible = true, ) assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active::class.java) assertThat((latest as OngoingActivityChipModel.Active).isHidden).isTrue() assertThat(latest!!.transitionManager!!.hideChipForTransition).isFalse() val factory = latest!!.transitionManager!!.controllerFactory assertThat(factory!!.component).isEqualTo(component) // Close the app without a return transition (e.g. from gesture nav) // [InCall(isAppVisible=true) -> InCall(isAppVisible=false), NoTransition]. kosmos.activityManagerRepository.fake.setIsAppVisible(NOTIFICATION_UID, false) assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active::class.java) assertThat((latest as OngoingActivityChipModel.Active).isHidden).isFalse() assertThat(latest!!.transitionManager!!.controllerFactory).isEqualTo(factory) assertThat(latest!!.transitionManager!!.hideChipForTransition).isFalse() // Launch the app from another source (e.g. the app icon) [InCall(isAppVisible=true) -> // InCall(isAppVisible=false), NoTransition]. kosmos.activityManagerRepository.fake.setIsAppVisible(NOTIFICATION_UID, true) assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active::class.java) assertThat((latest as OngoingActivityChipModel.Active).isHidden).isTrue() assertThat(latest!!.transitionManager!!.controllerFactory).isEqualTo(factory) assertThat(latest!!.transitionManager!!.hideChipForTransition).isFalse() } @Test @DisableFlags(StatusBarChipsReturnAnimations.FLAG_NAME) fun chipLegacy_hasNoTransitionAnimationInformation() = Loading packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt +8 −6 Original line number Diff line number Diff line Loading @@ -287,6 +287,7 @@ constructor( Cuj.CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP ) } else { transitionState.value = TransitionState.LaunchRequested // When return animations are enabled, we use a long-lived registration // with controllers created on-demand by the animation library instead // of explicitly creating one at the time of the click. By not passing Loading Loading @@ -452,12 +453,8 @@ constructor( // The call has just started and is visible. Hide the chip. if (oldState is OngoingCallModel.NoCall) return true // The state went from the app not being visible to visible. This happens when the chip // is tapped and a launch animation is about to start. Keep the chip showing. if (!(oldState as OngoingCallModel.InCall).isAppVisible) return false // The app was and remains visible, but the transition state has changed. A launch or // return animation has been requested or is ongoing. Keep the chip showing. // The transition state has changed. A launch or return animation has been requested or // is ongoing. Show the chip. if ( newTransitionState is TransitionState.LaunchRequested || newTransitionState is TransitionState.Launching || Loading @@ -467,6 +464,11 @@ constructor( return false } // The state went from the app not being visible to visible with no transition requested // or ongoing. This can happen when the app is opened by means other than tapping the // chip. Hide the chip. if (!(oldState as OngoingCallModel.InCall).isAppVisible) return true // The app was and remains visible, so we generally want to hide the chip. The only // exception is if a return transition has just ended. In this case, the transition // state changes shortly before the app visibility does. If we hide the chip between Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt +75 −7 Original line number Diff line number Diff line Loading @@ -588,15 +588,26 @@ class CallChipViewModelTest(flags: FlagsParameterization) : SysuiTestCase() { assertThat(latest!!.transitionManager!!.controllerFactory).isEqualTo(factory) assertThat(latest!!.transitionManager!!.hideChipForTransition).isFalse() // Trigger a launch transition [InCall(isAppVisible=false) -> InCall(isAppVisible=true), // NoTransition]. // Trigger a launch transition [InCall(isAppVisible=false), NoTransition -> // LaunchRequested]. val clickBehavior = (latest as OngoingActivityChipModel.Active).clickBehavior as OngoingActivityChipModel.ClickBehavior.ExpandAction clickBehavior.onClick(expandable) assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active::class.java) assertThat((latest as OngoingActivityChipModel.Active).isHidden).isFalse() assertThat(latest!!.transitionManager!!.controllerFactory).isEqualTo(factory) assertThat(latest!!.transitionManager!!.hideChipForTransition).isFalse() // System reacts to the tap [InCall(isAppVisible=false) -> InCall(isAppVisible=true), // LaunchRequested]. kosmos.activityManagerRepository.fake.setIsAppVisible(NOTIFICATION_UID, true) assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active::class.java) assertThat((latest as OngoingActivityChipModel.Active).isHidden).isFalse() assertThat(latest!!.transitionManager!!.controllerFactory).isEqualTo(factory) assertThat(latest!!.transitionManager!!.hideChipForTransition).isFalse() // Request the return transition [InCall(isAppVisible=true), NoTransition -> // Request the launch transition [InCall(isAppVisible=true), NoTransition -> // LaunchRequested]. controller = factory.createController(forLaunch = true) assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active::class.java) Loading @@ -604,7 +615,7 @@ class CallChipViewModelTest(flags: FlagsParameterization) : SysuiTestCase() { assertThat(latest!!.transitionManager!!.controllerFactory).isEqualTo(factory) assertThat(latest!!.transitionManager!!.hideChipForTransition).isFalse() // Start the return transition [InCall(isAppVisible=true), LaunchRequested -> // Start the launch transition [InCall(isAppVisible=true), LaunchRequested -> // Launching]. controller.onTransitionAnimationStart(isExpandingFullyAbove = false) assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active::class.java) Loading @@ -612,10 +623,10 @@ class CallChipViewModelTest(flags: FlagsParameterization) : SysuiTestCase() { assertThat(latest!!.transitionManager!!.controllerFactory).isEqualTo(factory) assertThat(latest!!.transitionManager!!.hideChipForTransition).isFalse() // End the return transition [InCall(isAppVisible=true), Launching -> NoTransition]. controller.onTransitionAnimationStart(isExpandingFullyAbove = false) // End the launch transition [InCall(isAppVisible=true), Launching -> NoTransition]. controller.onTransitionAnimationEnd(isExpandingFullyAbove = false) assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active::class.java) assertThat((latest as OngoingActivityChipModel.Active).isHidden).isFalse() assertThat((latest as OngoingActivityChipModel.Active).isHidden).isTrue() assertThat(latest!!.transitionManager!!.controllerFactory).isEqualTo(factory) assertThat(latest!!.transitionManager!!.hideChipForTransition).isFalse() Loading @@ -638,6 +649,63 @@ class CallChipViewModelTest(flags: FlagsParameterization) : SysuiTestCase() { assertThat(latest!!.transitionManager!!.controllerFactory).isNull() } @Test @EnableFlags(StatusBarChipsReturnAnimations.FLAG_NAME) @EnableChipsModernization fun chipWithReturnAnimation_updatesCorrectly_whenAppIsLaunchedAndClosedWithoutAnimation() = kosmos.runTest { val pendingIntent = mock<PendingIntent>() val intent = mock<Intent>() whenever(pendingIntent.intent).thenReturn(intent) val component = mock<ComponentName>() whenever(intent.component).thenReturn(component) val expandable = mock<Expandable>() val activityController = mock<ActivityTransitionAnimator.Controller>() whenever( expandable.activityTransitionController( anyOrNull(), anyOrNull(), any(), anyOrNull(), any(), ) ) .thenReturn(activityController) val latest by collectLastValue(underTest.chip) // Start off with a call with visible app. addOngoingCallState( key = NOTIFICATION_KEY, startTimeMs = 345, contentIntent = pendingIntent, uid = NOTIFICATION_UID, isAppVisible = true, ) assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active::class.java) assertThat((latest as OngoingActivityChipModel.Active).isHidden).isTrue() assertThat(latest!!.transitionManager!!.hideChipForTransition).isFalse() val factory = latest!!.transitionManager!!.controllerFactory assertThat(factory!!.component).isEqualTo(component) // Close the app without a return transition (e.g. from gesture nav) // [InCall(isAppVisible=true) -> InCall(isAppVisible=false), NoTransition]. kosmos.activityManagerRepository.fake.setIsAppVisible(NOTIFICATION_UID, false) assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active::class.java) assertThat((latest as OngoingActivityChipModel.Active).isHidden).isFalse() assertThat(latest!!.transitionManager!!.controllerFactory).isEqualTo(factory) assertThat(latest!!.transitionManager!!.hideChipForTransition).isFalse() // Launch the app from another source (e.g. the app icon) [InCall(isAppVisible=true) -> // InCall(isAppVisible=false), NoTransition]. kosmos.activityManagerRepository.fake.setIsAppVisible(NOTIFICATION_UID, true) assertThat(latest).isInstanceOf(OngoingActivityChipModel.Active::class.java) assertThat((latest as OngoingActivityChipModel.Active).isHidden).isTrue() assertThat(latest!!.transitionManager!!.controllerFactory).isEqualTo(factory) assertThat(latest!!.transitionManager!!.hideChipForTransition).isFalse() } @Test @DisableFlags(StatusBarChipsReturnAnimations.FLAG_NAME) fun chipLegacy_hasNoTransitionAnimationInformation() = Loading
packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt +8 −6 Original line number Diff line number Diff line Loading @@ -287,6 +287,7 @@ constructor( Cuj.CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP ) } else { transitionState.value = TransitionState.LaunchRequested // When return animations are enabled, we use a long-lived registration // with controllers created on-demand by the animation library instead // of explicitly creating one at the time of the click. By not passing Loading Loading @@ -452,12 +453,8 @@ constructor( // The call has just started and is visible. Hide the chip. if (oldState is OngoingCallModel.NoCall) return true // The state went from the app not being visible to visible. This happens when the chip // is tapped and a launch animation is about to start. Keep the chip showing. if (!(oldState as OngoingCallModel.InCall).isAppVisible) return false // The app was and remains visible, but the transition state has changed. A launch or // return animation has been requested or is ongoing. Keep the chip showing. // The transition state has changed. A launch or return animation has been requested or // is ongoing. Show the chip. if ( newTransitionState is TransitionState.LaunchRequested || newTransitionState is TransitionState.Launching || Loading @@ -467,6 +464,11 @@ constructor( return false } // The state went from the app not being visible to visible with no transition requested // or ongoing. This can happen when the app is opened by means other than tapping the // chip. Hide the chip. if (!(oldState as OngoingCallModel.InCall).isAppVisible) return true // The app was and remains visible, so we generally want to hide the chip. The only // exception is if a return transition has just ended. In this case, the transition // state changes shortly before the app visibility does. If we hide the chip between Loading