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

Commit 5a03acb8 authored by Jeff Chang's avatar Jeff Chang Committed by Android (Google) Code Review
Browse files

Merge "Remove TaskFragments while TaskFragmentOrganizer removed" into sc-v2-dev

parents ad40d06f 85c24dea
Loading
Loading
Loading
Loading
+78 −67
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@ import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import android.view.SurfaceControl;
import android.window.ITaskFragmentOrganizer;
import android.window.ITaskFragmentOrganizerController;
@@ -33,8 +33,8 @@ import android.window.TaskFragmentInfo;

import com.android.internal.protolog.common.ProtoLog;

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

/**
@@ -45,104 +45,112 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr

    private final ActivityTaskManagerService mAtmService;
    private final WindowManagerGlobalLock mGlobalLock;
    private final Set<ITaskFragmentOrganizer> mOrganizers = new ArraySet<>();
    private final Map<ITaskFragmentOrganizer, DeathRecipient> mDeathRecipients = new ArrayMap<>();
    private final Map<TaskFragment, TaskFragmentInfo> mLastSentTaskFragmentInfos =
            new WeakHashMap<>();
    private final Map<TaskFragment, Configuration> mLastSentTaskFragmentParentConfigs =
            new WeakHashMap<>();
    /**
     * A Map which manages the relationship between
     * {@link ITaskFragmentOrganizer} and {@link TaskFragmentOrganizerState}
     */
    private final ArrayMap<IBinder, TaskFragmentController> mTaskFragmentOrganizerControllers =
            new ArrayMap<>();

    TaskFragmentOrganizerController(ActivityTaskManagerService atm) {
        mAtmService = atm;
        mGlobalLock = atm.mGlobalLock;
    }

    private class DeathRecipient implements IBinder.DeathRecipient {
        final ITaskFragmentOrganizer mOrganizer;
    /**
     * A class to manage {@link ITaskFragmentOrganizer} and its organized
     * {@link TaskFragment TaskFragments}.
     */
    private class TaskFragmentController implements IBinder.DeathRecipient {
        private final ArrayList<TaskFragment> mOrganizedTaskFragments = new ArrayList<>();
        private final ITaskFragmentOrganizer mOrganizer;

        DeathRecipient(ITaskFragmentOrganizer organizer) {
        TaskFragmentController(ITaskFragmentOrganizer organizer) {
            mOrganizer = organizer;
            try {
                mOrganizer.asBinder().linkToDeath(this, 0 /*flags*/);
            } catch (RemoteException e) {
                Slog.e(TAG, "TaskFragmentOrganizer failed to register death recipient");
            }
        }

        @Override
        public void binderDied() {
            synchronized (mGlobalLock) {
                removeOrganizer(mOrganizer);
            }
        }

    TaskFragmentOrganizerController(ActivityTaskManagerService atm) {
        mAtmService = atm;
        mGlobalLock = atm.mGlobalLock;
        void addTaskFragment(TaskFragment taskFragment) {
            if (!mOrganizedTaskFragments.contains(taskFragment)) {
                mOrganizedTaskFragments.add(taskFragment);
            }
        }

        void removeTaskFragment(TaskFragment taskFragment) {
            mOrganizedTaskFragments.remove(taskFragment);
        }

        void dispose() {
            mOrganizedTaskFragments.forEach(TaskFragment::removeImmediately);
            mOrganizedTaskFragments.clear();
            mOrganizer.asBinder().unlinkToDeath(this, 0 /*flags*/);
        }
    }

    @Override
    public void registerOrganizer(ITaskFragmentOrganizer organizer) {
        final int pid = Binder.getCallingPid();
        final long uid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        try {
        synchronized (mGlobalLock) {
            ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
                    "Register task fragment organizer=%s uid=%d pid=%d",
                    organizer.asBinder(), uid, pid);
                if (mOrganizers.contains(organizer)) {
            if (mTaskFragmentOrganizerControllers.containsKey(organizer.asBinder())) {
                throw new IllegalStateException(
                        "Replacing existing organizer currently unsupported");
            }

                final DeathRecipient dr = new DeathRecipient(organizer);
                try {
                    organizer.asBinder().linkToDeath(dr, 0);
                } catch (RemoteException e) {
                    // Oh well...
                }

                mOrganizers.add(organizer);
                mDeathRecipients.put(organizer, dr);
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
            mTaskFragmentOrganizerControllers.put(organizer.asBinder(),
                    new TaskFragmentController(organizer));
        }
    }

    @Override
    public void unregisterOrganizer(ITaskFragmentOrganizer organizer) {
        validateAndGetController(organizer);
        final int pid = Binder.getCallingPid();
        final long uid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        try {
        synchronized (mGlobalLock) {
            ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
                    "Unregister task fragment organizer=%s uid=%d pid=%d",
                    organizer.asBinder(), uid, pid);
                if (!mOrganizers.contains(organizer)) {
                    throw new IllegalStateException(
                            "The task fragment organizer hasn't been registered.");
                }

                final DeathRecipient dr = mDeathRecipients.get(organizer);
                organizer.asBinder().unlinkToDeath(dr, 0);

            removeOrganizer(organizer);
        }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }

    void onTaskFragmentAppeared(ITaskFragmentOrganizer organizer, TaskFragment tf) {
        validateOrganizer(organizer);
        final TaskFragmentController controller = validateAndGetController(organizer);

        ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment appeared name=%s", tf.getName());
        final TaskFragmentInfo info = tf.getTaskFragmentInfo();
        final SurfaceControl outSurfaceControl = new SurfaceControl(tf.getSurfaceControl(),
                "TaskFragmentOrganizerController.onTaskFragmentInfoAppeared");
        controller.addTaskFragment(tf);
        try {
            organizer.onTaskFragmentAppeared(
                    new TaskFragmentAppearedInfo(info, outSurfaceControl));
            mLastSentTaskFragmentInfos.put(tf, info);
        } catch (RemoteException e) {
            // Oh well...
            Slog.e(TAG, "Exception sending onTaskFragmentAppeared callback", e);
        }
    }

    void onTaskFragmentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf) {
        validateOrganizer(organizer);
        validateAndGetController(organizer);

        // Check if the info is different from the last reported info.
        final TaskFragmentInfo info = tf.getTaskFragmentInfo();
@@ -157,25 +165,26 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
            organizer.onTaskFragmentInfoChanged(tf.getTaskFragmentInfo());
            mLastSentTaskFragmentInfos.put(tf, info);
        } catch (RemoteException e) {
            // Oh well...
            Slog.e(TAG, "Exception sending onTaskFragmentInfoChanged callback", e);
        }
    }

    void onTaskFragmentVanished(ITaskFragmentOrganizer organizer, TaskFragment tf) {
        validateOrganizer(organizer);
        final TaskFragmentController controller = validateAndGetController(organizer);

        ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment vanished name=%s", tf.getName());
        try {
            organizer.onTaskFragmentVanished(tf.getTaskFragmentInfo());
        } catch (RemoteException e) {
            // Oh well...
            Slog.e(TAG, "Exception sending onTaskFragmentVanished callback", e);
        }
        mLastSentTaskFragmentInfos.remove(tf);
        mLastSentTaskFragmentParentConfigs.remove(tf);
        controller.removeTaskFragment(tf);
    }

    void onTaskFragmentParentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf) {
        validateOrganizer(organizer);
        validateAndGetController(organizer);

        // Check if the parent info is different from the last reported parent info.
        if (tf.getParent() == null || tf.getParent().asTask() == null) {
@@ -196,16 +205,15 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
            organizer.onTaskFragmentParentInfoChanged(tf.getFragmentToken(), parentConfig);
            mLastSentTaskFragmentParentConfigs.put(tf, parentConfig);
        } catch (RemoteException e) {
            // Oh well...
            Slog.e(TAG, "Exception sending onTaskFragmentParentInfoChanged callback", e);
        }
    }

    private void removeOrganizer(ITaskFragmentOrganizer organizer) {
        synchronized (mGlobalLock) {
            mOrganizers.remove(organizer);
            mDeathRecipients.remove(organizer);
        }
        // TODO(b/190432728) move child activities of organized TaskFragment to leaf Task
        final TaskFragmentController controller = validateAndGetController(organizer);
        // remove all of the children of the organized TaskFragment
        controller.dispose();
        mTaskFragmentOrganizerControllers.remove(organizer.asBinder());
    }

    /**
@@ -214,10 +222,13 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
     * we wouldn't register {@link DeathRecipient} for the organizer, and might not remove the
     * {@link TaskFragment} after the organizer process died.
     */
    private void validateOrganizer(ITaskFragmentOrganizer organizer) {
        if (!mOrganizers.contains(organizer)) {
    private TaskFragmentController validateAndGetController(ITaskFragmentOrganizer organizer) {
        final TaskFragmentController controller =
                mTaskFragmentOrganizerControllers.get(organizer.asBinder());
        if (controller == null) {
            throw new IllegalArgumentException(
                    "TaskFragmentOrganizer has not been registered. Organizer=" + organizer);
        }
        return controller;
    }
}