Merge "Controls - Do not recreate intent" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
060ab6630b
@@ -18,6 +18,7 @@ package com.android.systemui.controls.ui
|
|||||||
|
|
||||||
import android.annotation.MainThread
|
import android.annotation.MainThread
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
|
import android.app.PendingIntent
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
@@ -88,7 +89,7 @@ class ControlActionCoordinatorImpl @Inject constructor(
|
|||||||
bouncerOrRun(createAction(cvh.cws.ci.controlId, {
|
bouncerOrRun(createAction(cvh.cws.ci.controlId, {
|
||||||
cvh.layout.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK)
|
cvh.layout.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK)
|
||||||
if (cvh.usePanel()) {
|
if (cvh.usePanel()) {
|
||||||
showDetail(cvh, control.getAppIntent().getIntent())
|
showDetail(cvh, control.getAppIntent())
|
||||||
} else {
|
} else {
|
||||||
cvh.action(CommandAction(templateId))
|
cvh.action(CommandAction(templateId))
|
||||||
}
|
}
|
||||||
@@ -116,7 +117,7 @@ class ControlActionCoordinatorImpl @Inject constructor(
|
|||||||
// Long press snould only be called when there is valid control state, otherwise ignore
|
// Long press snould only be called when there is valid control state, otherwise ignore
|
||||||
cvh.cws.control?.let {
|
cvh.cws.control?.let {
|
||||||
cvh.layout.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
|
cvh.layout.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
|
||||||
showDetail(cvh, it.getAppIntent().getIntent())
|
showDetail(cvh, it.getAppIntent())
|
||||||
}
|
}
|
||||||
}, false /* blockable */))
|
}, false /* blockable */))
|
||||||
}
|
}
|
||||||
@@ -167,10 +168,10 @@ class ControlActionCoordinatorImpl @Inject constructor(
|
|||||||
bgExecutor.execute { vibrator.vibrate(effect) }
|
bgExecutor.execute { vibrator.vibrate(effect) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showDetail(cvh: ControlViewHolder, intent: Intent) {
|
private fun showDetail(cvh: ControlViewHolder, pendingIntent: PendingIntent) {
|
||||||
bgExecutor.execute {
|
bgExecutor.execute {
|
||||||
val activities: List<ResolveInfo> = context.packageManager.queryIntentActivities(
|
val activities: List<ResolveInfo> = context.packageManager.queryIntentActivities(
|
||||||
intent,
|
pendingIntent.getIntent(),
|
||||||
PackageManager.MATCH_DEFAULT_ONLY
|
PackageManager.MATCH_DEFAULT_ONLY
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -178,7 +179,7 @@ class ControlActionCoordinatorImpl @Inject constructor(
|
|||||||
// make sure the intent is valid before attempting to open the dialog
|
// make sure the intent is valid before attempting to open the dialog
|
||||||
if (activities.isNotEmpty() && taskViewFactory.isPresent) {
|
if (activities.isNotEmpty() && taskViewFactory.isPresent) {
|
||||||
taskViewFactory.get().create(context, uiExecutor, {
|
taskViewFactory.get().create(context, uiExecutor, {
|
||||||
dialog = DetailDialog(activityContext, it, intent, cvh).also {
|
dialog = DetailDialog(activityContext, it, pendingIntent, cvh).also {
|
||||||
it.setOnDismissListener { _ -> dialog = null }
|
it.setOnDismissListener { _ -> dialog = null }
|
||||||
it.show()
|
it.show()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ import com.android.wm.shell.TaskView
|
|||||||
class DetailDialog(
|
class DetailDialog(
|
||||||
val activityContext: Context?,
|
val activityContext: Context?,
|
||||||
val taskView: TaskView,
|
val taskView: TaskView,
|
||||||
val intent: Intent,
|
val pendingIntent: PendingIntent,
|
||||||
val cvh: ControlViewHolder
|
val cvh: ControlViewHolder
|
||||||
) : Dialog(
|
) : Dialog(
|
||||||
activityContext ?: cvh.context,
|
activityContext ?: cvh.context,
|
||||||
@@ -59,6 +59,14 @@ class DetailDialog(
|
|||||||
|
|
||||||
var detailTaskId = INVALID_TASK_ID
|
var detailTaskId = INVALID_TASK_ID
|
||||||
|
|
||||||
|
private val fillInIntent = Intent().apply {
|
||||||
|
putExtra(EXTRA_USE_PANEL, true)
|
||||||
|
|
||||||
|
// Apply flags to make behaviour match documentLaunchMode=always.
|
||||||
|
addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
|
||||||
|
addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
|
||||||
|
}
|
||||||
|
|
||||||
fun removeDetailTask() {
|
fun removeDetailTask() {
|
||||||
if (detailTaskId == INVALID_TASK_ID) return
|
if (detailTaskId == INVALID_TASK_ID) return
|
||||||
ActivityTaskManager.getInstance().removeTask(detailTaskId)
|
ActivityTaskManager.getInstance().removeTask(detailTaskId)
|
||||||
@@ -67,13 +75,6 @@ class DetailDialog(
|
|||||||
|
|
||||||
val stateCallback = object : TaskView.Listener {
|
val stateCallback = object : TaskView.Listener {
|
||||||
override fun onInitialized() {
|
override fun onInitialized() {
|
||||||
val launchIntent = Intent(intent)
|
|
||||||
launchIntent.putExtra(EXTRA_USE_PANEL, true)
|
|
||||||
|
|
||||||
// Apply flags to make behaviour match documentLaunchMode=always.
|
|
||||||
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
|
|
||||||
launchIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
|
|
||||||
|
|
||||||
val options = activityContext?.let {
|
val options = activityContext?.let {
|
||||||
ActivityOptions.makeCustomAnimation(
|
ActivityOptions.makeCustomAnimation(
|
||||||
it,
|
it,
|
||||||
@@ -82,9 +83,8 @@ class DetailDialog(
|
|||||||
)
|
)
|
||||||
} ?: ActivityOptions.makeBasic()
|
} ?: ActivityOptions.makeBasic()
|
||||||
taskView.startActivity(
|
taskView.startActivity(
|
||||||
PendingIntent.getActivity(context, 0, launchIntent,
|
pendingIntent,
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE),
|
fillInIntent,
|
||||||
null /* fillInIntent */,
|
|
||||||
options,
|
options,
|
||||||
getTaskViewBounds()
|
getTaskViewBounds()
|
||||||
)
|
)
|
||||||
@@ -97,6 +97,9 @@ class DetailDialog(
|
|||||||
|
|
||||||
override fun onTaskCreated(taskId: Int, name: ComponentName?) {
|
override fun onTaskCreated(taskId: Int, name: ComponentName?) {
|
||||||
detailTaskId = taskId
|
detailTaskId = taskId
|
||||||
|
requireViewById<ViewGroup>(R.id.controls_activity_view).apply {
|
||||||
|
setAlpha(1f)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onReleased() {
|
override fun onReleased() {
|
||||||
@@ -121,6 +124,7 @@ class DetailDialog(
|
|||||||
|
|
||||||
requireViewById<ViewGroup>(R.id.controls_activity_view).apply {
|
requireViewById<ViewGroup>(R.id.controls_activity_view).apply {
|
||||||
addView(taskView)
|
addView(taskView)
|
||||||
|
setAlpha(0f)
|
||||||
}
|
}
|
||||||
|
|
||||||
requireViewById<ImageView>(R.id.control_detail_close).apply {
|
requireViewById<ImageView>(R.id.control_detail_close).apply {
|
||||||
@@ -134,7 +138,7 @@ class DetailDialog(
|
|||||||
removeDetailTask()
|
removeDetailTask()
|
||||||
dismiss()
|
dismiss()
|
||||||
context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
|
context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
|
||||||
v.context.startActivity(intent)
|
pendingIntent.send()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.systemui.controls.ui
|
||||||
|
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.testing.AndroidTestingRunner
|
||||||
|
import android.testing.TestableLooper
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.wm.shell.TaskView
|
||||||
|
import org.junit.Before
|
||||||
|
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.verify
|
||||||
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(AndroidTestingRunner::class)
|
||||||
|
@TestableLooper.RunWithLooper
|
||||||
|
class DetailDialogTest : SysuiTestCase() {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private lateinit var taskView: TaskView
|
||||||
|
@Mock
|
||||||
|
private lateinit var controlViewHolder: ControlViewHolder
|
||||||
|
@Mock
|
||||||
|
private lateinit var pendingIntent: PendingIntent
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testPendingIntentIsUnModified() {
|
||||||
|
// GIVEN the dialog is created with a PendingIntent
|
||||||
|
val dialog = createDialog(pendingIntent)
|
||||||
|
|
||||||
|
// WHEN the TaskView is initialized
|
||||||
|
dialog.stateCallback.onInitialized()
|
||||||
|
|
||||||
|
// THEN the PendingIntent used to call startActivity is unmodified by systemui
|
||||||
|
verify(taskView).startActivity(eq(pendingIntent), any(), any(), any())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createDialog(pendingIntent: PendingIntent): DetailDialog {
|
||||||
|
return DetailDialog(
|
||||||
|
mContext,
|
||||||
|
taskView,
|
||||||
|
pendingIntent,
|
||||||
|
controlViewHolder
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user