diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java index 51cb12aa8bdfd..a4ea17b3c2286 100644 --- a/core/java/android/app/ActivityView.java +++ b/core/java/android/app/ActivityView.java @@ -33,15 +33,18 @@ import android.view.MotionEvent; import android.view.Surface; import android.view.TextureView; import android.view.TextureView.SurfaceTextureListener; -import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; +import dalvik.system.CloseGuard; + +import java.lang.ref.WeakReference; /** @hide */ public class ActivityView extends ViewGroup { - private final String TAG = "ActivityView"; - private final boolean DEBUG = false; + private static final String TAG = "ActivityView"; + private static final boolean DEBUG = false; + DisplayMetrics mMetrics; private final TextureView mTextureView; private IActivityContainer mActivityContainer; private Activity mActivity; @@ -53,6 +56,8 @@ public class ActivityView extends ViewGroup { IIntentSender mQueuedPendingIntent; Intent mQueuedIntent; + private final CloseGuard mGuard = CloseGuard.get(); + public ActivityView(Context context) { this(context, null); } @@ -75,9 +80,24 @@ public class ActivityView extends ViewGroup { throw new IllegalStateException("The ActivityView's Context is not an Activity."); } + try { + mActivityContainer = ActivityManagerNative.getDefault().createActivityContainer( + mActivity.getActivityToken(), new ActivityContainerCallback(this)); + } catch (RemoteException e) { + throw new IllegalStateException("ActivityView: Unable to create ActivityContainer. " + + e); + } + mTextureView = new TextureView(context); mTextureView.setSurfaceTextureListener(new ActivityViewSurfaceTextureListener()); addView(mTextureView); + + WindowManager wm = (WindowManager)mActivity.getSystemService(Context.WINDOW_SERVICE); + mMetrics = new DisplayMetrics(); + wm.getDefaultDisplay().getMetrics(mMetrics); + + mGuard.open("release"); + if (DEBUG) Log.v(TAG, "ctor()"); } @@ -86,51 +106,6 @@ public class ActivityView extends ViewGroup { mTextureView.layout(0, 0, r - l, b - t); } - @Override - protected void onAttachedToWindow() { - if (DEBUG) Log.v(TAG, "onAttachedToWindow()"); - super.onAttachedToWindow(); - try { - final IBinder token = mActivity.getActivityToken(); - mActivityContainer = ActivityManagerNative.getDefault().createActivityContainer(token, - new ActivityContainerCallback()); - } catch (RemoteException e) { - throw new IllegalStateException("ActivityView: Unable to create ActivityContainer. " - + e); - } - - attachToSurfaceWhenReady(); - } - - @Override - protected void onDetachedFromWindow() { - if (DEBUG) Log.v(TAG, "onDetachedFromWindow(): mActivityContainer=" + mActivityContainer); - super.onDetachedFromWindow(); - if (mActivityContainer != null) { - detach(); - try { - ActivityManagerNative.getDefault().deleteActivityContainer(mActivityContainer); - } catch (RemoteException e) { - } - mActivityContainer = null; - } - } - - @Override - protected void onWindowVisibilityChanged(int visibility) { - if (DEBUG) Log.v(TAG, "onWindowVisibilityChanged(): visibility=" + visibility); - super.onWindowVisibilityChanged(visibility); - switch (visibility) { - case View.VISIBLE: - attachToSurfaceWhenReady(); - break; - case View.INVISIBLE: - break; - case View.GONE: - break; - } - } - private boolean injectInputEvent(InputEvent event) { try { return mActivityContainer != null && mActivityContainer.injectEvent(event); @@ -159,6 +134,9 @@ public class ActivityView extends ViewGroup { } public void startActivity(Intent intent) { + if (mActivityContainer == null) { + throw new IllegalStateException("Attempt to call startActivity after release"); + } if (DEBUG) Log.v(TAG, "startActivity(): intent=" + intent + " " + (isAttachedToDisplay() ? "" : "not") + " attached"); if (mSurface != null) { @@ -183,6 +161,9 @@ public class ActivityView extends ViewGroup { } public void startActivity(IntentSender intentSender) { + if (mActivityContainer == null) { + throw new IllegalStateException("Attempt to call startActivity after release"); + } if (DEBUG) Log.v(TAG, "startActivityIntentSender(): intentSender=" + intentSender + " " + (isAttachedToDisplay() ? "" : "not") + " attached"); final IIntentSender iIntentSender = intentSender.getTarget(); @@ -195,6 +176,9 @@ public class ActivityView extends ViewGroup { } public void startActivity(PendingIntent pendingIntent) { + if (mActivityContainer == null) { + throw new IllegalStateException("Attempt to call startActivity after release"); + } if (DEBUG) Log.v(TAG, "startActivityPendingIntent(): PendingIntent=" + pendingIntent + " " + (isAttachedToDisplay() ? "" : "not") + " attached"); final IIntentSender iIntentSender = pendingIntent.getTarget(); @@ -206,24 +190,54 @@ public class ActivityView extends ViewGroup { } } + public void release() { + if (DEBUG) Log.v(TAG, "release()"); + if (mActivityContainer == null) { + Log.e(TAG, "Duplicate call to release"); + return; + } + try { + mActivityContainer.release(); + } catch (RemoteException e) { + } + mActivityContainer = null; + + if (mSurface != null) { + mSurface.release(); + mSurface = null; + } + + mTextureView.setSurfaceTextureListener(null); + + mGuard.close(); + } + + @Override + protected void finalize() throws Throwable { + try { + if (mGuard != null) { + mGuard.warnIfOpen(); + release(); + } + } finally { + super.finalize(); + } + } + private void attachToSurfaceWhenReady() { final SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture(); - if (mActivityContainer == null || surfaceTexture == null || mSurface != null) { + if (surfaceTexture == null || mSurface != null) { // Either not ready to attach, or already attached. return; } - WindowManager wm = (WindowManager)mActivity.getSystemService(Context.WINDOW_SERVICE); - DisplayMetrics metrics = new DisplayMetrics(); - wm.getDefaultDisplay().getMetrics(metrics); - mSurface = new Surface(surfaceTexture); try { - mActivityContainer.attachToSurface(mSurface, mWidth, mHeight, metrics.densityDpi); + mActivityContainer.setSurface(mSurface, mWidth, mHeight, mMetrics.densityDpi); } catch (RemoteException e) { mSurface.release(); mSurface = null; - throw new IllegalStateException( + throw new RuntimeException( "ActivityView: Unable to create ActivityContainer. " + e); } @@ -238,41 +252,43 @@ public class ActivityView extends ViewGroup { } } - private void detach() { - if (DEBUG) Log.d(TAG, "detach: attached=" + isAttachedToDisplay()); - if (mSurface != null) { - try { - mActivityContainer.detachFromDisplay(); - } catch (RemoteException e) { - } - mSurface.release(); - mSurface = null; - } - } - private class ActivityViewSurfaceTextureListener implements SurfaceTextureListener { @Override public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) { + if (mActivityContainer == null) { + return; + } if (DEBUG) Log.d(TAG, "onSurfaceTextureAvailable: width=" + width + " height=" + height); mWidth = width; mHeight = height; - if (mActivityContainer != null) { - attachToSurfaceWhenReady(); - } + attachToSurfaceWhenReady(); } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) { + if (mActivityContainer == null) { + return; + } if (DEBUG) Log.d(TAG, "onSurfaceTextureSizeChanged: w=" + width + " h=" + height); } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { + if (mActivityContainer == null) { + return true; + } if (DEBUG) Log.d(TAG, "onSurfaceTextureDestroyed"); - detach(); + mSurface.release(); + mSurface = null; + try { + mActivityContainer.setSurface(null, mWidth, mHeight, mMetrics.densityDpi); + } catch (RemoteException e) { + throw new RuntimeException( + "ActivityView: Unable to set surface of ActivityContainer. " + e); + } return true; } @@ -283,13 +299,17 @@ public class ActivityView extends ViewGroup { } - private class ActivityContainerCallback extends IActivityContainerCallback.Stub { + private static class ActivityContainerCallback extends IActivityContainerCallback.Stub { + private final WeakReference mActivityViewWeakReference; + + ActivityContainerCallback(ActivityView activityView) { + mActivityViewWeakReference = new WeakReference(activityView); + } + @Override public void setVisible(IBinder container, boolean visible) { - if (DEBUG) Log.v(TAG, "setVisible(): container=" + container + " visible=" + visible); - if (visible) { - } else { - } + if (DEBUG) Log.v(TAG, "setVisible(): container=" + container + " visible=" + visible + + " ActivityView=" + mActivityViewWeakReference.get()); } } } diff --git a/core/java/android/app/IActivityContainer.aidl b/core/java/android/app/IActivityContainer.aidl index 5b80e06e1611b..cc3b10cfa88fc 100644 --- a/core/java/android/app/IActivityContainer.aidl +++ b/core/java/android/app/IActivityContainer.aidl @@ -26,10 +26,10 @@ import android.view.Surface; /** @hide */ interface IActivityContainer { void attachToDisplay(int displayId); - void attachToSurface(in Surface surface, int width, int height, int density); - void detachFromDisplay(); + void setSurface(in Surface surface, int width, int height, int density); int startActivity(in Intent intent); int startActivityIntentSender(in IIntentSender intentSender); int getDisplayId(); boolean injectEvent(in InputEvent event); + void release(); } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 76074198070e6..ecbb0d94a2817 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -7240,6 +7240,9 @@ public final class ActivityManagerService extends ActivityManagerNative if (r == null) { return null; } + if (callback == null) { + throw new IllegalArgumentException("callback must not be null"); + } return mStackSupervisor.createActivityContainer(r, callback); } } diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index d596472b5eb58..60adfb0375242 100755 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -139,7 +139,7 @@ final class ActivityRecord { boolean forceNewConfig; // force re-create with new config next time int launchCount; // count of launches since last state long lastLaunchTime; // time of last lauch of this activity - ArrayList mChildContainers = new ArrayList(); + ArrayList mChildContainers = new ArrayList(); String stringName; // for caching of toString(). diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 8dd43170099b1..e586ec35769b2 100755 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -36,6 +36,8 @@ import static com.android.server.am.ActivityStackSupervisor.DEBUG_SAVED_STATE; import static com.android.server.am.ActivityStackSupervisor.DEBUG_STATES; import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID; +import static com.android.server.am.ActivityStackSupervisor.ActivityContainer.CONTAINER_STATE_HAS_SURFACE; + import com.android.internal.os.BatteryStatsImpl; import com.android.server.Watchdog; import com.android.server.am.ActivityManagerService.ItemMatcher; @@ -1066,9 +1068,9 @@ final class ActivityStack { private void setVisibile(ActivityRecord r, boolean visible) { r.visible = visible; mWindowManager.setAppVisibility(r.appToken, visible); - final ArrayList containers = r.mChildContainers; + final ArrayList containers = r.mChildContainers; for (int containerNdx = containers.size() - 1; containerNdx >= 0; --containerNdx) { - ActivityContainer container = containers.get(containerNdx).mActivityContainer; + ActivityContainer container = containers.get(containerNdx); container.setVisible(visible); } } @@ -1336,7 +1338,8 @@ final class ActivityStack { if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen(""); ActivityRecord parent = mActivityContainer.mParentActivity; - if (parent != null && parent.state != ActivityState.RESUMED) { + if ((parent != null && parent.state != ActivityState.RESUMED) || + mActivityContainer.mContainerState != CONTAINER_STATE_HAS_SURFACE) { // Do not resume this stack if its parent is not resumed. // TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st. return false; @@ -2624,6 +2627,20 @@ final class ActivityStack { return r; } + void finishAllActivitiesLocked() { + for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { + final ArrayList activities = mTaskHistory.get(taskNdx).mActivities; + for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { + final ActivityRecord r = activities.get(activityNdx); + if (r.finishing) { + continue; + } + Slog.d(TAG, "finishAllActivitiesLocked: finishing " + r); + finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false); + } + } + } + final boolean navigateUpToLocked(IBinder token, Intent destIntent, int resultCode, Intent resultData) { final ActivityRecord srec = ActivityRecord.forToken(token); @@ -2862,7 +2879,6 @@ final class ActivityStack { } if (activityRemoved) { mStackSupervisor.resumeTopActivitiesLocked(); - } } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 63f9d098cc143..fa8e5c948f523 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -96,7 +96,6 @@ import com.android.server.wm.WindowManagerService; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; -import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; @@ -225,11 +224,11 @@ public final class ActivityStackSupervisor implements DisplayListener { // TODO: Add listener for removal of references. /** Mapping from (ActivityStack/TaskStack).mStackId to their current state */ - SparseArray> mActivityContainers = - new SparseArray>(); + SparseArray mActivityContainers = new SparseArray(); /** Mapping from displayId to display current state */ - private SparseArray mActivityDisplays = new SparseArray(); + private final SparseArray mActivityDisplays = + new SparseArray(); InputManagerInternal mInputManagerInternal; @@ -265,7 +264,7 @@ public final class ActivityStackSupervisor implements DisplayListener { mActivityDisplays.put(displayId, activityDisplay); } - createStackOnDisplay(null, HOME_STACK_ID, Display.DEFAULT_DISPLAY); + createStackOnDisplay(HOME_STACK_ID, Display.DEFAULT_DISPLAY); mHomeStack = mFocusedStack = mLastFocusedStack = getStack(HOME_STACK_ID); mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); @@ -1386,7 +1385,7 @@ public final class ActivityStackSupervisor implements DisplayListener { } // Need to create an app stack for this user. - int stackId = createStackOnDisplay(null, getNextStackId(), Display.DEFAULT_DISPLAY); + int stackId = createStackOnDisplay(getNextStackId(), Display.DEFAULT_DISPLAY); if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: New stack r=" + r + " stackId=" + stackId); mFocusedStack = getStack(stackId); @@ -2154,14 +2153,9 @@ public final class ActivityStackSupervisor implements DisplayListener { } ActivityStack getStack(int stackId) { - WeakReference weakReference = mActivityContainers.get(stackId); - if (weakReference != null) { - ActivityContainer activityContainer = weakReference.get(); - if (activityContainer != null) { - return activityContainer.mStack; - } else { - mActivityContainers.remove(stackId); - } + ActivityContainer activityContainer = mActivityContainers.get(stackId); + if (activityContainer != null) { + return activityContainer.mStack; } return null; } @@ -2191,49 +2185,26 @@ public final class ActivityStackSupervisor implements DisplayListener { return null; } - ActivityContainer createActivityContainer(ActivityRecord parentActivity, int stackId, + ActivityContainer createActivityContainer(ActivityRecord parentActivity, IActivityContainerCallback callback) { - ActivityContainer activityContainer = new ActivityContainer(parentActivity, stackId, - callback); - mActivityContainers.put(stackId, new WeakReference(activityContainer)); - if (parentActivity != null) { - parentActivity.mChildContainers.add(activityContainer.mStack); - } + ActivityContainer activityContainer = new VirtualActivityContainer(parentActivity, callback); + mActivityContainers.put(activityContainer.mStackId, activityContainer); + parentActivity.mChildContainers.add(activityContainer); return activityContainer; } - ActivityContainer createActivityContainer(ActivityRecord parentActivity, - IActivityContainerCallback callback) { - return createActivityContainer(parentActivity, getNextStackId(), callback); - } - void removeChildActivityContainers(ActivityRecord parentActivity) { - for (int ndx = mActivityContainers.size() - 1; ndx >= 0; --ndx) { - final ActivityContainer container = mActivityContainers.valueAt(ndx).get(); - if (container == null) { - mActivityContainers.removeAt(ndx); - continue; - } - if (container.mParentActivity != parentActivity) { - continue; - } - - ActivityStack stack = container.mStack; - 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 parent destroyed"); - } - mActivityContainers.removeAt(ndx); - container.detachLocked(); + final ArrayList childStacks = parentActivity.mChildContainers; + for (int containerNdx = childStacks.size() - 1; containerNdx >= 0; --containerNdx) { + ActivityContainer container = childStacks.remove(containerNdx); + container.release(); } } void deleteActivityContainer(IActivityContainer container) { ActivityContainer activityContainer = (ActivityContainer)container; if (activityContainer != null) { - activityContainer.mStack.destroyActivitiesLocked(null, true, - "deleteActivityContainer"); + activityContainer.mStack.finishAllActivitiesLocked(); final ActivityRecord parent = activityContainer.mParentActivity; if (parent != null) { parent.mChildContainers.remove(activityContainer); @@ -2244,14 +2215,14 @@ public final class ActivityStackSupervisor implements DisplayListener { } } - private int createStackOnDisplay(ActivityRecord parentActivity, int stackId, int displayId) { + private int createStackOnDisplay(int stackId, int displayId) { ActivityDisplay activityDisplay = mActivityDisplays.get(displayId); if (activityDisplay == null) { return -1; } - ActivityContainer activityContainer = - createActivityContainer(parentActivity, stackId, null); + ActivityContainer activityContainer = new ActivityContainer(stackId); + mActivityContainers.put(stackId, activityContainer); activityContainer.attachToDisplayLocked(activityDisplay); return stackId; } @@ -2334,9 +2305,9 @@ public final class ActivityStackSupervisor implements DisplayListener { } boolean shutdownLocked(int timeout) { - boolean timedout = false; goingToSleepLocked(); + boolean timedout = false; final long endTime = System.currentTimeMillis() + timeout; while (true) { boolean cantShutdown = false; @@ -3030,24 +3001,26 @@ public final class ActivityStackSupervisor implements DisplayListener { class ActivityContainer extends IActivityContainer.Stub { final int mStackId; - final IActivityContainerCallback mCallback; + IActivityContainerCallback mCallback = null; final ActivityStack mStack; - final ActivityRecord mParentActivity; - final String mIdString; + ActivityRecord mParentActivity = null; + String mIdString; boolean mVisible = true; /** Display this ActivityStack is currently on. Null if not attached to a Display. */ ActivityDisplay mActivityDisplay; - ActivityContainer(ActivityRecord parentActivity, int stackId, - IActivityContainerCallback callback) { + final static int CONTAINER_STATE_HAS_SURFACE = 0; + final static int CONTAINER_STATE_NO_SURFACE = 1; + final static int CONTAINER_STATE_FINISHING = 2; + int mContainerState = CONTAINER_STATE_HAS_SURFACE; + + ActivityContainer(int stackId) { synchronized (mService) { mStackId = stackId; mStack = new ActivityStack(this); - mParentActivity = parentActivity; - mCallback = callback; - mIdString = "ActivtyContainer{" + mStackId + ", parent=" + mParentActivity + "}"; + mIdString = "ActivtyContainer{" + mStackId + "}"; if (DEBUG_STACK) Slog.d(TAG, "Creating " + this); } } @@ -3097,6 +3070,14 @@ public final class ActivityStackSupervisor implements DisplayListener { } } + @Override + public void release() { + mContainerState = CONTAINER_STATE_FINISHING; + mStack.finishAllActivitiesLocked(); + detachLocked(); + mWindowManager.removeStack(mStackId); + } + private void detachLocked() { if (DEBUG_STACK) Slog.d(TAG, "detachLocked: " + this + " from display=" + mActivityDisplay + " Callers=" + Debug.getCallers(2)); @@ -3109,13 +3090,6 @@ public final class ActivityStackSupervisor implements DisplayListener { } } - @Override - public void detachFromDisplay() { - synchronized (mService) { - detachLocked(); - } - } - @Override public final int startActivity(Intent intent) { mService.enforceNotIsolatedCaller("ActivityContainer.startActivity"); @@ -3149,23 +3123,8 @@ public final class ActivityStackSupervisor implements DisplayListener { } @Override - public void attachToSurface(Surface surface, int width, int height, int density) { + public void setSurface(Surface surface, int width, int height, int density) { mService.enforceNotIsolatedCaller("ActivityContainer.attachToSurface"); - - final long origId = Binder.clearCallingIdentity(); - try { - synchronized (mService) { - ActivityDisplay activityDisplay = - new ActivityDisplay(surface, width, height, density); - mActivityDisplays.put(activityDisplay.mDisplayId, activityDisplay); - attachToDisplayLocked(activityDisplay); - mStack.resumeTopActivityLocked(null); - } - if (DEBUG_STACK) Slog.d(TAG, "attachToSurface: " + this + " to display=" - + mActivityDisplay); - } finally { - Binder.restoreCallingIdentity(origId); - } } ActivityStackSupervisor getOuter() { @@ -3200,46 +3159,87 @@ public final class ActivityStackSupervisor implements DisplayListener { } } + private class VirtualActivityContainer extends ActivityContainer { + Surface mSurface; + + VirtualActivityContainer(ActivityRecord parent, IActivityContainerCallback callback) { + super(getNextStackId()); + mParentActivity = parent; + mCallback = callback; + mContainerState = CONTAINER_STATE_NO_SURFACE; + mIdString = "VirtualActivtyContainer{" + mStackId + ", parent=" + mParentActivity + "}"; + } + + @Override + public void setSurface(Surface surface, int width, int height, int density) { + super.setSurface(surface, width, height, density); + + synchronized (mService) { + final long origId = Binder.clearCallingIdentity(); + try { + setSurfaceLocked(surface, width, height, density); + } finally { + Binder.restoreCallingIdentity(origId); + } + } + } + + private void setSurfaceLocked(Surface surface, int width, int height, int density) { + if (mContainerState == CONTAINER_STATE_FINISHING) { + return; + } + VirtualActivityDisplay virtualActivityDisplay = + (VirtualActivityDisplay) mActivityDisplay; + if (virtualActivityDisplay == null) { + virtualActivityDisplay = + new VirtualActivityDisplay(surface, width, height, density); + mActivityDisplay = virtualActivityDisplay; + mActivityDisplays.put(virtualActivityDisplay.mDisplayId, virtualActivityDisplay); + attachToDisplayLocked(virtualActivityDisplay); + } + + if (mSurface != null) { + mSurface.release(); + mSurface = null; + } + + if (surface != null) { + mContainerState = CONTAINER_STATE_HAS_SURFACE; + mSurface = surface; + mStack.resumeTopActivityLocked(null); + } else { + mContainerState = CONTAINER_STATE_NO_SURFACE; + if (mStack.mPausingActivity == null && mStack.mResumedActivity != null) { + mStack.startPausingLocked(false, true); + } + } + if (DEBUG_STACK) Slog.d(TAG, "setSurface: " + this + " to display=" + + virtualActivityDisplay); + + virtualActivityDisplay.setSurface(surface); + } + } + /** Exactly one of these classes per Display in the system. Capable of holding zero or more * attached {@link ActivityStack}s */ - final class ActivityDisplay { + class ActivityDisplay { /** Actual Display this object tracks. */ int mDisplayId; Display mDisplay; DisplayInfo mDisplayInfo = new DisplayInfo(); - Surface mSurface; /** All of the stacks on this display. Order matters, topmost stack is in front of all other * stacks, bottommost behind. Accessed directly by ActivityManager package classes */ final ArrayList mStacks = new ArrayList(); - /** If this display is for an ActivityView then the VirtualDisplay created for it is stored - * here. */ - VirtualDisplay mVirtualDisplay; + ActivityDisplay() { + } ActivityDisplay(int displayId) { init(mDisplayManager.getDisplay(displayId)); } - ActivityDisplay(Surface surface, int width, int height, int density) { - DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance(); - long ident = Binder.clearCallingIdentity(); - try { - mVirtualDisplay = dm.createVirtualDisplay(mService.mContext, - VIRTUAL_DISPLAY_BASE_NAME, width, height, density, surface, - DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC | - DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY); - } finally { - Binder.restoreCallingIdentity(ident); - } - - init(mVirtualDisplay.getDisplay()); - mSurface = surface; - - mWindowManager.handleDisplayAdded(mDisplayId); - } - - private void init(Display display) { + void init(Display display) { mDisplay = display; mDisplayId = display.getDisplayId(); mDisplay.getDisplayInfo(mDisplayInfo); @@ -3255,11 +3255,6 @@ public final class ActivityStackSupervisor implements DisplayListener { if (DEBUG_STACK) Slog.v(TAG, "detachActivitiesLocked: detaching " + stack + " from displayId=" + mDisplayId); mStacks.remove(stack); - if (mStacks.isEmpty() && mVirtualDisplay != null) { - mVirtualDisplay.release(); - mVirtualDisplay = null; - } - mSurface.release(); } void getBounds(Point bounds) { @@ -3270,8 +3265,42 @@ public final class ActivityStackSupervisor implements DisplayListener { @Override public String toString() { - return "ActivityDisplay={" + mDisplayId + (mVirtualDisplay == null ? "" : "V") - + " numStacks=" + mStacks.size() + "}"; + return "ActivityDisplay={" + mDisplayId + " numStacks=" + mStacks.size() + "}"; + } + } + + class VirtualActivityDisplay extends ActivityDisplay { + VirtualDisplay mVirtualDisplay; + + VirtualActivityDisplay(Surface surface, int width, int height, int density) { + DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance(); + mVirtualDisplay = dm.createVirtualDisplay(mService.mContext, VIRTUAL_DISPLAY_BASE_NAME, + width, height, density, surface, DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC | + DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY); + + init(mVirtualDisplay.getDisplay()); + + mWindowManager.handleDisplayAdded(mDisplayId); + } + + void setSurface(Surface surface) { + if (mVirtualDisplay != null) { + mVirtualDisplay.setSurface(surface); + } + } + + @Override + void detachActivitiesLocked(ActivityStack stack) { + super.detachActivitiesLocked(stack); + if (mVirtualDisplay != null) { + mVirtualDisplay.release(); + mVirtualDisplay = null; + } + } + + @Override + public String toString() { + return "VirtualActivityDisplay={" + mDisplayId + "}"; } } }