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

Commit c21aca86 authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Made ShellTaskOrganizer thread safe

- Post callbacks from WM Core on executor.
- Added lock to protect critical sections.

Bug: 171384876
Test: They pass!
Change-Id: Ia1808b66104c2a1e6efb9f43c31e6a3a2f67a952
parent 05c11205
Loading
Loading
Loading
Loading
+12 −7
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@ import android.view.SurfaceControl;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;


import java.util.List;
import java.util.List;
import java.util.concurrent.Executor;


/**
/**
 * Interface for ActivityTaskManager/WindowManager to delegate control of tasks.
 * Interface for ActivityTaskManager/WindowManager to delegate control of tasks.
@@ -37,15 +38,19 @@ import java.util.List;
@TestApi
@TestApi
public class TaskOrganizer extends WindowOrganizer {
public class TaskOrganizer extends WindowOrganizer {


    private ITaskOrganizerController mTaskOrganizerController;
    private final ITaskOrganizerController mTaskOrganizerController;
    // Callbacks WM Core are posted on this executor if it isn't null, otherwise direct calls are
    // made on the incoming binder call.
    private final Executor mExecutor;


    public TaskOrganizer() {
    public TaskOrganizer() {
        this(null);
        this(null /*taskOrganizerController*/, null /*executor*/);
    }
    }


    /** @hide */
    /** @hide */
    @VisibleForTesting
    @VisibleForTesting
    public TaskOrganizer(ITaskOrganizerController taskOrganizerController) {
    public TaskOrganizer(ITaskOrganizerController taskOrganizerController, Executor executor) {
        mExecutor = executor != null ? executor : command -> command.run();
        mTaskOrganizerController = taskOrganizerController != null
        mTaskOrganizerController = taskOrganizerController != null
                ? taskOrganizerController : getController();
                ? taskOrganizerController : getController();
    }
    }
@@ -183,22 +188,22 @@ public class TaskOrganizer extends WindowOrganizer {


        @Override
        @Override
        public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
        public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
            TaskOrganizer.this.onTaskAppeared(taskInfo, leash);
            mExecutor.execute(() -> TaskOrganizer.this.onTaskAppeared(taskInfo, leash));
        }
        }


        @Override
        @Override
        public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
        public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
            TaskOrganizer.this.onTaskVanished(taskInfo);
            mExecutor.execute(() -> TaskOrganizer.this.onTaskVanished(taskInfo));
        }
        }


        @Override
        @Override
        public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
        public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
            TaskOrganizer.this.onTaskInfoChanged(info);
            mExecutor.execute(() -> TaskOrganizer.this.onTaskInfoChanged(info));
        }
        }


        @Override
        @Override
        public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo info) {
        public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo info) {
            TaskOrganizer.this.onBackPressedOnTaskRoot(info);
            mExecutor.execute(() -> TaskOrganizer.this.onBackPressedOnTaskRoot(info));
        }
        }
    };
    };


+134 −110
Original line number Original line Diff line number Diff line
@@ -105,6 +105,8 @@ public class ShellTaskOrganizer extends TaskOrganizer {
    // TODO(shell-transitions): move to a more "global" Shell location as this isn't only for Tasks
    // TODO(shell-transitions): move to a more "global" Shell location as this isn't only for Tasks
    private final Transitions mTransitions;
    private final Transitions mTransitions;


    private final Object mLock = new Object();

    public ShellTaskOrganizer(SyncTransactionQueue syncQueue, TransactionPool transactionPool,
    public ShellTaskOrganizer(SyncTransactionQueue syncQueue, TransactionPool transactionPool,
            ShellExecutor mainExecutor, ShellExecutor animExecutor) {
            ShellExecutor mainExecutor, ShellExecutor animExecutor) {
        this(null, syncQueue, transactionPool, mainExecutor, animExecutor);
        this(null, syncQueue, transactionPool, mainExecutor, animExecutor);
@@ -114,7 +116,7 @@ public class ShellTaskOrganizer extends TaskOrganizer {
    ShellTaskOrganizer(ITaskOrganizerController taskOrganizerController,
    ShellTaskOrganizer(ITaskOrganizerController taskOrganizerController,
            SyncTransactionQueue syncQueue, TransactionPool transactionPool,
            SyncTransactionQueue syncQueue, TransactionPool transactionPool,
            ShellExecutor mainExecutor, ShellExecutor animExecutor) {
            ShellExecutor mainExecutor, ShellExecutor animExecutor) {
        super(taskOrganizerController);
        super(taskOrganizerController, mainExecutor);
        addListenerForType(new FullscreenTaskListener(syncQueue), TASK_LISTENER_TYPE_FULLSCREEN);
        addListenerForType(new FullscreenTaskListener(syncQueue), TASK_LISTENER_TYPE_FULLSCREEN);
        mTransitions = new Transitions(this, transactionPool, mainExecutor, animExecutor);
        mTransitions = new Transitions(this, transactionPool, mainExecutor, animExecutor);
        if (Transitions.ENABLE_SHELL_TRANSITIONS) registerTransitionPlayer(mTransitions);
        if (Transitions.ENABLE_SHELL_TRANSITIONS) registerTransitionPlayer(mTransitions);
@@ -122,21 +124,23 @@ public class ShellTaskOrganizer extends TaskOrganizer {


    @Override
    @Override
    public List<TaskAppearedInfo> registerOrganizer() {
    public List<TaskAppearedInfo> registerOrganizer() {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Registering organizer");
        synchronized (mLock) {
            ProtoLog.v(WM_SHELL_TASK_ORG, "Registering organizer");
            final List<TaskAppearedInfo> taskInfos = super.registerOrganizer();
            final List<TaskAppearedInfo> taskInfos = super.registerOrganizer();
            for (int i = 0; i < taskInfos.size(); i++) {
            for (int i = 0; i < taskInfos.size(); i++) {
                final TaskAppearedInfo info = taskInfos.get(i);
                final TaskAppearedInfo info = taskInfos.get(i);
            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Existing task: id=%d component=%s",
                ProtoLog.v(WM_SHELL_TASK_ORG, "Existing task: id=%d component=%s",
                        info.getTaskInfo().taskId, info.getTaskInfo().baseIntent);
                        info.getTaskInfo().taskId, info.getTaskInfo().baseIntent);
                onTaskAppeared(info);
                onTaskAppeared(info);
            }
            }
            return taskInfos;
            return taskInfos;
        }
        }
    }


    public TaskAppearedInfo createRootTask(
    public TaskAppearedInfo createRootTask(
            int displayId, int windowingMode, TaskListener listener) {
            int displayId, int windowingMode, TaskListener listener) {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG,
        synchronized (mLock) {
                "createRootTask() displayId=%d winMode=%d listener=%s",
            ProtoLog.v(WM_SHELL_TASK_ORG, "createRootTask() displayId=%d winMode=%d listener=%s",
                    displayId, windowingMode, listener.toString());
                    displayId, windowingMode, listener.toString());
            final TaskAppearedInfo info = super.createRootTask(displayId, windowingMode);
            final TaskAppearedInfo info = super.createRootTask(displayId, windowingMode);


@@ -145,14 +149,17 @@ public class ShellTaskOrganizer extends TaskOrganizer {
            onTaskAppeared(info);
            onTaskAppeared(info);
            return info;
            return info;
        }
        }
    }


    /**
    /**
     * Adds a listener for a specific task id.
     * Adds a listener for a specific task id.
     */
     */
    public void addListenerForTaskId(TaskListener listener, int taskId) {
    public void addListenerForTaskId(TaskListener listener, int taskId) {
        synchronized (mLock) {
            ProtoLog.v(WM_SHELL_TASK_ORG, "addListenerForTaskId taskId=%s", taskId);
            ProtoLog.v(WM_SHELL_TASK_ORG, "addListenerForTaskId taskId=%s", taskId);
            if (mTaskListeners.get(taskId) != null) {
            if (mTaskListeners.get(taskId) != null) {
            throw new IllegalArgumentException("Listener for taskId=" + taskId + " already exists");
                throw new IllegalArgumentException(
                        "Listener for taskId=" + taskId + " already exists");
            }
            }


            final TaskAppearedInfo info = mTasks.get(taskId);
            final TaskAppearedInfo info = mTasks.get(taskId);
@@ -164,11 +171,13 @@ public class ShellTaskOrganizer extends TaskOrganizer {
            mTaskListeners.put(taskId, listener);
            mTaskListeners.put(taskId, listener);
            updateTaskListenerIfNeeded(info.getTaskInfo(), info.getLeash(), oldListener, listener);
            updateTaskListenerIfNeeded(info.getTaskInfo(), info.getLeash(), oldListener, listener);
        }
        }
    }


    /**
    /**
     * Adds a listener for tasks with given types.
     * Adds a listener for tasks with given types.
     */
     */
    public void addListenerForType(TaskListener listener, @TaskListenerType int... listenerTypes) {
    public void addListenerForType(TaskListener listener, @TaskListenerType int... listenerTypes) {
        synchronized (mLock) {
            ProtoLog.v(WM_SHELL_TASK_ORG, "addListenerForType types=%s listener=%s",
            ProtoLog.v(WM_SHELL_TASK_ORG, "addListenerForType types=%s listener=%s",
                    Arrays.toString(listenerTypes), listener);
                    Arrays.toString(listenerTypes), listener);
            for (int listenerType : listenerTypes) {
            for (int listenerType : listenerTypes) {
@@ -187,11 +196,13 @@ public class ShellTaskOrganizer extends TaskOrganizer {
                }
                }
            }
            }
        }
        }
    }


    /**
    /**
     * Removes a registered listener.
     * Removes a registered listener.
     */
     */
    public void removeListener(TaskListener listener) {
    public void removeListener(TaskListener listener) {
        synchronized (mLock) {
            ProtoLog.v(WM_SHELL_TASK_ORG, "Remove listener=%s", listener);
            ProtoLog.v(WM_SHELL_TASK_ORG, "Remove listener=%s", listener);
            final int index = mTaskListeners.indexOfValue(listener);
            final int index = mTaskListeners.indexOfValue(listener);
            if (index == -1) {
            if (index == -1) {
@@ -218,19 +229,24 @@ public class ShellTaskOrganizer extends TaskOrganizer {
                        null /* oldListener already removed*/, getTaskListener(data.getTaskInfo()));
                        null /* oldListener already removed*/, getTaskListener(data.getTaskInfo()));
            }
            }
        }
        }
    }


    /**
    /**
     * Associated a listener to a pending launch cookie so we can route the task later once it
     * Associated a listener to a pending launch cookie so we can route the task later once it
     * appears.
     * appears.
     */
     */
    public void setPendingLaunchCookieListener(IBinder cookie, TaskListener listener) {
    public void setPendingLaunchCookieListener(IBinder cookie, TaskListener listener) {
        synchronized (mLock) {
            mLaunchCookieToListener.put(cookie, listener);
            mLaunchCookieToListener.put(cookie, listener);
        }
        }
    }


    @Override
    @Override
    public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
    public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
        synchronized (mLock) {
            onTaskAppeared(new TaskAppearedInfo(taskInfo, leash));
            onTaskAppeared(new TaskAppearedInfo(taskInfo, leash));
        }
        }
    }


    private void onTaskAppeared(TaskAppearedInfo info) {
    private void onTaskAppeared(TaskAppearedInfo info) {
        final int taskId = info.getTaskInfo().taskId;
        final int taskId = info.getTaskInfo().taskId;
@@ -245,6 +261,7 @@ public class ShellTaskOrganizer extends TaskOrganizer {


    @Override
    @Override
    public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
    public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
        synchronized (mLock) {
            ProtoLog.v(WM_SHELL_TASK_ORG, "Task info changed taskId=%d", taskInfo.taskId);
            ProtoLog.v(WM_SHELL_TASK_ORG, "Task info changed taskId=%d", taskInfo.taskId);
            final TaskAppearedInfo data = mTasks.get(taskInfo.taskId);
            final TaskAppearedInfo data = mTasks.get(taskInfo.taskId);
            final TaskListener oldListener = getTaskListener(data.getTaskInfo());
            final TaskListener oldListener = getTaskListener(data.getTaskInfo());
@@ -256,18 +273,22 @@ public class ShellTaskOrganizer extends TaskOrganizer {
                newListener.onTaskInfoChanged(taskInfo);
                newListener.onTaskInfoChanged(taskInfo);
            }
            }
        }
        }
    }


    @Override
    @Override
    public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
    public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
        synchronized (mLock) {
            ProtoLog.v(WM_SHELL_TASK_ORG, "Task root back pressed taskId=%d", taskInfo.taskId);
            ProtoLog.v(WM_SHELL_TASK_ORG, "Task root back pressed taskId=%d", taskInfo.taskId);
            final TaskListener listener = getTaskListener(taskInfo);
            final TaskListener listener = getTaskListener(taskInfo);
            if (listener != null) {
            if (listener != null) {
                listener.onBackPressedOnTaskRoot(taskInfo);
                listener.onBackPressedOnTaskRoot(taskInfo);
            }
            }
        }
        }
    }


    @Override
    @Override
    public void onTaskVanished(RunningTaskInfo taskInfo) {
    public void onTaskVanished(RunningTaskInfo taskInfo) {
        synchronized (mLock) {
            ProtoLog.v(WM_SHELL_TASK_ORG, "Task vanished taskId=%d", taskInfo.taskId);
            ProtoLog.v(WM_SHELL_TASK_ORG, "Task vanished taskId=%d", taskInfo.taskId);
            final int taskId = taskInfo.taskId;
            final int taskId = taskInfo.taskId;
            final TaskListener listener = getTaskListener(mTasks.get(taskId).getTaskInfo());
            final TaskListener listener = getTaskListener(mTasks.get(taskId).getTaskInfo());
@@ -276,6 +297,7 @@ public class ShellTaskOrganizer extends TaskOrganizer {
                listener.onTaskVanished(taskInfo);
                listener.onTaskVanished(taskInfo);
            }
            }
        }
        }
    }


    private boolean updateTaskListenerIfNeeded(RunningTaskInfo taskInfo, SurfaceControl leash,
    private boolean updateTaskListenerIfNeeded(RunningTaskInfo taskInfo, SurfaceControl leash,
            TaskListener oldListener, TaskListener newListener) {
            TaskListener oldListener, TaskListener newListener) {
@@ -368,6 +390,7 @@ public class ShellTaskOrganizer extends TaskOrganizer {
    }
    }


    public void dump(@NonNull PrintWriter pw, String prefix) {
    public void dump(@NonNull PrintWriter pw, String prefix) {
        synchronized (mLock) {
            final String innerPrefix = prefix + "  ";
            final String innerPrefix = prefix + "  ";
            final String childPrefix = innerPrefix + "  ";
            final String childPrefix = innerPrefix + "  ";
            pw.println(prefix + TAG);
            pw.println(prefix + TAG);
@@ -397,3 +420,4 @@ public class ShellTaskOrganizer extends TaskOrganizer {
            }
            }
        }
        }
    }
    }
}