diff --git a/src/org/lineageos/setupwizard/FinishActivity.java b/src/org/lineageos/setupwizard/FinishActivity.java index f6162d3c..b36ca79f 100644 --- a/src/org/lineageos/setupwizard/FinishActivity.java +++ b/src/org/lineageos/setupwizard/FinishActivity.java @@ -25,6 +25,8 @@ import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; +import com.google.android.setupcompat.util.SystemBarHelper; + import org.lineageos.setupwizard.util.SetupWizardUtils; public class FinishActivity extends BaseSetupWizardActivity { @@ -33,10 +35,17 @@ public class FinishActivity extends BaseSetupWizardActivity { private final Handler mHandler = new Handler(Looper.getMainLooper()); + private enum FinishState { + NONE, + SHOULD_ANIMATE, + ANIMATING, + FINISHED + } + // "Why not just start this activity with an Intent extra?" you might ask. Been there. // We need this to affect the theme, and even onCreate is not early enough for that, - // so "static volatile boolean" it is. Feel free to rework this if you dare. - private static volatile boolean sIsFinishing; + // so "static volatile" it is. Feel free to rework this if you dare. + private static volatile FinishState sFinishState = FinishState.NONE; private View mRootView; private Resources.Theme mEdgeToEdgeWallpaperBackgroundTheme; @@ -44,6 +53,9 @@ public class FinishActivity extends BaseSetupWizardActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + Log.i(TAG, "onCreate: sFinishState=" + sFinishState); + overrideActivityTransition(OVERRIDE_TRANSITION_CLOSE, R.anim.translucent_enter, R.anim.translucent_exit); if (LOGV) { @@ -72,8 +84,23 @@ public class FinishActivity extends BaseSetupWizardActivity { return WindowInsetsCompat.CONSUMED; }); - if (sIsFinishing) { - startFinishSequence(); + if (sFinishState != FinishState.NONE) { + hideNextButton(); + } + + switch (sFinishState) { + case NONE: + break; + case SHOULD_ANIMATE: + startFinishSequence(); + break; + case FINISHED: + Log.e(TAG, "Should not start again when finished!"); + finish(); + break; + default: + Log.w(TAG, "Unexpected onCreate state " + sFinishState); + break; } } @@ -84,14 +111,14 @@ public class FinishActivity extends BaseSetupWizardActivity { @Override protected void applyForwardTransition() { - if (!sIsFinishing) { + if (sFinishState == FinishState.NONE) { super.applyForwardTransition(); } } @Override protected void applyBackwardTransition() { - if (!sIsFinishing) { + if (sFinishState == FinishState.NONE) { super.applyBackwardTransition(); } } @@ -104,28 +131,42 @@ public class FinishActivity extends BaseSetupWizardActivity { @Override public Resources.Theme getTheme() { Resources.Theme theme = super.getTheme(); - if (sIsFinishing) { - if (mEdgeToEdgeWallpaperBackgroundTheme == null) { - theme.applyStyle(R.style.EdgeToEdgeWallpaperBackground, true); - mEdgeToEdgeWallpaperBackgroundTheme = theme; - } - return mEdgeToEdgeWallpaperBackgroundTheme; + if (sFinishState == FinishState.NONE) { + return theme; } - return theme; + if (mEdgeToEdgeWallpaperBackgroundTheme == null) { + theme.applyStyle(R.style.EdgeToEdgeWallpaperBackground, true); + mEdgeToEdgeWallpaperBackgroundTheme = theme; + } + return mEdgeToEdgeWallpaperBackgroundTheme; } @Override public void onNavigateNext() { - if (!sIsFinishing) { - sIsFinishing = true; - startActivity(getIntent()); - finish(); - disableActivityTransitions(); + switch (sFinishState) { + case NONE: + relaunchAndRunAnimation(); + break; + default: + Log.e(TAG, "Unexpected state " + sFinishState + " when navigating next"); } - hideNextButton(); + } + + private void relaunchAndRunAnimation() { + sFinishState = FinishState.SHOULD_ANIMATE; + // Relaunching the activity before finishing is the only way currently known to prevent + // an out-of-place slide transition from happening, even when disabling transitions, and + // regardless of when we disable them. This also means we can't simply call recreate(), but + // another reason is that recreate() doesn't seem to reinitialize the theme, which is the + // entire point of relaunching - to ensure this activity reveals a wallpaper background. + // These theme shenanigans and relaunching were not necessary prior to Android 14 QPR3. + startActivity(getIntent()); + finish(); + disableActivityTransitions(); } private void startFinishSequence() { + sFinishState = FinishState.ANIMATING; setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED); hideNextButton(); @@ -148,11 +189,14 @@ public class FinishActivity extends BaseSetupWizardActivity { } private void animateOut() { + if (sFinishState != FinishState.ANIMATING) { + Log.e(TAG, "animateOut but in " + sFinishState + " phase. How?"); + return; + } final int cx = (mRootView.getLeft() + mRootView.getRight()) / 2; final int cy = (mRootView.getTop() + mRootView.getBottom()) / 2; final float fullRadius = (float) Math.hypot(cx, cy); - Animator anim = - ViewAnimationUtils.createCircularReveal(mRootView, cx, cy, fullRadius, 0f); + Animator anim = ViewAnimationUtils.createCircularReveal(mRootView, cx, cy, fullRadius, 0f); anim.setDuration(900); anim.addListener(new AnimatorListenerAdapter() { @Override @@ -167,10 +211,15 @@ public class FinishActivity extends BaseSetupWizardActivity { if (LOGV) { Log.v(TAG, "Animation ended"); } - SetupWizardUtils.finishSetupWizard(FinishActivity.this); + finishAfterAnimation(); }); } }); anim.start(); } + + private void finishAfterAnimation() { + SetupWizardUtils.finishSetupWizard(FinishActivity.this); + sFinishState = FinishState.FINISHED; + } }