Cleanup after ActivityView
- Release Surface and VirtualDisplay when shutting down ActivityView.
- Shut down child stacks when relaunching parent activity.
Change-Id: I60314b2b43bd2da5406cf6ec871293b5baca157c
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index fef4597..25cde8c 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -24,6 +24,7 @@
import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.view.Surface;
import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener;
@@ -31,12 +32,15 @@
import android.view.WindowManager;
public class ActivityView extends ViewGroup {
+ private final String TAG = "ActivityView";
+
private final TextureView mTextureView;
private IActivityContainer mActivityContainer;
private Activity mActivity;
private boolean mAttached;
private int mWidth;
private int mHeight;
+ private Surface mSurface;
public ActivityView(Context context) {
this(context, null);
@@ -83,20 +87,18 @@
final SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
if (surfaceTexture != null) {
- createActivityView(surfaceTexture);
+ attachToSurface(surfaceTexture);
}
}
@Override
protected void onDetachedFromWindow() {
- if (mActivityContainer != null) {
- try {
- mActivityContainer.deleteActivityView();
- } catch (RemoteException e) {
- }
- mActivityContainer = null;
- }
- mAttached = false;
+ detachFromSurface();
+ }
+
+ @Override
+ public boolean isAttachedToWindow() {
+ return mAttached;
}
public void startActivity(Intent intent) {
@@ -110,22 +112,41 @@
}
/** Call when both mActivityContainer and mTextureView's SurfaceTexture are not null */
- private void createActivityView(SurfaceTexture surfaceTexture) {
+ private void attachToSurface(SurfaceTexture surfaceTexture) {
WindowManager wm = (WindowManager)mActivity.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metrics);
+ mSurface = new Surface(surfaceTexture);
try {
- mActivityContainer.createActivityView(new Surface(surfaceTexture), mWidth, mHeight,
+ mActivityContainer.attachToSurface(mSurface, mWidth, mHeight,
metrics.densityDpi);
} catch (RemoteException e) {
mActivityContainer = null;
+ mSurface.release();
+ mSurface = null;
+ mAttached = false;
throw new IllegalStateException(
"ActivityView: Unable to create ActivityContainer. " + e);
}
mAttached = true;
}
+ private void detachFromSurface() {
+ if (mActivityContainer != null) {
+ try {
+ mActivityContainer.detachFromDisplay();
+ } catch (RemoteException e) {
+ }
+ mActivityContainer = null;
+ }
+ if (mSurface != null) {
+ mSurface.release();
+ mSurface = null;
+ }
+ mAttached = false;
+ }
+
private class ActivityViewSurfaceTextureListener implements SurfaceTextureListener {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width,
@@ -133,30 +154,26 @@
mWidth = width;
mHeight = height;
if (mActivityContainer != null) {
- createActivityView(surfaceTexture);
+ attachToSurface(surfaceTexture);
}
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width,
int height) {
+ Log.d(TAG, "onSurfaceTextureSizeChanged: w=" + width + " h=" + height);
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
- try {
- mActivityContainer.deleteActivityView();
- // TODO: Add binderDied to handle this nullification.
- mActivityContainer = null;
- } catch (RemoteException r) {
- }
- mAttached = false;
- return false;
+ Log.d(TAG, "onSurfaceTextureDestroyed");
+ detachFromSurface();
+ return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
-
+// Log.d(TAG, "onSurfaceTextureUpdated");
}
}
diff --git a/core/java/android/app/IActivityContainer.aidl b/core/java/android/app/IActivityContainer.aidl
index b03a459..df1cf91 100644
--- a/core/java/android/app/IActivityContainer.aidl
+++ b/core/java/android/app/IActivityContainer.aidl
@@ -24,9 +24,8 @@
/** @hide */
interface IActivityContainer {
void attachToDisplay(int displayId);
- int getDisplayId();
+ void attachToSurface(in Surface surface, int width, int height, int density);
void detachFromDisplay();
int startActivity(in Intent intent);
- void createActivityView(in Surface surface, int width, int height, int density);
- void deleteActivityView();
+ int getDisplayId();
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 600cc58..c9d6222 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -322,7 +322,7 @@
}
}
- private int numActivities() {
+ int numActivities() {
int count = 0;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
count += mTaskHistory.get(taskNdx).mActivities.size();
@@ -2675,6 +2675,7 @@
}
private void removeActivityFromHistoryLocked(ActivityRecord r) {
+ mStackSupervisor.removeChildActivityContainers(r);
finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
r.makeFinishing();
if (DEBUG_ADD_REMOVE) {
@@ -3318,6 +3319,8 @@
r.startFreezingScreenLocked(r.app, 0);
+ mStackSupervisor.removeChildActivityContainers(r);
+
try {
if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
(andResume ? "Relaunching to RESUMED " : "Relaunching to PAUSED ")
@@ -3350,14 +3353,20 @@
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = activities.get(activityNdx);
if (r.appToken == token) {
- return true;
+ return true;
}
if (r.fullscreen && !r.finishing) {
return false;
}
}
}
- return true;
+ final ActivityRecord r = ActivityRecord.forToken(token);
+ if (r == null) {
+ return false;
+ }
+ if (r.finishing) Slog.e(TAG, "willActivityBeVisibleLocked: Returning false,"
+ + " would have returned true for r=" + r);
+ return !r.finishing;
}
void closeSystemDialogsLocked() {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 7acca84..c31669d 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -417,11 +417,13 @@
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
- if (!isFrontStack(stack)) {
+ if (!isFrontStack(stack) || stack.numActivities() == 0) {
continue;
}
final ActivityRecord resumedActivity = stack.mResumedActivity;
if (resumedActivity == null || !resumedActivity.idle) {
+ if (DEBUG_STATES) Slog.d(TAG, "allResumedActivitiesIdle: stack="
+ + stack.mStackId + " " + resumedActivity + " not idle");
return false;
}
}
@@ -2130,6 +2132,28 @@
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 removal");
+ }
+ mActivityContainers.removeAt(ndx);
+ container.detachLocked();
+ }
+ }
+
private int createStackOnDisplay(ActivityRecord parentActivity, int stackId, int displayId) {
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
if (activityDisplay == null) {
@@ -2683,7 +2707,9 @@
}
final void scheduleResumeTopActivities() {
- mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
+ if (!mHandler.hasMessages(RESUME_TOP_ACTIVITY_MSG)) {
+ mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
+ }
}
void removeSleepTimeouts() {
@@ -2731,7 +2757,7 @@
if (activityDisplay != null) {
ArrayList<ActivityStack> stacks = activityDisplay.mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- activityDisplay.detachActivitiesLocked(stacks.get(stackNdx));
+ stacks.get(stackNdx).mActivityContainer.detachLocked();
}
mActivityDisplays.remove(displayId);
}
@@ -2872,6 +2898,7 @@
final IActivityContainerCallback mCallback;
final ActivityStack mStack;
final ActivityRecord mParentActivity;
+ final String mIdString;
/** Display this ActivityStack is currently on. Null if not attached to a Display. */
ActivityDisplay mActivityDisplay;
@@ -2883,10 +2910,14 @@
mStack = new ActivityStack(this);
mParentActivity = parentActivity;
mCallback = callback;
+ mIdString = "ActivtyContainer{" + mStackId + ", parent=" + mParentActivity + "}";
+ if (DEBUG_STACK) Slog.d(TAG, "Creating " + this);
}
}
void attachToDisplayLocked(ActivityDisplay activityDisplay) {
+ if (DEBUG_STACK) Slog.d(TAG, "attachToDisplayLocked: " + this
+ + " to display=" + activityDisplay);
mActivityDisplay = activityDisplay;
mStack.mDisplayId = activityDisplay.mDisplayId;
mStack.mStacks = activityDisplay.mStacks;
@@ -2914,7 +2945,9 @@
return -1;
}
- void detachLocked() {
+ private void detachLocked() {
+ if (DEBUG_STACK) Slog.d(TAG, "detachLocked: " + this + " from display="
+ + mActivityDisplay + " Callers=" + Debug.getCallers(2));
if (mActivityDisplay != null) {
mActivityDisplay.detachActivitiesLocked(mStack);
mActivityDisplay = null;
@@ -2951,45 +2984,15 @@
}
@Override
- public void createActivityView(Surface surface, int width, int height, int density) {
- DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
- VirtualDisplay virtualDisplay;
- long ident = Binder.clearCallingIdentity();
- try {
- virtualDisplay = 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);
- }
-
- final Display display = virtualDisplay.getDisplay();
- final int displayId = display.getDisplayId();
-
- mWindowManager.handleDisplayAdded(displayId);
-
+ public void attachToSurface(Surface surface, int width, int height, int density) {
synchronized (mService) {
- ActivityDisplay activityDisplay = new ActivityDisplay(display);
- mActivityDisplays.put(displayId, activityDisplay);
+ ActivityDisplay activityDisplay =
+ new ActivityDisplay(surface, width, height, density);
+ mActivityDisplays.put(activityDisplay.mDisplayId, activityDisplay);
attachToDisplayLocked(activityDisplay);
- activityDisplay.mVirtualDisplay = virtualDisplay;
}
- }
-
- @Override
- public void deleteActivityView() {
- synchronized (mService) {
- if (!isAttached()) {
- return;
- }
- VirtualDisplay virtualDisplay = mActivityDisplay.mVirtualDisplay;
- if (virtualDisplay != null) {
- virtualDisplay.release();
- mActivityDisplay.mVirtualDisplay = null;
- }
- detachLocked();
- }
+ if (DEBUG_STACK) Slog.d(TAG, "attachToSurface: " + this + " to display="
+ + mActivityDisplay);
}
ActivityStackSupervisor getOuter() {
@@ -3007,15 +3010,21 @@
outBounds.set(0, 0);
}
}
+
+ @Override
+ public String toString() {
+ return mIdString + (mActivityDisplay == null ? "N" : "A");
+ }
}
/** Exactly one of these classes per Display in the system. Capable of holding zero or more
* attached {@link ActivityStack}s */
final class ActivityDisplay {
/** Actual Display this object tracks. */
- final int mDisplayId;
- final Display mDisplay;
- final DisplayInfo mDisplayInfo = new DisplayInfo();
+ 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 */
@@ -3026,10 +3035,32 @@
VirtualDisplay mVirtualDisplay;
ActivityDisplay(int displayId) {
- this(mDisplayManager.getDisplay(displayId));
+ init(mDisplayManager.getDisplay(displayId));
}
ActivityDisplay(Display display) {
+ init(display);
+ }
+
+ 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) {
mDisplay = display;
mDisplayId = display.getDisplayId();
mDisplay.getDisplayInfo(mDisplayInfo);
@@ -3042,9 +3073,14 @@
}
void detachActivitiesLocked(ActivityStack stack) {
- if (DEBUG_STACK) Slog.v(TAG, "attachActivities: detaching " + stack
+ 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) {
@@ -3052,5 +3088,11 @@
bounds.x = mDisplayInfo.appWidth;
bounds.y = mDisplayInfo.appHeight;
}
+
+ @Override
+ public String toString() {
+ return "ActivityDisplay={" + mDisplayId + (mVirtualDisplay == null ? "" : "V")
+ + " numStacks=" + mStacks.size() + "}";
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 6e66d83..9be5347 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -18,8 +18,6 @@
import static android.view.WindowManager.LayoutParams.*;
-import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
-
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import android.app.AppOpsManager;
@@ -3622,7 +3620,7 @@
if (freezeThisOneIfNeeded != null) {
AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded);
if (atoken != null) {
- startAppFreezingScreenLocked(atoken, ActivityInfo.CONFIG_ORIENTATION);
+ startAppFreezingScreenLocked(atoken);
}
}
config = computeNewConfigurationLocked();
@@ -4395,8 +4393,7 @@
}
}
- public void startAppFreezingScreenLocked(AppWindowToken wtoken,
- int configChanges) {
+ private void startAppFreezingScreenLocked(AppWindowToken wtoken) {
if (DEBUG_ORIENTATION) {
RuntimeException e = null;
if (!HIDE_STACK_CRAWLS) {
@@ -4445,7 +4442,7 @@
return;
}
final long origId = Binder.clearCallingIdentity();
- startAppFreezingScreenLocked(wtoken, configChanges);
+ startAppFreezingScreenLocked(wtoken);
Binder.restoreCallingIdentity(origId);
}
}
@@ -8313,8 +8310,7 @@
// it frozen/off until this window draws at its new
// orientation.
if (!okToDisplay()) {
- if (DEBUG_ORIENTATION) Slog.v(TAG,
- "Changing surface while display frozen: " + w);
+ if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w);
w.mOrientationChanging = true;
w.mLastFreezeDuration = 0;
mInnerFields.mOrientationChangeComplete = false;