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

Commit 41472f82 authored by Liran Binyamin's avatar Liran Binyamin
Browse files

Create BubbleTaskView

This is an initial no-op change that introduces BubbleTaskView, which is a class that wraps a TaskView and a listener.

This change moves the creation of TaskView outside of the bubble expanded view class, and instead passes it a TaskView instance.

In follow up cls BubbleTaskView will be stored in the Bubble class so that we can keep the TaskView when switching between floating and bar modes. See ag/25863141 for a prototype of how this would work.

Bug: 316358859
Test: atest BubbleTaskViewTest
Change-Id: Idc8caa256f9c8e408d7a62a0db40dc717ea5ea45
parent 8860603b
Loading
Loading
Loading
Loading
+75 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.wm.shell.bubbles

import android.content.ComponentName
import android.content.Context
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.wm.shell.taskview.TaskView
import com.android.wm.shell.taskview.TaskViewTaskController

import com.google.common.truth.Truth.assertThat
import com.google.common.util.concurrent.MoreExecutors.directExecutor
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.mock

@SmallTest
@RunWith(AndroidJUnit4::class)
class BubbleTaskViewTest {

    private lateinit var bubbleTaskView: BubbleTaskView
    private val context = ApplicationProvider.getApplicationContext<Context>()

    @Before
    fun setUp() {
        val taskView = TaskView(context, mock<TaskViewTaskController>())
        bubbleTaskView = BubbleTaskView(taskView, directExecutor())
    }

    @Test
    fun onTaskCreated_updatesState() {
        val componentName = ComponentName(context, "TestClass")
        bubbleTaskView.listener.onTaskCreated(123, componentName)

        assertThat(bubbleTaskView.taskId).isEqualTo(123)
        assertThat(bubbleTaskView.componentName).isEqualTo(componentName)
        assertThat(bubbleTaskView.isCreated).isTrue()
    }

    @Test
    fun onTaskCreated_callsDelegateListener() {
        var actualTaskId = -1
        var actualComponentName: ComponentName? = null
        val delegateListener = object : TaskView.Listener {
            override fun onTaskCreated(taskId: Int, name: ComponentName) {
                actualTaskId = taskId
                actualComponentName = name
            }
        }
        bubbleTaskView.delegateListener = delegateListener

        val componentName = ComponentName(context, "TestClass")
        bubbleTaskView.listener.onTaskCreated(123, componentName)

        assertThat(actualTaskId).isEqualTo(123)
        assertThat(actualComponentName).isEqualTo(componentName)
    }
}
+14 −10
Original line number Diff line number Diff line
@@ -74,7 +74,6 @@ import com.android.wm.shell.R;
import com.android.wm.shell.common.AlphaOptimizedButton;
import com.android.wm.shell.common.TriangleShape;
import com.android.wm.shell.taskview.TaskView;
import com.android.wm.shell.taskview.TaskViewTaskController;

import java.io.PrintWriter;

@@ -146,7 +145,6 @@ public class BubbleExpandedView extends LinearLayout {

    private AlphaOptimizedButton mManageButton;
    private TaskView mTaskView;
    private TaskViewTaskController mTaskViewTaskController;
    private BubbleOverflowContainerView mOverflowView;

    private int mTaskId = INVALID_TASK_ID;
@@ -434,7 +432,8 @@ public class BubbleExpandedView extends LinearLayout {
     * Initialize {@link BubbleController} and {@link BubbleStackView} here, this method must need
     * to be called after view inflate.
     */
    void initialize(BubbleController controller, BubbleStackView stackView, boolean isOverflow) {
    void initialize(BubbleController controller, BubbleStackView stackView, boolean isOverflow,
            @Nullable BubbleTaskView bubbleTaskView) {
        mController = controller;
        mStackView = stackView;
        mIsOverflow = isOverflow;
@@ -451,18 +450,22 @@ public class BubbleExpandedView extends LinearLayout {
            bringChildToFront(mOverflowView);
            mManageButton.setVisibility(GONE);
        } else {
            mTaskViewTaskController = new TaskViewTaskController(mContext,
                    mController.getTaskOrganizer(),
                    mController.getTaskViewTransitions(), mController.getSyncTransactionQueue());
            mTaskView = new TaskView(mContext, mTaskViewTaskController);
            mTaskView.setListener(mController.getMainExecutor(), mTaskViewListener);
            mTaskView = bubbleTaskView.getTaskView();
            bubbleTaskView.setDelegateListener(mTaskViewListener);

            // set a fixed width so it is not recalculated as part of a rotation. the width will be
            // updated manually after the rotation.
            FrameLayout.LayoutParams lp =
                    new FrameLayout.LayoutParams(getContentWidth(), MATCH_PARENT);
            if (mTaskView.getParent() != null) {
                ((ViewGroup) mTaskView.getParent()).removeView(mTaskView);
            }
            mExpandedViewContainer.addView(mTaskView, lp);
            bringChildToFront(mTaskView);
            if (bubbleTaskView.isCreated()) {
                mTaskViewListener.onTaskCreated(
                        bubbleTaskView.getTaskId(), bubbleTaskView.getComponentName());
            }
        }
    }

@@ -876,7 +879,7 @@ public class BubbleExpandedView extends LinearLayout {
            return;
        }
        boolean isNew = mBubble == null || didBackingContentChange(bubble);
        if (isNew || bubble != null && bubble.getKey().equals(mBubble.getKey())) {
        if (isNew || bubble.getKey().equals(mBubble.getKey())) {
            mBubble = bubble;
            mManageButton.setContentDescription(getResources().getString(
                    R.string.bubbles_settings_button_description, bubble.getAppName()));
@@ -1107,7 +1110,8 @@ public class BubbleExpandedView extends LinearLayout {
     * has been removed.
     *
     * If this view should be reused after this method is called, then
     * {@link #initialize(BubbleController, BubbleStackView, boolean)} must be invoked first.
     * {@link #initialize(BubbleController, BubbleStackView, boolean, BubbleTaskView)}
     * must be invoked first.
     */
    public void cleanUpExpandedState() {
        if (DEBUG_BUBBLE_EXPANDED_VIEW) {
+13 −3
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.util.PathParser
import android.view.LayoutInflater
import android.view.View.VISIBLE
import android.widget.FrameLayout
import androidx.core.content.ContextCompat
import com.android.launcher3.icons.BubbleIconFactory
import com.android.wm.shell.R
import com.android.wm.shell.bubbles.bar.BubbleBarExpandedView
@@ -57,10 +58,16 @@ class BubbleOverflow(private val context: Context, private val positioner: Bubbl
    /** Call before use and again if cleanUpExpandedState was called. */
    fun initialize(controller: BubbleController, forBubbleBar: Boolean) {
        if (forBubbleBar) {
            createBubbleBarExpandedView().initialize(controller, true /* isOverflow */)
            createBubbleBarExpandedView()
                .initialize(controller, /* isOverflow= */ true, /* bubbleTaskView= */ null)
        } else {
            createExpandedView()
                .initialize(controller, controller.stackView, true /* isOverflow */)
                .initialize(
                    controller,
                    controller.stackView,
                    /* isOverflow= */ true,
                    /* bubbleTaskView= */ null
                )
        }
    }

@@ -113,7 +120,10 @@ class BubbleOverflow(private val context: Context, private val positioner: Bubbl
                context,
                res.getDimensionPixelSize(R.dimen.bubble_size),
                res.getDimensionPixelSize(R.dimen.bubble_badge_size),
                res.getColor(com.android.launcher3.icons.R.color.important_conversation),
                ContextCompat.getColor(
                    context,
                    com.android.launcher3.icons.R.color.important_conversation
                ),
                res.getDimensionPixelSize(com.android.internal.R.dimen.importance_ring_stroke_width)
            )

+81 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.wm.shell.bubbles

import android.app.ActivityTaskManager.INVALID_TASK_ID
import android.content.ComponentName
import androidx.annotation.VisibleForTesting
import com.android.wm.shell.taskview.TaskView
import java.util.concurrent.Executor

/**
 * A wrapper class around [TaskView] for bubble expanded views.
 *
 * [delegateListener] allows callers to change listeners after a task has been created.
 */
class BubbleTaskView(val taskView: TaskView, executor: Executor) {

    /** Whether the task is already created. */
    var isCreated = false
      private set

    /** The task id. */
    var taskId = INVALID_TASK_ID
      private set

    /** The component name of the application running in the task. */
    var componentName: ComponentName? = null
      private set

    /** [TaskView.Listener] for users of this class. */
    var delegateListener: TaskView.Listener? = null

    /** A [TaskView.Listener] that delegates to [delegateListener]. */
    @get:VisibleForTesting
    val listener = object : TaskView.Listener {
        override fun onInitialized() {
            delegateListener?.onInitialized()
        }

        override fun onReleased() {
            delegateListener?.onReleased()
        }

        override fun onTaskCreated(taskId: Int, name: ComponentName) {
            delegateListener?.onTaskCreated(taskId, name)
            this@BubbleTaskView.taskId = taskId
            isCreated = true
            componentName = name
        }

        override fun onTaskVisibilityChanged(taskId: Int, visible: Boolean) {
            delegateListener?.onTaskVisibilityChanged(taskId, visible)
        }

        override fun onTaskRemovalStarted(taskId: Int) {
            delegateListener?.onTaskRemovalStarted(taskId)
        }

        override fun onBackPressedOnTaskRoot(taskId: Int) {
            delegateListener?.onBackPressedOnTaskRoot(taskId)
        }
    }

    init {
        taskView.setListener(executor, listener)
    }
}
+7 −11
Original line number Diff line number Diff line
@@ -35,10 +35,7 @@ import android.view.View;

import androidx.annotation.Nullable;

import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.taskview.TaskView;
import com.android.wm.shell.taskview.TaskViewTaskController;

/**
 * Handles creating and updating the {@link TaskView} associated with a {@link Bubble}.
@@ -65,7 +62,6 @@ public class BubbleTaskViewHelper {

    private final Context mContext;
    private final BubbleController mController;
    private final @ShellMainThread ShellExecutor mMainExecutor;
    private final BubbleTaskViewHelper.Listener mListener;
    private final View mParentView;

@@ -73,7 +69,6 @@ public class BubbleTaskViewHelper {
    private Bubble mBubble;
    @Nullable
    private PendingIntent mPendingIntent;
    private TaskViewTaskController mTaskViewTaskController;
    @Nullable
    private TaskView mTaskView;
    private int mTaskId = INVALID_TASK_ID;
@@ -204,17 +199,18 @@ public class BubbleTaskViewHelper {
    public BubbleTaskViewHelper(Context context,
            BubbleController controller,
            BubbleTaskViewHelper.Listener listener,
            BubbleTaskView bubbleTaskView,
            View parent) {
        mContext = context;
        mController = controller;
        mMainExecutor = mController.getMainExecutor();
        mListener = listener;
        mParentView = parent;
        mTaskViewTaskController = new TaskViewTaskController(mContext,
                mController.getTaskOrganizer(),
                mController.getTaskViewTransitions(), mController.getSyncTransactionQueue());
        mTaskView = new TaskView(mContext, mTaskViewTaskController);
        mTaskView.setListener(mMainExecutor, mTaskViewListener);
        mTaskView = bubbleTaskView.getTaskView();
        bubbleTaskView.setDelegateListener(mTaskViewListener);
        if (bubbleTaskView.isCreated()) {
            mTaskId = bubbleTaskView.getTaskId();
            mListener.onTaskCreated();
        }
    }

    /**
Loading