Force transitioning views to be visible when transition interrupted.

Bug 17553034

When an Activity Transition was interrupted prior to starting the
enter transition, the views were not being made visible.

Override the return ActivityOptions if interrupted so that the
entering activity doesn't launch with a transition when coming
back from recents.

Change-Id: Id4e00c7bb138babfee4de71247a9df4431376e21
diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java
index bc2e6ca..555d20b 100644
--- a/core/java/android/app/ActivityTransitionState.java
+++ b/core/java/android/app/ActivityTransitionState.java
@@ -67,6 +67,12 @@
     private ExitTransitionCoordinator mCalledExitCoordinator;
 
     /**
+     * The ExitTransitionCoordinator used to return to a previous Activity when called with
+     * {@link android.app.Activity#finishAfterTransition()}.
+     */
+    private ExitTransitionCoordinator mReturnExitCoordinator;
+
+    /**
      * We must be able to cancel entering transitions to stop changing the Window to
      * opaque when we exit before making the Window opaque.
      */
@@ -218,6 +224,10 @@
             mEnterTransitionCoordinator.stop();
             mEnterTransitionCoordinator = null;
         }
+        if (mReturnExitCoordinator != null) {
+            mReturnExitCoordinator.stop();
+            mReturnExitCoordinator = null;
+        }
     }
 
     public void onResume() {
@@ -260,12 +270,12 @@
                     }
                 }
 
-                ExitTransitionCoordinator exitCoordinator =
+                mReturnExitCoordinator =
                         new ExitTransitionCoordinator(activity, mEnteringNames, null, null, true);
                 if (enterViewsTransition != null && decor != null) {
                     enterViewsTransition.resume(decor);
                 }
-                exitCoordinator.startExit(activity.mResultCode, activity.mResultData);
+                mReturnExitCoordinator.startExit(activity.mResultCode, activity.mResultData);
             }
             return true;
         }
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index 216d6ba..add67f2 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -30,6 +30,7 @@
 import android.view.ViewGroup;
 import android.view.ViewGroupOverlay;
 import android.view.ViewTreeObserver;
+import android.view.Window;
 
 import java.util.ArrayList;
 
@@ -265,10 +266,14 @@
     }
 
     protected void prepareEnter() {
+        ViewGroup decorView = getDecor();
+        if (mActivity == null || decorView == null) {
+            return;
+        }
         mActivity.overridePendingTransition(0, 0);
         if (!mIsReturning) {
             mWasOpaque = mActivity.convertToTranslucent(null, null);
-            Drawable background = getDecor().getBackground();
+            Drawable background = decorView.getBackground();
             if (background != null) {
                 getWindow().setBackgroundDrawable(null);
                 background = background.mutate();
@@ -282,18 +287,26 @@
 
     @Override
     protected Transition getViewsTransition() {
+        Window window = getWindow();
+        if (window == null) {
+            return null;
+        }
         if (mIsReturning) {
-            return getWindow().getReenterTransition();
+            return window.getReenterTransition();
         } else {
-            return getWindow().getEnterTransition();
+            return window.getEnterTransition();
         }
     }
 
     protected Transition getSharedElementTransition() {
+        Window window = getWindow();
+        if (window == null) {
+            return null;
+        }
         if (mIsReturning) {
-            return getWindow().getSharedElementReenterTransition();
+            return window.getSharedElementReenterTransition();
         } else {
-            return getWindow().getSharedElementEnterTransition();
+            return window.getSharedElementEnterTransition();
         }
     }
 
@@ -518,15 +531,29 @@
     }
 
     public void stop() {
-        makeOpaque();
-        mIsCanceled = true;
-        mResultReceiver = null;
+        // Restore the background to its previous state since the
+        // Activity is stopping.
         if (mBackgroundAnimator != null) {
             mBackgroundAnimator.end();
             mBackgroundAnimator = null;
+        } else if (mWasOpaque) {
+            ViewGroup decorView = getDecor();
+            if (decorView != null) {
+                Drawable drawable = decorView.getBackground();
+                if (drawable != null) {
+                    drawable.setAlpha(1);
+                }
+            }
         }
+        makeOpaque();
+        mIsCanceled = true;
+        mResultReceiver = null;
         mActivity = null;
         moveSharedElementsFromOverlay();
+        if (mTransitioningViews != null) {
+            showViews(mTransitioningViews, true);
+        }
+        showViews(mSharedElements, true);
         clearState();
     }
 
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index d4d3eda..dd3df47 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -255,6 +255,16 @@
         }
     }
 
+    public void stop() {
+        if (mIsReturning && mActivity != null) {
+            // Override the previous ActivityOptions. We don't want the
+            // activity to have options since we're essentially canceling the
+            // transition and finishing right now.
+            mActivity.convertToTranslucent(null, null);
+            finish();
+        }
+    }
+
     private void startExitTransition() {
         Transition transition = getExitTransition();
         ViewGroup decorView = getDecor();
@@ -425,13 +435,14 @@
 
     private void finish() {
         stopCancel();
-        mActivity.mActivityTransitionState.clear();
+        if (mActivity != null) {
+            mActivity.mActivityTransitionState.clear();
+            mActivity.finish();
+            mActivity.overridePendingTransition(0, 0);
+            mActivity = null;
+        }
         // Clear the state so that we can't hold any references accidentally and leak memory.
-        mHandler.removeMessages(MSG_CANCEL);
         mHandler = null;
-        mActivity.finish();
-        mActivity.overridePendingTransition(0, 0);
-        mActivity = null;
         mSharedElementBundle = null;
         if (mBackgroundAnimator != null) {
             mBackgroundAnimator.cancel();