Merge "Add Transition for App -> Recents on TV." into nyc-dev
diff --git a/packages/SystemUI/res/layout/recents_on_tv.xml b/packages/SystemUI/res/layout/recents_on_tv.xml
index 3a7c1d1..567e009 100644
--- a/packages/SystemUI/res/layout/recents_on_tv.xml
+++ b/packages/SystemUI/res/layout/recents_on_tv.xml
@@ -18,7 +18,6 @@
     android:id="@+id/recents_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:background="@drawable/recents_tv_background_gradient"
     android:clipChildren="false"
     android:clipToPadding="false"
     android:layoutDirection="rtl">
diff --git a/packages/SystemUI/res/layout/recents_tv_task_card_view.xml b/packages/SystemUI/res/layout/recents_tv_task_card_view.xml
index c5b1a7a..54e97da 100644
--- a/packages/SystemUI/res/layout/recents_tv_task_card_view.xml
+++ b/packages/SystemUI/res/layout/recents_tv_task_card_view.xml
@@ -59,7 +59,7 @@
         <ImageView
                 android:id="@+id/card_view_thumbnail"
                 android:layout_width="match_parent"
-                android:layout_height="@dimen/recents_tv_card_height"
+                android:layout_height="@dimen/recents_tv_screenshot_height"
                 android:scaleType="centerCrop"
                 android:gravity="center"
                 android:layout_alignParentTop="true"
diff --git a/packages/SystemUI/res/values/dimens_tv.xml b/packages/SystemUI/res/values/dimens_tv.xml
index b589110..6b153d1 100644
--- a/packages/SystemUI/res/values/dimens_tv.xml
+++ b/packages/SystemUI/res/values/dimens_tv.xml
@@ -19,7 +19,7 @@
 <resources>
     <!-- Dimens for recents card in the recents view on tv -->
     <dimen name="recents_tv_card_width">268dip</dimen>
-    <dimen name="recents_tv_card_height">151dip</dimen>
+    <dimen name="recents_tv_screenshot_height">151dip</dimen>
     <dimen name="recents_tv_card_extra_badge_size">20dip</dimen>
     <dimen name="recents_tv_banner_width">114dip</dimen>
     <dimen name="recents_tv_banner_height">64dip</dimen>
diff --git a/packages/SystemUI/res/values/values_tv.xml b/packages/SystemUI/res/values/values_tv.xml
index 1fcc9e4..6a72e54 100644
--- a/packages/SystemUI/res/values/values_tv.xml
+++ b/packages/SystemUI/res/values/values_tv.xml
@@ -15,4 +15,5 @@
 -->
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
     <item format="float" type="integer" name="unselected_scale">1.0</item>
+    <item format="float" type="integer" name="selected_scale">1.1</item>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index d864df8..9be24de 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -66,6 +66,7 @@
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskGrouping;
 import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.tv.views.TaskCardView;
 import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
 import com.android.systemui.recents.views.TaskStackView;
 import com.android.systemui.recents.views.TaskStackViewScroller;
@@ -166,6 +167,7 @@
     boolean mCanReuseTaskStackViews = true;
     boolean mDraggingInRecents;
     boolean mLaunchedWhileDocking;
+    private boolean mIsRunningOnTv;
 
     // Task launching
     Rect mSearchBarBounds = new Rect();
@@ -230,8 +232,10 @@
         UiModeManager uiModeManager = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE);
         if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
             mRecentsIntentActivityName = RECENTS_TV_ACTIVITY;
+            mIsRunningOnTv = true;
         } else {
             mRecentsIntentActivityName = RECENTS_ACTIVITY;
+            mIsRunningOnTv = false;
         }
     }
 
@@ -793,6 +797,22 @@
         }
     }
 
+    /**
+     * Creates the activity options for an app->recents transition on TV.
+     */
+    private ActivityOptions getThumbnailTransitionActivityOptionsForTV(
+            ActivityManager.RunningTaskInfo topTask) {
+        Bitmap thumbnail = mThumbnailTransitionBitmapCache;
+        Rect rect = TaskCardView.getStartingCardThumbnailRect(mContext);
+        if (thumbnail != null) {
+            return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
+                    null, (int) rect.left, (int) rect.top,
+                    (int) rect.width(), (int) rect.height(), mHandler, null);
+        }
+        // If both the screenshot and thumbnail fails, then just fall back to the default transition
+        return getUnknownTransitionActivityOptions();
+    }
+
     private Bitmap getThumbnailBitmap(ActivityManager.RunningTaskInfo topTask, Task toTask,
             TaskViewTransform toTransform) {
         Bitmap thumbnail;
@@ -872,6 +892,11 @@
             boolean isTopTaskHome, boolean animate) {
         RecentsTaskLoader loader = Recents.getTaskLoader();
 
+        // If we are on TV, divert to a different helper method
+        if (mIsRunningOnTv) {
+            setUpAndStartTvRecents(topTask, isTopTaskHome, animate);
+            return;
+        }
         // In the case where alt-tab is triggered, we never get a preloadRecents() call, so we
         // should always preload the tasks now. If we are dragging in recents, reload them as
         // the stacks might have changed.
@@ -947,6 +972,90 @@
     }
 
     /**
+     * Used to set up the animations of Tv Recents, then start the Recents Activity.
+     * TODO: Add the Transitions for Home -> Recents TV
+     * TODO: Shift Transition code to separate class under /tv directory and access
+     *              from here
+     */
+    private void setUpAndStartTvRecents(ActivityManager.RunningTaskInfo topTask,
+                                      boolean isTopTaskHome, boolean animate) {
+        RecentsTaskLoader loader = Recents.getTaskLoader();
+
+        // In the case where alt-tab is triggered, we never get a preloadRecents() call, so we
+        // should always preload the tasks now. If we are dragging in recents, reload them as
+        // the stacks might have changed.
+        if (mLaunchedWhileDocking || mTriggeredFromAltTab || sInstanceLoadPlan == null) {
+            // Create a new load plan if preloadRecents() was never triggered
+            sInstanceLoadPlan = loader.createLoadPlan(mContext);
+        }
+        if (mLaunchedWhileDocking || mTriggeredFromAltTab || !sInstanceLoadPlan.hasTasks()) {
+            loader.preloadTasks(sInstanceLoadPlan, topTask.id, isTopTaskHome);
+        }
+        TaskStack stack = sInstanceLoadPlan.getTaskStack();
+
+        // Update the header bar if necessary
+        updateHeaderBarLayout(false /* tryAndBindSearchWidget */, stack);
+
+        // Prepare the dummy stack for the transition
+        TaskStackLayoutAlgorithm.VisibilityReport stackVr =
+                mDummyStackView.computeStackVisibilityReport();
+
+        if (!animate) {
+            ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, -1, -1);
+            startRecentsActivity(topTask, opts, false /* fromHome */,
+                    false /* fromSearchHome */, false /* fromThumbnail*/, stackVr);
+            return;
+        }
+
+        boolean hasRecentTasks = stack.getTaskCount() > 0;
+        boolean useThumbnailTransition = (topTask != null) && !isTopTaskHome && hasRecentTasks;
+
+        if (useThumbnailTransition) {
+            // Try starting with a thumbnail transition
+            ActivityOptions opts = getThumbnailTransitionActivityOptionsForTV(topTask);
+            if (opts != null) {
+                startRecentsActivity(topTask, opts, false /* fromHome */,
+                        false /* fromSearchHome */, true /* fromThumbnail */, stackVr);
+            } else {
+                // Fall through below to the non-thumbnail transition
+                useThumbnailTransition = false;
+            }
+        }
+
+        if (!useThumbnailTransition) {
+            // If there is no thumbnail transition, but is launching from home into recents, then
+            // use a quick home transition and do the animation from home
+            if (hasRecentTasks) {
+                SystemServicesProxy ssp = Recents.getSystemServices();
+                String homeActivityPackage = ssp.getHomeActivityPackageName();
+                String searchWidgetPackage = null;
+                if (RecentsDebugFlags.Static.EnableSearchBar) {
+                    searchWidgetPackage = Prefs.getString(mContext,
+                            Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_PACKAGE, null);
+                } else {
+                    AppWidgetProviderInfo searchWidgetInfo = ssp.resolveSearchAppWidget();
+                    if (searchWidgetInfo != null) {
+                        searchWidgetPackage = searchWidgetInfo.provider.getPackageName();
+                    }
+                }
+
+                // Determine whether we are coming from a search owned home activity
+                boolean fromSearchHome = (homeActivityPackage != null) &&
+                        homeActivityPackage.equals(searchWidgetPackage);
+                ActivityOptions opts = getHomeTransitionActivityOptions(fromSearchHome);
+                startRecentsActivity(topTask, opts, true /* fromHome */, fromSearchHome,
+                        false /* fromThumbnail */, stackVr);
+            } else {
+                // Otherwise we do the normal fade from an unknown source
+                ActivityOptions opts = getUnknownTransitionActivityOptions();
+                startRecentsActivity(topTask, opts, true /* fromHome */,
+                        false /* fromSearchHome */, false /* fromThumbnail */, stackVr);
+            }
+        }
+        mLastToggleTime = SystemClock.elapsedRealtime();
+    }
+
+    /**
      * Starts the recents activity.
      */
     private void startRecentsActivity(ActivityManager.RunningTaskInfo topTask,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
index 48a1904..365b29d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
@@ -29,6 +29,7 @@
 
 public class ViewFocusAnimator implements View.OnFocusChangeListener {
     private final float mUnselectedScale;
+    private final float mSelectedScale;
     private final float mSelectedScaleDelta;
     private final float mUnselectedZ;
     private final float mSelectedZDelta;
@@ -49,8 +50,9 @@
         TypedValue out = new TypedValue();
         res.getValue(R.integer.unselected_scale, out, true);
         mUnselectedScale = out.getFloat();
-        mSelectedScaleDelta = res.getFraction(R.fraction.lb_focus_zoom_factor_medium, 1, 1) -
-                mUnselectedScale;
+        res.getValue(R.integer.selected_scale, out, true);
+        mSelectedScale = out.getFloat();
+        mSelectedScaleDelta = mSelectedScale - mUnselectedScale;
 
         mUnselectedZ = res.getDimensionPixelOffset(R.dimen.recents_tv_unselected_item_z);
         mSelectedZDelta = res.getDimensionPixelOffset(R.dimen.recents_tv_selected_item_z_delta);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java
index ef8d48e..bd3143f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java
@@ -16,10 +16,8 @@
 package com.android.systemui.recents.tv.views;
 
 import android.annotation.Nullable;
-import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.content.Context;
-import android.graphics.Bitmap;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Handler;
@@ -121,10 +119,10 @@
             };
         }
         try {
-            Rect taskRect = taskView.getGlobalRect();
+            Rect taskRect = taskView.getFocusedThumbnailRect();
             WindowManagerGlobal.getWindowManagerService()
-                    .overridePendingAppTransitionThumb(task.thumbnail, taskRect.left,
-                            taskRect.top, callback, true);
+                    .overridePendingAppTransitionAspectScaledThumb(task.thumbnail, taskRect.left,
+                            taskRect.top, taskRect.width(), taskRect.height(), callback, true);
         } catch (RemoteException e) {
             Log.w(TAG, "Failed to override transition: " + e);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
index 7d8a3ce..5775b60 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
@@ -16,8 +16,13 @@
 package com.android.systemui.recents.tv.views;
 
 import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.Display;
+import android.view.WindowManager;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -71,15 +76,46 @@
         mThumbnailView.getFocusedRect(r);
     }
 
-    public Rect getFocusedRect() {
+    public Rect getFocusedThumbnailRect() {
         Rect r = new Rect();
-        getFocusedRect(r);
+        mThumbnailView.getGlobalVisibleRect(r);
+        TypedValue out = new TypedValue();
+        getContext().getResources().getValue(R.integer.selected_scale, out, true);
+        float deltaScale = (out.getFloat() - 1.0f) / 2;
+        r.set((int) (r.left - r.left * deltaScale),
+                (int) (r.top - r.top * deltaScale),
+                (int) (r.right + r.right * deltaScale),
+                (int) (r.bottom + r.bottom * deltaScale));
         return r;
     }
 
-    public Rect getGlobalRect() {
-        Rect r = new Rect();
-        getGlobalVisibleRect(r);
-        return r;
+    public static Rect getStartingCardThumbnailRect(Context context) {
+        Resources res = context.getResources();
+
+        TypedValue out = new TypedValue();
+        res.getValue(R.integer.selected_scale, out, true);
+        float scale = out.getFloat();
+
+        int width = res.getDimensionPixelOffset(R.dimen.recents_tv_card_width);
+        int widthDelta = (int) (width * scale - width);
+        int height = (int) (res.getDimensionPixelOffset(
+                R.dimen.recents_tv_screenshot_height) * scale);
+        int padding = res.getDimensionPixelOffset(R.dimen.recents_tv_grid_row_padding);
+
+        int headerHeight = (int) ((res.getDimensionPixelOffset(
+                R.dimen.recents_tv_card_extra_badge_size) +
+                res.getDimensionPixelOffset(R.dimen.recents_tv_icon_padding_bottom)) * scale);
+
+        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        Display display = wm.getDefaultDisplay();
+        Point size = new Point();
+        display.getSize(size);
+        int screenWidth = size.x;
+        int screenHeight = size.y;
+
+        return new Rect(screenWidth - width - padding - widthDelta / 2,
+                screenHeight / 2 - height / 2 + headerHeight / 2,
+                screenWidth - padding + widthDelta / 2,
+                screenHeight / 2 + height / 2 + headerHeight / 2);
     }
 }