diff options
3 files changed, 64 insertions, 72 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt index 9b93522b2d5f..e8a84449566d 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt @@ -18,26 +18,25 @@ package com.android.systemui.controls.ui import android.app.Activity import android.app.ActivityOptions -import android.app.ActivityTaskManager -import android.app.ActivityTaskManager.INVALID_TASK_ID import android.app.ComponentOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED import android.app.Dialog import android.app.PendingIntent import android.content.ComponentName import android.content.Context import android.content.Intent -import android.graphics.Rect import android.view.View import android.view.ViewGroup import android.view.WindowInsets import android.view.WindowInsets.Type import android.view.WindowManager import android.widget.ImageView +import androidx.annotation.VisibleForTesting import com.android.internal.policy.ScreenDecorationsUtils import com.android.systemui.res.R import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.policy.KeyguardStateController +import com.android.systemui.util.boundsOnScreen import com.android.wm.shell.taskview.TaskView /** @@ -65,8 +64,8 @@ class DetailDialog( private const val EXTRA_USE_PANEL = "controls.DISPLAY_IN_PANEL" } - var detailTaskId = INVALID_TASK_ID private lateinit var taskViewContainer: View + private lateinit var controlDetailRoot: View private val taskWidthPercentWidth = activityContext.resources.getFloat( R.dimen.controls_task_view_width_percentage ) @@ -79,12 +78,7 @@ class DetailDialog( addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK) } - fun removeDetailTask() { - if (detailTaskId == INVALID_TASK_ID) return - ActivityTaskManager.getInstance().removeTask(detailTaskId) - detailTaskId = INVALID_TASK_ID - } - + @VisibleForTesting val stateCallback = object : TaskView.Listener { override fun onInitialized() { taskViewContainer.apply { @@ -98,33 +92,29 @@ class DetailDialog( activityContext, 0 /* enterResId */, 0 /* exitResId */ - ).setPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOWED) - options.isPendingIntentBackgroundActivityLaunchAllowedByPermission = true + ).apply { + pendingIntentBackgroundActivityStartMode = MODE_BACKGROUND_ACTIVITY_START_ALLOWED + isPendingIntentBackgroundActivityLaunchAllowedByPermission = true + taskAlwaysOnTop = true + } taskView.startActivity( pendingIntent, fillInIntent, options, - getTaskViewBounds() + taskView.boundsOnScreen, ) } override fun onTaskRemovalStarted(taskId: Int) { - detailTaskId = INVALID_TASK_ID - dismiss() + taskView.release() } override fun onTaskCreated(taskId: Int, name: ComponentName?) { - detailTaskId = taskId requireViewById<ViewGroup>(R.id.controls_activity_view).apply { setAlpha(1f) } } - - override fun onReleased() { - removeDetailTask() - } - override fun onBackPressedOnTaskRoot(taskId: Int) { dismiss() } @@ -138,6 +128,9 @@ class DetailDialog( setContentView(R.layout.controls_detail_dialog) taskViewContainer = requireViewById<ViewGroup>(R.id.control_task_view_container) + controlDetailRoot = requireViewById<View>(R.id.control_detail_root).apply { + setOnClickListener { _: View -> dismiss() } + } requireViewById<ViewGroup>(R.id.controls_activity_view).apply { addView(taskView) @@ -147,13 +140,9 @@ class DetailDialog( requireViewById<ImageView>(R.id.control_detail_close).apply { setOnClickListener { _: View -> dismiss() } } - requireViewById<View>(R.id.control_detail_root).apply { - setOnClickListener { _: View -> dismiss() } - } requireViewById<ImageView>(R.id.control_detail_open_in_app).apply { setOnClickListener { v: View -> - removeDetailTask() dismiss() val action = ActivityStarter.OnDismissAction { @@ -201,26 +190,9 @@ class DetailDialog( taskView.setListener(cvh.uiExecutor, stateCallback) } - fun getTaskViewBounds(): Rect { - val wm = checkNotNull(context.getSystemService(WindowManager::class.java)) - val windowMetrics = wm.getCurrentWindowMetrics() - val rect = windowMetrics.bounds - val metricInsets = windowMetrics.windowInsets - val insets = metricInsets.getInsetsIgnoringVisibility(Type.systemBars() - or Type.displayCutout()) - val headerHeight = context.resources.getDimensionPixelSize( - R.dimen.controls_detail_dialog_header_height) - - val finalRect = Rect(rect.left - insets.left /* left */, - rect.top + insets.top + headerHeight /* top */, - rect.right - insets.right /* right */, - rect.bottom - insets.bottom /* bottom */) - return finalRect - } - override fun dismiss() { if (!isShowing()) return - taskView.release() + taskView.removeTask() val isActivityFinishing = (activityContext as? Activity)?.let { it.isFinishing || it.isDestroyed } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt index 1b0d03276415..848c78644659 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt @@ -18,7 +18,6 @@ package com.android.systemui.controls.ui import android.app.ActivityOptions -import android.app.ActivityTaskManager.INVALID_TASK_ID import android.app.PendingIntent import android.content.ComponentName import android.content.Context @@ -45,8 +44,6 @@ class PanelTaskViewController( taskView.alpha = 0f } - private var detailTaskId = INVALID_TASK_ID - private val fillInIntent = Intent().apply { // Apply flags to make behaviour match documentLaunchMode=always. @@ -57,7 +54,6 @@ class PanelTaskViewController( private val stateCallback = object : TaskView.Listener { override fun onInitialized() { - val options = ActivityOptions.makeCustomAnimation( activityContext, @@ -88,12 +84,10 @@ class PanelTaskViewController( } override fun onTaskRemovalStarted(taskId: Int) { - detailTaskId = INVALID_TASK_ID release() } override fun onTaskCreated(taskId: Int, name: ComponentName?) { - detailTaskId = taskId taskView.alpha = 1f } diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt index 54142590b453..677108cab291 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt @@ -18,10 +18,13 @@ package com.android.systemui.controls.ui import android.app.ActivityOptions import android.app.PendingIntent +import android.content.Context import android.testing.AndroidTestingRunner import android.testing.TestableLooper +import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.activity.EmptyTestActivity import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.policy.KeyguardStateController @@ -30,11 +33,13 @@ import com.android.systemui.util.mockito.capture import com.android.wm.shell.taskview.TaskView import com.google.common.truth.Truth.assertThat import org.junit.Before +import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.eq import org.mockito.Mock import org.mockito.Mockito.any +import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @@ -43,31 +48,31 @@ import org.mockito.MockitoAnnotations @TestableLooper.RunWithLooper class DetailDialogTest : SysuiTestCase() { - @Mock - private lateinit var taskView: TaskView - @Mock - private lateinit var broadcastSender: BroadcastSender - @Mock - private lateinit var controlViewHolder: ControlViewHolder - @Mock - private lateinit var pendingIntent: PendingIntent - @Mock - private lateinit var keyguardStateController: KeyguardStateController - @Mock - private lateinit var activityStarter: ActivityStarter + @Rule + @JvmField + val activityRule: ActivityScenarioRule<EmptyTestActivity> = + ActivityScenarioRule(EmptyTestActivity::class.java) + + @Mock private lateinit var taskView: TaskView + @Mock private lateinit var broadcastSender: BroadcastSender + @Mock private lateinit var controlViewHolder: ControlViewHolder + @Mock private lateinit var pendingIntent: PendingIntent + @Mock private lateinit var keyguardStateController: KeyguardStateController + @Mock private lateinit var activityStarter: ActivityStarter + + private lateinit var underTest: DetailDialog @Before fun setUp() { MockitoAnnotations.initMocks(this) + + underTest = createDialog(pendingIntent) } @Test fun testPendingIntentIsUnModified() { - // GIVEN the dialog is created with a PendingIntent - val dialog = createDialog(pendingIntent) - // WHEN the TaskView is initialized - dialog.stateCallback.onInitialized() + underTest.stateCallback.onInitialized() // THEN the PendingIntent used to call startActivity is unmodified by systemui verify(taskView).startActivity(eq(pendingIntent), any(), any(), any()) @@ -75,11 +80,8 @@ class DetailDialogTest : SysuiTestCase() { @Test fun testActivityOptionsAllowBal() { - // GIVEN the dialog is created with a PendingIntent - val dialog = createDialog(pendingIntent) - // WHEN the TaskView is initialized - dialog.stateCallback.onInitialized() + underTest.stateCallback.onInitialized() val optionsCaptor = argumentCaptor<ActivityOptions>() @@ -90,17 +92,41 @@ class DetailDialogTest : SysuiTestCase() { .isEqualTo(ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED) assertThat(optionsCaptor.value.isPendingIntentBackgroundActivityLaunchAllowedByPermission) .isTrue() + assertThat(optionsCaptor.value.taskAlwaysOnTop).isTrue() + } + + @Test + fun testDismissRemovesTheTask() { + activityRule.scenario.onActivity { + underTest = createDialog(pendingIntent, it) + underTest.show() + + underTest.dismiss() + + verify(taskView).removeTask() + verify(taskView, never()).release() + } + } + + @Test + fun testTaskRemovalReleasesTaskView() { + underTest.stateCallback.onTaskRemovalStarted(0) + + verify(taskView).release() } - private fun createDialog(pendingIntent: PendingIntent): DetailDialog { + private fun createDialog( + pendingIntent: PendingIntent, + context: Context = mContext, + ): DetailDialog { return DetailDialog( - mContext, + context, broadcastSender, taskView, pendingIntent, controlViewHolder, keyguardStateController, - activityStarter + activityStarter, ) } } |