diff options
9 files changed, 127 insertions, 43 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 7b81713c0fcc..7695eccabc60 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -2036,6 +2036,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case DELETE_ACTIVITY_CONTAINER_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IActivityContainer activityContainer = + IActivityContainer.Stub.asInterface(data.readStrongBinder()); + deleteActivityContainer(activityContainer); + reply.writeNoException(); + return true; + } + case GET_ACTIVITY_CONTAINER_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder activityToken = data.readStrongBinder(); @@ -4692,6 +4701,18 @@ class ActivityManagerProxy implements IActivityManager return res; } + public void deleteActivityContainer(IActivityContainer activityContainer) + throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(activityContainer.asBinder()); + mRemote.transact(DELETE_ACTIVITY_CONTAINER_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + public IActivityContainer getEnclosingActivityContainer(IBinder activityToken) throws RemoteException { Parcel data = Parcel.obtain(); diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java index 14f08298e404..113f1230386e 100644 --- a/core/java/android/app/ActivityView.java +++ b/core/java/android/app/ActivityView.java @@ -37,6 +37,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; +/** @hide */ public class ActivityView extends ViewGroup { private final String TAG = "ActivityView"; private final boolean DEBUG = false; @@ -107,6 +108,10 @@ public class ActivityView extends ViewGroup { super.onDetachedFromWindow(); if (mActivityContainer != null) { detach(); + try { + ActivityManagerNative.getDefault().deleteActivityContainer(mActivityContainer); + } catch (RemoteException e) { + } mActivityContainer = null; } } @@ -122,7 +127,6 @@ public class ActivityView extends ViewGroup { case View.INVISIBLE: break; case View.GONE: - detach(); break; } } diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 3ed3f7bdf20e..02a6343bf746 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -407,9 +407,13 @@ public interface IActivityManager extends IInterface { public void performIdleMaintenance() throws RemoteException; + /** @hide */ public IActivityContainer createActivityContainer(IBinder parentActivityToken, IActivityContainerCallback callback) throws RemoteException; + /** @hide */ + public void deleteActivityContainer(IActivityContainer container) throws RemoteException; + public IActivityContainer getEnclosingActivityContainer(IBinder activityToken) throws RemoteException; @@ -703,4 +707,5 @@ public interface IActivityManager extends IInterface { int APP_NOT_RESPONDING_VIA_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+182; int GET_HOME_ACTIVITY_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+183; int GET_ACTIVITY_CONTAINER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+184; + int DELETE_ACTIVITY_CONTAINER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+185; } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 46891f5920a4..4dde117e9528 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -7082,6 +7082,15 @@ public final class ActivityManagerService extends ActivityManagerNative } @Override + public void deleteActivityContainer(IActivityContainer container) throws RemoteException { + enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS, + "deleteActivityContainer()"); + synchronized (this) { + mStackSupervisor.deleteActivityContainer(container); + } + } + + @Override public IActivityContainer getEnclosingActivityContainer(IBinder activityToken) throws RemoteException { synchronized (this) { diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 3587241aad1c..ad6ff0e10649 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -2179,13 +2179,28 @@ public final class ActivityStackSupervisor implements DisplayListener { ActivityRecord top = stack.topRunningNonDelayedActivityLocked(null); if (top != null) { // TODO: Make sure the next activity doesn't start up when top is destroyed. - stack.destroyActivityLocked(top, true, true, "stack removal"); + stack.destroyActivityLocked(top, true, true, "stack parent destroyed"); } mActivityContainers.removeAt(ndx); container.detachLocked(); } } + void deleteActivityContainer(IActivityContainer container) { + ActivityContainer activityContainer = (ActivityContainer)container; + if (activityContainer != null) { + activityContainer.mStack.destroyActivitiesLocked(null, true, + "deleteActivityContainer"); + final ActivityRecord parent = activityContainer.mParentActivity; + if (parent != null) { + parent.mChildContainers.remove(activityContainer); + } + final int stackId = activityContainer.mStackId; + mActivityContainers.remove(stackId); + mWindowManager.removeStack(stackId); + } + } + private int createStackOnDisplay(ActivityRecord parentActivity, int stackId, int displayId) { ActivityDisplay activityDisplay = mActivityDisplays.get(displayId); if (activityDisplay == null) { @@ -2556,6 +2571,7 @@ public final class ActivityStackSupervisor implements DisplayListener { pw.print(prefix); pw.println("mSleepTimeout=" + mSleepTimeout); pw.print(prefix); pw.println("mCurTaskId=" + mCurTaskId); pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront); + pw.print(prefix); pw.println("mActivityContainers=" + mActivityContainers); } ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) { diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 68834d8f691b..d4bcd5c48083 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -102,9 +102,8 @@ class DisplayContent { final WindowManagerService mService; - static final int DEFER_DETACH = 1; - static final int DEFER_REMOVAL = 2; - int mDeferredActions; + /** Remove this display when animation on it has completed. */ + boolean mDeferredRemoval; /** * @param display May not be null. @@ -302,6 +301,49 @@ class DisplayContent { } } + boolean isAnimating() { + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + final TaskStack stack = mStacks.get(stackNdx); + if (stack.isAnimating()) { + return true; + } + } + return false; + } + + void checkForDeferredActions() { + boolean animating = false; + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + final TaskStack stack = mStacks.get(stackNdx); + if (stack.isAnimating()) { + animating = true; + } else { + if (stack.mDeferDetach) { + mService.detachStackLocked(this, stack); + } + final ArrayList<Task> tasks = stack.getTasks(); + for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { + final Task task = tasks.get(taskNdx); + AppTokenList tokens = task.mAppTokens; + for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { + AppWindowToken wtoken = tokens.get(tokenNdx); + if (wtoken.mDeferRemoval) { + wtoken.mDeferRemoval = false; + mService.removeAppFromTaskLocked(wtoken); + } + } + if (task.mDeferRemoval) { + task.mDeferRemoval = false; + mService.removeTaskLocked(task); + } + } + } + } + if (!animating && mDeferredRemoval) { + mService.onDisplayRemoved(mDisplayId); + } + } + public void dump(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId); final String subPrefix = " " + prefix; @@ -325,7 +367,8 @@ class DisplayContent { pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight); pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth); pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight); - pw.print(subPrefix); pw.print("layoutNeeded="); pw.println(layoutNeeded); + pw.print(subPrefix); pw.print("deferred="); pw.print(mDeferredRemoval); + pw.print(" layoutNeeded="); pw.println(layoutNeeded); for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { final TaskStack stack = mStacks.get(stackNdx); pw.print(prefix); pw.print("mStacks[" + stackNdx + "]"); pw.println(stack.mStackId); diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index c70bc621658b..81db8b306aa0 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -75,6 +75,9 @@ public class TaskStack { /** Application tokens that are exiting, but still on screen for animations. */ final AppTokenList mExitingAppTokens = new AppTokenList(); + /** Detach this stack from its display when animation completes. */ + boolean mDeferDetach; + TaskStack(WindowManagerService service, int stackId) { mService = service; mStackId = stackId; @@ -362,36 +365,9 @@ public class TaskStack { mAnimationBackgroundSurface.mDimSurface.destroy(); } - void checkForDeferredActions() { - if (mDisplayContent != null && - (mDisplayContent.mDeferredActions & DisplayContent.DEFER_DETACH) != 0 && - !isAnimating()) { - mDisplayContent.mDeferredActions &= ~DisplayContent.DEFER_DETACH; - if ((mDisplayContent.mDeferredActions & DisplayContent.DEFER_REMOVAL) != 0) { - mDisplayContent.mDeferredActions &= ~DisplayContent.DEFER_REMOVAL; - mService.onDisplayRemoved(mDisplayContent.getDisplayId()); - } - mService.detachStack(mStackId); - } - for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) { - final Task task = mTasks.get(taskNdx); - AppTokenList tokens = task.mAppTokens; - for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { - AppWindowToken wtoken = tokens.get(tokenNdx); - if (wtoken.mDeferRemoval) { - wtoken.mDeferRemoval = false; - mService.removeAppFromTaskLocked(wtoken); - } - } - if (task.mDeferRemoval) { - task.mDeferRemoval = false; - mService.removeTaskLocked(task); - } - } - } - public void dump(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("mStackId="); pw.println(mStackId); + pw.print(prefix); pw.print("mDeferDetach="); pw.println(mDeferDetach); for (int taskNdx = 0; taskNdx < mTasks.size(); ++taskNdx) { pw.print(prefix); pw.println(mTasks.get(taskNdx)); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 9557b1b152f4..fb5d7a79c025 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -188,6 +188,7 @@ public class WindowManagerService extends IWindowManager.Stub static final boolean DEBUG_WINDOW_TRACE = false; static final boolean DEBUG_TASK_MOVEMENT = false; static final boolean DEBUG_STACK = false; + static final boolean DEBUG_DISPLAY = false; static final boolean SHOW_SURFACE_ALLOC = false; static final boolean SHOW_TRANSACTIONS = false; static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS; @@ -4931,6 +4932,11 @@ public class WindowManagerService extends IWindowManager.Stub } } + void detachStackLocked(DisplayContent displayContent, TaskStack stack) { + displayContent.detachStack(stack); + stack.detachDisplay(); + } + public void detachStack(int stackId) { synchronized (mWindowMap) { TaskStack stack = mStackIdToStack.get(stackId); @@ -4938,16 +4944,19 @@ public class WindowManagerService extends IWindowManager.Stub final DisplayContent displayContent = stack.getDisplayContent(); if (displayContent != null) { if (stack.isAnimating()) { - displayContent.mDeferredActions |= DisplayContent.DEFER_DETACH; + stack.mDeferDetach = true; return; } - displayContent.detachStack(stack); - stack.detachDisplay(); + detachStackLocked(displayContent, stack); } } } } + public void removeStack(int stackId) { + mStackIdToStack.remove(stackId); + } + void removeTaskLocked(Task task) { final int taskId = task.taskId; final TaskStack stack = task.mStack; @@ -9499,9 +9508,9 @@ public class WindowManagerService extends IWindowManager.Stub } } - // Remove all deferred Stacks, tasks, and activities. - for (int stackNdx = mPendingStacksRemove.size() - 1; stackNdx >= 0; --stackNdx) { - mPendingStacksRemove.removeAt(stackNdx).checkForDeferredActions(); + // Remove all deferred displays stacks, tasks, and activities. + for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) { + mDisplayContents.valueAt(displayNdx).checkForDeferredActions(); } setFocusedStackFrame(); @@ -10780,6 +10789,7 @@ public class WindowManagerService extends IWindowManager.Stub private DisplayContent newDisplayContentLocked(final Display display) { DisplayContent displayContent = new DisplayContent(display, this); final int displayId = display.getDisplayId(); + if (DEBUG_DISPLAY) Slog.v(TAG, "Adding display=" + display); mDisplayContents.put(displayId, displayContent); DisplayInfo displayInfo = displayContent.getDisplayInfo(); @@ -10881,10 +10891,11 @@ public class WindowManagerService extends IWindowManager.Stub private void handleDisplayRemovedLocked(int displayId) { final DisplayContent displayContent = getDisplayContentLocked(displayId); if (displayContent != null) { - if ((displayContent.mDeferredActions & DisplayContent.DEFER_DETACH) != 0) { - displayContent.mDeferredActions |= DisplayContent.DEFER_REMOVAL; + if (displayContent.isAnimating()) { + displayContent.mDeferredRemoval = true; return; } + if (DEBUG_DISPLAY) Slog.v(TAG, "Removing display=" + displayContent); mDisplayContents.delete(displayId); displayContent.close(); if (displayId == Display.DEFAULT_DISPLAY) { diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index f98b724d339b..93f6d2292e6b 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -430,7 +430,6 @@ class WindowStateAnimator { mService.mPendingRemove.add(mWin); mWin.mRemoveOnExit = false; } - mService.mPendingStacksRemove.add(mWin.getStack()); mAnimator.hideWallpapersLocked(mWin); } |