Adapt FinishActivity and outro for 14 QPR3

windowShowWallpaper behaves unexpectedly with transitions as of 14 QPR3.
As a result, the changes of "Revamp outro animation" were causing the
transition into the final page of the wizard to instantaneously have
a transparent wallpaper background, even before the animation finished.
This was jarring and odd, so now we use a regular theme until we are
ready to start our animation, at which point we recreate the activity
with the EdgeToEdgeWallpaperBackground (windowShowWallpaper) theme
before running the animation.

Change-Id: Ib19918d7d2a615aff44a48066b17ec9d2f04bac6
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 30d5357..f9fdd4a 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -284,7 +284,6 @@
 
         <activity
             android:name=".FinishActivity"
-            android:theme="@style/EdgeToEdgeWallpaperBackground"
             android:label="@string/activity_label_empty"
             android:configChanges="mcc|mnc"
             android:immersive="true"
diff --git a/src/org/lineageos/setupwizard/FinishActivity.java b/src/org/lineageos/setupwizard/FinishActivity.java
index 71e61ba..96a8de8 100644
--- a/src/org/lineageos/setupwizard/FinishActivity.java
+++ b/src/org/lineageos/setupwizard/FinishActivity.java
@@ -10,7 +10,9 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
+import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.res.Resources;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -32,7 +34,13 @@
 
     private final Handler mHandler = new Handler(Looper.getMainLooper());
 
-    private boolean mIsFinishing;
+    // "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;
+
+    private View mRootView;
+    private Resources.Theme mEdgeToEdgeWallpaperBackgroundTheme;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -52,8 +60,8 @@
         window.setNavigationBarContrastEnforced(false);
 
         // Ensure the main layout (not including the background view) does not get obscured by bars.
-        final View rootView = findViewById(R.id.root);
-        ViewCompat.setOnApplyWindowInsetsListener(rootView, (view, windowInsets) -> {
+        mRootView = findViewById(R.id.root);
+        ViewCompat.setOnApplyWindowInsetsListener(mRootView, (view, windowInsets) -> {
             final View linearLayout = findViewById(R.id.linear_layout);
             final Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
             final MarginLayoutParams params = (MarginLayoutParams) linearLayout.getLayoutParams();
@@ -64,6 +72,29 @@
             linearLayout.setLayoutParams(params);
             return WindowInsetsCompat.CONSUMED;
         });
+
+        if (sIsFinishing) {
+            startFinishSequence();
+        }
+    }
+
+    private void disableActivityTransitions() {
+        overrideActivityTransition(OVERRIDE_TRANSITION_OPEN, 0, 0);
+        overrideActivityTransition(OVERRIDE_TRANSITION_CLOSE, 0, 0);
+    }
+
+    @Override
+    protected void applyForwardTransition() {
+        if (!sIsFinishing) {
+            super.applyForwardTransition();
+        }
+    }
+
+    @Override
+    protected void applyBackwardTransition() {
+        if (!sIsFinishing) {
+            super.applyBackwardTransition();
+        }
     }
 
     @Override
@@ -72,40 +103,67 @@
     }
 
     @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;
+        }
+        return theme;
+    }
+
+    @Override
     public void onNavigateNext() {
-        startFinishSequence();
+        if (!sIsFinishing) {
+            sIsFinishing = true;
+            startActivity(getIntent());
+            finish();
+            disableActivityTransitions();
+        }
+        hideNextButton();
     }
 
     private void startFinishSequence() {
-        if (mIsFinishing) {
-            return;
-        }
-        mIsFinishing = true;
-
         setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
         hideNextButton();
 
         // Begin outro animation.
-        animateOut();
+        if (mRootView.isAttachedToWindow()) {
+            mHandler.post(() -> animateOut());
+        } else {
+            mRootView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
+                @Override
+                public void onViewAttachedToWindow(View v) {
+                    mHandler.post(() -> animateOut());
+                }
+
+                @Override
+                public void onViewDetachedFromWindow(View v) {
+                    // Do nothing
+                }
+            });
+        }
     }
 
     private void animateOut() {
-        final View rootView = findViewById(R.id.root);
-        final int cx = (rootView.getLeft() + rootView.getRight()) / 2;
-        final int cy = (rootView.getTop() + rootView.getBottom()) / 2;
+        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(rootView, cx, cy, fullRadius, 0f);
+                ViewAnimationUtils.createCircularReveal(mRootView, cx, cy, fullRadius, 0f);
         anim.setDuration(900);
         anim.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationStart(Animator animation) {
-                rootView.setVisibility(View.VISIBLE);
+                mRootView.setVisibility(View.VISIBLE);
             }
 
             @Override
             public void onAnimationEnd(Animator animation) {
-                rootView.setVisibility(View.INVISIBLE);
+                mRootView.setVisibility(View.INVISIBLE);
                 mHandler.post(() -> {
                     if (LOGV) {
                         Log.v(TAG, "Animation ended");