Loading packages/SystemUI/aconfig/systemui.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -1105,3 +1105,13 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "media_lockscreen_launch_animation" namespace : "systemui" description : "Enable the origin launch animation for UMO when opening on top of lockscreen." bug : "346865769" metadata { purpose: PURPOSE_BUGFIX } } packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImplTest.kt +169 −50 Original line number Diff line number Diff line Loading @@ -20,8 +20,11 @@ import android.app.ActivityOptions import android.app.PendingIntent import android.content.Intent import android.os.Bundle import android.os.Handler import android.os.RemoteException import android.os.UserHandle import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.view.View import android.widget.FrameLayout import android.window.SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR Loading @@ -29,6 +32,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.ActivityIntentHelper import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.animation.ActivityTransitionAnimator import com.android.systemui.animation.LaunchableView Loading @@ -36,7 +40,6 @@ import com.android.systemui.assist.AssistManager import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.keyguard.KeyguardViewMediator import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.plugins.ActivityStarter.OnDismissAction import com.android.systemui.settings.UserTracker import com.android.systemui.shade.ShadeController import com.android.systemui.shade.data.repository.FakeShadeRepository Loading @@ -51,11 +54,6 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.statusbar.window.StatusBarWindowController import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.nullable import com.android.systemui.util.mockito.whenever import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat import java.util.Optional Loading @@ -64,14 +62,19 @@ import kotlinx.coroutines.flow.MutableStateFlow import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.nullable import org.mockito.Mock import org.mockito.Mockito.anyBoolean import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations import org.mockito.kotlin.any import org.mockito.kotlin.argumentCaptor import org.mockito.kotlin.eq import org.mockito.kotlin.never import org.mockito.kotlin.times import org.mockito.kotlin.verify @ExperimentalCoroutinesApi @SmallTest Loading Loading @@ -132,22 +135,22 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { mainExecutor = mainExecutor, communalSceneInteractor = communalSceneInteractor, ) whenever(userTracker.userHandle).thenReturn(UserHandle.OWNER) whenever(communalSceneInteractor.isIdleOnCommunal).thenReturn(MutableStateFlow(false)) `when`(userTracker.userHandle).thenReturn(UserHandle.OWNER) `when`(communalSceneInteractor.isIdleOnCommunal).thenReturn(MutableStateFlow(false)) } @Test fun startPendingIntentDismissingKeyguard_keyguardShowing_dismissWithAction() { val pendingIntent = mock(PendingIntent::class.java) whenever(pendingIntent.isActivity).thenReturn(true) whenever(keyguardStateController.isShowing).thenReturn(true) whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) `when`(pendingIntent.isActivity).thenReturn(true) `when`(keyguardStateController.isShowing).thenReturn(true) `when`(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) underTest.startPendingIntentDismissingKeyguard(intent = pendingIntent, dismissShade = true) mainExecutor.runAllReady() verify(statusBarKeyguardViewManager) .dismissWithAction(any(OnDismissAction::class.java), eq(null), anyBoolean(), eq(null)) .dismissWithAction(any(), eq(null), anyBoolean(), eq(null)) } @Test Loading @@ -160,10 +163,10 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { } parent.addView(view) val controller = ActivityTransitionAnimator.Controller.fromView(view) whenever(pendingIntent.isActivity).thenReturn(true) whenever(keyguardStateController.isShowing).thenReturn(true) whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) whenever(activityIntentHelper.wouldPendingShowOverLockscreen(eq(pendingIntent), anyInt())) `when`(pendingIntent.isActivity).thenReturn(true) `when`(keyguardStateController.isShowing).thenReturn(true) `when`(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) `when`(activityIntentHelper.wouldPendingShowOverLockscreen(eq(pendingIntent), anyInt())) .thenReturn(true) startPendingIntentMaybeDismissingKeyguard( Loading @@ -175,9 +178,9 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { verify(activityTransitionAnimator) .startPendingIntentWithAnimation( nullable(), nullable(ActivityTransitionAnimator.Controller::class.java), eq(true), nullable(), nullable(String::class.java), eq(true), any(), ) Loading @@ -193,10 +196,10 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { } parent.addView(view) val controller = ActivityTransitionAnimator.Controller.fromView(view) whenever(pendingIntent.isActivity).thenReturn(true) whenever(keyguardStateController.isShowing).thenReturn(true) whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) whenever(activityIntentHelper.wouldPendingShowOverLockscreen(eq(pendingIntent), anyInt())) `when`(pendingIntent.isActivity).thenReturn(true) `when`(keyguardStateController.isShowing).thenReturn(true) `when`(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) `when`(activityIntentHelper.wouldPendingShowOverLockscreen(eq(pendingIntent), anyInt())) .thenReturn(false) // extra activity options to set on pending intent Loading @@ -220,12 +223,12 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { eq(context), eq(0), eq(fillInIntent), nullable(), nullable(), nullable(), nullable(PendingIntent.OnFinished::class.java), nullable(Handler::class.java), nullable(String::class.java), bundleCaptor.capture() ) val options = ActivityOptions.fromBundle(bundleCaptor.value) val options = ActivityOptions.fromBundle(bundleCaptor.firstValue) assertThat(options.isPendingIntentBackgroundActivityLaunchAllowedByPermission).isFalse() assertThat(options.splashScreenStyle).isEqualTo(SPLASH_SCREEN_STYLE_SOLID_COLOR) } Loading @@ -245,6 +248,74 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { verify(centralSurfaces).getAnimatorControllerFromNotification(associatedView) } @EnableFlags(Flags.FLAG_MEDIA_LOCKSCREEN_LAUNCH_ANIMATION) @Test fun startPendingIntentDismissingKeyguard_transitionAnimator_animateOverOcclusion() { val parent = FrameLayout(context) val view = object : View(context), LaunchableView { override fun setShouldBlockVisibilityChanges(block: Boolean) {} } parent.addView(view) val controller = ActivityTransitionAnimator.Controller.fromView(view) val pendingIntent = mock(PendingIntent::class.java) `when`(pendingIntent.isActivity).thenReturn(true) `when`(keyguardStateController.isShowing).thenReturn(true) `when`(keyguardStateController.isOccluded).thenReturn(true) underTest.startPendingIntentDismissingKeyguard( intent = pendingIntent, dismissShade = true, animationController = controller, showOverLockscreen = true, skipLockscreenChecks = true ) mainExecutor.runAllReady() verify(activityTransitionAnimator) .startPendingIntentWithAnimation( nullable(ActivityTransitionAnimator.Controller::class.java), eq(true), nullable(String::class.java), eq(true), any(), ) } @DisableFlags(Flags.FLAG_MEDIA_LOCKSCREEN_LAUNCH_ANIMATION) @Test fun startPendingIntentDismissingKeyguard_transitionAnimator_doNotAnimateOverOcclusion() { val parent = FrameLayout(context) val view = object : View(context), LaunchableView { override fun setShouldBlockVisibilityChanges(block: Boolean) {} } parent.addView(view) val controller = ActivityTransitionAnimator.Controller.fromView(view) val pendingIntent = mock(PendingIntent::class.java) `when`(pendingIntent.isActivity).thenReturn(true) `when`(keyguardStateController.isShowing).thenReturn(true) `when`(keyguardStateController.isOccluded).thenReturn(true) underTest.startPendingIntentDismissingKeyguard( intent = pendingIntent, dismissShade = true, animationController = controller, showOverLockscreen = true, skipLockscreenChecks = true ) mainExecutor.runAllReady() verify(activityTransitionAnimator) .startPendingIntentWithAnimation( nullable(ActivityTransitionAnimator.Controller::class.java), eq(false), nullable(String::class.java), eq(true), any(), ) } @Test fun startActivity_noUserHandleProvided_getUserHandle() { val intent = mock(Intent::class.java) Loading @@ -254,13 +325,66 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { verify(userTracker).userHandle } @EnableFlags(Flags.FLAG_MEDIA_LOCKSCREEN_LAUNCH_ANIMATION) @Test fun startActivity_transitionAnimator_animateOverOcclusion() { val intent = mock(Intent::class.java) val parent = FrameLayout(context) val view = object : View(context), LaunchableView { override fun setShouldBlockVisibilityChanges(block: Boolean) {} } parent.addView(view) val controller = ActivityTransitionAnimator.Controller.fromView(view) `when`(keyguardStateController.isShowing).thenReturn(true) `when`(keyguardStateController.isOccluded).thenReturn(true) mainExecutor.runAllReady() underTest.startActivity(intent, true, controller, true, null) verify(activityTransitionAnimator) .startIntentWithAnimation( nullable(ActivityTransitionAnimator.Controller::class.java), eq(true), nullable(String::class.java), eq(true), any(), ) } @DisableFlags(Flags.FLAG_MEDIA_LOCKSCREEN_LAUNCH_ANIMATION) @Test fun startActivity_transitionAnimator_doNotAnimateOverOcclusion() { val intent = mock(Intent::class.java) val parent = FrameLayout(context) val view = object : View(context), LaunchableView { override fun setShouldBlockVisibilityChanges(block: Boolean) {} } parent.addView(view) val controller = ActivityTransitionAnimator.Controller.fromView(view) `when`(keyguardStateController.isShowing).thenReturn(true) `when`(keyguardStateController.isOccluded).thenReturn(true) mainExecutor.runAllReady() underTest.startActivity(intent, true, controller, true, null) verify(activityTransitionAnimator) .startIntentWithAnimation( nullable(ActivityTransitionAnimator.Controller::class.java), eq(false), nullable(String::class.java), eq(true), any(), ) } @Test fun dismissKeyguardThenExecute_startWakeAndUnlock() { whenever(wakefulnessLifecycle.wakefulness) .thenReturn(WakefulnessLifecycle.WAKEFULNESS_ASLEEP) whenever(keyguardStateController.canDismissLockScreen()).thenReturn(true) whenever(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(false) whenever(dozeServiceHost.isPulsing).thenReturn(true) `when`(wakefulnessLifecycle.wakefulness).thenReturn(WakefulnessLifecycle.WAKEFULNESS_ASLEEP) `when`(keyguardStateController.canDismissLockScreen()).thenReturn(true) `when`(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(false) `when`(dozeServiceHost.isPulsing).thenReturn(true) underTest.dismissKeyguardThenExecute({ true }, {}, false) Loading @@ -271,25 +395,20 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { @Test fun dismissKeyguardThenExecute_keyguardIsShowing_dismissWithAction() { val customMessage = "Enter your pin." whenever(keyguardStateController.isShowing).thenReturn(true) `when`(keyguardStateController.isShowing).thenReturn(true) underTest.dismissKeyguardThenExecute({ true }, {}, false, customMessage) verify(statusBarKeyguardViewManager) .dismissWithAction( any(OnDismissAction::class.java), any(Runnable::class.java), eq(false), eq(customMessage) ) .dismissWithAction(any(), any(), eq(false), eq(customMessage)) } @Test fun dismissKeyguardThenExecute_awakeDreams() { val customMessage = "Enter your pin." var dismissActionExecuted = false whenever(keyguardStateController.isShowing).thenReturn(false) whenever(keyguardUpdateMonitor.isDreaming).thenReturn(true) `when`(keyguardStateController.isShowing).thenReturn(false) `when`(keyguardUpdateMonitor.isDreaming).thenReturn(true) underTest.dismissKeyguardThenExecute( { Loading @@ -308,9 +427,9 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { @Test @Throws(RemoteException::class) fun executeRunnableDismissingKeyguard_dreaming_notShowing_awakenDreams() { whenever(keyguardStateController.isShowing).thenReturn(false) whenever(keyguardStateController.isOccluded).thenReturn(false) whenever(keyguardUpdateMonitor.isDreaming).thenReturn(true) `when`(keyguardStateController.isShowing).thenReturn(false) `when`(keyguardStateController.isOccluded).thenReturn(false) `when`(keyguardUpdateMonitor.isDreaming).thenReturn(true) underTest.executeRunnableDismissingKeyguard( runnable = {}, Loading @@ -326,9 +445,9 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { @Test @Throws(RemoteException::class) fun executeRunnableDismissingKeyguard_notDreaming_notShowing_doNotAwakenDreams() { whenever(keyguardStateController.isShowing).thenReturn(false) whenever(keyguardStateController.isOccluded).thenReturn(false) whenever(keyguardUpdateMonitor.isDreaming).thenReturn(false) `when`(keyguardStateController.isShowing).thenReturn(false) `when`(keyguardStateController.isOccluded).thenReturn(false) `when`(keyguardUpdateMonitor.isDreaming).thenReturn(false) underTest.executeRunnableDismissingKeyguard( runnable = {}, Loading packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java +18 −7 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.media.controls.ui.controller; import static android.provider.Settings.ACTION_MEDIA_CONTROLS_SETTINGS; import static com.android.settingslib.flags.Flags.legacyLeAudioSharing; import static com.android.systemui.Flags.mediaLockscreenLaunchAnimation; import static com.android.systemui.media.controls.shared.model.SmartspaceMediaDataKt.NUM_REQUIRED_RECOMMENDATIONS; import android.animation.Animator; Loading Loading @@ -577,6 +578,15 @@ public class MediaControlPanel { && mActivityIntentHelper.wouldPendingShowOverLockscreen(clickIntent, mLockscreenUserManager.getCurrentUserId()); if (showOverLockscreen) { if (mediaLockscreenLaunchAnimation()) { mActivityStarter.startPendingIntentMaybeDismissingKeyguard( clickIntent, /* dismissShade = */ true, /* intentSentUiThreadCallback = */ null, buildLaunchAnimatorController(mMediaViewHolder.getPlayer()), /* fillIntent = */ null, /* extraOptions = */ null); } else { try { ActivityOptions opts = ActivityOptions.makeBasic(); opts.setPendingIntentBackgroundActivityStartMode( Loading @@ -585,6 +595,7 @@ public class MediaControlPanel { } catch (PendingIntent.CanceledException e) { Log.e(TAG, "Pending intent for " + key + " was cancelled"); } } } else { mActivityStarter.postStartActivityDismissingKeyguard(clickIntent, buildLaunchAnimatorController(mMediaViewHolder.getPlayer())); Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt +4 −2 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.view.WindowManager import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.ActivityIntentHelper import com.android.systemui.Flags.communalHub import com.android.systemui.Flags.mediaLockscreenLaunchAnimation import com.android.systemui.animation.ActivityTransitionAnimator import com.android.systemui.animation.DelegateTransitionAnimatorController import com.android.systemui.assist.AssistManager Loading Loading @@ -635,8 +636,9 @@ constructor( isActivityIntent: Boolean, showOverLockscreen: Boolean, ): Boolean { // TODO(b/294418322): Support launch animations when occluded. if (keyguardStateController.isOccluded) { // TODO(b/294418322): always support launch animations when occluded. val ignoreOcclusion = showOverLockscreen && mediaLockscreenLaunchAnimation() if (keyguardStateController.isOccluded && !ignoreOcclusion) { return false } Loading packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt +34 −1 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import android.media.MediaMetadata import android.media.session.MediaSession import android.media.session.PlaybackState import android.os.Bundle import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.platform.test.annotations.RequiresFlagsEnabled import android.platform.test.flag.junit.DeviceFlagsValueProvider Loading Loading @@ -1771,8 +1772,40 @@ public class MediaControlPanelTest : SysuiTestCase() { verify(logger).logSeek(anyInt(), eq(PACKAGE), eq(instanceId)) } @EnableFlags(Flags.FLAG_MEDIA_LOCKSCREEN_LAUNCH_ANIMATION) @Test fun tapContentView_showOverLockscreen_openActivity() { fun tapContentView_showOverLockscreen_openActivity_withOriginAnimation() { // WHEN we are on lockscreen and this activity can show over lockscreen whenever(keyguardStateController.isShowing).thenReturn(true) whenever(activityIntentHelper.wouldPendingShowOverLockscreen(any(), any())).thenReturn(true) val clickIntent = mock(Intent::class.java) val pendingIntent = mock(PendingIntent::class.java) whenever(pendingIntent.intent).thenReturn(clickIntent) val captor = ArgumentCaptor.forClass(View.OnClickListener::class.java) val data = mediaData.copy(clickIntent = pendingIntent) player.attachPlayer(viewHolder) player.bindPlayer(data, KEY) verify(viewHolder.player).setOnClickListener(captor.capture()) // THEN it sends the PendingIntent without dismissing keyguard first, // and does not use the Intent directly (see b/271845008) captor.value.onClick(viewHolder.player) verify(activityStarter) .startPendingIntentMaybeDismissingKeyguard( eq(pendingIntent), eq(true), eq(null), any(), eq(null), eq(null), ) verify(activityStarter, never()).postStartActivityDismissingKeyguard(eq(clickIntent), any()) } @DisableFlags(Flags.FLAG_MEDIA_LOCKSCREEN_LAUNCH_ANIMATION) @Test fun tapContentView_showOverLockscreen_openActivity_withoutOriginAnimation() { // WHEN we are on lockscreen and this activity can show over lockscreen whenever(keyguardStateController.isShowing).thenReturn(true) whenever(activityIntentHelper.wouldPendingShowOverLockscreen(any(), any())).thenReturn(true) Loading Loading
packages/SystemUI/aconfig/systemui.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -1105,3 +1105,13 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "media_lockscreen_launch_animation" namespace : "systemui" description : "Enable the origin launch animation for UMO when opening on top of lockscreen." bug : "346865769" metadata { purpose: PURPOSE_BUGFIX } }
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImplTest.kt +169 −50 Original line number Diff line number Diff line Loading @@ -20,8 +20,11 @@ import android.app.ActivityOptions import android.app.PendingIntent import android.content.Intent import android.os.Bundle import android.os.Handler import android.os.RemoteException import android.os.UserHandle import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.view.View import android.widget.FrameLayout import android.window.SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR Loading @@ -29,6 +32,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.ActivityIntentHelper import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.animation.ActivityTransitionAnimator import com.android.systemui.animation.LaunchableView Loading @@ -36,7 +40,6 @@ import com.android.systemui.assist.AssistManager import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.keyguard.KeyguardViewMediator import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.plugins.ActivityStarter.OnDismissAction import com.android.systemui.settings.UserTracker import com.android.systemui.shade.ShadeController import com.android.systemui.shade.data.repository.FakeShadeRepository Loading @@ -51,11 +54,6 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.statusbar.window.StatusBarWindowController import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.nullable import com.android.systemui.util.mockito.whenever import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat import java.util.Optional Loading @@ -64,14 +62,19 @@ import kotlinx.coroutines.flow.MutableStateFlow import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.nullable import org.mockito.Mock import org.mockito.Mockito.anyBoolean import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations import org.mockito.kotlin.any import org.mockito.kotlin.argumentCaptor import org.mockito.kotlin.eq import org.mockito.kotlin.never import org.mockito.kotlin.times import org.mockito.kotlin.verify @ExperimentalCoroutinesApi @SmallTest Loading Loading @@ -132,22 +135,22 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { mainExecutor = mainExecutor, communalSceneInteractor = communalSceneInteractor, ) whenever(userTracker.userHandle).thenReturn(UserHandle.OWNER) whenever(communalSceneInteractor.isIdleOnCommunal).thenReturn(MutableStateFlow(false)) `when`(userTracker.userHandle).thenReturn(UserHandle.OWNER) `when`(communalSceneInteractor.isIdleOnCommunal).thenReturn(MutableStateFlow(false)) } @Test fun startPendingIntentDismissingKeyguard_keyguardShowing_dismissWithAction() { val pendingIntent = mock(PendingIntent::class.java) whenever(pendingIntent.isActivity).thenReturn(true) whenever(keyguardStateController.isShowing).thenReturn(true) whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) `when`(pendingIntent.isActivity).thenReturn(true) `when`(keyguardStateController.isShowing).thenReturn(true) `when`(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) underTest.startPendingIntentDismissingKeyguard(intent = pendingIntent, dismissShade = true) mainExecutor.runAllReady() verify(statusBarKeyguardViewManager) .dismissWithAction(any(OnDismissAction::class.java), eq(null), anyBoolean(), eq(null)) .dismissWithAction(any(), eq(null), anyBoolean(), eq(null)) } @Test Loading @@ -160,10 +163,10 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { } parent.addView(view) val controller = ActivityTransitionAnimator.Controller.fromView(view) whenever(pendingIntent.isActivity).thenReturn(true) whenever(keyguardStateController.isShowing).thenReturn(true) whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) whenever(activityIntentHelper.wouldPendingShowOverLockscreen(eq(pendingIntent), anyInt())) `when`(pendingIntent.isActivity).thenReturn(true) `when`(keyguardStateController.isShowing).thenReturn(true) `when`(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) `when`(activityIntentHelper.wouldPendingShowOverLockscreen(eq(pendingIntent), anyInt())) .thenReturn(true) startPendingIntentMaybeDismissingKeyguard( Loading @@ -175,9 +178,9 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { verify(activityTransitionAnimator) .startPendingIntentWithAnimation( nullable(), nullable(ActivityTransitionAnimator.Controller::class.java), eq(true), nullable(), nullable(String::class.java), eq(true), any(), ) Loading @@ -193,10 +196,10 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { } parent.addView(view) val controller = ActivityTransitionAnimator.Controller.fromView(view) whenever(pendingIntent.isActivity).thenReturn(true) whenever(keyguardStateController.isShowing).thenReturn(true) whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) whenever(activityIntentHelper.wouldPendingShowOverLockscreen(eq(pendingIntent), anyInt())) `when`(pendingIntent.isActivity).thenReturn(true) `when`(keyguardStateController.isShowing).thenReturn(true) `when`(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) `when`(activityIntentHelper.wouldPendingShowOverLockscreen(eq(pendingIntent), anyInt())) .thenReturn(false) // extra activity options to set on pending intent Loading @@ -220,12 +223,12 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { eq(context), eq(0), eq(fillInIntent), nullable(), nullable(), nullable(), nullable(PendingIntent.OnFinished::class.java), nullable(Handler::class.java), nullable(String::class.java), bundleCaptor.capture() ) val options = ActivityOptions.fromBundle(bundleCaptor.value) val options = ActivityOptions.fromBundle(bundleCaptor.firstValue) assertThat(options.isPendingIntentBackgroundActivityLaunchAllowedByPermission).isFalse() assertThat(options.splashScreenStyle).isEqualTo(SPLASH_SCREEN_STYLE_SOLID_COLOR) } Loading @@ -245,6 +248,74 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { verify(centralSurfaces).getAnimatorControllerFromNotification(associatedView) } @EnableFlags(Flags.FLAG_MEDIA_LOCKSCREEN_LAUNCH_ANIMATION) @Test fun startPendingIntentDismissingKeyguard_transitionAnimator_animateOverOcclusion() { val parent = FrameLayout(context) val view = object : View(context), LaunchableView { override fun setShouldBlockVisibilityChanges(block: Boolean) {} } parent.addView(view) val controller = ActivityTransitionAnimator.Controller.fromView(view) val pendingIntent = mock(PendingIntent::class.java) `when`(pendingIntent.isActivity).thenReturn(true) `when`(keyguardStateController.isShowing).thenReturn(true) `when`(keyguardStateController.isOccluded).thenReturn(true) underTest.startPendingIntentDismissingKeyguard( intent = pendingIntent, dismissShade = true, animationController = controller, showOverLockscreen = true, skipLockscreenChecks = true ) mainExecutor.runAllReady() verify(activityTransitionAnimator) .startPendingIntentWithAnimation( nullable(ActivityTransitionAnimator.Controller::class.java), eq(true), nullable(String::class.java), eq(true), any(), ) } @DisableFlags(Flags.FLAG_MEDIA_LOCKSCREEN_LAUNCH_ANIMATION) @Test fun startPendingIntentDismissingKeyguard_transitionAnimator_doNotAnimateOverOcclusion() { val parent = FrameLayout(context) val view = object : View(context), LaunchableView { override fun setShouldBlockVisibilityChanges(block: Boolean) {} } parent.addView(view) val controller = ActivityTransitionAnimator.Controller.fromView(view) val pendingIntent = mock(PendingIntent::class.java) `when`(pendingIntent.isActivity).thenReturn(true) `when`(keyguardStateController.isShowing).thenReturn(true) `when`(keyguardStateController.isOccluded).thenReturn(true) underTest.startPendingIntentDismissingKeyguard( intent = pendingIntent, dismissShade = true, animationController = controller, showOverLockscreen = true, skipLockscreenChecks = true ) mainExecutor.runAllReady() verify(activityTransitionAnimator) .startPendingIntentWithAnimation( nullable(ActivityTransitionAnimator.Controller::class.java), eq(false), nullable(String::class.java), eq(true), any(), ) } @Test fun startActivity_noUserHandleProvided_getUserHandle() { val intent = mock(Intent::class.java) Loading @@ -254,13 +325,66 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { verify(userTracker).userHandle } @EnableFlags(Flags.FLAG_MEDIA_LOCKSCREEN_LAUNCH_ANIMATION) @Test fun startActivity_transitionAnimator_animateOverOcclusion() { val intent = mock(Intent::class.java) val parent = FrameLayout(context) val view = object : View(context), LaunchableView { override fun setShouldBlockVisibilityChanges(block: Boolean) {} } parent.addView(view) val controller = ActivityTransitionAnimator.Controller.fromView(view) `when`(keyguardStateController.isShowing).thenReturn(true) `when`(keyguardStateController.isOccluded).thenReturn(true) mainExecutor.runAllReady() underTest.startActivity(intent, true, controller, true, null) verify(activityTransitionAnimator) .startIntentWithAnimation( nullable(ActivityTransitionAnimator.Controller::class.java), eq(true), nullable(String::class.java), eq(true), any(), ) } @DisableFlags(Flags.FLAG_MEDIA_LOCKSCREEN_LAUNCH_ANIMATION) @Test fun startActivity_transitionAnimator_doNotAnimateOverOcclusion() { val intent = mock(Intent::class.java) val parent = FrameLayout(context) val view = object : View(context), LaunchableView { override fun setShouldBlockVisibilityChanges(block: Boolean) {} } parent.addView(view) val controller = ActivityTransitionAnimator.Controller.fromView(view) `when`(keyguardStateController.isShowing).thenReturn(true) `when`(keyguardStateController.isOccluded).thenReturn(true) mainExecutor.runAllReady() underTest.startActivity(intent, true, controller, true, null) verify(activityTransitionAnimator) .startIntentWithAnimation( nullable(ActivityTransitionAnimator.Controller::class.java), eq(false), nullable(String::class.java), eq(true), any(), ) } @Test fun dismissKeyguardThenExecute_startWakeAndUnlock() { whenever(wakefulnessLifecycle.wakefulness) .thenReturn(WakefulnessLifecycle.WAKEFULNESS_ASLEEP) whenever(keyguardStateController.canDismissLockScreen()).thenReturn(true) whenever(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(false) whenever(dozeServiceHost.isPulsing).thenReturn(true) `when`(wakefulnessLifecycle.wakefulness).thenReturn(WakefulnessLifecycle.WAKEFULNESS_ASLEEP) `when`(keyguardStateController.canDismissLockScreen()).thenReturn(true) `when`(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(false) `when`(dozeServiceHost.isPulsing).thenReturn(true) underTest.dismissKeyguardThenExecute({ true }, {}, false) Loading @@ -271,25 +395,20 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { @Test fun dismissKeyguardThenExecute_keyguardIsShowing_dismissWithAction() { val customMessage = "Enter your pin." whenever(keyguardStateController.isShowing).thenReturn(true) `when`(keyguardStateController.isShowing).thenReturn(true) underTest.dismissKeyguardThenExecute({ true }, {}, false, customMessage) verify(statusBarKeyguardViewManager) .dismissWithAction( any(OnDismissAction::class.java), any(Runnable::class.java), eq(false), eq(customMessage) ) .dismissWithAction(any(), any(), eq(false), eq(customMessage)) } @Test fun dismissKeyguardThenExecute_awakeDreams() { val customMessage = "Enter your pin." var dismissActionExecuted = false whenever(keyguardStateController.isShowing).thenReturn(false) whenever(keyguardUpdateMonitor.isDreaming).thenReturn(true) `when`(keyguardStateController.isShowing).thenReturn(false) `when`(keyguardUpdateMonitor.isDreaming).thenReturn(true) underTest.dismissKeyguardThenExecute( { Loading @@ -308,9 +427,9 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { @Test @Throws(RemoteException::class) fun executeRunnableDismissingKeyguard_dreaming_notShowing_awakenDreams() { whenever(keyguardStateController.isShowing).thenReturn(false) whenever(keyguardStateController.isOccluded).thenReturn(false) whenever(keyguardUpdateMonitor.isDreaming).thenReturn(true) `when`(keyguardStateController.isShowing).thenReturn(false) `when`(keyguardStateController.isOccluded).thenReturn(false) `when`(keyguardUpdateMonitor.isDreaming).thenReturn(true) underTest.executeRunnableDismissingKeyguard( runnable = {}, Loading @@ -326,9 +445,9 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { @Test @Throws(RemoteException::class) fun executeRunnableDismissingKeyguard_notDreaming_notShowing_doNotAwakenDreams() { whenever(keyguardStateController.isShowing).thenReturn(false) whenever(keyguardStateController.isOccluded).thenReturn(false) whenever(keyguardUpdateMonitor.isDreaming).thenReturn(false) `when`(keyguardStateController.isShowing).thenReturn(false) `when`(keyguardStateController.isOccluded).thenReturn(false) `when`(keyguardUpdateMonitor.isDreaming).thenReturn(false) underTest.executeRunnableDismissingKeyguard( runnable = {}, Loading
packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java +18 −7 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.media.controls.ui.controller; import static android.provider.Settings.ACTION_MEDIA_CONTROLS_SETTINGS; import static com.android.settingslib.flags.Flags.legacyLeAudioSharing; import static com.android.systemui.Flags.mediaLockscreenLaunchAnimation; import static com.android.systemui.media.controls.shared.model.SmartspaceMediaDataKt.NUM_REQUIRED_RECOMMENDATIONS; import android.animation.Animator; Loading Loading @@ -577,6 +578,15 @@ public class MediaControlPanel { && mActivityIntentHelper.wouldPendingShowOverLockscreen(clickIntent, mLockscreenUserManager.getCurrentUserId()); if (showOverLockscreen) { if (mediaLockscreenLaunchAnimation()) { mActivityStarter.startPendingIntentMaybeDismissingKeyguard( clickIntent, /* dismissShade = */ true, /* intentSentUiThreadCallback = */ null, buildLaunchAnimatorController(mMediaViewHolder.getPlayer()), /* fillIntent = */ null, /* extraOptions = */ null); } else { try { ActivityOptions opts = ActivityOptions.makeBasic(); opts.setPendingIntentBackgroundActivityStartMode( Loading @@ -585,6 +595,7 @@ public class MediaControlPanel { } catch (PendingIntent.CanceledException e) { Log.e(TAG, "Pending intent for " + key + " was cancelled"); } } } else { mActivityStarter.postStartActivityDismissingKeyguard(clickIntent, buildLaunchAnimatorController(mMediaViewHolder.getPlayer())); Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt +4 −2 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.view.WindowManager import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.ActivityIntentHelper import com.android.systemui.Flags.communalHub import com.android.systemui.Flags.mediaLockscreenLaunchAnimation import com.android.systemui.animation.ActivityTransitionAnimator import com.android.systemui.animation.DelegateTransitionAnimatorController import com.android.systemui.assist.AssistManager Loading Loading @@ -635,8 +636,9 @@ constructor( isActivityIntent: Boolean, showOverLockscreen: Boolean, ): Boolean { // TODO(b/294418322): Support launch animations when occluded. if (keyguardStateController.isOccluded) { // TODO(b/294418322): always support launch animations when occluded. val ignoreOcclusion = showOverLockscreen && mediaLockscreenLaunchAnimation() if (keyguardStateController.isOccluded && !ignoreOcclusion) { return false } Loading
packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt +34 −1 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import android.media.MediaMetadata import android.media.session.MediaSession import android.media.session.PlaybackState import android.os.Bundle import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.platform.test.annotations.RequiresFlagsEnabled import android.platform.test.flag.junit.DeviceFlagsValueProvider Loading Loading @@ -1771,8 +1772,40 @@ public class MediaControlPanelTest : SysuiTestCase() { verify(logger).logSeek(anyInt(), eq(PACKAGE), eq(instanceId)) } @EnableFlags(Flags.FLAG_MEDIA_LOCKSCREEN_LAUNCH_ANIMATION) @Test fun tapContentView_showOverLockscreen_openActivity() { fun tapContentView_showOverLockscreen_openActivity_withOriginAnimation() { // WHEN we are on lockscreen and this activity can show over lockscreen whenever(keyguardStateController.isShowing).thenReturn(true) whenever(activityIntentHelper.wouldPendingShowOverLockscreen(any(), any())).thenReturn(true) val clickIntent = mock(Intent::class.java) val pendingIntent = mock(PendingIntent::class.java) whenever(pendingIntent.intent).thenReturn(clickIntent) val captor = ArgumentCaptor.forClass(View.OnClickListener::class.java) val data = mediaData.copy(clickIntent = pendingIntent) player.attachPlayer(viewHolder) player.bindPlayer(data, KEY) verify(viewHolder.player).setOnClickListener(captor.capture()) // THEN it sends the PendingIntent without dismissing keyguard first, // and does not use the Intent directly (see b/271845008) captor.value.onClick(viewHolder.player) verify(activityStarter) .startPendingIntentMaybeDismissingKeyguard( eq(pendingIntent), eq(true), eq(null), any(), eq(null), eq(null), ) verify(activityStarter, never()).postStartActivityDismissingKeyguard(eq(clickIntent), any()) } @DisableFlags(Flags.FLAG_MEDIA_LOCKSCREEN_LAUNCH_ANIMATION) @Test fun tapContentView_showOverLockscreen_openActivity_withoutOriginAnimation() { // WHEN we are on lockscreen and this activity can show over lockscreen whenever(keyguardStateController.isShowing).thenReturn(true) whenever(activityIntentHelper.wouldPendingShowOverLockscreen(any(), any())).thenReturn(true) Loading