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

Commit aff506bb authored by Winson Chung's avatar Winson Chung
Browse files

Fix small issue with task org state cleanup

- When the task org binder died, it previously did not remove from
  the mTaskOrganizersForWindowingMode list and handle replacements
  the same way as unregistering.  Likewise when unregistering,
  the code to handle replacements could override the existing
  state since it only checks if the previous state was not disposed
  before setting it.

  Alternatively, we can keep the list of TaskOrganizerStates for a
  windowing mode in a list. The last item in the list is the current
  task org for that windowing mode. When a task org is removed or
  its binder dies, we simply remove from that list.

Bug: 152134222
Test: atest WmTests:TaskOrganizerTests

Change-Id: I1c7fd8907c7f025da25d62b0fa939edbb789e0cb
parent 97b93168
Loading
Loading
Loading
Loading
+1 −2
Original line number Original line Diff line number Diff line
@@ -4111,8 +4111,7 @@ class Task extends WindowContainer<WindowContainer> {
        return true;
        return true;
    }
    }


    // Called on Binder death.
    void taskOrganizerUnregistered() {
    void taskOrganizerDied() {
        mTaskOrganizer = null;
        mTaskOrganizer = null;
        mLastTaskOrganizerWindowingMode = -1;
        mLastTaskOrganizerWindowingMode = -1;
        onTaskOrganizerChanged();
        onTaskOrganizerChanged();
+33 −48
Original line number Original line Diff line number Diff line
@@ -34,6 +34,7 @@ import android.os.Binder;
import android.os.IBinder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.RemoteException;
import android.util.Slog;
import android.util.Slog;
import android.util.SparseArray;
import android.window.ITaskOrganizer;
import android.window.ITaskOrganizer;
import android.window.ITaskOrganizerController;
import android.window.ITaskOrganizerController;
import android.window.IWindowContainer;
import android.window.IWindowContainer;
@@ -42,6 +43,7 @@ import com.android.internal.util.ArrayUtils;


import java.util.ArrayList;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.List;
import java.util.WeakHashMap;
import java.util.WeakHashMap;


@@ -51,6 +53,7 @@ import java.util.WeakHashMap;
 */
 */
class TaskOrganizerController extends ITaskOrganizerController.Stub {
class TaskOrganizerController extends ITaskOrganizerController.Stub {
    private static final String TAG = "TaskOrganizerController";
    private static final String TAG = "TaskOrganizerController";
    private static final LinkedList<TaskOrganizerState> EMPTY_LIST = new LinkedList<>();


    /**
    /**
     * Masks specifying which configurations are important to report back to an organizer when
     * Masks specifying which configurations are important to report back to an organizer when
@@ -73,32 +76,20 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
        @Override
        @Override
        public void binderDied() {
        public void binderDied() {
            synchronized (mGlobalLock) {
            synchronized (mGlobalLock) {
                final TaskOrganizerState state =
                final TaskOrganizerState state = mTaskOrganizerStates.remove(
                    mTaskOrganizerStates.get(mTaskOrganizer.asBinder());
                        mTaskOrganizer.asBinder());
                state.releaseTasks();
                state.dispose();
                mTaskOrganizerStates.remove(mTaskOrganizer.asBinder());
                if (mTaskOrganizersForWindowingMode.get(mWindowingMode) == mTaskOrganizer) {
                    mTaskOrganizersForWindowingMode.remove(mWindowingMode);
                }
            }
            }
        }
        }
    };
    };


    class TaskOrganizerState {
    private class TaskOrganizerState {
        ITaskOrganizer mOrganizer;
        private final ITaskOrganizer mOrganizer;
        DeathRecipient mDeathRecipient;
        private final DeathRecipient mDeathRecipient;
        int mWindowingMode;
        private final int mWindowingMode;

        private final ArrayList<Task> mOrganizedTasks = new ArrayList<>();
        ArrayList<Task> mOrganizedTasks = new ArrayList<>();

        // Save the TaskOrganizer which we replaced registration for
        // so it can be re-registered if we unregister.
        TaskOrganizerState mReplacementFor;
        boolean mDisposed = false;



        TaskOrganizerState(ITaskOrganizer organizer, int windowingMode) {
        TaskOrganizerState(ITaskOrganizer organizer, int windowingMode,
                @Nullable TaskOrganizerState replacing) {
            mOrganizer = organizer;
            mOrganizer = organizer;
            mDeathRecipient = new DeathRecipient(organizer, windowingMode);
            mDeathRecipient = new DeathRecipient(organizer, windowingMode);
            try {
            try {
@@ -107,7 +98,6 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
                Slog.e(TAG, "TaskOrganizer failed to register death recipient");
                Slog.e(TAG, "TaskOrganizer failed to register death recipient");
            }
            }
            mWindowingMode = windowingMode;
            mWindowingMode = windowingMode;
            mReplacementFor = replacing;
        }
        }


        void addTask(Task t) {
        void addTask(Task t) {
@@ -129,35 +119,26 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
        }
        }


        void dispose() {
        void dispose() {
            mDisposed = true;
            releaseTasks();
            releaseTasks();
            handleReplacement();
            mTaskOrganizersForWindowingMode.get(mWindowingMode).remove(this);
        }
        }


        void releaseTasks() {
        private void releaseTasks() {
            for (int i = mOrganizedTasks.size() - 1; i >= 0; i--) {
            for (int i = mOrganizedTasks.size() - 1; i >= 0; i--) {
                final Task t = mOrganizedTasks.get(i);
                final Task t = mOrganizedTasks.get(i);
                t.taskOrganizerDied();
                removeTask(t);
                removeTask(t);
            }
                t.taskOrganizerUnregistered();
        }

        void handleReplacement() {
            if (mReplacementFor != null && !mReplacementFor.mDisposed) {
                mTaskOrganizersForWindowingMode.put(mWindowingMode, mReplacementFor);
            }
            }
        }
        }


        void unlinkDeath() {
        void unlinkDeath() {
            mDisposed = true;
            mOrganizer.asBinder().unlinkToDeath(mDeathRecipient, 0);
            mOrganizer.asBinder().unlinkToDeath(mDeathRecipient, 0);
        }
        }
    };
    }


    final HashMap<Integer, TaskOrganizerState> mTaskOrganizersForWindowingMode = new HashMap();
    final HashMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new HashMap();


    private final SparseArray<LinkedList<TaskOrganizerState>> mTaskOrganizersForWindowingMode =
            new SparseArray<>();
    private final HashMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new HashMap<>();
    private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>();
    private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>();
    private final ArrayList<Task> mPendingTaskInfoChanges = new ArrayList<>();
    private final ArrayList<Task> mPendingTaskInfoChanges = new ArrayList<>();


@@ -196,11 +177,17 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
                    Slog.w(TAG, "Task organizer already exists for windowing mode: "
                    Slog.w(TAG, "Task organizer already exists for windowing mode: "
                            + windowingMode);
                            + windowingMode);
                }
                }
                final TaskOrganizerState previousState =

                        mTaskOrganizersForWindowingMode.get(windowingMode);
                LinkedList<TaskOrganizerState> states;
                final TaskOrganizerState state = new TaskOrganizerState(organizer, windowingMode,
                if (mTaskOrganizersForWindowingMode.contains(windowingMode)) {
                        previousState);
                    states = mTaskOrganizersForWindowingMode.get(windowingMode);
                mTaskOrganizersForWindowingMode.put(windowingMode, state);
                } else {
                    states = new LinkedList<>();
                    mTaskOrganizersForWindowingMode.put(windowingMode, states);
                }
                final TaskOrganizerState previousState = states.peekLast();
                final TaskOrganizerState state = new TaskOrganizerState(organizer, windowingMode);
                states.add(state);
                mTaskOrganizerStates.put(organizer.asBinder(), state);
                mTaskOrganizerStates.put(organizer.asBinder(), state);


                if (previousState == null) {
                if (previousState == null) {
@@ -221,16 +208,14 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {


    @Override
    @Override
    public void unregisterTaskOrganizer(ITaskOrganizer organizer) {
    public void unregisterTaskOrganizer(ITaskOrganizer organizer) {
        final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
        final TaskOrganizerState state = mTaskOrganizerStates.remove(organizer.asBinder());
        state.unlinkDeath();
        state.unlinkDeath();
        if (mTaskOrganizersForWindowingMode.get(state.mWindowingMode) == state) {
            mTaskOrganizersForWindowingMode.remove(state.mWindowingMode);
        }
        state.dispose();
        state.dispose();
    }
    }


    ITaskOrganizer getTaskOrganizer(int windowingMode) {
    ITaskOrganizer getTaskOrganizer(int windowingMode) {
        final TaskOrganizerState state = mTaskOrganizersForWindowingMode.get(windowingMode);
        final TaskOrganizerState state = mTaskOrganizersForWindowingMode.get(windowingMode,
                EMPTY_LIST).peekLast();
        if (state == null) {
        if (state == null) {
            return null;
            return null;
        }
        }