Protect BackStackRecord from accessing null mHost.
Bug 33177567
The fragment manager is being accessed after it has been torn
down. This protects BackStackRecord from accessing the null
mHost in that case.
Test: cts-tradefed run singleCommand cts -d --skip-preconditions
--skip-connectivity-check -m CtsFragmentTestCases
Change-Id: Id927eb1bc78e3750b01f685523418bde5a9cf8a0
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 84adbe5..105d2ca 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -351,17 +351,7 @@
public BackStackRecord(FragmentManagerImpl manager) {
mManager = manager;
- FragmentHostCallback host = manager.mHost;
- if (host != null) {
- Context context = host.getContext();
- if (context != null) {
- ApplicationInfo info = context.getApplicationInfo();
- if (info != null) {
- int targetSdkVersion = info.targetSdkVersion;
- mAllowOptimization = targetSdkVersion > Build.VERSION_CODES.N_MR1;
- }
- }
- }
+ mAllowOptimization = getTargetSdk() > Build.VERSION_CODES.N_MR1;
}
public int getId() {
@@ -377,14 +367,14 @@
}
public CharSequence getBreadCrumbTitle() {
- if (mBreadCrumbTitleRes != 0) {
+ if (mBreadCrumbTitleRes != 0 && mManager.mHost != null) {
return mManager.mHost.getContext().getText(mBreadCrumbTitleRes);
}
return mBreadCrumbTitleText;
}
public CharSequence getBreadCrumbShortTitle() {
- if (mBreadCrumbShortTitleRes != 0) {
+ if (mBreadCrumbShortTitleRes != 0 && mManager.mHost != null) {
return mManager.mHost.getContext().getText(mBreadCrumbShortTitleRes);
}
return mBreadCrumbShortTitleText;
@@ -414,14 +404,10 @@
}
private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
- if (mManager.mHost.getContext() != null) {
- final int targetSdkVersion =
- mManager.mHost.getContext().getApplicationInfo().targetSdkVersion;
+ if (getTargetSdk() > Build.VERSION_CODES.N_MR1) {
final Class fragmentClass = fragment.getClass();
final int modifiers = fragmentClass.getModifiers();
- // TODO: make the check N_MR1 or O
- if (targetSdkVersion > Build.VERSION_CODES.N && (fragmentClass.isAnonymousClass()
- || !Modifier.isPublic(modifiers)
+ if ((fragmentClass.isAnonymousClass() || !Modifier.isPublic(modifiers)
|| (fragmentClass.isMemberClass() && !Modifier.isStatic(modifiers)))) {
throw new IllegalStateException("Fragment " + fragmentClass.getCanonicalName()
+ " must be a public static class to be properly recreated from"
@@ -927,4 +913,22 @@
public boolean isEmpty() {
return mOps.isEmpty();
}
+
+ /**
+ * @return the target SDK of the FragmentManager's application info. If the
+ * FragmentManager has been torn down, then 0 is returned.
+ */
+ private int getTargetSdk() {
+ FragmentHostCallback host = mManager.mHost;
+ if (host != null) {
+ Context context = host.getContext();
+ if (context != null) {
+ ApplicationInfo info = context.getApplicationInfo();
+ if (info != null) {
+ return info.targetSdkVersion;
+ }
+ }
+ }
+ return 0;
+ }
}