Properly track fragments from pop operations.
am: e7e8d3d3a5

Change-Id: Ibffe0f20f43db35f0e0d273d1c78a01040ef71d1
diff --git a/fragment/java/android/support/v4/app/BackStackRecord.java b/fragment/java/android/support/v4/app/BackStackRecord.java
index acfa924..3b41d60 100644
--- a/fragment/java/android/support/v4/app/BackStackRecord.java
+++ b/fragment/java/android/support/v4/app/BackStackRecord.java
@@ -795,7 +795,7 @@
                 default:
                     throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
             }
-            if (!mAllowOptimization && op.cmd != OP_ADD) {
+            if (!mAllowOptimization && op.cmd != OP_REMOVE) {
                 mManager.moveFragmentToExpectedState(f);
             }
         }
@@ -861,6 +861,29 @@
         }
     }
 
+    /**
+     * Removes fragments that are added or removed during a pop operation.
+     *
+     * @param added Initialized to the fragments that are in the mManager.mAdded, this
+     *              will be modified to contain the fragments that will be in mAdded
+     *              after the execution ({@link #executeOps()}.
+     */
+    void trackAddedFragmentsInPop(ArrayList<Fragment> added) {
+        for (int opNum = 0; opNum < mOps.size(); opNum++) {
+            final Op op = mOps.get(opNum);
+            switch (op.cmd) {
+                case OP_ADD:
+                case OP_ATTACH:
+                    added.remove(op.fragment);
+                    break;
+                case OP_REMOVE:
+                case OP_DETACH:
+                    added.add(op.fragment);
+                    break;
+            }
+        }
+    }
+
     boolean isPostponed() {
         for (int opNum = 0; opNum < mOps.size(); opNum++) {
             final Op op = mOps.get(opNum);
diff --git a/fragment/java/android/support/v4/app/FragmentManager.java b/fragment/java/android/support/v4/app/FragmentManager.java
index b10170a..bf1c371 100644
--- a/fragment/java/android/support/v4/app/FragmentManager.java
+++ b/fragment/java/android/support/v4/app/FragmentManager.java
@@ -2128,6 +2128,8 @@
             final boolean isPop = isRecordPop.get(recordNum);
             if (!isPop) {
                 record.expandReplaceOps(mTmpAddedFragments);
+            } else {
+                record.trackAddedFragmentsInPop(mTmpAddedFragments);
             }
             final int bumpAmount = isPop ? -1 : 1;
             record.bumpBackStackNesting(bumpAmount);
diff --git a/fragment/tests/java/android/support/v4/app/FragmentViewTests.java b/fragment/tests/java/android/support/v4/app/FragmentViewTests.java
index ad970c8..98c9d40 100644
--- a/fragment/tests/java/android/support/v4/app/FragmentViewTests.java
+++ b/fragment/tests/java/android/support/v4/app/FragmentViewTests.java
@@ -902,6 +902,43 @@
         assertEquals(View.GONE, fragment2.getView().getVisibility());
     }
 
+    // Test to ensure that popping and adding a fragment properly track the fragments added
+    // and removed.
+    @Test
+    public void popAdd() throws Throwable {
+        FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
+        ViewGroup container = (ViewGroup)
+                mActivityRule.getActivity().findViewById(R.id.fragmentContainer);
+        final FragmentManager fm = mActivityRule.getActivity().getSupportFragmentManager();
+
+        // One fragment with a view
+        final StrictViewFragment fragment1 = new StrictViewFragment();
+        fm.beginTransaction().add(R.id.fragmentContainer, fragment1).addToBackStack(null).commit();
+        FragmentTestUtil.executePendingTransactions(mActivityRule);
+        FragmentTestUtil.assertChildren(container, fragment1);
+
+        final StrictViewFragment fragment2 = new StrictViewFragment();
+        final StrictViewFragment fragment3 = new StrictViewFragment();
+        mInstrumentation.runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                fm.popBackStack();
+                fm.beginTransaction()
+                        .replace(R.id.fragmentContainer, fragment2)
+                        .addToBackStack(null)
+                        .commit();
+                fm.executePendingTransactions();
+                fm.popBackStack();
+                fm.beginTransaction()
+                        .replace(R.id.fragmentContainer, fragment3)
+                        .addToBackStack(null)
+                        .commit();
+                fm.executePendingTransactions();
+            }
+        });
+        FragmentTestUtil.assertChildren(container, fragment3);
+    }
+
     private View findViewById(int viewId) {
         return mActivityRule.getActivity().findViewById(viewId);
     }