diff options
author | Dianne Hackborn <hackbod@google.com> | 2011-03-01 14:31:38 -0800 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2011-03-01 14:45:28 -0800 |
commit | ce418e661ab52a08a2a2c3b2f10a4dd9adf33305 (patch) | |
tree | 2a79f6d41e0edab908f20e6c03edafcf7c457436 | |
parent | 6c2193a7e26c0794f45dfb60d2a0cf6ae776f390 (diff) | |
download | frameworks_base-ce418e661ab52a08a2a2c3b2f10a4dd9adf33305.zip frameworks_base-ce418e661ab52a08a2a2c3b2f10a4dd9adf33305.tar.gz frameworks_base-ce418e661ab52a08a2a2c3b2f10a4dd9adf33305.tar.bz2 |
Fix issue #3495749: Crash on choosing to open the downloaded images
This is due to the window doing a relayout after its activity is
stopped, at which point it may need to interact with the adapter
to load data.
The fix here is to tell ViewRoot about an activity being stopped
and, if in this state, hold off on doing any new measurements and
layouts of the hierarchy until it is no longer stopped.
In this case the relayout was happening due to the cursor
being deactivated, with causes the adapter to invalidate
its data. Because this is now in a dialog window, this
allows the window to actually be resized smaller (unlike when
in a full screen activity), and boom.
Change-Id: I26442b4679819b4a4e6bc56289afd3445526750b
-rw-r--r-- | core/java/android/app/Activity.java | 8 | ||||
-rw-r--r-- | core/java/android/view/ViewRoot.java | 103 | ||||
-rw-r--r-- | core/java/android/view/WindowManagerImpl.java | 14 |
3 files changed, 81 insertions, 44 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 9e72c1b..210fd5d 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -66,6 +66,7 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; +import android.view.WindowManagerImpl; import android.view.View.OnCreateContextMenuListener; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; @@ -4401,6 +4402,9 @@ public class Activity extends ContextThemeWrapper if (mStopped) { mStopped = false; mCalled = false; + if (mToken != null && mParent == null) { + WindowManagerImpl.getDefault().setStoppedState(mToken, false); + } mInstrumentation.callActivityOnRestart(this); if (!mCalled) { throw new SuperNotCalledException( @@ -4477,6 +4481,10 @@ public class Activity extends ContextThemeWrapper mWindow.closeAllPanels(); } + if (mToken != null && mParent == null) { + WindowManagerImpl.getDefault().setStoppedState(mToken, true); + } + mFragments.dispatchStop(); mCalled = false; diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index c7b1955..965c959 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -155,6 +155,10 @@ public final class ViewRoot extends Handler implements ViewParent, int mViewVisibility; boolean mAppVisible = true; + // Set to true if the owner of this window is in the stopped state, + // so the window should no longer be active. + boolean mStopped = false; + SurfaceHolder.Callback2 mSurfaceHolderCallback; BaseSurfaceHolder mSurfaceHolder; boolean mIsCreating; @@ -618,6 +622,15 @@ public final class ViewRoot extends Handler implements ViewParent, scheduleTraversals(); } + void setStopped(boolean stopped) { + if (mStopped != stopped) { + mStopped = stopped; + if (!stopped) { + scheduleTraversals(); + } + } + } + public ViewParent getParent() { return null; } @@ -760,7 +773,7 @@ public final class ViewRoot extends Handler implements ViewParent, boolean insetsChanged = false; - if (mLayoutRequested) { + if (mLayoutRequested && !mStopped) { // Execute enqueued actions on every layout in case a view that was detached // enqueued an action after being detached getRunQueue().executeActions(attachInfo.mHandler); @@ -1143,54 +1156,56 @@ public final class ViewRoot extends Handler implements ViewParent, mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight); } - boolean focusChangedDueToTouchMode = ensureTouchModeLocally( - (relayoutResult&WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE) != 0); - if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth() - || mHeight != host.getMeasuredHeight() || contentInsetsChanged) { - childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width); - childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height); - - if (DEBUG_LAYOUT) Log.v(TAG, "Ooops, something changed! mWidth=" - + mWidth + " measuredWidth=" + host.getMeasuredWidth() - + " mHeight=" + mHeight - + " measuredHeight=" + host.getMeasuredHeight() - + " coveredInsetsChanged=" + contentInsetsChanged); - - // Ask host how big it wants to be - host.measure(childWidthMeasureSpec, childHeightMeasureSpec); - - // Implementation of weights from WindowManager.LayoutParams - // We just grow the dimensions as needed and re-measure if - // needs be - int width = host.getMeasuredWidth(); - int height = host.getMeasuredHeight(); - boolean measureAgain = false; - - if (lp.horizontalWeight > 0.0f) { - width += (int) ((mWidth - width) * lp.horizontalWeight); - childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width, - MeasureSpec.EXACTLY); - measureAgain = true; - } - if (lp.verticalWeight > 0.0f) { - height += (int) ((mHeight - height) * lp.verticalWeight); - childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, - MeasureSpec.EXACTLY); - measureAgain = true; - } - - if (measureAgain) { - if (DEBUG_LAYOUT) Log.v(TAG, - "And hey let's measure once more: width=" + width - + " height=" + height); + if (!mStopped) { + boolean focusChangedDueToTouchMode = ensureTouchModeLocally( + (relayoutResult&WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE) != 0); + if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth() + || mHeight != host.getMeasuredHeight() || contentInsetsChanged) { + childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width); + childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height); + + if (DEBUG_LAYOUT) Log.v(TAG, "Ooops, something changed! mWidth=" + + mWidth + " measuredWidth=" + host.getMeasuredWidth() + + " mHeight=" + mHeight + + " measuredHeight=" + host.getMeasuredHeight() + + " coveredInsetsChanged=" + contentInsetsChanged); + + // Ask host how big it wants to be host.measure(childWidthMeasureSpec, childHeightMeasureSpec); + + // Implementation of weights from WindowManager.LayoutParams + // We just grow the dimensions as needed and re-measure if + // needs be + int width = host.getMeasuredWidth(); + int height = host.getMeasuredHeight(); + boolean measureAgain = false; + + if (lp.horizontalWeight > 0.0f) { + width += (int) ((mWidth - width) * lp.horizontalWeight); + childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width, + MeasureSpec.EXACTLY); + measureAgain = true; + } + if (lp.verticalWeight > 0.0f) { + height += (int) ((mHeight - height) * lp.verticalWeight); + childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, + MeasureSpec.EXACTLY); + measureAgain = true; + } + + if (measureAgain) { + if (DEBUG_LAYOUT) Log.v(TAG, + "And hey let's measure once more: width=" + width + + " height=" + height); + host.measure(childWidthMeasureSpec, childHeightMeasureSpec); + } + + mLayoutRequested = true; } - - mLayoutRequested = true; } } - final boolean didLayout = mLayoutRequested; + final boolean didLayout = mLayoutRequested && !mStopped; boolean triggerGlobalLayoutListener = didLayout || attachInfo.mRecomputeGlobalAttributes; if (didLayout) { diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index 07953d6..a4c4544 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -302,6 +302,20 @@ public class WindowManagerImpl implements WindowManager { } } + public void setStoppedState(IBinder token, boolean stopped) { + synchronized (this) { + if (mViews == null) + return; + int count = mViews.length; + for (int i=0; i<count; i++) { + if (token == null || mParams[i].token == token) { + ViewRoot root = mRoots[i]; + root.setStopped(stopped); + } + } + } + } + public WindowManager.LayoutParams getRootViewLayoutParameter(View view) { ViewParent vp = view.getParent(); while (vp != null && !(vp instanceof ViewRoot)) { |