Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d5f70891 authored by George Mount's avatar George Mount
Browse files

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
parent 5438fbba
Loading
Loading
Loading
Loading
+23 −19
Original line number Diff line number Diff line
@@ -351,17 +351,7 @@ final class BackStackRecord extends FragmentTransaction implements

    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 @@ final class BackStackRecord extends FragmentTransaction implements
    }

    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 @@ final class BackStackRecord extends FragmentTransaction implements
    }

    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 @@ final class BackStackRecord extends FragmentTransaction implements
    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;
    }
}