summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCraig Mautner <cmautner@google.com>2014-04-17 18:39:38 -0700
committerCraig Mautner <cmautner@google.com>2014-04-21 15:28:42 -0700
commitf4c909bcb87d6f103c9f9e8255fa61bd86f4de67 (patch)
tree4bda1df837e743ddf10e33424de390571603907e
parent72eec7f6c9509fb86f46fbdb619523efacb8d02e (diff)
downloadframeworks_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
-rw-r--r--core/java/android/app/ActivityView.java170
-rw-r--r--core/java/android/app/IActivityContainer.aidl4
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java3
-rw-r--r--services/core/java/com/android/server/am/ActivityRecord.java2
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityStack.java24
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java253
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 + "}";
}
}
}