diff options
author | Craig Mautner <cmautner@google.com> | 2014-04-17 18:39:38 -0700 |
---|---|---|
committer | Craig Mautner <cmautner@google.com> | 2014-04-21 15:28:42 -0700 |
commit | f4c909bcb87d6f103c9f9e8255fa61bd86f4de67 (patch) | |
tree | 4bda1df837e743ddf10e33424de390571603907e | |
parent | 72eec7f6c9509fb86f46fbdb619523efacb8d02e (diff) | |
download | frameworks_base-f4c909bcb87d6f103c9f9e8255fa61bd86f4de67.zip frameworks_base-f4c909bcb87d6f103c9f9e8255fa61bd86f4de67.tar.gz frameworks_base-f4c909bcb87d6f103c9f9e8255fa61bd86f4de67.tar.bz2 |
Fix ActivityView lifecycle
Major changes to maintain the VirtualDisplay across repeated
attach/detach cycles of an ActivityView. This keeps the activities
and VirtualDisplays in the ActivityView from getting into bad states.
Fixes bug 14107002.
Change-Id: Idc2aaf85ac496eab0eeb436736cb10a2020040e8
6 files changed, 262 insertions, 194 deletions
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java index 51cb12a..a4ea17b 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,60 +80,30 @@ public class ActivityView extends ViewGroup { throw new IllegalStateException("The ActivityView's Context is not an Activity."); } - mTextureView = new TextureView(context); - mTextureView.setSurfaceTextureListener(new ActivityViewSurfaceTextureListener()); - addView(mTextureView); - if (DEBUG) Log.v(TAG, "ctor()"); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - 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()); + mActivityContainer = ActivityManagerNative.getDefault().createActivityContainer( + mActivity.getActivityToken(), new ActivityContainerCallback(this)); } catch (RemoteException e) { throw new IllegalStateException("ActivityView: Unable to create ActivityContainer. " + e); } - attachToSurfaceWhenReady(); - } + mTextureView = new TextureView(context); + mTextureView.setSurfaceTextureListener(new ActivityViewSurfaceTextureListener()); + addView(mTextureView); - @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; - } + WindowManager wm = (WindowManager)mActivity.getSystemService(Context.WINDOW_SERVICE); + mMetrics = new DisplayMetrics(); + wm.getDefaultDisplay().getMetrics(mMetrics); + + mGuard.open("release"); + + if (DEBUG) Log.v(TAG, "ctor()"); } @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; - } + protected void onLayout(boolean changed, int l, int t, int r, int b) { + mTextureView.layout(0, 0, r - l, b - t); } private boolean injectInputEvent(InputEvent 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<ActivityView> mActivityViewWeakReference; + + ActivityContainerCallback(ActivityView activityView) { + mActivityViewWeakReference = new WeakReference<ActivityView>(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 5b80e06..cc3b10c 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 98cbe7d..d09ee96 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -7078,6 +7078,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 a27288a..5a9e690 100644 --- 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<ActivityStack> mChildContainers = new ArrayList<ActivityStack>(); + ArrayList<ActivityContainer> mChildContainers = new ArrayList<ActivityContainer>(); 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 42e1a37..f4f39e2 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; @@ -1028,9 +1030,9 @@ final class ActivityStack { private void setVisibile(ActivityRecord r, boolean visible) { r.visible = visible; mWindowManager.setAppVisibility(r.appToken, visible); - final ArrayList<ActivityStack> containers = r.mChildContainers; + final ArrayList<ActivityContainer> 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); } } @@ -1271,7 +1273,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; @@ -2552,6 +2555,20 @@ final class ActivityStack { return r; } + void finishAllActivitiesLocked() { + for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { + final ArrayList<ActivityRecord> 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); @@ -2787,7 +2804,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 efa3ad49..a316336 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -95,7 +95,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; @@ -224,11 +223,11 @@ public final class ActivityStackSupervisor implements DisplayListener { // TODO: Add listener for removal of references. /** Mapping from (ActivityStack/TaskStack).mStackId to their current state */ - SparseArray<WeakReference<ActivityContainer>> mActivityContainers = - new SparseArray<WeakReference<ActivityContainer>>(); + SparseArray<ActivityContainer> mActivityContainers = new SparseArray<ActivityContainer>(); /** Mapping from displayId to display current state */ - private SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<ActivityDisplay>(); + private final SparseArray<ActivityDisplay> mActivityDisplays = + new SparseArray<ActivityDisplay>(); InputManagerInternal mInputManagerInternal; @@ -260,7 +259,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); @@ -1378,7 +1377,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); @@ -2127,14 +2126,9 @@ public final class ActivityStackSupervisor implements DisplayListener { } ActivityStack getStack(int stackId) { - WeakReference<ActivityContainer> 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; } @@ -2164,49 +2158,26 @@ public final class ActivityStackSupervisor implements DisplayListener { return null; } - ActivityContainer createActivityContainer(ActivityRecord parentActivity, int stackId, - IActivityContainerCallback callback) { - ActivityContainer activityContainer = new ActivityContainer(parentActivity, stackId, - callback); - mActivityContainers.put(stackId, new WeakReference<ActivityContainer>(activityContainer)); - if (parentActivity != null) { - parentActivity.mChildContainers.add(activityContainer.mStack); - } - return activityContainer; - } - ActivityContainer createActivityContainer(ActivityRecord parentActivity, IActivityContainerCallback callback) { - return createActivityContainer(parentActivity, getNextStackId(), callback); + ActivityContainer activityContainer = new VirtualActivityContainer(parentActivity, callback); + mActivityContainers.put(activityContainer.mStackId, activityContainer); + parentActivity.mChildContainers.add(activityContainer); + return activityContainer; } 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<ActivityContainer> 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); @@ -2217,14 +2188,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; } @@ -2306,9 +2277,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; @@ -2967,24 +2938,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); } } @@ -3034,6 +3007,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)); @@ -3047,13 +3028,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"); int userId = mService.handleIncomingUser(Binder.getCallingPid(), @@ -3086,23 +3060,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() { @@ -3137,46 +3096,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<ActivityStack> mStacks = new ArrayList<ActivityStack>(); - /** 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); @@ -3192,11 +3192,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) { @@ -3207,8 +3202,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 + "}"; } } } |