Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 467bcd0a authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Controls - Do not recreate intent" into sc-dev am: 060ab663

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16148688

Change-Id: I61e2d7bf3daadb242e02e1dec689d7c720fa6bc3
parents cff660f9 060ab663
Loading
Loading
Loading
Loading
+6 −5
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.systemui.controls.ui

import android.annotation.MainThread
import android.app.Dialog
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
@@ -88,7 +89,7 @@ class ControlActionCoordinatorImpl @Inject constructor(
        bouncerOrRun(createAction(cvh.cws.ci.controlId, {
            cvh.layout.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK)
            if (cvh.usePanel()) {
                showDetail(cvh, control.getAppIntent().getIntent())
                showDetail(cvh, control.getAppIntent())
            } else {
                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
            cvh.cws.control?.let {
                cvh.layout.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
                showDetail(cvh, it.getAppIntent().getIntent())
                showDetail(cvh, it.getAppIntent())
            }
        }, false /* blockable */))
    }
@@ -167,10 +168,10 @@ class ControlActionCoordinatorImpl @Inject constructor(
        bgExecutor.execute { vibrator.vibrate(effect) }
    }

    private fun showDetail(cvh: ControlViewHolder, intent: Intent) {
    private fun showDetail(cvh: ControlViewHolder, pendingIntent: PendingIntent) {
        bgExecutor.execute {
            val activities: List<ResolveInfo> = context.packageManager.queryIntentActivities(
                intent,
                pendingIntent.getIntent(),
                PackageManager.MATCH_DEFAULT_ONLY
            )

@@ -178,7 +179,7 @@ class ControlActionCoordinatorImpl @Inject constructor(
                // make sure the intent is valid before attempting to open the dialog
                if (activities.isNotEmpty() && taskViewFactory.isPresent) {
                    taskViewFactory.get().create(context, uiExecutor, {
                        dialog = DetailDialog(activityContext, it, intent, cvh).also {
                        dialog = DetailDialog(activityContext, it, pendingIntent, cvh).also {
                            it.setOnDismissListener { _ -> dialog = null }
                            it.show()
                        }
+16 −12
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ import com.android.wm.shell.TaskView
class DetailDialog(
    val activityContext: Context?,
    val taskView: TaskView,
    val intent: Intent,
    val pendingIntent: PendingIntent,
    val cvh: ControlViewHolder
) : Dialog(
    activityContext ?: cvh.context,
@@ -59,6 +59,14 @@ class DetailDialog(

    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() {
        if (detailTaskId == INVALID_TASK_ID) return
        ActivityTaskManager.getInstance().removeTask(detailTaskId)
@@ -67,13 +75,6 @@ class DetailDialog(

    val stateCallback = object : TaskView.Listener {
        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 {
                ActivityOptions.makeCustomAnimation(
                    it,
@@ -82,9 +83,8 @@ class DetailDialog(
                )
            } ?: ActivityOptions.makeBasic()
            taskView.startActivity(
                PendingIntent.getActivity(context, 0, launchIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE),
                null /* fillInIntent */,
                pendingIntent,
                fillInIntent,
                options,
                getTaskViewBounds()
            )
@@ -97,6 +97,9 @@ class DetailDialog(

        override fun onTaskCreated(taskId: Int, name: ComponentName?) {
            detailTaskId = taskId
            requireViewById<ViewGroup>(R.id.controls_activity_view).apply {
                setAlpha(1f)
            }
        }

        override fun onReleased() {
@@ -121,6 +124,7 @@ class DetailDialog(

        requireViewById<ViewGroup>(R.id.controls_activity_view).apply {
            addView(taskView)
            setAlpha(0f)
        }

        requireViewById<ImageView>(R.id.control_detail_close).apply {
@@ -134,7 +138,7 @@ class DetailDialog(
                removeDetailTask()
                dismiss()
                context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
                v.context.startActivity(intent)
                pendingIntent.send()
            }
        }

+71 −0
Original line number Diff line number Diff line
/*
 * 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
        )
    }
}