Loading packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt +14 −1 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ import android.content.Intent import android.view.View import android.widget.FrameLayout import android.widget.RemoteViews.RemoteResponse import androidx.core.util.component1 import androidx.core.util.component2 import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase Loading @@ -29,6 +31,7 @@ import com.android.systemui.util.mockito.eq import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.refEq import org.mockito.Mock import org.mockito.Mockito.isNull import org.mockito.Mockito.notNull Loading Loading @@ -62,6 +65,7 @@ class WidgetInteractionHandlerTest : SysuiTestCase() { val parent = FrameLayout(context) val view = CommunalAppWidgetHostView(context) parent.addView(view) val (fillInIntent, activityOptions) = testResponse.getLaunchOptions(view) underTest.onInteraction(view, testIntent, testResponse) Loading @@ -70,6 +74,8 @@ class WidgetInteractionHandlerTest : SysuiTestCase() { eq(testIntent), isNull(), notNull(), refEq(fillInIntent), refEq(activityOptions.toBundle()), ) } Loading @@ -78,10 +84,17 @@ class WidgetInteractionHandlerTest : SysuiTestCase() { val parent = FrameLayout(context) val view = View(context) parent.addView(view) val (fillInIntent, activityOptions) = testResponse.getLaunchOptions(view) underTest.onInteraction(view, testIntent, testResponse) verify(activityStarter) .startPendingIntentMaybeDismissingKeyguard(eq(testIntent), isNull(), isNull()) .startPendingIntentMaybeDismissingKeyguard( eq(testIntent), isNull(), isNull(), refEq(fillInIntent), refEq(activityOptions.toBundle()), ) } } packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt +51 −0 Original line number Diff line number Diff line Loading @@ -16,12 +16,15 @@ package com.android.systemui.statusbar.phone import android.app.ActivityOptions import android.app.PendingIntent import android.content.Intent import android.os.Bundle import android.os.RemoteException import android.os.UserHandle import android.view.View import android.widget.FrameLayout import android.window.SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.keyguard.KeyguardUpdateMonitor Loading @@ -48,6 +51,7 @@ 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 Loading Loading @@ -173,6 +177,53 @@ class ActivityStarterImplTest : SysuiTestCase() { ) } fun startPendingIntentDismissingKeyguard_fillInIntentAndExtraOptions_sendAndReturnResult() { val pendingIntent = mock(PendingIntent::class.java) val fillInIntent = 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) whenever(pendingIntent.isActivity).thenReturn(true) whenever(keyguardStateController.isShowing).thenReturn(true) whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) whenever(activityIntentHelper.wouldPendingShowOverLockscreen(eq(pendingIntent), anyInt())) .thenReturn(false) // extra activity options to set on pending intent val activityOptions = mock(ActivityOptions::class.java) activityOptions.splashScreenStyle = SPLASH_SCREEN_STYLE_SOLID_COLOR activityOptions.isPendingIntentBackgroundActivityLaunchAllowedByPermission = false val bundleCaptor = argumentCaptor<Bundle>() underTest.startPendingIntentMaybeDismissingKeyguard( intent = pendingIntent, animationController = controller, intentSentUiThreadCallback = null, fillInIntent = fillInIntent, extraOptions = activityOptions.toBundle(), ) mainExecutor.runAllReady() // Fill-in intent is passed and options contain extra values specified verify(pendingIntent) .sendAndReturnResult( eq(context), eq(0), eq(fillInIntent), nullable(), nullable(), nullable(), bundleCaptor.capture() ) val options = ActivityOptions.fromBundle(bundleCaptor.value) assertThat(options.isPendingIntentBackgroundActivityLaunchAllowedByPermission).isFalse() assertThat(options.splashScreenStyle).isEqualTo(SPLASH_SCREEN_STYLE_SOLID_COLOR) } @Test fun startPendingIntentDismissingKeyguard_associatedView_getAnimatorController() { val pendingIntent = mock(PendingIntent::class.java) Loading packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java +12 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.plugins; import android.annotation.Nullable; import android.app.PendingIntent; import android.content.Intent; import android.os.Bundle; import android.os.UserHandle; import android.view.View; Loading Loading @@ -66,6 +67,17 @@ public interface ActivityStarter { @Nullable Runnable intentSentUiThreadCallback, @Nullable ActivityTransitionAnimator.Controller animationController); /** * Similar to {@link #startPendingIntentMaybeDismissingKeyguard(PendingIntent, Runnable, * ActivityTransitionAnimator.Controller)}, but also specifies a fill-in intent and extra * options that could be used to populate the pending intent and launch the activity. */ void startPendingIntentMaybeDismissingKeyguard(PendingIntent intent, @Nullable Runnable intentSentUiThreadCallback, @Nullable ActivityTransitionAnimator.Controller animationController, @Nullable Intent fillInIntent, @Nullable Bundle extraOptions); /** * The intent flag can be specified in startActivity(). */ Loading packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt +24 −7 Original line number Diff line number Diff line Loading @@ -16,9 +16,14 @@ package com.android.systemui.communal.widgets import android.app.ActivityOptions import android.app.PendingIntent import android.content.Intent import android.util.Pair import android.view.View import android.widget.RemoteViews import androidx.core.util.component1 import androidx.core.util.component2 import com.android.systemui.animation.ActivityTransitionAnimator import com.android.systemui.common.ui.view.getNearestParent import com.android.systemui.plugins.ActivityStarter Loading @@ -33,21 +38,33 @@ constructor( view: View, pendingIntent: PendingIntent, response: RemoteViews.RemoteResponse ): Boolean = when { pendingIntent.isActivity -> startActivity(view, pendingIntent) else -> RemoteViews.startPendingIntent(view, pendingIntent, response.getLaunchOptions(view)) ): Boolean { val launchOptions = response.getLaunchOptions(view) return when { pendingIntent.isActivity -> // Forward the fill-in intent and activity options retrieved from the response // to populate the pending intent, so that list items can launch respective // activities. startActivity(view, pendingIntent, launchOptions) else -> RemoteViews.startPendingIntent(view, pendingIntent, launchOptions) } } private fun startActivity(view: View, pendingIntent: PendingIntent): Boolean { private fun startActivity( view: View, pendingIntent: PendingIntent, launchOptions: Pair<Intent, ActivityOptions>, ): Boolean { val hostView = view.getNearestParent<CommunalAppWidgetHostView>() val animationController = hostView?.let(ActivityTransitionAnimator.Controller::fromView) val (fillInIntent, activityOptions) = launchOptions activityStarter.startPendingIntentMaybeDismissingKeyguard( pendingIntent, /* intentSentUiThreadCallback = */ null, animationController animationController, fillInIntent, activityOptions.toBundle(), ) return true } Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt +26 −5 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.app.PendingIntent import android.app.TaskStackBuilder import android.content.Context import android.content.Intent import android.os.Bundle import android.os.RemoteException import android.os.UserHandle import android.provider.Settings Loading Loading @@ -149,6 +150,23 @@ constructor( ) } override fun startPendingIntentMaybeDismissingKeyguard( intent: PendingIntent, intentSentUiThreadCallback: Runnable?, animationController: ActivityTransitionAnimator.Controller?, fillInIntent: Intent?, extraOptions: Bundle?, ) { activityStarterInternal.startPendingIntentDismissingKeyguard( intent = intent, intentSentUiThreadCallback = intentSentUiThreadCallback, animationController = animationController, showOverLockscreen = true, fillInIntent = fillInIntent, extraOptions = extraOptions, ) } /** * TODO(b/279084380): Change callers to just call startActivityDismissingKeyguard and deprecate * this. Loading Loading @@ -554,6 +572,8 @@ constructor( associatedView: View? = null, animationController: ActivityTransitionAnimator.Controller? = null, showOverLockscreen: Boolean = false, fillInIntent: Intent? = null, extraOptions: Bundle? = null, ) { val animationController = if (associatedView is ExpandableNotificationRow) { Loading Loading @@ -617,6 +637,7 @@ constructor( displayId, animationAdapter ) .apply { extraOptions?.let { putAll(it) } } ) // TODO b/221255671: restrict this to only be set for // notifications Loading @@ -625,9 +646,9 @@ constructor( ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED ) return intent.sendAndReturnResult( null, context, 0, null, fillInIntent, null, null, null, Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt +14 −1 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ import android.content.Intent import android.view.View import android.widget.FrameLayout import android.widget.RemoteViews.RemoteResponse import androidx.core.util.component1 import androidx.core.util.component2 import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase Loading @@ -29,6 +31,7 @@ import com.android.systemui.util.mockito.eq import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.refEq import org.mockito.Mock import org.mockito.Mockito.isNull import org.mockito.Mockito.notNull Loading Loading @@ -62,6 +65,7 @@ class WidgetInteractionHandlerTest : SysuiTestCase() { val parent = FrameLayout(context) val view = CommunalAppWidgetHostView(context) parent.addView(view) val (fillInIntent, activityOptions) = testResponse.getLaunchOptions(view) underTest.onInteraction(view, testIntent, testResponse) Loading @@ -70,6 +74,8 @@ class WidgetInteractionHandlerTest : SysuiTestCase() { eq(testIntent), isNull(), notNull(), refEq(fillInIntent), refEq(activityOptions.toBundle()), ) } Loading @@ -78,10 +84,17 @@ class WidgetInteractionHandlerTest : SysuiTestCase() { val parent = FrameLayout(context) val view = View(context) parent.addView(view) val (fillInIntent, activityOptions) = testResponse.getLaunchOptions(view) underTest.onInteraction(view, testIntent, testResponse) verify(activityStarter) .startPendingIntentMaybeDismissingKeyguard(eq(testIntent), isNull(), isNull()) .startPendingIntentMaybeDismissingKeyguard( eq(testIntent), isNull(), isNull(), refEq(fillInIntent), refEq(activityOptions.toBundle()), ) } }
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt +51 −0 Original line number Diff line number Diff line Loading @@ -16,12 +16,15 @@ package com.android.systemui.statusbar.phone import android.app.ActivityOptions import android.app.PendingIntent import android.content.Intent import android.os.Bundle import android.os.RemoteException import android.os.UserHandle import android.view.View import android.widget.FrameLayout import android.window.SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.keyguard.KeyguardUpdateMonitor Loading @@ -48,6 +51,7 @@ 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 Loading Loading @@ -173,6 +177,53 @@ class ActivityStarterImplTest : SysuiTestCase() { ) } fun startPendingIntentDismissingKeyguard_fillInIntentAndExtraOptions_sendAndReturnResult() { val pendingIntent = mock(PendingIntent::class.java) val fillInIntent = 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) whenever(pendingIntent.isActivity).thenReturn(true) whenever(keyguardStateController.isShowing).thenReturn(true) whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) whenever(activityIntentHelper.wouldPendingShowOverLockscreen(eq(pendingIntent), anyInt())) .thenReturn(false) // extra activity options to set on pending intent val activityOptions = mock(ActivityOptions::class.java) activityOptions.splashScreenStyle = SPLASH_SCREEN_STYLE_SOLID_COLOR activityOptions.isPendingIntentBackgroundActivityLaunchAllowedByPermission = false val bundleCaptor = argumentCaptor<Bundle>() underTest.startPendingIntentMaybeDismissingKeyguard( intent = pendingIntent, animationController = controller, intentSentUiThreadCallback = null, fillInIntent = fillInIntent, extraOptions = activityOptions.toBundle(), ) mainExecutor.runAllReady() // Fill-in intent is passed and options contain extra values specified verify(pendingIntent) .sendAndReturnResult( eq(context), eq(0), eq(fillInIntent), nullable(), nullable(), nullable(), bundleCaptor.capture() ) val options = ActivityOptions.fromBundle(bundleCaptor.value) assertThat(options.isPendingIntentBackgroundActivityLaunchAllowedByPermission).isFalse() assertThat(options.splashScreenStyle).isEqualTo(SPLASH_SCREEN_STYLE_SOLID_COLOR) } @Test fun startPendingIntentDismissingKeyguard_associatedView_getAnimatorController() { val pendingIntent = mock(PendingIntent::class.java) Loading
packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java +12 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.plugins; import android.annotation.Nullable; import android.app.PendingIntent; import android.content.Intent; import android.os.Bundle; import android.os.UserHandle; import android.view.View; Loading Loading @@ -66,6 +67,17 @@ public interface ActivityStarter { @Nullable Runnable intentSentUiThreadCallback, @Nullable ActivityTransitionAnimator.Controller animationController); /** * Similar to {@link #startPendingIntentMaybeDismissingKeyguard(PendingIntent, Runnable, * ActivityTransitionAnimator.Controller)}, but also specifies a fill-in intent and extra * options that could be used to populate the pending intent and launch the activity. */ void startPendingIntentMaybeDismissingKeyguard(PendingIntent intent, @Nullable Runnable intentSentUiThreadCallback, @Nullable ActivityTransitionAnimator.Controller animationController, @Nullable Intent fillInIntent, @Nullable Bundle extraOptions); /** * The intent flag can be specified in startActivity(). */ Loading
packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt +24 −7 Original line number Diff line number Diff line Loading @@ -16,9 +16,14 @@ package com.android.systemui.communal.widgets import android.app.ActivityOptions import android.app.PendingIntent import android.content.Intent import android.util.Pair import android.view.View import android.widget.RemoteViews import androidx.core.util.component1 import androidx.core.util.component2 import com.android.systemui.animation.ActivityTransitionAnimator import com.android.systemui.common.ui.view.getNearestParent import com.android.systemui.plugins.ActivityStarter Loading @@ -33,21 +38,33 @@ constructor( view: View, pendingIntent: PendingIntent, response: RemoteViews.RemoteResponse ): Boolean = when { pendingIntent.isActivity -> startActivity(view, pendingIntent) else -> RemoteViews.startPendingIntent(view, pendingIntent, response.getLaunchOptions(view)) ): Boolean { val launchOptions = response.getLaunchOptions(view) return when { pendingIntent.isActivity -> // Forward the fill-in intent and activity options retrieved from the response // to populate the pending intent, so that list items can launch respective // activities. startActivity(view, pendingIntent, launchOptions) else -> RemoteViews.startPendingIntent(view, pendingIntent, launchOptions) } } private fun startActivity(view: View, pendingIntent: PendingIntent): Boolean { private fun startActivity( view: View, pendingIntent: PendingIntent, launchOptions: Pair<Intent, ActivityOptions>, ): Boolean { val hostView = view.getNearestParent<CommunalAppWidgetHostView>() val animationController = hostView?.let(ActivityTransitionAnimator.Controller::fromView) val (fillInIntent, activityOptions) = launchOptions activityStarter.startPendingIntentMaybeDismissingKeyguard( pendingIntent, /* intentSentUiThreadCallback = */ null, animationController animationController, fillInIntent, activityOptions.toBundle(), ) return true } Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt +26 −5 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.app.PendingIntent import android.app.TaskStackBuilder import android.content.Context import android.content.Intent import android.os.Bundle import android.os.RemoteException import android.os.UserHandle import android.provider.Settings Loading Loading @@ -149,6 +150,23 @@ constructor( ) } override fun startPendingIntentMaybeDismissingKeyguard( intent: PendingIntent, intentSentUiThreadCallback: Runnable?, animationController: ActivityTransitionAnimator.Controller?, fillInIntent: Intent?, extraOptions: Bundle?, ) { activityStarterInternal.startPendingIntentDismissingKeyguard( intent = intent, intentSentUiThreadCallback = intentSentUiThreadCallback, animationController = animationController, showOverLockscreen = true, fillInIntent = fillInIntent, extraOptions = extraOptions, ) } /** * TODO(b/279084380): Change callers to just call startActivityDismissingKeyguard and deprecate * this. Loading Loading @@ -554,6 +572,8 @@ constructor( associatedView: View? = null, animationController: ActivityTransitionAnimator.Controller? = null, showOverLockscreen: Boolean = false, fillInIntent: Intent? = null, extraOptions: Bundle? = null, ) { val animationController = if (associatedView is ExpandableNotificationRow) { Loading Loading @@ -617,6 +637,7 @@ constructor( displayId, animationAdapter ) .apply { extraOptions?.let { putAll(it) } } ) // TODO b/221255671: restrict this to only be set for // notifications Loading @@ -625,9 +646,9 @@ constructor( ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED ) return intent.sendAndReturnResult( null, context, 0, null, fillInIntent, null, null, null, Loading