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

Commit 27da718e authored by Kevin Chyn's avatar Kevin Chyn
Browse files

7/n: Gracefully handle configuration change during animations

If the dialog goes through configuration change but is already animating
away, we should send the callback immediately. Similary, there is no need
to re-create the dialog in onConfigurationChanged, since the lifecycle
is already ended and the callback is already sent to the client.

Bug: 123378871

Test: atest com.android.systemui.biometrics
Test: manual
Change-Id: I5c771982a3eef1a0583fb5171ffc7a9d91756396
parent 889de4c6
Loading
Loading
Loading
Loading
+26 −9
Original line number Diff line number Diff line
@@ -55,12 +55,12 @@ public class AuthContainerView extends LinearLayout
    private static final int ANIMATION_DURATION_SHOW_MS = 250;
    private static final int ANIMATION_DURATION_AWAY_MS = 350; // ms

    private static final int STATE_UNKNOWN = 0;
    private static final int STATE_ANIMATING_IN = 1;
    private static final int STATE_PENDING_DISMISS = 2;
    private static final int STATE_SHOWING = 3;
    private static final int STATE_ANIMATING_OUT = 4;
    private static final int STATE_GONE = 5;
    static final int STATE_UNKNOWN = 0;
    static final int STATE_ANIMATING_IN = 1;
    static final int STATE_PENDING_DISMISS = 2;
    static final int STATE_SHOWING = 3;
    static final int STATE_ANIMATING_OUT = 4;
    static final int STATE_GONE = 5;

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({STATE_UNKNOWN, STATE_ANIMATING_IN, STATE_PENDING_DISMISS, STATE_SHOWING,
@@ -87,6 +87,9 @@ public class AuthContainerView extends LinearLayout

    private @ContainerState int mContainerState = STATE_UNKNOWN;

    // Non-null only if the dialog is in the act of dismissing and has not sent the reason yet.
    @Nullable @AuthDialogCallback.DismissedReason Integer mPendingCallbackReason;

    static class Config {
        Context mContext;
        AuthDialogCallback mCallback;
@@ -327,6 +330,7 @@ public class AuthContainerView extends LinearLayout

    @Override
    public void onSaveState(@NonNull Bundle outState) {
        outState.putInt(AuthDialog.KEY_CONTAINER_STATE, mContainerState);
        mBiometricView.onSaveState(outState);
    }

@@ -353,12 +357,15 @@ public class AuthContainerView extends LinearLayout
        }
        mContainerState = STATE_ANIMATING_OUT;

        if (sendReason) {
            mPendingCallbackReason = reason;
        } else {
            mPendingCallbackReason = null;
        }

        final Runnable endActionRunnable = () -> {
            setVisibility(View.INVISIBLE);
            removeWindowIfAttached();
            if (sendReason) {
                mConfig.mCallback.onDismissed(reason);
            }
        };

        postOnAnimation(() -> {
@@ -384,7 +391,17 @@ public class AuthContainerView extends LinearLayout
        });
    }

    private void sendPendingCallbackIfNotNull() {
        Log.d(TAG, "pendingCallback: " + mPendingCallbackReason);
        if (mPendingCallbackReason != null) {
            mConfig.mCallback.onDismissed(mPendingCallbackReason);
            mPendingCallbackReason = null;
        }
    }

    private void removeWindowIfAttached() {
        sendPendingCallbackIfNotNull();

        if (mContainerState == STATE_GONE) {
            return;
        }
+6 −1
Original line number Diff line number Diff line
@@ -305,9 +305,14 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
            mCurrentDialog.dismissWithoutCallback(false /* animate */);
            mCurrentDialog = null;

            // Only show the dialog if necessary. If it was animating out, the dialog is supposed
            // to send its pending callback immediately.
            if (savedState.getInt(AuthDialog.KEY_CONTAINER_STATE)
                    != AuthContainerView.STATE_ANIMATING_OUT) {
                showDialog(mCurrentDialogArgs, true /* skipAnimation */, savedState);
            }
        }
    }

    protected AuthDialog buildDialog(Bundle biometricPromptBundle, boolean requireConfirmation,
            int userId, int type, String opPackageName, boolean skipIntro) {
+3 −0
Original line number Diff line number Diff line
@@ -29,6 +29,9 @@ import java.lang.annotation.RetentionPolicy;
 * Interface for the biometric dialog UI.
 */
public interface AuthDialog {

    String KEY_CONTAINER_STATE = "container_state";

    String KEY_BIOMETRIC_TRY_AGAIN_VISIBILITY = "try_agian_visibility";
    String KEY_BIOMETRIC_STATE = "state";
    String KEY_BIOMETRIC_INDICATOR_STRING = "indicator_string"; // error / help / hint