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

Commit b9095b1e authored by Ats Jenk's avatar Ats Jenk Committed by Android (Google) Code Review
Browse files

Merge changes I180f432e,Ie4766452 into main

* changes:
  Use a weakref hashmap to store controllers
  Always clean up taskview
parents 87f1176f d78ec6b3
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -53,6 +53,8 @@ android_robolectric_test {
        "mockito-robolectric-prebuilt",
        "mockito-kotlin2",
        "truth",
        "flag-junit-base",
        "flag-junit",
    ],
    auto_gen_config: true,
}
+29 −2
Original line number Diff line number Diff line
@@ -18,14 +18,19 @@ package com.android.wm.shell.bubbles

import android.content.ComponentName
import android.content.Context
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.SetFlagsRule
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.wm.shell.Flags
import com.android.wm.shell.taskview.TaskView

import com.google.common.truth.Truth.assertThat
import com.google.common.util.concurrent.MoreExecutors.directExecutor
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.mock
@@ -36,6 +41,9 @@ import org.mockito.kotlin.verify
@RunWith(AndroidJUnit4::class)
class BubbleTaskViewTest {

    @get:Rule
    val setFlagsRule = SetFlagsRule()

    private lateinit var bubbleTaskView: BubbleTaskView
    private val context = ApplicationProvider.getApplicationContext<Context>()
    private lateinit var taskView: TaskView
@@ -75,14 +83,33 @@ class BubbleTaskViewTest {
        assertThat(actualComponentName).isEqualTo(componentName)
    }

    @DisableFlags(Flags.FLAG_ENABLE_TASK_VIEW_CONTROLLER_CLEANUP)
    @Test
    fun cleanup_invalidTaskId_doesNotRemoveTask() {
    fun cleanup_flagOff_invalidTaskId_doesNotRemoveTask() {
        bubbleTaskView.cleanup()
        verify(taskView, never()).removeTask()
    }

    @EnableFlags(Flags.FLAG_ENABLE_TASK_VIEW_CONTROLLER_CLEANUP)
    @Test
    fun cleanup_flagOn_invalidTaskId_removesTask() {
        bubbleTaskView.cleanup()
        verify(taskView).removeTask()
    }

    @DisableFlags(Flags.FLAG_ENABLE_TASK_VIEW_CONTROLLER_CLEANUP)
    @Test
    fun cleanup_flagOff_validTaskId_removesTask() {
        val componentName = ComponentName(context, "TestClass")
        bubbleTaskView.listener.onTaskCreated(123, componentName)

        bubbleTaskView.cleanup()
        verify(taskView).removeTask()
    }

    @EnableFlags(Flags.FLAG_ENABLE_TASK_VIEW_CONTROLLER_CLEANUP)
    @Test
    fun cleanup_validTaskId_removesTask() {
    fun cleanup_flagOn_validTaskId_removesTask() {
        val componentName = ComponentName(context, "TestClass")
        bubbleTaskView.listener.onTaskCreated(123, componentName)

+3 −19
Original line number Diff line number Diff line
@@ -16,14 +16,11 @@

package com.android.wm.shell.bubbles

import android.app.ActivityTaskManager
import android.app.ActivityTaskManager.INVALID_TASK_ID
import android.content.ComponentName
import android.os.RemoteException
import android.util.Log
import androidx.annotation.VisibleForTesting
import com.android.wm.shell.Flags
import com.android.wm.shell.taskview.TaskView
import com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS
import java.util.concurrent.Executor

/**
@@ -89,21 +86,8 @@ class BubbleTaskView(val taskView: TaskView, executor: Executor) {
     * This should be called after all other cleanup animations have finished.
     */
    fun cleanup() {
        if (taskId != INVALID_TASK_ID) {
            // Ensure the task is removed from WM
            if (ENABLE_SHELL_TRANSITIONS) {
        if (Flags.enableTaskViewControllerCleanup() || taskId != INVALID_TASK_ID) {
            taskView.removeTask()
            } else {
                try {
                    ActivityTaskManager.getService().removeTask(taskId)
                } catch (e: RemoteException) {
                    Log.w(TAG, e.message ?: "")
        }
    }
}
    }

    private companion object {
        const val TAG = "BubbleTaskView"
    }
}
+8 −2
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import android.view.WindowInsets;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;

import com.android.wm.shell.Flags;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.SyncTransactionQueue;

@@ -525,8 +526,13 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
     */
    void removeTask() {
        if (mTaskToken == null) {
            if (Flags.enableTaskViewControllerCleanup()) {
                // We don't have a task yet. Only clean up the controller
                mTaskViewTransitions.removeTaskView(this);
            } else {
                // Call to remove task before we have one, do nothing
                Slog.w(TAG, "Trying to remove a task that was never added? (no taskToken)");
            }
            return;
        }
        mShellExecutor.execute(() -> {
+32 −6
Original line number Diff line number Diff line
@@ -37,11 +37,14 @@ import android.window.WindowContainerTransaction;

import androidx.annotation.VisibleForTesting;

import com.android.wm.shell.Flags;
import com.android.wm.shell.shared.TransitionUtil;
import com.android.wm.shell.transition.Transitions;

import java.util.ArrayList;
import java.util.Map;
import java.util.Objects;
import java.util.WeakHashMap;

/**
 * Handles Shell Transitions that involve TaskView tasks.
@@ -49,8 +52,15 @@ import java.util.Objects;
public class TaskViewTransitions implements Transitions.TransitionHandler {
    static final String TAG = "TaskViewTransitions";

    private final ArrayMap<TaskViewTaskController, TaskViewRequestedState> mTaskViews =
            new ArrayMap<>();
    /**
     * Map of {@link TaskViewTaskController} to {@link TaskViewRequestedState}.
     * <p>
     * {@link TaskView} keeps a reference to the {@link TaskViewTaskController} instance and
     * manages its lifecycle.
     * Only keep a weak reference to the controller instance here to allow for it to be cleaned
     * up when its TaskView is no longer used.
     */
    private final Map<TaskViewTaskController, TaskViewRequestedState> mTaskViews;
    private final ArrayList<PendingTransition> mPending = new ArrayList<>();
    private final Transitions mTransitions;
    private final boolean[] mRegistered = new boolean[]{false};
@@ -95,6 +105,11 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {

    public TaskViewTransitions(Transitions transitions) {
        mTransitions = transitions;
        if (Flags.enableTaskViewControllerCleanup()) {
            mTaskViews = new WeakHashMap<>();
        } else {
            mTaskViews = new ArrayMap<>();
        }
        // Defer registration until the first TaskView because we want this to be the "first" in
        // priority when handling requests.
        // TODO(210041388): register here once we have an explicit ordering mechanism.
@@ -208,10 +223,21 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {
    }

    private TaskViewTaskController findTaskView(ActivityManager.RunningTaskInfo taskInfo) {
        for (int i = 0; i < mTaskViews.size(); ++i) {
            if (mTaskViews.keyAt(i).getTaskInfo() == null) continue;
            if (taskInfo.token.equals(mTaskViews.keyAt(i).getTaskInfo().token)) {
                return mTaskViews.keyAt(i);
        if (Flags.enableTaskViewControllerCleanup()) {
            for (TaskViewTaskController controller : mTaskViews.keySet()) {
                if (controller.getTaskInfo() == null) continue;
                if (taskInfo.token.equals(controller.getTaskInfo().token)) {
                    return controller;
                }
            }
        } else {
            ArrayMap<TaskViewTaskController, TaskViewRequestedState> taskViews =
                    (ArrayMap<TaskViewTaskController, TaskViewRequestedState>) mTaskViews;
            for (int i = 0; i < taskViews.size(); ++i) {
                if (taskViews.keyAt(i).getTaskInfo() == null) continue;
                if (taskInfo.token.equals(taskViews.keyAt(i).getTaskInfo().token)) {
                    return taskViews.keyAt(i);
                }
            }
        }
        return null;
Loading