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

Commit e6b44f27 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Allow dangerous reentrant behavior for older apps"

parents 327dfaa6 f1d88e6e
Loading
Loading
Loading
Loading
+2 −20
Original line number Diff line number Diff line
@@ -370,7 +370,7 @@ final class BackStackRecord extends FragmentTransaction implements

    public BackStackRecord(FragmentManagerImpl manager) {
        mManager = manager;
        mAllowOptimization = getTargetSdk() > Build.VERSION_CODES.N_MR1;
        mAllowOptimization = mManager.getTargetSdk() > Build.VERSION_CODES.N_MR1;
    }

    public int getId() {
@@ -423,7 +423,7 @@ final class BackStackRecord extends FragmentTransaction implements
    }

    private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
        if (getTargetSdk() > Build.VERSION_CODES.N_MR1) {
        if (mManager.getTargetSdk() > Build.VERSION_CODES.N_MR1) {
            final Class fragmentClass = fragment.getClass();
            final int modifiers = fragmentClass.getModifiers();
            if ((fragmentClass.isAnonymousClass() || !Modifier.isPublic(modifiers)
@@ -1022,22 +1022,4 @@ 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;
    }
}
+54 −25
Original line number Diff line number Diff line
@@ -23,9 +23,11 @@ import android.animation.AnimatorSet;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.content.res.Resources.NotFoundException;
import android.content.res.TypedArray;
import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
import android.os.Looper;
@@ -674,6 +676,10 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
    // Postponed transactions.
    ArrayList<StartEnterTransitionListener> mPostponedTransactions;

    // Prior to O, we allowed executing transactions during fragment manager state changes.
    // This is dangerous, but we want to keep from breaking old applications.
    boolean mAllowOldReentrantBehavior;

    Runnable mExecCommit = new Runnable() {
        @Override
        public void run() {
@@ -2815,6 +2821,24 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
        mHost = host;
        mContainer = container;
        mParent = parent;
        mAllowOldReentrantBehavior = getTargetSdk() <= Build.VERSION_CODES.N_MR1;
    }

    /**
     * @return the target SDK of the FragmentManager's application info. If the
     * FragmentManager has been torn down, then 0 is returned.
     */
    int getTargetSdk() {
        if (mHost != null) {
            Context context = mHost.getContext();
            if (context != null) {
                ApplicationInfo info = context.getApplicationInfo();
                if (info != null) {
                    return info.targetSdkVersion;
                }
            }
        }
        return 0;
    }

    public void noteStateNotSaved() {
@@ -2823,61 +2847,66 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
    
    public void dispatchCreate() {
        mStateSaved = false;
        mExecutingActions = true;
        moveToState(Fragment.CREATED, false);
        mExecutingActions = false;
        dispatchMoveToState(Fragment.CREATED);
    }
    
    public void dispatchActivityCreated() {
        mStateSaved = false;
        mExecutingActions = true;
        moveToState(Fragment.ACTIVITY_CREATED, false);
        mExecutingActions = false;
        dispatchMoveToState(Fragment.ACTIVITY_CREATED);
    }
    
    public void dispatchStart() {
        mStateSaved = false;
        mExecutingActions = true;
        moveToState(Fragment.STARTED, false);
        mExecutingActions = false;
        dispatchMoveToState(Fragment.STARTED);
    }
    
    public void dispatchResume() {
        mStateSaved = false;
        mExecutingActions = true;
        moveToState(Fragment.RESUMED, false);
        mExecutingActions = false;
        dispatchMoveToState(Fragment.RESUMED);
    }
    
    public void dispatchPause() {
        mExecutingActions = true;
        moveToState(Fragment.STARTED, false);
        mExecutingActions = false;
        dispatchMoveToState(Fragment.STARTED);
    }
    
    public void dispatchStop() {
        mExecutingActions = true;
        moveToState(Fragment.STOPPED, false);
        mExecutingActions = false;
        dispatchMoveToState(Fragment.STOPPED);
    }
    
    public void dispatchDestroyView() {
        mExecutingActions = true;
        moveToState(Fragment.CREATED, false);
        mExecutingActions = false;
        dispatchMoveToState(Fragment.CREATED);
    }

    public void dispatchDestroy() {
        mDestroyed = true;
        execPendingActions();
        mExecutingActions = true;
        moveToState(Fragment.INITIALIZING, false);
        mExecutingActions = false;
        dispatchMoveToState(Fragment.INITIALIZING);
        mHost = null;
        mContainer = null;
        mParent = null;
    }

    /**
     * This method is called by dispatch* methods to change the FragmentManager's state.
     * It calls moveToState directly if the target SDK is older than O. Otherwise, it sets and
     * clears mExecutingActions to ensure that there is no reentrancy while the
     * FragmentManager is changing state.
     *
     * @param state The new state of the FragmentManager.
     */
    private void dispatchMoveToState(int state) {
        if (mAllowOldReentrantBehavior) {
            moveToState(state, false);
        } else {
            try {
                mExecutingActions = true;
                moveToState(state, false);
            } finally {
                mExecutingActions = false;
            }
        }
    }

    public void dispatchMultiWindowModeChanged(boolean isInMultiWindowMode) {
        if (mAdded == null) {
            return;