Merge "Remove TaskFragments while TaskFragmentOrganizer removed" into sc-v2-dev
This commit is contained in:
@@ -24,7 +24,7 @@ import android.os.Binder;
|
|||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.ArraySet;
|
import android.util.Slog;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
import android.window.ITaskFragmentOrganizer;
|
import android.window.ITaskFragmentOrganizer;
|
||||||
import android.window.ITaskFragmentOrganizerController;
|
import android.window.ITaskFragmentOrganizerController;
|
||||||
@@ -33,8 +33,8 @@ import android.window.TaskFragmentInfo;
|
|||||||
|
|
||||||
import com.android.internal.protolog.common.ProtoLog;
|
import com.android.internal.protolog.common.ProtoLog;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,104 +45,112 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
|||||||
|
|
||||||
private final ActivityTaskManagerService mAtmService;
|
private final ActivityTaskManagerService mAtmService;
|
||||||
private final WindowManagerGlobalLock mGlobalLock;
|
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 =
|
private final Map<TaskFragment, TaskFragmentInfo> mLastSentTaskFragmentInfos =
|
||||||
new WeakHashMap<>();
|
new WeakHashMap<>();
|
||||||
private final Map<TaskFragment, Configuration> mLastSentTaskFragmentParentConfigs =
|
private final Map<TaskFragment, Configuration> mLastSentTaskFragmentParentConfigs =
|
||||||
new WeakHashMap<>();
|
new WeakHashMap<>();
|
||||||
|
/**
|
||||||
private class DeathRecipient implements IBinder.DeathRecipient {
|
* A Map which manages the relationship between
|
||||||
final ITaskFragmentOrganizer mOrganizer;
|
* {@link ITaskFragmentOrganizer} and {@link TaskFragmentOrganizerState}
|
||||||
|
*/
|
||||||
DeathRecipient(ITaskFragmentOrganizer organizer) {
|
private final ArrayMap<IBinder, TaskFragmentController> mTaskFragmentOrganizerControllers =
|
||||||
mOrganizer = organizer;
|
new ArrayMap<>();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void binderDied() {
|
|
||||||
removeOrganizer(mOrganizer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskFragmentOrganizerController(ActivityTaskManagerService atm) {
|
TaskFragmentOrganizerController(ActivityTaskManagerService atm) {
|
||||||
mAtmService = atm;
|
mAtmService = atm;
|
||||||
mGlobalLock = atm.mGlobalLock;
|
mGlobalLock = atm.mGlobalLock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
public void registerOrganizer(ITaskFragmentOrganizer organizer) {
|
public void registerOrganizer(ITaskFragmentOrganizer organizer) {
|
||||||
final int pid = Binder.getCallingPid();
|
final int pid = Binder.getCallingPid();
|
||||||
final long uid = Binder.getCallingUid();
|
final long uid = Binder.getCallingUid();
|
||||||
final long origId = Binder.clearCallingIdentity();
|
synchronized (mGlobalLock) {
|
||||||
try {
|
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
|
||||||
synchronized (mGlobalLock) {
|
"Register task fragment organizer=%s uid=%d pid=%d",
|
||||||
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
|
organizer.asBinder(), uid, pid);
|
||||||
"Register task fragment organizer=%s uid=%d pid=%d",
|
if (mTaskFragmentOrganizerControllers.containsKey(organizer.asBinder())) {
|
||||||
organizer.asBinder(), uid, pid);
|
throw new IllegalStateException(
|
||||||
if (mOrganizers.contains(organizer)) {
|
"Replacing existing organizer currently unsupported");
|
||||||
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 {
|
mTaskFragmentOrganizerControllers.put(organizer.asBinder(),
|
||||||
Binder.restoreCallingIdentity(origId);
|
new TaskFragmentController(organizer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unregisterOrganizer(ITaskFragmentOrganizer organizer) {
|
public void unregisterOrganizer(ITaskFragmentOrganizer organizer) {
|
||||||
|
validateAndGetController(organizer);
|
||||||
final int pid = Binder.getCallingPid();
|
final int pid = Binder.getCallingPid();
|
||||||
final long uid = Binder.getCallingUid();
|
final long uid = Binder.getCallingUid();
|
||||||
final long origId = Binder.clearCallingIdentity();
|
synchronized (mGlobalLock) {
|
||||||
try {
|
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
|
||||||
synchronized (mGlobalLock) {
|
"Unregister task fragment organizer=%s uid=%d pid=%d",
|
||||||
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
|
organizer.asBinder(), uid, pid);
|
||||||
"Unregister task fragment organizer=%s uid=%d pid=%d",
|
removeOrganizer(organizer);
|
||||||
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) {
|
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());
|
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment appeared name=%s", tf.getName());
|
||||||
final TaskFragmentInfo info = tf.getTaskFragmentInfo();
|
final TaskFragmentInfo info = tf.getTaskFragmentInfo();
|
||||||
final SurfaceControl outSurfaceControl = new SurfaceControl(tf.getSurfaceControl(),
|
final SurfaceControl outSurfaceControl = new SurfaceControl(tf.getSurfaceControl(),
|
||||||
"TaskFragmentOrganizerController.onTaskFragmentInfoAppeared");
|
"TaskFragmentOrganizerController.onTaskFragmentInfoAppeared");
|
||||||
|
controller.addTaskFragment(tf);
|
||||||
try {
|
try {
|
||||||
organizer.onTaskFragmentAppeared(
|
organizer.onTaskFragmentAppeared(
|
||||||
new TaskFragmentAppearedInfo(info, outSurfaceControl));
|
new TaskFragmentAppearedInfo(info, outSurfaceControl));
|
||||||
mLastSentTaskFragmentInfos.put(tf, info);
|
mLastSentTaskFragmentInfos.put(tf, info);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// Oh well...
|
Slog.e(TAG, "Exception sending onTaskFragmentAppeared callback", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onTaskFragmentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf) {
|
void onTaskFragmentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf) {
|
||||||
validateOrganizer(organizer);
|
validateAndGetController(organizer);
|
||||||
|
|
||||||
// Check if the info is different from the last reported info.
|
// Check if the info is different from the last reported info.
|
||||||
final TaskFragmentInfo info = tf.getTaskFragmentInfo();
|
final TaskFragmentInfo info = tf.getTaskFragmentInfo();
|
||||||
@@ -157,25 +165,26 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
|||||||
organizer.onTaskFragmentInfoChanged(tf.getTaskFragmentInfo());
|
organizer.onTaskFragmentInfoChanged(tf.getTaskFragmentInfo());
|
||||||
mLastSentTaskFragmentInfos.put(tf, info);
|
mLastSentTaskFragmentInfos.put(tf, info);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// Oh well...
|
Slog.e(TAG, "Exception sending onTaskFragmentInfoChanged callback", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onTaskFragmentVanished(ITaskFragmentOrganizer organizer, TaskFragment tf) {
|
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());
|
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment vanished name=%s", tf.getName());
|
||||||
try {
|
try {
|
||||||
organizer.onTaskFragmentVanished(tf.getTaskFragmentInfo());
|
organizer.onTaskFragmentVanished(tf.getTaskFragmentInfo());
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// Oh well...
|
Slog.e(TAG, "Exception sending onTaskFragmentVanished callback", e);
|
||||||
}
|
}
|
||||||
mLastSentTaskFragmentInfos.remove(tf);
|
mLastSentTaskFragmentInfos.remove(tf);
|
||||||
mLastSentTaskFragmentParentConfigs.remove(tf);
|
mLastSentTaskFragmentParentConfigs.remove(tf);
|
||||||
|
controller.removeTaskFragment(tf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onTaskFragmentParentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf) {
|
void onTaskFragmentParentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf) {
|
||||||
validateOrganizer(organizer);
|
validateAndGetController(organizer);
|
||||||
|
|
||||||
// Check if the parent info is different from the last reported parent info.
|
// Check if the parent info is different from the last reported parent info.
|
||||||
if (tf.getParent() == null || tf.getParent().asTask() == null) {
|
if (tf.getParent() == null || tf.getParent().asTask() == null) {
|
||||||
@@ -196,16 +205,15 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
|||||||
organizer.onTaskFragmentParentInfoChanged(tf.getFragmentToken(), parentConfig);
|
organizer.onTaskFragmentParentInfoChanged(tf.getFragmentToken(), parentConfig);
|
||||||
mLastSentTaskFragmentParentConfigs.put(tf, parentConfig);
|
mLastSentTaskFragmentParentConfigs.put(tf, parentConfig);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// Oh well...
|
Slog.e(TAG, "Exception sending onTaskFragmentParentInfoChanged callback", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeOrganizer(ITaskFragmentOrganizer organizer) {
|
private void removeOrganizer(ITaskFragmentOrganizer organizer) {
|
||||||
synchronized (mGlobalLock) {
|
final TaskFragmentController controller = validateAndGetController(organizer);
|
||||||
mOrganizers.remove(organizer);
|
// remove all of the children of the organized TaskFragment
|
||||||
mDeathRecipients.remove(organizer);
|
controller.dispose();
|
||||||
}
|
mTaskFragmentOrganizerControllers.remove(organizer.asBinder());
|
||||||
// TODO(b/190432728) move child activities of organized TaskFragment to leaf Task
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -214,10 +222,13 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
|
|||||||
* we wouldn't register {@link DeathRecipient} for the organizer, and might not remove the
|
* we wouldn't register {@link DeathRecipient} for the organizer, and might not remove the
|
||||||
* {@link TaskFragment} after the organizer process died.
|
* {@link TaskFragment} after the organizer process died.
|
||||||
*/
|
*/
|
||||||
private void validateOrganizer(ITaskFragmentOrganizer organizer) {
|
private TaskFragmentController validateAndGetController(ITaskFragmentOrganizer organizer) {
|
||||||
if (!mOrganizers.contains(organizer)) {
|
final TaskFragmentController controller =
|
||||||
|
mTaskFragmentOrganizerControllers.get(organizer.asBinder());
|
||||||
|
if (controller == null) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"TaskFragmentOrganizer has not been registered. Organizer=" + organizer);
|
"TaskFragmentOrganizer has not been registered. Organizer=" + organizer);
|
||||||
}
|
}
|
||||||
|
return controller;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user