Loading packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt +2 −1 Original line number Diff line number Diff line Loading @@ -290,9 +290,10 @@ class ActivityLaunchAnimator( controller: Controller?, animate: Boolean = true, packageName: String? = null, showOverLockscreen: Boolean = false, intentStarter: PendingIntentStarter ) { startIntentWithAnimation(controller, animate, packageName) { startIntentWithAnimation(controller, animate, packageName, showOverLockscreen) { intentStarter.startPendingIntent(it) } } Loading packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java +10 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,16 @@ public interface ActivityStarter { Runnable intentSentUiThreadCallback, @Nullable ActivityLaunchAnimator.Controller animationController); /** * Similar to {@link #startPendingIntentDismissingKeyguard}, except that it supports launching * activities on top of the keyguard. If the activity supports {@code showOverLockscreen}, it * will show over keyguard without first dimissing it. If it doesn't support it, calling this * method is exactly the same as calling {@link #startPendingIntentDismissingKeyguard}. */ void startPendingIntentMaybeDismissingKeyguard(PendingIntent intent, @Nullable Runnable intentSentUiThreadCallback, @Nullable ActivityLaunchAnimator.Controller animationController); /** * The intent flag can be specified in startActivity(). */ Loading packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java +12 −6 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ import android.widget.Switch; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.animation.ActivityLaunchAnimator; Loading Loading @@ -538,12 +539,17 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener, Log.i(TAG, "Launching activity before click"); } else { Log.i(TAG, "The activity is starting"); ActivityLaunchAnimator.Controller controller = mViewClicked == null ? null : ActivityLaunchAnimator.Controller.fromView(mViewClicked, 0); mUiHandler.post(() -> mActivityStarter.startPendingIntentDismissingKeyguard( pendingIntent, null, controller) ActivityLaunchAnimator.Controller controller = mViewClicked == null ? null : ActivityLaunchAnimator.Controller.fromView( mViewClicked, InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE ); mActivityStarter.startPendingIntentMaybeDismissingKeyguard( pendingIntent, /* intentSentUiThreadCallback= */ null, controller ); } } Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt +177 −127 Original line number Diff line number Diff line Loading @@ -30,7 +30,6 @@ import android.view.View import android.view.WindowManager import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.ActivityIntentHelper import com.android.systemui.res.R import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.animation.ActivityLaunchAnimator.PendingIntentStarter import com.android.systemui.animation.DelegateLaunchAnimatorController Loading @@ -43,6 +42,7 @@ import com.android.systemui.keyguard.KeyguardViewMediator import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.ActivityStarter.OnDismissAction import com.android.systemui.res.R import com.android.systemui.settings.UserTracker import com.android.systemui.shade.ShadeController import com.android.systemui.shade.ShadeViewController Loading Loading @@ -134,6 +134,19 @@ constructor( ) } override fun startPendingIntentMaybeDismissingKeyguard( intent: PendingIntent, intentSentUiThreadCallback: Runnable?, animationController: ActivityLaunchAnimator.Controller? ) { activityStarterInternal.startPendingIntentDismissingKeyguard( intent = intent, intentSentUiThreadCallback = intentSentUiThreadCallback, animationController = animationController, showOverLockscreen = true, ) } /** * TODO(b/279084380): Change callers to just call startActivityDismissingKeyguard and deprecate * this. Loading Loading @@ -454,7 +467,7 @@ constructor( !willLaunchResolverActivity && shouldAnimateLaunch(isActivityIntent = true) val animController = wrapAnimationController( wrapAnimationControllerForShadeOrStatusBar( animationController = animationController, dismissShade = dismissShade, isLaunchForActivity = true, Loading Loading @@ -547,12 +560,18 @@ constructor( ) } /** Starts a pending intent after dismissing keyguard. */ /** * Starts a pending intent after dismissing keyguard. * * This can be called in a background thread (to prevent calls in [ActivityIntentHelper] in * the main thread). */ fun startPendingIntentDismissingKeyguard( intent: PendingIntent, intentSentUiThreadCallback: Runnable? = null, associatedView: View? = null, animationController: ActivityLaunchAnimator.Controller? = null, showOverLockscreen: Boolean = false, ) { val animationController = if (associatedView is ExpandableNotificationRow) { Loading @@ -566,31 +585,46 @@ constructor( lockScreenUserManager.currentUserId, )) val actuallyShowOverLockscreen = showOverLockscreen && intent.isActivity && activityIntentHelper.wouldPendingShowOverLockscreen( intent, lockScreenUserManager.currentUserId ) val animate = !willLaunchResolverActivity && animationController != null && shouldAnimateLaunch(intent.isActivity) shouldAnimateLaunch(intent.isActivity, actuallyShowOverLockscreen) // If we animate, don't collapse the shade and defer the keyguard dismiss (in case we // run the animation on the keyguard). The animation will take care of (instantly) // collapsing the shade and hiding the keyguard once it is done. val collapse = !animate executeRunnableDismissingKeyguard( runnable = { try { // We wrap animationCallback with a StatusBarLaunchAnimatorController so // that the shade is collapsed after the animation (or when it is cancelled, // aborted, etc). val controller: ActivityLaunchAnimator.Controller? = wrapAnimationController( val statusBarController = wrapAnimationControllerForShadeOrStatusBar( animationController = animationController, dismissShade = true, isLaunchForActivity = intent.isActivity, ) val controller = if (actuallyShowOverLockscreen) { wrapAnimationControllerForLockscreen(statusBarController) } else { statusBarController } // If we animate, don't collapse the shade and defer the keyguard dismiss (in case we // run the animation on the keyguard). The animation will take care of (instantly) // collapsing the shade and hiding the keyguard once it is done. val collapse = !animate val runnable = Runnable { try { activityLaunchAnimator.startPendingIntentWithAnimation( controller, animate, intent.creatorPackage, actuallyShowOverLockscreen, object : PendingIntentStarter { override fun startPendingIntent( animationAdapter: RemoteAnimationAdapter? Loading Loading @@ -634,12 +668,21 @@ constructor( assistManagerLazy.get().hideAssist() } intentSentUiThreadCallback?.let { postOnUiThread(runnable = it) } }, } if (!actuallyShowOverLockscreen) { postOnUiThread(delay = 0) { executeRunnableDismissingKeyguard( runnable = runnable, afterKeyguardGone = willLaunchResolverActivity, dismissShade = collapse, willAnimateOnKeyguard = animate, ) } } else { postOnUiThread(delay = 0, runnable) } } /** Starts an Activity. */ fun startActivity( Loading Loading @@ -678,71 +721,12 @@ constructor( // Wrap the animation controller to dismiss the shade and set // mIsLaunchingActivityOverLockscreen during the animation. val delegate = wrapAnimationController( wrapAnimationControllerForShadeOrStatusBar( animationController = animationController, dismissShade = dismissShade, isLaunchForActivity = true, ) delegate?.let { controller = object : DelegateLaunchAnimatorController(delegate) { override fun onIntentStarted(willAnimate: Boolean) { delegate?.onIntentStarted(willAnimate) if (willAnimate) { centralSurfaces?.setIsLaunchingActivityOverLockscreen(true) } } override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) { super.onLaunchAnimationStart(isExpandingFullyAbove) // Double check that the keyguard is still showing and not going // away, but if so set the keyguard occluded. Typically, WM will let // KeyguardViewMediator know directly, but we're overriding that to // play the custom launch animation, so we need to take care of that // here. The unocclude animation is not overridden, so WM will call // KeyguardViewMediator's unocclude animation runner when the // activity is exited. if ( keyguardStateController.isShowing && !keyguardStateController.isKeyguardGoingAway ) { Log.d(TAG, "Setting occluded = true in #startActivity.") keyguardViewMediatorLazy .get() .setOccluded(true /* isOccluded */, true /* animate */) } } override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) { // Set mIsLaunchingActivityOverLockscreen to false before actually // finishing the animation so that we can assume that // mIsLaunchingActivityOverLockscreen being true means that we will // collapse the shade (or at least run the post collapse runnables) // later on. centralSurfaces?.setIsLaunchingActivityOverLockscreen(false) delegate?.onLaunchAnimationEnd(isExpandingFullyAbove) } override fun onLaunchAnimationCancelled( newKeyguardOccludedState: Boolean? ) { if (newKeyguardOccludedState != null) { keyguardViewMediatorLazy .get() .setOccluded(newKeyguardOccludedState, false /* animate */) } // Set mIsLaunchingActivityOverLockscreen to false before actually // finishing the animation so that we can assume that // mIsLaunchingActivityOverLockscreen being true means that we will // collapse the shade (or at least run the // post collapse // runnables) later on. centralSurfaces?.setIsLaunchingActivityOverLockscreen(false) delegate.onLaunchAnimationCancelled(newKeyguardOccludedState) } } } controller = wrapAnimationControllerForLockscreen(delegate) } else if (dismissShade) { // The animation will take care of dismissing the shade at the end of the animation. // If we don't animate, collapse it directly. Loading Loading @@ -874,7 +858,7 @@ constructor( * window. * @param isLaunchForActivity whether the launch is for an activity. */ private fun wrapAnimationController( private fun wrapAnimationControllerForShadeOrStatusBar( animationController: ActivityLaunchAnimator.Controller?, dismissShade: Boolean, isLaunchForActivity: Boolean, Loading Loading @@ -909,6 +893,72 @@ constructor( return animationController } /** * Wraps an animation controller so that if an activity would be launched on top of the * lockscreen, the correct flags are set for it to be occluded. */ private fun wrapAnimationControllerForLockscreen( animationController: ActivityLaunchAnimator.Controller? ): ActivityLaunchAnimator.Controller? { return animationController?.let { object : DelegateLaunchAnimatorController(it) { override fun onIntentStarted(willAnimate: Boolean) { delegate.onIntentStarted(willAnimate) if (willAnimate) { centralSurfaces?.setIsLaunchingActivityOverLockscreen(true) } } override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) { super.onLaunchAnimationStart(isExpandingFullyAbove) // Double check that the keyguard is still showing and not going // away, but if so set the keyguard occluded. Typically, WM will let // KeyguardViewMediator know directly, but we're overriding that to // play the custom launch animation, so we need to take care of that // here. The unocclude animation is not overridden, so WM will call // KeyguardViewMediator's unocclude animation runner when the // activity is exited. if ( keyguardStateController.isShowing && !keyguardStateController.isKeyguardGoingAway ) { Log.d(TAG, "Setting occluded = true in #startActivity.") keyguardViewMediatorLazy .get() .setOccluded(true /* isOccluded */, true /* animate */) } } override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) { // Set mIsLaunchingActivityOverLockscreen to false before actually // finishing the animation so that we can assume that // mIsLaunchingActivityOverLockscreen being true means that we will // collapse the shade (or at least run the post collapse runnables) // later on. centralSurfaces?.setIsLaunchingActivityOverLockscreen(false) delegate.onLaunchAnimationEnd(isExpandingFullyAbove) } override fun onLaunchAnimationCancelled(newKeyguardOccludedState: Boolean?) { if (newKeyguardOccludedState != null) { keyguardViewMediatorLazy .get() .setOccluded(newKeyguardOccludedState, false /* animate */) } // Set mIsLaunchingActivityOverLockscreen to false before actually // finishing the animation so that we can assume that // mIsLaunchingActivityOverLockscreen being true means that we will // collapse the shade (or at least run the // post collapse // runnables) later on. centralSurfaces?.setIsLaunchingActivityOverLockscreen(false) delegate.onLaunchAnimationCancelled(newKeyguardOccludedState) } } } } /** Retrieves the current user handle to start the Activity. */ private fun getActivityUserHandle(intent: Intent): UserHandle { val packages: Array<String> = Loading packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt +4 −6 Original line number Diff line number Diff line Loading @@ -37,7 +37,6 @@ import android.testing.TestableLooper import android.view.IWindowManager import android.view.View import com.android.internal.logging.MetricsLogger import com.android.systemui.res.R import com.android.systemui.SysuiTestCase import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.animation.view.LaunchableFrameLayout Loading @@ -48,6 +47,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger import com.android.systemui.res.R import com.android.systemui.settings.FakeDisplayTracker import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq Loading Loading @@ -343,8 +343,7 @@ class CustomTileTest : SysuiTestCase() { testableLooper.processAllMessages() verify(activityStarter, never()) .startPendingIntentDismissingKeyguard( any(), any(), any(ActivityLaunchAnimator.Controller::class.java)) .startPendingIntentMaybeDismissingKeyguard(any(), nullable(), nullable()) } @Test Loading @@ -357,8 +356,7 @@ class CustomTileTest : SysuiTestCase() { testableLooper.processAllMessages() verify(activityStarter, never()) .startPendingIntentDismissingKeyguard( any(), any(), any(ActivityLaunchAnimator.Controller::class.java)) .startPendingIntentMaybeDismissingKeyguard(any(), nullable(), nullable()) } @Test Loading @@ -373,7 +371,7 @@ class CustomTileTest : SysuiTestCase() { testableLooper.processAllMessages() verify(activityStarter) .startPendingIntentDismissingKeyguard( .startPendingIntentMaybeDismissingKeyguard( eq(pi), nullable(), nullable<ActivityLaunchAnimator.Controller>()) } Loading Loading
packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt +2 −1 Original line number Diff line number Diff line Loading @@ -290,9 +290,10 @@ class ActivityLaunchAnimator( controller: Controller?, animate: Boolean = true, packageName: String? = null, showOverLockscreen: Boolean = false, intentStarter: PendingIntentStarter ) { startIntentWithAnimation(controller, animate, packageName) { startIntentWithAnimation(controller, animate, packageName, showOverLockscreen) { intentStarter.startPendingIntent(it) } } Loading
packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java +10 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,16 @@ public interface ActivityStarter { Runnable intentSentUiThreadCallback, @Nullable ActivityLaunchAnimator.Controller animationController); /** * Similar to {@link #startPendingIntentDismissingKeyguard}, except that it supports launching * activities on top of the keyguard. If the activity supports {@code showOverLockscreen}, it * will show over keyguard without first dimissing it. If it doesn't support it, calling this * method is exactly the same as calling {@link #startPendingIntentDismissingKeyguard}. */ void startPendingIntentMaybeDismissingKeyguard(PendingIntent intent, @Nullable Runnable intentSentUiThreadCallback, @Nullable ActivityLaunchAnimator.Controller animationController); /** * The intent flag can be specified in startActivity(). */ Loading
packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java +12 −6 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ import android.widget.Switch; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.animation.ActivityLaunchAnimator; Loading Loading @@ -538,12 +539,17 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener, Log.i(TAG, "Launching activity before click"); } else { Log.i(TAG, "The activity is starting"); ActivityLaunchAnimator.Controller controller = mViewClicked == null ? null : ActivityLaunchAnimator.Controller.fromView(mViewClicked, 0); mUiHandler.post(() -> mActivityStarter.startPendingIntentDismissingKeyguard( pendingIntent, null, controller) ActivityLaunchAnimator.Controller controller = mViewClicked == null ? null : ActivityLaunchAnimator.Controller.fromView( mViewClicked, InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE ); mActivityStarter.startPendingIntentMaybeDismissingKeyguard( pendingIntent, /* intentSentUiThreadCallback= */ null, controller ); } } Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt +177 −127 Original line number Diff line number Diff line Loading @@ -30,7 +30,6 @@ import android.view.View import android.view.WindowManager import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.ActivityIntentHelper import com.android.systemui.res.R import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.animation.ActivityLaunchAnimator.PendingIntentStarter import com.android.systemui.animation.DelegateLaunchAnimatorController Loading @@ -43,6 +42,7 @@ import com.android.systemui.keyguard.KeyguardViewMediator import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.ActivityStarter.OnDismissAction import com.android.systemui.res.R import com.android.systemui.settings.UserTracker import com.android.systemui.shade.ShadeController import com.android.systemui.shade.ShadeViewController Loading Loading @@ -134,6 +134,19 @@ constructor( ) } override fun startPendingIntentMaybeDismissingKeyguard( intent: PendingIntent, intentSentUiThreadCallback: Runnable?, animationController: ActivityLaunchAnimator.Controller? ) { activityStarterInternal.startPendingIntentDismissingKeyguard( intent = intent, intentSentUiThreadCallback = intentSentUiThreadCallback, animationController = animationController, showOverLockscreen = true, ) } /** * TODO(b/279084380): Change callers to just call startActivityDismissingKeyguard and deprecate * this. Loading Loading @@ -454,7 +467,7 @@ constructor( !willLaunchResolverActivity && shouldAnimateLaunch(isActivityIntent = true) val animController = wrapAnimationController( wrapAnimationControllerForShadeOrStatusBar( animationController = animationController, dismissShade = dismissShade, isLaunchForActivity = true, Loading Loading @@ -547,12 +560,18 @@ constructor( ) } /** Starts a pending intent after dismissing keyguard. */ /** * Starts a pending intent after dismissing keyguard. * * This can be called in a background thread (to prevent calls in [ActivityIntentHelper] in * the main thread). */ fun startPendingIntentDismissingKeyguard( intent: PendingIntent, intentSentUiThreadCallback: Runnable? = null, associatedView: View? = null, animationController: ActivityLaunchAnimator.Controller? = null, showOverLockscreen: Boolean = false, ) { val animationController = if (associatedView is ExpandableNotificationRow) { Loading @@ -566,31 +585,46 @@ constructor( lockScreenUserManager.currentUserId, )) val actuallyShowOverLockscreen = showOverLockscreen && intent.isActivity && activityIntentHelper.wouldPendingShowOverLockscreen( intent, lockScreenUserManager.currentUserId ) val animate = !willLaunchResolverActivity && animationController != null && shouldAnimateLaunch(intent.isActivity) shouldAnimateLaunch(intent.isActivity, actuallyShowOverLockscreen) // If we animate, don't collapse the shade and defer the keyguard dismiss (in case we // run the animation on the keyguard). The animation will take care of (instantly) // collapsing the shade and hiding the keyguard once it is done. val collapse = !animate executeRunnableDismissingKeyguard( runnable = { try { // We wrap animationCallback with a StatusBarLaunchAnimatorController so // that the shade is collapsed after the animation (or when it is cancelled, // aborted, etc). val controller: ActivityLaunchAnimator.Controller? = wrapAnimationController( val statusBarController = wrapAnimationControllerForShadeOrStatusBar( animationController = animationController, dismissShade = true, isLaunchForActivity = intent.isActivity, ) val controller = if (actuallyShowOverLockscreen) { wrapAnimationControllerForLockscreen(statusBarController) } else { statusBarController } // If we animate, don't collapse the shade and defer the keyguard dismiss (in case we // run the animation on the keyguard). The animation will take care of (instantly) // collapsing the shade and hiding the keyguard once it is done. val collapse = !animate val runnable = Runnable { try { activityLaunchAnimator.startPendingIntentWithAnimation( controller, animate, intent.creatorPackage, actuallyShowOverLockscreen, object : PendingIntentStarter { override fun startPendingIntent( animationAdapter: RemoteAnimationAdapter? Loading Loading @@ -634,12 +668,21 @@ constructor( assistManagerLazy.get().hideAssist() } intentSentUiThreadCallback?.let { postOnUiThread(runnable = it) } }, } if (!actuallyShowOverLockscreen) { postOnUiThread(delay = 0) { executeRunnableDismissingKeyguard( runnable = runnable, afterKeyguardGone = willLaunchResolverActivity, dismissShade = collapse, willAnimateOnKeyguard = animate, ) } } else { postOnUiThread(delay = 0, runnable) } } /** Starts an Activity. */ fun startActivity( Loading Loading @@ -678,71 +721,12 @@ constructor( // Wrap the animation controller to dismiss the shade and set // mIsLaunchingActivityOverLockscreen during the animation. val delegate = wrapAnimationController( wrapAnimationControllerForShadeOrStatusBar( animationController = animationController, dismissShade = dismissShade, isLaunchForActivity = true, ) delegate?.let { controller = object : DelegateLaunchAnimatorController(delegate) { override fun onIntentStarted(willAnimate: Boolean) { delegate?.onIntentStarted(willAnimate) if (willAnimate) { centralSurfaces?.setIsLaunchingActivityOverLockscreen(true) } } override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) { super.onLaunchAnimationStart(isExpandingFullyAbove) // Double check that the keyguard is still showing and not going // away, but if so set the keyguard occluded. Typically, WM will let // KeyguardViewMediator know directly, but we're overriding that to // play the custom launch animation, so we need to take care of that // here. The unocclude animation is not overridden, so WM will call // KeyguardViewMediator's unocclude animation runner when the // activity is exited. if ( keyguardStateController.isShowing && !keyguardStateController.isKeyguardGoingAway ) { Log.d(TAG, "Setting occluded = true in #startActivity.") keyguardViewMediatorLazy .get() .setOccluded(true /* isOccluded */, true /* animate */) } } override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) { // Set mIsLaunchingActivityOverLockscreen to false before actually // finishing the animation so that we can assume that // mIsLaunchingActivityOverLockscreen being true means that we will // collapse the shade (or at least run the post collapse runnables) // later on. centralSurfaces?.setIsLaunchingActivityOverLockscreen(false) delegate?.onLaunchAnimationEnd(isExpandingFullyAbove) } override fun onLaunchAnimationCancelled( newKeyguardOccludedState: Boolean? ) { if (newKeyguardOccludedState != null) { keyguardViewMediatorLazy .get() .setOccluded(newKeyguardOccludedState, false /* animate */) } // Set mIsLaunchingActivityOverLockscreen to false before actually // finishing the animation so that we can assume that // mIsLaunchingActivityOverLockscreen being true means that we will // collapse the shade (or at least run the // post collapse // runnables) later on. centralSurfaces?.setIsLaunchingActivityOverLockscreen(false) delegate.onLaunchAnimationCancelled(newKeyguardOccludedState) } } } controller = wrapAnimationControllerForLockscreen(delegate) } else if (dismissShade) { // The animation will take care of dismissing the shade at the end of the animation. // If we don't animate, collapse it directly. Loading Loading @@ -874,7 +858,7 @@ constructor( * window. * @param isLaunchForActivity whether the launch is for an activity. */ private fun wrapAnimationController( private fun wrapAnimationControllerForShadeOrStatusBar( animationController: ActivityLaunchAnimator.Controller?, dismissShade: Boolean, isLaunchForActivity: Boolean, Loading Loading @@ -909,6 +893,72 @@ constructor( return animationController } /** * Wraps an animation controller so that if an activity would be launched on top of the * lockscreen, the correct flags are set for it to be occluded. */ private fun wrapAnimationControllerForLockscreen( animationController: ActivityLaunchAnimator.Controller? ): ActivityLaunchAnimator.Controller? { return animationController?.let { object : DelegateLaunchAnimatorController(it) { override fun onIntentStarted(willAnimate: Boolean) { delegate.onIntentStarted(willAnimate) if (willAnimate) { centralSurfaces?.setIsLaunchingActivityOverLockscreen(true) } } override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) { super.onLaunchAnimationStart(isExpandingFullyAbove) // Double check that the keyguard is still showing and not going // away, but if so set the keyguard occluded. Typically, WM will let // KeyguardViewMediator know directly, but we're overriding that to // play the custom launch animation, so we need to take care of that // here. The unocclude animation is not overridden, so WM will call // KeyguardViewMediator's unocclude animation runner when the // activity is exited. if ( keyguardStateController.isShowing && !keyguardStateController.isKeyguardGoingAway ) { Log.d(TAG, "Setting occluded = true in #startActivity.") keyguardViewMediatorLazy .get() .setOccluded(true /* isOccluded */, true /* animate */) } } override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) { // Set mIsLaunchingActivityOverLockscreen to false before actually // finishing the animation so that we can assume that // mIsLaunchingActivityOverLockscreen being true means that we will // collapse the shade (or at least run the post collapse runnables) // later on. centralSurfaces?.setIsLaunchingActivityOverLockscreen(false) delegate.onLaunchAnimationEnd(isExpandingFullyAbove) } override fun onLaunchAnimationCancelled(newKeyguardOccludedState: Boolean?) { if (newKeyguardOccludedState != null) { keyguardViewMediatorLazy .get() .setOccluded(newKeyguardOccludedState, false /* animate */) } // Set mIsLaunchingActivityOverLockscreen to false before actually // finishing the animation so that we can assume that // mIsLaunchingActivityOverLockscreen being true means that we will // collapse the shade (or at least run the // post collapse // runnables) later on. centralSurfaces?.setIsLaunchingActivityOverLockscreen(false) delegate.onLaunchAnimationCancelled(newKeyguardOccludedState) } } } } /** Retrieves the current user handle to start the Activity. */ private fun getActivityUserHandle(intent: Intent): UserHandle { val packages: Array<String> = Loading
packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt +4 −6 Original line number Diff line number Diff line Loading @@ -37,7 +37,6 @@ import android.testing.TestableLooper import android.view.IWindowManager import android.view.View import com.android.internal.logging.MetricsLogger import com.android.systemui.res.R import com.android.systemui.SysuiTestCase import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.animation.view.LaunchableFrameLayout Loading @@ -48,6 +47,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger import com.android.systemui.res.R import com.android.systemui.settings.FakeDisplayTracker import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq Loading Loading @@ -343,8 +343,7 @@ class CustomTileTest : SysuiTestCase() { testableLooper.processAllMessages() verify(activityStarter, never()) .startPendingIntentDismissingKeyguard( any(), any(), any(ActivityLaunchAnimator.Controller::class.java)) .startPendingIntentMaybeDismissingKeyguard(any(), nullable(), nullable()) } @Test Loading @@ -357,8 +356,7 @@ class CustomTileTest : SysuiTestCase() { testableLooper.processAllMessages() verify(activityStarter, never()) .startPendingIntentDismissingKeyguard( any(), any(), any(ActivityLaunchAnimator.Controller::class.java)) .startPendingIntentMaybeDismissingKeyguard(any(), nullable(), nullable()) } @Test Loading @@ -373,7 +371,7 @@ class CustomTileTest : SysuiTestCase() { testableLooper.processAllMessages() verify(activityStarter) .startPendingIntentDismissingKeyguard( .startPendingIntentMaybeDismissingKeyguard( eq(pi), nullable(), nullable<ActivityLaunchAnimator.Controller>()) } Loading