From 27b0dc0287022ce7b644ec92d8de6f98e33a6c09 Mon Sep 17 00:00:00 2001 From: George Mount Date: Tue, 21 Feb 2017 10:24:09 -0800 Subject: [PATCH] Expose isStateSaved() in FragmentManager. Bug 35594367 Protect the FragmentManager during onBackPressed() from changing the state after the state was saved. Test: I15891a70699308eddda4e55fa0eb96064ffa7b17 Change-Id: I10f823801e85ca200351a64b14975c4421b9068b --- api/current.txt | 1 + api/system-current.txt | 1 + api/test-current.txt | 1 + core/java/android/app/Activity.java | 4 +++- core/java/android/app/FragmentManager.java | 14 ++++++++++++++ 5 files changed, 20 insertions(+), 1 deletion(-) diff --git a/api/current.txt b/api/current.txt index 6d71f441fdcfc..626cdae536636 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4737,6 +4737,7 @@ package android.app { method public abstract android.app.Fragment getPrimaryNavigationFragment(); method public void invalidateOptionsMenu(); method public abstract boolean isDestroyed(); + method public abstract boolean isStateSaved(); method public abstract void popBackStack(); method public abstract void popBackStack(java.lang.String, int); method public abstract void popBackStack(int, int); diff --git a/api/system-current.txt b/api/system-current.txt index 8413036182df4..0c042c3cd575d 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4898,6 +4898,7 @@ package android.app { method public abstract android.app.Fragment getPrimaryNavigationFragment(); method public void invalidateOptionsMenu(); method public abstract boolean isDestroyed(); + method public abstract boolean isStateSaved(); method public abstract void popBackStack(); method public abstract void popBackStack(java.lang.String, int); method public abstract void popBackStack(int, int); diff --git a/api/test-current.txt b/api/test-current.txt index 00a83394df36e..428594a7804a2 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -4747,6 +4747,7 @@ package android.app { method public abstract android.app.Fragment getPrimaryNavigationFragment(); method public void invalidateOptionsMenu(); method public abstract boolean isDestroyed(); + method public abstract boolean isStateSaved(); method public abstract void popBackStack(); method public abstract void popBackStack(java.lang.String, int); method public abstract void popBackStack(int, int); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 6fc60e9eaaf22..95dc52dea79a1 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -2820,7 +2820,9 @@ public class Activity extends ContextThemeWrapper return; } - if (!mFragments.getFragmentManager().popBackStackImmediate()) { + FragmentManager fragmentManager = mFragments.getFragmentManager(); + + if (fragmentManager.isStateSaved() || !fragmentManager.popBackStackImmediate()) { finishAfterTransition(); } } diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 8ad7810a13e84..977931a66e1e0 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -396,6 +396,19 @@ public abstract class FragmentManager { */ public void invalidateOptionsMenu() { } + /** + * Returns {@code true} if the FragmentManager's state has already been saved + * by its host. Any operations that would change saved state should not be performed + * if this method returns true. For example, any popBackStack() method, such as + * {@link #popBackStackImmediate()} or any FragmentTransaction using + * {@link FragmentTransaction#commit()} instead of + * {@link FragmentTransaction#commitAllowingStateLoss()} will change + * the state and will result in an error. + * + * @return true if this FragmentManager's state has already been saved by its host + */ + public abstract boolean isStateSaved(); + /** * Callback interface for listening to fragment state changes that happen * within a given FragmentManager. @@ -1787,6 +1800,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate } } + @Override public boolean isStateSaved() { return mStateSaved; }