1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.support.v4.app; 18 19import android.os.Parcel; 20import android.os.Parcelable; 21import android.text.TextUtils; 22import android.util.Log; 23 24import java.io.FileDescriptor; 25import java.io.PrintWriter; 26import java.util.ArrayList; 27 28final class BackStackState implements Parcelable { 29 final int[] mOps; 30 final int mTransition; 31 final int mTransitionStyle; 32 final String mName; 33 final int mIndex; 34 final int mBreadCrumbTitleRes; 35 final CharSequence mBreadCrumbTitleText; 36 final int mBreadCrumbShortTitleRes; 37 final CharSequence mBreadCrumbShortTitleText; 38 39 public BackStackState(FragmentManagerImpl fm, BackStackRecord bse) { 40 int numRemoved = 0; 41 BackStackRecord.Op op = bse.mHead; 42 while (op != null) { 43 if (op.removed != null) numRemoved += op.removed.size(); 44 op = op.next; 45 } 46 mOps = new int[bse.mNumOp*7 + numRemoved]; 47 48 if (!bse.mAddToBackStack) { 49 throw new IllegalStateException("Not on back stack"); 50 } 51 52 op = bse.mHead; 53 int pos = 0; 54 while (op != null) { 55 mOps[pos++] = op.cmd; 56 mOps[pos++] = op.fragment.mIndex; 57 mOps[pos++] = op.enterAnim; 58 mOps[pos++] = op.exitAnim; 59 mOps[pos++] = op.popEnterAnim; 60 mOps[pos++] = op.popExitAnim; 61 if (op.removed != null) { 62 final int N = op.removed.size(); 63 mOps[pos++] = N; 64 for (int i=0; i<N; i++) { 65 mOps[pos++] = op.removed.get(i).mIndex; 66 } 67 } else { 68 mOps[pos++] = 0; 69 } 70 op = op.next; 71 } 72 mTransition = bse.mTransition; 73 mTransitionStyle = bse.mTransitionStyle; 74 mName = bse.mName; 75 mIndex = bse.mIndex; 76 mBreadCrumbTitleRes = bse.mBreadCrumbTitleRes; 77 mBreadCrumbTitleText = bse.mBreadCrumbTitleText; 78 mBreadCrumbShortTitleRes = bse.mBreadCrumbShortTitleRes; 79 mBreadCrumbShortTitleText = bse.mBreadCrumbShortTitleText; 80 } 81 82 public BackStackState(Parcel in) { 83 mOps = in.createIntArray(); 84 mTransition = in.readInt(); 85 mTransitionStyle = in.readInt(); 86 mName = in.readString(); 87 mIndex = in.readInt(); 88 mBreadCrumbTitleRes = in.readInt(); 89 mBreadCrumbTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); 90 mBreadCrumbShortTitleRes = in.readInt(); 91 mBreadCrumbShortTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); 92 } 93 94 public BackStackRecord instantiate(FragmentManagerImpl fm) { 95 BackStackRecord bse = new BackStackRecord(fm); 96 int pos = 0; 97 while (pos < mOps.length) { 98 BackStackRecord.Op op = new BackStackRecord.Op(); 99 op.cmd = mOps[pos++]; 100 if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG, 101 "BSE " + bse + " set base fragment #" + mOps[pos]); 102 Fragment f = fm.mActive.get(mOps[pos++]); 103 op.fragment = f; 104 op.enterAnim = mOps[pos++]; 105 op.exitAnim = mOps[pos++]; 106 op.popEnterAnim = mOps[pos++]; 107 op.popExitAnim = mOps[pos++]; 108 final int N = mOps[pos++]; 109 if (N > 0) { 110 op.removed = new ArrayList<Fragment>(N); 111 for (int i=0; i<N; i++) { 112 if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG, 113 "BSE " + bse + " set remove fragment #" + mOps[pos]); 114 Fragment r = fm.mActive.get(mOps[pos++]); 115 op.removed.add(r); 116 } 117 } 118 bse.addOp(op); 119 } 120 bse.mTransition = mTransition; 121 bse.mTransitionStyle = mTransitionStyle; 122 bse.mName = mName; 123 bse.mIndex = mIndex; 124 bse.mAddToBackStack = true; 125 bse.mBreadCrumbTitleRes = mBreadCrumbTitleRes; 126 bse.mBreadCrumbTitleText = mBreadCrumbTitleText; 127 bse.mBreadCrumbShortTitleRes = mBreadCrumbShortTitleRes; 128 bse.mBreadCrumbShortTitleText = mBreadCrumbShortTitleText; 129 bse.bumpBackStackNesting(1); 130 return bse; 131 } 132 133 public int describeContents() { 134 return 0; 135 } 136 137 public void writeToParcel(Parcel dest, int flags) { 138 dest.writeIntArray(mOps); 139 dest.writeInt(mTransition); 140 dest.writeInt(mTransitionStyle); 141 dest.writeString(mName); 142 dest.writeInt(mIndex); 143 dest.writeInt(mBreadCrumbTitleRes); 144 TextUtils.writeToParcel(mBreadCrumbTitleText, dest, 0); 145 dest.writeInt(mBreadCrumbShortTitleRes); 146 TextUtils.writeToParcel(mBreadCrumbShortTitleText, dest, 0); 147 } 148 149 public static final Parcelable.Creator<BackStackState> CREATOR 150 = new Parcelable.Creator<BackStackState>() { 151 public BackStackState createFromParcel(Parcel in) { 152 return new BackStackState(in); 153 } 154 155 public BackStackState[] newArray(int size) { 156 return new BackStackState[size]; 157 } 158 }; 159} 160 161/** 162 * @hide Entry of an operation on the fragment back stack. 163 */ 164final class BackStackRecord extends FragmentTransaction implements 165 FragmentManager.BackStackEntry, Runnable { 166 static final String TAG = "BackStackEntry"; 167 168 final FragmentManagerImpl mManager; 169 170 static final int OP_NULL = 0; 171 static final int OP_ADD = 1; 172 static final int OP_REPLACE = 2; 173 static final int OP_REMOVE = 3; 174 static final int OP_HIDE = 4; 175 static final int OP_SHOW = 5; 176 static final int OP_DETACH = 6; 177 static final int OP_ATTACH = 7; 178 179 static final class Op { 180 Op next; 181 Op prev; 182 int cmd; 183 Fragment fragment; 184 int enterAnim; 185 int exitAnim; 186 int popEnterAnim; 187 int popExitAnim; 188 ArrayList<Fragment> removed; 189 } 190 191 Op mHead; 192 Op mTail; 193 int mNumOp; 194 int mEnterAnim; 195 int mExitAnim; 196 int mPopEnterAnim; 197 int mPopExitAnim; 198 int mTransition; 199 int mTransitionStyle; 200 boolean mAddToBackStack; 201 boolean mAllowAddToBackStack = true; 202 String mName; 203 boolean mCommitted; 204 int mIndex; 205 206 int mBreadCrumbTitleRes; 207 CharSequence mBreadCrumbTitleText; 208 int mBreadCrumbShortTitleRes; 209 CharSequence mBreadCrumbShortTitleText; 210 211 public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 212 writer.print(prefix); writer.print("mName="); writer.print(mName); 213 writer.print(" mIndex="); writer.print(mIndex); 214 writer.print(" mCommitted="); writer.println(mCommitted); 215 if (mTransition != FragmentTransaction.TRANSIT_NONE) { 216 writer.print(prefix); writer.print("mTransition=#"); 217 writer.print(Integer.toHexString(mTransition)); 218 writer.print(" mTransitionStyle=#"); 219 writer.println(Integer.toHexString(mTransitionStyle)); 220 } 221 if (mEnterAnim != 0 || mExitAnim !=0) { 222 writer.print(prefix); writer.print("mEnterAnim=#"); 223 writer.print(Integer.toHexString(mEnterAnim)); 224 writer.print(" mExitAnim=#"); 225 writer.println(Integer.toHexString(mExitAnim)); 226 } 227 if (mPopEnterAnim != 0 || mPopExitAnim !=0) { 228 writer.print(prefix); writer.print("mPopEnterAnim=#"); 229 writer.print(Integer.toHexString(mPopEnterAnim)); 230 writer.print(" mPopExitAnim=#"); 231 writer.println(Integer.toHexString(mPopExitAnim)); 232 } 233 if (mBreadCrumbTitleRes != 0 || mBreadCrumbTitleText != null) { 234 writer.print(prefix); writer.print("mBreadCrumbTitleRes=#"); 235 writer.print(Integer.toHexString(mBreadCrumbTitleRes)); 236 writer.print(" mBreadCrumbTitleText="); 237 writer.println(mBreadCrumbTitleText); 238 } 239 if (mBreadCrumbShortTitleRes != 0 || mBreadCrumbShortTitleText != null) { 240 writer.print(prefix); writer.print("mBreadCrumbShortTitleRes=#"); 241 writer.print(Integer.toHexString(mBreadCrumbShortTitleRes)); 242 writer.print(" mBreadCrumbShortTitleText="); 243 writer.println(mBreadCrumbShortTitleText); 244 } 245 246 if (mHead != null) { 247 writer.print(prefix); writer.println("Operations:"); 248 String innerPrefix = prefix + " "; 249 Op op = mHead; 250 int num = 0; 251 while (op != null) { 252 writer.print(prefix); writer.print(" Op #"); writer.print(num); 253 writer.println(":"); 254 writer.print(innerPrefix); writer.print("cmd="); writer.print(op.cmd); 255 writer.print(" fragment="); writer.println(op.fragment); 256 if (op.enterAnim != 0 || op.exitAnim != 0) { 257 writer.print(prefix); writer.print("enterAnim=#"); 258 writer.print(Integer.toHexString(op.enterAnim)); 259 writer.print(" exitAnim=#"); 260 writer.println(Integer.toHexString(op.exitAnim)); 261 } 262 if (op.popEnterAnim != 0 || op.popExitAnim != 0) { 263 writer.print(prefix); writer.print("popEnterAnim=#"); 264 writer.print(Integer.toHexString(op.popEnterAnim)); 265 writer.print(" popExitAnim=#"); 266 writer.println(Integer.toHexString(op.popExitAnim)); 267 } 268 if (op.removed != null && op.removed.size() > 0) { 269 for (int i=0; i<op.removed.size(); i++) { 270 writer.print(innerPrefix); 271 if (op.removed.size() == 1) { 272 writer.print("Removed: "); 273 } else { 274 writer.println("Removed:"); 275 writer.print(innerPrefix); writer.print(" #"); writer.print(num); 276 writer.print(": "); 277 } 278 writer.println(op.removed.get(i)); 279 } 280 } 281 op = op.next; 282 } 283 } 284 } 285 286 public BackStackRecord(FragmentManagerImpl manager) { 287 mManager = manager; 288 } 289 290 public int getId() { 291 return mIndex; 292 } 293 294 public int getBreadCrumbTitleRes() { 295 return mBreadCrumbTitleRes; 296 } 297 298 public int getBreadCrumbShortTitleRes() { 299 return mBreadCrumbShortTitleRes; 300 } 301 302 public CharSequence getBreadCrumbTitle() { 303 if (mBreadCrumbTitleRes != 0) { 304 return mManager.mActivity.getText(mBreadCrumbTitleRes); 305 } 306 return mBreadCrumbTitleText; 307 } 308 309 public CharSequence getBreadCrumbShortTitle() { 310 if (mBreadCrumbShortTitleRes != 0) { 311 return mManager.mActivity.getText(mBreadCrumbShortTitleRes); 312 } 313 return mBreadCrumbShortTitleText; 314 } 315 316 void addOp(Op op) { 317 if (mHead == null) { 318 mHead = mTail = op; 319 } else { 320 op.prev = mTail; 321 mTail.next = op; 322 mTail = op; 323 } 324 op.enterAnim = mEnterAnim; 325 op.exitAnim = mExitAnim; 326 op.popEnterAnim = mPopEnterAnim; 327 op.popExitAnim = mPopExitAnim; 328 mNumOp++; 329 } 330 331 public FragmentTransaction add(Fragment fragment, String tag) { 332 doAddOp(0, fragment, tag, OP_ADD); 333 return this; 334 } 335 336 public FragmentTransaction add(int containerViewId, Fragment fragment) { 337 doAddOp(containerViewId, fragment, null, OP_ADD); 338 return this; 339 } 340 341 public FragmentTransaction add(int containerViewId, Fragment fragment, String tag) { 342 doAddOp(containerViewId, fragment, tag, OP_ADD); 343 return this; 344 } 345 346 private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) { 347 fragment.mFragmentManager = mManager; 348 349 if (tag != null) { 350 if (fragment.mTag != null && !tag.equals(fragment.mTag)) { 351 throw new IllegalStateException("Can't change tag of fragment " 352 + fragment + ": was " + fragment.mTag 353 + " now " + tag); 354 } 355 fragment.mTag = tag; 356 } 357 358 if (containerViewId != 0) { 359 if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) { 360 throw new IllegalStateException("Can't change container ID of fragment " 361 + fragment + ": was " + fragment.mFragmentId 362 + " now " + containerViewId); 363 } 364 fragment.mContainerId = fragment.mFragmentId = containerViewId; 365 } 366 367 Op op = new Op(); 368 op.cmd = opcmd; 369 op.fragment = fragment; 370 addOp(op); 371 } 372 373 public FragmentTransaction replace(int containerViewId, Fragment fragment) { 374 return replace(containerViewId, fragment, null); 375 } 376 377 public FragmentTransaction replace(int containerViewId, Fragment fragment, String tag) { 378 if (containerViewId == 0) { 379 throw new IllegalArgumentException("Must use non-zero containerViewId"); 380 } 381 382 doAddOp(containerViewId, fragment, tag, OP_REPLACE); 383 return this; 384 } 385 386 public FragmentTransaction remove(Fragment fragment) { 387 Op op = new Op(); 388 op.cmd = OP_REMOVE; 389 op.fragment = fragment; 390 addOp(op); 391 392 return this; 393 } 394 395 public FragmentTransaction hide(Fragment fragment) { 396 Op op = new Op(); 397 op.cmd = OP_HIDE; 398 op.fragment = fragment; 399 addOp(op); 400 401 return this; 402 } 403 404 public FragmentTransaction show(Fragment fragment) { 405 Op op = new Op(); 406 op.cmd = OP_SHOW; 407 op.fragment = fragment; 408 addOp(op); 409 410 return this; 411 } 412 413 public FragmentTransaction detach(Fragment fragment) { 414 Op op = new Op(); 415 op.cmd = OP_DETACH; 416 op.fragment = fragment; 417 addOp(op); 418 419 return this; 420 } 421 422 public FragmentTransaction attach(Fragment fragment) { 423 Op op = new Op(); 424 op.cmd = OP_ATTACH; 425 op.fragment = fragment; 426 addOp(op); 427 428 return this; 429 } 430 431 public FragmentTransaction setCustomAnimations(int enter, int exit) { 432 return setCustomAnimations(enter, exit, 0, 0); 433 } 434 435 public FragmentTransaction setCustomAnimations(int enter, int exit, 436 int popEnter, int popExit) { 437 mEnterAnim = enter; 438 mExitAnim = exit; 439 mPopEnterAnim = popEnter; 440 mPopExitAnim = popExit; 441 return this; 442 } 443 444 public FragmentTransaction setTransition(int transition) { 445 mTransition = transition; 446 return this; 447 } 448 449 public FragmentTransaction setTransitionStyle(int styleRes) { 450 mTransitionStyle = styleRes; 451 return this; 452 } 453 454 public FragmentTransaction addToBackStack(String name) { 455 if (!mAllowAddToBackStack) { 456 throw new IllegalStateException( 457 "This FragmentTransaction is not allowed to be added to the back stack."); 458 } 459 mAddToBackStack = true; 460 mName = name; 461 return this; 462 } 463 464 public boolean isAddToBackStackAllowed() { 465 return mAllowAddToBackStack; 466 } 467 468 public FragmentTransaction disallowAddToBackStack() { 469 if (mAddToBackStack) { 470 throw new IllegalStateException( 471 "This transaction is already being added to the back stack"); 472 } 473 mAllowAddToBackStack = false; 474 return this; 475 } 476 477 public FragmentTransaction setBreadCrumbTitle(int res) { 478 mBreadCrumbTitleRes = res; 479 mBreadCrumbTitleText = null; 480 return this; 481 } 482 483 public FragmentTransaction setBreadCrumbTitle(CharSequence text) { 484 mBreadCrumbTitleRes = 0; 485 mBreadCrumbTitleText = text; 486 return this; 487 } 488 489 public FragmentTransaction setBreadCrumbShortTitle(int res) { 490 mBreadCrumbShortTitleRes = res; 491 mBreadCrumbShortTitleText = null; 492 return this; 493 } 494 495 public FragmentTransaction setBreadCrumbShortTitle(CharSequence text) { 496 mBreadCrumbShortTitleRes = 0; 497 mBreadCrumbShortTitleText = text; 498 return this; 499 } 500 501 void bumpBackStackNesting(int amt) { 502 if (!mAddToBackStack) { 503 return; 504 } 505 if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting in " + this 506 + " by " + amt); 507 Op op = mHead; 508 while (op != null) { 509 op.fragment.mBackStackNesting += amt; 510 if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of " 511 + op.fragment + " to " + op.fragment.mBackStackNesting); 512 if (op.removed != null) { 513 for (int i=op.removed.size()-1; i>=0; i--) { 514 Fragment r = op.removed.get(i); 515 r.mBackStackNesting += amt; 516 if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of " 517 + r + " to " + r.mBackStackNesting); 518 } 519 } 520 op = op.next; 521 } 522 } 523 524 public int commit() { 525 return commitInternal(false); 526 } 527 528 public int commitAllowingStateLoss() { 529 return commitInternal(true); 530 } 531 532 int commitInternal(boolean allowStateLoss) { 533 if (mCommitted) throw new IllegalStateException("commit already called"); 534 if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Commit: " + this); 535 mCommitted = true; 536 if (mAddToBackStack) { 537 mIndex = mManager.allocBackStackIndex(this); 538 } else { 539 mIndex = -1; 540 } 541 mManager.enqueueAction(this, allowStateLoss); 542 return mIndex; 543 } 544 545 public void run() { 546 if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Run: " + this); 547 548 if (mAddToBackStack) { 549 if (mIndex < 0) { 550 throw new IllegalStateException("addToBackStack() called after commit()"); 551 } 552 } 553 554 bumpBackStackNesting(1); 555 556 Op op = mHead; 557 while (op != null) { 558 switch (op.cmd) { 559 case OP_ADD: { 560 Fragment f = op.fragment; 561 f.mNextAnim = op.enterAnim; 562 mManager.addFragment(f, false); 563 } break; 564 case OP_REPLACE: { 565 Fragment f = op.fragment; 566 if (mManager.mAdded != null) { 567 for (int i=0; i<mManager.mAdded.size(); i++) { 568 Fragment old = mManager.mAdded.get(i); 569 if (FragmentManagerImpl.DEBUG) Log.v(TAG, 570 "OP_REPLACE: adding=" + f + " old=" + old); 571 if (old.mContainerId == f.mContainerId) { 572 if (op.removed == null) { 573 op.removed = new ArrayList<Fragment>(); 574 } 575 op.removed.add(old); 576 old.mNextAnim = op.exitAnim; 577 if (mAddToBackStack) { 578 old.mBackStackNesting += 1; 579 if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of " 580 + old + " to " + old.mBackStackNesting); 581 } 582 mManager.removeFragment(old, mTransition, mTransitionStyle); 583 } 584 } 585 } 586 f.mNextAnim = op.enterAnim; 587 mManager.addFragment(f, false); 588 } break; 589 case OP_REMOVE: { 590 Fragment f = op.fragment; 591 f.mNextAnim = op.exitAnim; 592 mManager.removeFragment(f, mTransition, mTransitionStyle); 593 } break; 594 case OP_HIDE: { 595 Fragment f = op.fragment; 596 f.mNextAnim = op.exitAnim; 597 mManager.hideFragment(f, mTransition, mTransitionStyle); 598 } break; 599 case OP_SHOW: { 600 Fragment f = op.fragment; 601 f.mNextAnim = op.enterAnim; 602 mManager.showFragment(f, mTransition, mTransitionStyle); 603 } break; 604 case OP_DETACH: { 605 Fragment f = op.fragment; 606 f.mNextAnim = op.exitAnim; 607 mManager.detachFragment(f, mTransition, mTransitionStyle); 608 } break; 609 case OP_ATTACH: { 610 Fragment f = op.fragment; 611 f.mNextAnim = op.enterAnim; 612 mManager.attachFragment(f, mTransition, mTransitionStyle); 613 } break; 614 default: { 615 throw new IllegalArgumentException("Unknown cmd: " + op.cmd); 616 } 617 } 618 619 op = op.next; 620 } 621 622 mManager.moveToState(mManager.mCurState, mTransition, 623 mTransitionStyle, true); 624 625 if (mAddToBackStack) { 626 mManager.addBackStackState(this); 627 } 628 } 629 630 public void popFromBackStack(boolean doStateMove) { 631 if (FragmentManagerImpl.DEBUG) Log.v(TAG, "popFromBackStack: " + this); 632 633 bumpBackStackNesting(-1); 634 635 Op op = mTail; 636 while (op != null) { 637 switch (op.cmd) { 638 case OP_ADD: { 639 Fragment f = op.fragment; 640 f.mNextAnim = op.popExitAnim; 641 mManager.removeFragment(f, 642 FragmentManagerImpl.reverseTransit(mTransition), 643 mTransitionStyle); 644 } break; 645 case OP_REPLACE: { 646 Fragment f = op.fragment; 647 f.mNextAnim = op.popExitAnim; 648 mManager.removeFragment(f, 649 FragmentManagerImpl.reverseTransit(mTransition), 650 mTransitionStyle); 651 if (op.removed != null) { 652 for (int i=0; i<op.removed.size(); i++) { 653 Fragment old = op.removed.get(i); 654 old.mNextAnim = op.popEnterAnim; 655 mManager.addFragment(old, false); 656 } 657 } 658 } break; 659 case OP_REMOVE: { 660 Fragment f = op.fragment; 661 f.mNextAnim = op.popEnterAnim; 662 mManager.addFragment(f, false); 663 } break; 664 case OP_HIDE: { 665 Fragment f = op.fragment; 666 f.mNextAnim = op.popEnterAnim; 667 mManager.showFragment(f, 668 FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); 669 } break; 670 case OP_SHOW: { 671 Fragment f = op.fragment; 672 f.mNextAnim = op.popExitAnim; 673 mManager.hideFragment(f, 674 FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); 675 } break; 676 case OP_DETACH: { 677 Fragment f = op.fragment; 678 f.mNextAnim = op.popEnterAnim; 679 mManager.attachFragment(f, 680 FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); 681 } break; 682 case OP_ATTACH: { 683 Fragment f = op.fragment; 684 f.mNextAnim = op.popEnterAnim; 685 mManager.detachFragment(f, 686 FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle); 687 } break; 688 default: { 689 throw new IllegalArgumentException("Unknown cmd: " + op.cmd); 690 } 691 } 692 693 op = op.prev; 694 } 695 696 if (doStateMove) { 697 mManager.moveToState(mManager.mCurState, 698 FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle, true); 699 } 700 701 if (mIndex >= 0) { 702 mManager.freeBackStackIndex(mIndex); 703 mIndex = -1; 704 } 705 } 706 707 public String getName() { 708 return mName; 709 } 710 711 public int getTransition() { 712 return mTransition; 713 } 714 715 public int getTransitionStyle() { 716 return mTransitionStyle; 717 } 718 719 public boolean isEmpty() { 720 return mNumOp == 0; 721 } 722} 723