summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Anton Potapov <apotapov@google.com> 2023-09-05 17:27:01 +0100
committer Anton Potapov <apotapov@google.com> 2023-09-25 11:27:19 +0000
commit70eef43e2e8d051b742c62afd1afa38e3dfefb77 (patch)
tree7cc5085999e799ba7ac9fdb09def1b4bb9ee16a3
parent6324143df3de569a847338f19c4e6329477391d4 (diff)
Fix TaskView usage in DetailsDialog
We've done some changes to how we deal with the TaskView in PanelTaskViewController to address issues with the Home Panel. This CL migrates those changes to DetailsDialog, which to improves TaskView behaviour and fixes the issue. Test: manual: open Device Controls, tap on a camera control, long tap outside of the TaskView. Test: atest DetailDialogTest Fixes: 282144424 Change-Id: If583934773a6a8e728475aa0eb4a0b54563a89e3
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt58
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt72
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,
)
}
}