summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2012-09-27 00:53:39 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-09-27 00:54:55 -0700
commit66442c7e7b86d0fb45e02b32b8750ed06b93ef06 (patch)
tree2a9cde0674ab065c5d31ec24caaf5fd90c8fb510
parent2480bc12a525a55ebff453dbf6ca95258b9f23cf (diff)
parentf43a33c5ea5adb8d100ab0c3da965bac33155cb8 (diff)
downloadframeworks_base-66442c7e7b86d0fb45e02b32b8750ed06b93ef06.zip
frameworks_base-66442c7e7b86d0fb45e02b32b8750ed06b93ef06.tar.gz
frameworks_base-66442c7e7b86d0fb45e02b32b8750ed06b93ef06.tar.bz2
Merge "Work on issue #7232641: ISE crash when rotating phone in label list mode" into jb-mr1-dev
-rw-r--r--core/java/android/app/BackStackRecord.java158
-rw-r--r--core/java/android/app/FragmentManager.java40
2 files changed, 137 insertions, 61 deletions
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 96814b7..1b1d341 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -20,6 +20,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Log;
+import android.util.LogWriter;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -94,11 +95,12 @@ final class BackStackState implements Parcelable {
public BackStackRecord instantiate(FragmentManagerImpl fm) {
BackStackRecord bse = new BackStackRecord(fm);
int pos = 0;
+ int num = 0;
while (pos < mOps.length) {
BackStackRecord.Op op = new BackStackRecord.Op();
op.cmd = mOps[pos++];
if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG,
- "BSE " + bse + " set base fragment #" + mOps[pos]);
+ "Instantiate " + bse + " op #" + num + " base fragment #" + mOps[pos]);
int findex = mOps[pos++];
if (findex >= 0) {
Fragment f = fm.mActive.get(findex);
@@ -115,12 +117,13 @@ final class BackStackState implements Parcelable {
op.removed = new ArrayList<Fragment>(N);
for (int i=0; i<N; i++) {
if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG,
- "BSE " + bse + " set remove fragment #" + mOps[pos]);
+ "Instantiate " + bse + " set remove fragment #" + mOps[pos]);
Fragment r = fm.mActive.get(mOps[pos++]);
op.removed.add(r);
}
}
bse.addOp(op);
+ num++;
}
bse.mTransition = mTransition;
bse.mTransitionStyle = mTransitionStyle;
@@ -168,7 +171,7 @@ final class BackStackState implements Parcelable {
*/
final class BackStackRecord extends FragmentTransaction implements
FragmentManager.BackStackEntry, Runnable {
- static final String TAG = "BackStackEntry";
+ static final String TAG = FragmentManagerImpl.TAG;
final FragmentManagerImpl mManager;
@@ -206,46 +209,69 @@ final class BackStackRecord extends FragmentTransaction implements
boolean mAllowAddToBackStack = true;
String mName;
boolean mCommitted;
- int mIndex;
+ int mIndex = -1;
int mBreadCrumbTitleRes;
CharSequence mBreadCrumbTitleText;
int mBreadCrumbShortTitleRes;
CharSequence mBreadCrumbShortTitleText;
- public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
- writer.print(prefix); writer.print("mName="); writer.print(mName);
- writer.print(" mIndex="); writer.print(mIndex);
- writer.print(" mCommitted="); writer.println(mCommitted);
- if (mTransition != FragmentTransaction.TRANSIT_NONE) {
- writer.print(prefix); writer.print("mTransition=#");
- writer.print(Integer.toHexString(mTransition));
- writer.print(" mTransitionStyle=#");
- writer.println(Integer.toHexString(mTransitionStyle));
- }
- if (mEnterAnim != 0 || mExitAnim !=0) {
- writer.print(prefix); writer.print("mEnterAnim=#");
- writer.print(Integer.toHexString(mEnterAnim));
- writer.print(" mExitAnim=#");
- writer.println(Integer.toHexString(mExitAnim));
- }
- if (mPopEnterAnim != 0 || mPopExitAnim !=0) {
- writer.print(prefix); writer.print("mPopEnterAnim=#");
- writer.print(Integer.toHexString(mPopEnterAnim));
- writer.print(" mPopExitAnim=#");
- writer.println(Integer.toHexString(mPopExitAnim));
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("BackStackEntry{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ if (mIndex >= 0) {
+ sb.append(" #");
+ sb.append(mIndex);
}
- if (mBreadCrumbTitleRes != 0 || mBreadCrumbTitleText != null) {
- writer.print(prefix); writer.print("mBreadCrumbTitleRes=#");
- writer.print(Integer.toHexString(mBreadCrumbTitleRes));
- writer.print(" mBreadCrumbTitleText=");
- writer.println(mBreadCrumbTitleText);
+ if (mName != null) {
+ sb.append(" ");
+ sb.append(mName);
}
- if (mBreadCrumbShortTitleRes != 0 || mBreadCrumbShortTitleText != null) {
- writer.print(prefix); writer.print("mBreadCrumbShortTitleRes=#");
- writer.print(Integer.toHexString(mBreadCrumbShortTitleRes));
- writer.print(" mBreadCrumbShortTitleText=");
- writer.println(mBreadCrumbShortTitleText);
+ sb.append("}");
+ return sb.toString();
+ }
+
+ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ dump(prefix, writer, true);
+ }
+
+ void dump(String prefix, PrintWriter writer, boolean full) {
+ if (full) {
+ writer.print(prefix); writer.print("mName="); writer.print(mName);
+ writer.print(" mIndex="); writer.print(mIndex);
+ writer.print(" mCommitted="); writer.println(mCommitted);
+ if (mTransition != FragmentTransaction.TRANSIT_NONE) {
+ writer.print(prefix); writer.print("mTransition=#");
+ writer.print(Integer.toHexString(mTransition));
+ writer.print(" mTransitionStyle=#");
+ writer.println(Integer.toHexString(mTransitionStyle));
+ }
+ if (mEnterAnim != 0 || mExitAnim !=0) {
+ writer.print(prefix); writer.print("mEnterAnim=#");
+ writer.print(Integer.toHexString(mEnterAnim));
+ writer.print(" mExitAnim=#");
+ writer.println(Integer.toHexString(mExitAnim));
+ }
+ if (mPopEnterAnim != 0 || mPopExitAnim !=0) {
+ writer.print(prefix); writer.print("mPopEnterAnim=#");
+ writer.print(Integer.toHexString(mPopEnterAnim));
+ writer.print(" mPopExitAnim=#");
+ writer.println(Integer.toHexString(mPopExitAnim));
+ }
+ if (mBreadCrumbTitleRes != 0 || mBreadCrumbTitleText != null) {
+ writer.print(prefix); writer.print("mBreadCrumbTitleRes=#");
+ writer.print(Integer.toHexString(mBreadCrumbTitleRes));
+ writer.print(" mBreadCrumbTitleText=");
+ writer.println(mBreadCrumbTitleText);
+ }
+ if (mBreadCrumbShortTitleRes != 0 || mBreadCrumbShortTitleText != null) {
+ writer.print(prefix); writer.print("mBreadCrumbShortTitleRes=#");
+ writer.print(Integer.toHexString(mBreadCrumbShortTitleRes));
+ writer.print(" mBreadCrumbShortTitleText=");
+ writer.println(mBreadCrumbShortTitleText);
+ }
}
if (mHead != null) {
@@ -254,21 +280,34 @@ final class BackStackRecord extends FragmentTransaction implements
Op op = mHead;
int num = 0;
while (op != null) {
- writer.print(prefix); writer.print(" Op #"); writer.print(num);
- writer.println(":");
- writer.print(innerPrefix); writer.print("cmd="); writer.print(op.cmd);
- writer.print(" fragment="); writer.println(op.fragment);
- if (op.enterAnim != 0 || op.exitAnim != 0) {
- writer.print(prefix); writer.print("enterAnim=#");
- writer.print(Integer.toHexString(op.enterAnim));
- writer.print(" exitAnim=#");
- writer.println(Integer.toHexString(op.exitAnim));
+ String cmdStr;
+ switch (op.cmd) {
+ case OP_NULL: cmdStr="NULL"; break;
+ case OP_ADD: cmdStr="ADD"; break;
+ case OP_REPLACE: cmdStr="REPLACE"; break;
+ case OP_REMOVE: cmdStr="REMOVE"; break;
+ case OP_HIDE: cmdStr="HIDE"; break;
+ case OP_SHOW: cmdStr="SHOW"; break;
+ case OP_DETACH: cmdStr="DETACH"; break;
+ case OP_ATTACH: cmdStr="ATTACH"; break;
+ default: cmdStr="cmd=" + op.cmd; break;
}
- if (op.popEnterAnim != 0 || op.popExitAnim != 0) {
- writer.print(prefix); writer.print("popEnterAnim=#");
- writer.print(Integer.toHexString(op.popEnterAnim));
- writer.print(" popExitAnim=#");
- writer.println(Integer.toHexString(op.popExitAnim));
+ writer.print(prefix); writer.print(" Op #"); writer.print(num);
+ writer.print(": "); writer.print(cmdStr);
+ writer.print(" "); writer.println(op.fragment);
+ if (full) {
+ if (op.enterAnim != 0 || op.exitAnim != 0) {
+ writer.print(innerPrefix); writer.print("enterAnim=#");
+ writer.print(Integer.toHexString(op.enterAnim));
+ writer.print(" exitAnim=#");
+ writer.println(Integer.toHexString(op.exitAnim));
+ }
+ if (op.popEnterAnim != 0 || op.popExitAnim != 0) {
+ writer.print(innerPrefix); writer.print("popEnterAnim=#");
+ writer.print(Integer.toHexString(op.popEnterAnim));
+ writer.print(" popExitAnim=#");
+ writer.println(Integer.toHexString(op.popExitAnim));
+ }
}
if (op.removed != null && op.removed.size() > 0) {
for (int i=0; i<op.removed.size(); i++) {
@@ -276,14 +315,17 @@ final class BackStackRecord extends FragmentTransaction implements
if (op.removed.size() == 1) {
writer.print("Removed: ");
} else {
- writer.println("Removed:");
- writer.print(innerPrefix); writer.print(" #"); writer.print(num);
+ if (i == 0) {
+ writer.println("Removed:");
+ }
+ writer.print(innerPrefix); writer.print(" #"); writer.print(i);
writer.print(": ");
}
writer.println(op.removed.get(i));
}
}
op = op.next;
+ num++;
}
}
}
@@ -538,7 +580,12 @@ final class BackStackRecord extends FragmentTransaction implements
int commitInternal(boolean allowStateLoss) {
if (mCommitted) throw new IllegalStateException("commit already called");
- if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Commit: " + this);
+ if (FragmentManagerImpl.DEBUG) {
+ Log.v(TAG, "Commit: " + this);
+ LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
+ PrintWriter pw = new PrintWriter(logw);
+ dump(" ", null, pw, null);
+ }
mCommitted = true;
if (mAddToBackStack) {
mIndex = mManager.allocBackStackIndex(this);
@@ -641,7 +688,12 @@ final class BackStackRecord extends FragmentTransaction implements
}
public void popFromBackStack(boolean doStateMove) {
- if (FragmentManagerImpl.DEBUG) Log.v(TAG, "popFromBackStack: " + this);
+ if (FragmentManagerImpl.DEBUG) {
+ Log.v(TAG, "popFromBackStack: " + this);
+ LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
+ PrintWriter pw = new PrintWriter(logw);
+ dump(" ", null, pw, null);
+ }
bumpBackStackNesting(-1);
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index aad5487..e983299 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -22,6 +22,7 @@ import android.animation.AnimatorListenerAdapter;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.os.Bundle;
+import android.os.Debug;
import android.os.Handler;
import android.os.Looper;
import android.os.Parcel;
@@ -771,9 +772,9 @@ final class FragmentManagerImpl extends FragmentManager {
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
- //if (DEBUG) Log.v(TAG, "moveToState: " + f
- // + " oldState=" + f.mState + " newState=" + newState
- // + " mRemoving=" + f.mRemoving + " Callers=" + Debug.getCallers(5));
+ if (DEBUG && false) Log.v(TAG, "moveToState: " + f
+ + " oldState=" + f.mState + " newState=" + newState
+ + " mRemoving=" + f.mRemoving + " Callers=" + Debug.getCallers(5));
// Fragments that are not currently added will sit in the onCreate() state.
if ((!f.mAdded || f.mDetached) && newState > Fragment.CREATED) {
@@ -1112,6 +1113,9 @@ final class FragmentManagerImpl extends FragmentManager {
if (DEBUG) Log.v(TAG, "add: " + fragment);
makeActive(fragment);
if (!fragment.mDetached) {
+ if (mAdded.contains(fragment)) {
+ throw new IllegalStateException("Fragment already added: " + fragment);
+ }
mAdded.add(fragment);
fragment.mAdded = true;
fragment.mRemoving = false;
@@ -1128,6 +1132,14 @@ final class FragmentManagerImpl extends FragmentManager {
if (DEBUG) Log.v(TAG, "remove: " + fragment + " nesting=" + fragment.mBackStackNesting);
final boolean inactive = !fragment.isInBackStack();
if (!fragment.mDetached || inactive) {
+ if (false) {
+ // Would be nice to catch a bad remove here, but we need
+ // time to test this to make sure we aren't crashes cases
+ // where it is not a problem.
+ if (!mAdded.contains(fragment)) {
+ throw new IllegalStateException("Fragment not added: " + fragment);
+ }
+ }
if (mAdded != null) {
mAdded.remove(fragment);
}
@@ -1200,6 +1212,7 @@ final class FragmentManagerImpl extends FragmentManager {
if (fragment.mAdded) {
// We are not already in back stack, so need to remove the fragment.
if (mAdded != null) {
+ if (DEBUG) Log.v(TAG, "remove from detach: " + fragment);
mAdded.remove(fragment);
}
if (fragment.mHasMenu && fragment.mMenuVisible) {
@@ -1219,6 +1232,10 @@ final class FragmentManagerImpl extends FragmentManager {
if (mAdded == null) {
mAdded = new ArrayList<Fragment>();
}
+ if (mAdded.contains(fragment)) {
+ throw new IllegalStateException("Fragment already added: " + fragment);
+ }
+ if (DEBUG) Log.v(TAG, "add from attach: " + fragment);
mAdded.add(fragment);
fragment.mAdded = true;
if (fragment.mHasMenu && fragment.mMenuVisible) {
@@ -1717,19 +1734,18 @@ final class FragmentManagerImpl extends FragmentManager {
FragmentState fs = fms.mActive[i];
if (fs != null) {
Fragment f = fs.instantiate(mActivity, mParent);
- if (DEBUG) Log.v(TAG, "restoreAllState: adding #" + i + ": " + f);
+ if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f);
mActive.add(f);
// Now that the fragment is instantiated (or came from being
// retained above), clear mInstance in case we end up re-restoring
// from this FragmentState again.
fs.mInstance = null;
} else {
- if (DEBUG) Log.v(TAG, "restoreAllState: adding #" + i + ": (null)");
mActive.add(null);
if (mAvailIndices == null) {
mAvailIndices = new ArrayList<Integer>();
}
- if (DEBUG) Log.v(TAG, "restoreAllState: adding avail #" + i);
+ if (DEBUG) Log.v(TAG, "restoreAllState: avail #" + i);
mAvailIndices.add(i);
}
}
@@ -1760,7 +1776,10 @@ final class FragmentManagerImpl extends FragmentManager {
"No instantiated fragment for index #" + fms.mAdded[i]));
}
f.mAdded = true;
- if (DEBUG) Log.v(TAG, "restoreAllState: making added #" + i + ": " + f);
+ if (DEBUG) Log.v(TAG, "restoreAllState: added #" + i + ": " + f);
+ if (mAdded.contains(f)) {
+ throw new IllegalStateException("Already added!");
+ }
mAdded.add(f);
}
} else {
@@ -1772,8 +1791,13 @@ final class FragmentManagerImpl extends FragmentManager {
mBackStack = new ArrayList<BackStackRecord>(fms.mBackStack.length);
for (int i=0; i<fms.mBackStack.length; i++) {
BackStackRecord bse = fms.mBackStack[i].instantiate(this);
- if (DEBUG) Log.v(TAG, "restoreAllState: adding bse #" + i
+ if (DEBUG) {
+ Log.v(TAG, "restoreAllState: back stack #" + i
+ " (index " + bse.mIndex + "): " + bse);
+ LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
+ PrintWriter pw = new PrintWriter(logw);
+ bse.dump(" ", pw, false);
+ }
mBackStack.add(bse);
if (bse.mIndex >= 0) {
setBackStackIndex(bse.mIndex, bse);