[DO NOT MERGE] Controls - Do not recreate intent am: d7b16dd2a5
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16012418 Change-Id: I7d17da929ecd548c21c0d088557ff20209952efe
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
package com.android.systemui.controls.ui
|
||||
|
||||
import android.app.Dialog
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
@@ -74,7 +75,7 @@ class ControlActionCoordinatorImpl @Inject constructor(
|
||||
bouncerOrRun(Action(cvh.cws.ci.controlId, {
|
||||
cvh.layout.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK)
|
||||
if (cvh.usePanel()) {
|
||||
showDialog(cvh, control.getAppIntent().getIntent())
|
||||
showDetail(cvh, control.getAppIntent())
|
||||
} else {
|
||||
cvh.action(CommandAction(templateId))
|
||||
}
|
||||
@@ -100,7 +101,7 @@ class ControlActionCoordinatorImpl @Inject constructor(
|
||||
// Long press snould only be called when there is valid control state, otherwise ignore
|
||||
cvh.cws.control?.let {
|
||||
cvh.layout.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
|
||||
showDialog(cvh, it.getAppIntent().getIntent())
|
||||
showDetail(cvh, it.getAppIntent())
|
||||
}
|
||||
}, false /* blockable */))
|
||||
}
|
||||
@@ -155,17 +156,17 @@ class ControlActionCoordinatorImpl @Inject constructor(
|
||||
bgExecutor.execute { vibrator.vibrate(effect) }
|
||||
}
|
||||
|
||||
private fun showDialog(cvh: ControlViewHolder, intent: Intent) {
|
||||
private fun showDetail(cvh: ControlViewHolder, pendingIntent: PendingIntent) {
|
||||
bgExecutor.execute {
|
||||
val activities: List<ResolveInfo> = cvh.context.packageManager.queryIntentActivities(
|
||||
intent,
|
||||
val activities: List<ResolveInfo> = context.packageManager.queryIntentActivities(
|
||||
pendingIntent.getIntent(),
|
||||
PackageManager.MATCH_DEFAULT_ONLY
|
||||
)
|
||||
|
||||
uiExecutor.execute {
|
||||
// make sure the intent is valid before attempting to open the dialog
|
||||
if (activities.isNotEmpty()) {
|
||||
dialog = DetailDialog(cvh, intent).also {
|
||||
dialog = DetailDialog(cvh, pendingIntent).also {
|
||||
it.setOnDismissListener { _ -> dialog = null }
|
||||
it.show()
|
||||
}
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
|
||||
package com.android.systemui.controls.ui
|
||||
|
||||
import android.app.ActivityOptions
|
||||
import android.app.ActivityView
|
||||
import android.app.PendingIntent
|
||||
import android.app.Dialog
|
||||
import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
import android.provider.Settings
|
||||
import android.view.View
|
||||
@@ -37,9 +40,8 @@ import com.android.systemui.R
|
||||
*/
|
||||
class DetailDialog(
|
||||
val cvh: ControlViewHolder,
|
||||
val intent: Intent
|
||||
val pendingIntent: PendingIntent
|
||||
) : Dialog(cvh.context, R.style.Theme_SystemUI_Dialog_Control_DetailPanel) {
|
||||
|
||||
companion object {
|
||||
private const val PANEL_TOP_OFFSET = "systemui.controls_panel_top_offset"
|
||||
/*
|
||||
@@ -49,18 +51,19 @@ class DetailDialog(
|
||||
private const val EXTRA_USE_PANEL = "controls.DISPLAY_IN_PANEL"
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
var activityView = ActivityView(context, null, 0, false)
|
||||
|
||||
val stateCallback: ActivityView.StateCallback = object : ActivityView.StateCallback() {
|
||||
override fun onActivityViewReady(view: ActivityView) {
|
||||
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)
|
||||
|
||||
view.startActivity(launchIntent)
|
||||
view.startActivity(pendingIntent, fillInIntent, ActivityOptions.makeBasic())
|
||||
}
|
||||
|
||||
override fun onActivityViewDestroyed(view: ActivityView) {}
|
||||
@@ -68,6 +71,12 @@ class DetailDialog(
|
||||
override fun onTaskRemovalStarted(taskId: Int) {
|
||||
dismiss()
|
||||
}
|
||||
|
||||
override fun onTaskCreated(taskId: Int, name: ComponentName?) {
|
||||
requireViewById<ViewGroup>(R.id.controls_activity_view).apply {
|
||||
setAlpha(1f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
@@ -76,6 +85,7 @@ class DetailDialog(
|
||||
|
||||
requireViewById<ViewGroup>(R.id.controls_activity_view).apply {
|
||||
addView(activityView)
|
||||
setAlpha(0f)
|
||||
}
|
||||
|
||||
requireViewById<ImageView>(R.id.control_detail_close).apply {
|
||||
@@ -86,7 +96,7 @@ class DetailDialog(
|
||||
setOnClickListener { v: View ->
|
||||
dismiss()
|
||||
context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
|
||||
v.context.startActivity(intent)
|
||||
pendingIntent.send()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.ActivityView
|
||||
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.systemui.util.mockito.capture
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentCaptor
|
||||
import org.mockito.ArgumentMatchers.eq
|
||||
import org.mockito.Captor
|
||||
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 activityView: ActivityView
|
||||
@Mock
|
||||
private lateinit var controlViewHolder: ControlViewHolder
|
||||
@Mock
|
||||
private lateinit var pendingIntent: PendingIntent
|
||||
@Captor
|
||||
private lateinit var viewCaptor: ArgumentCaptor<ActivityView>
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPendingIntentIsUnModified() {
|
||||
// GIVEN the dialog is created with a PendingIntent
|
||||
val dialog = createDialog(pendingIntent)
|
||||
|
||||
// WHEN the ActivityView is initialized
|
||||
dialog.stateCallback.onActivityViewReady(capture(viewCaptor))
|
||||
|
||||
// THEN the PendingIntent used to call startActivity is unmodified by systemui
|
||||
verify(viewCaptor.value).startActivity(eq(pendingIntent), any(), any())
|
||||
}
|
||||
|
||||
private fun createDialog(pendingIntent: PendingIntent): DetailDialog {
|
||||
return DetailDialog(
|
||||
controlViewHolder,
|
||||
pendingIntent
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user