diff --git a/packages/SystemUI/res/layout/recents_on_tv.xml b/packages/SystemUI/res/layout/recents_on_tv.xml index 3a7c1d10e642b..567e009d07eec 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 c5b1a7a517826..54e97da1471e2 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 @@ 268dip - 151dip + 151dip 20dip 114dip 64dip diff --git a/packages/SystemUI/res/values/values_tv.xml b/packages/SystemUI/res/values/values_tv.xml index 1fcc9e4a9d7ef..6a72e542482b0 100644 --- a/packages/SystemUI/res/values/values_tv.xml +++ b/packages/SystemUI/res/values/values_tv.xml @@ -15,4 +15,5 @@ limitations under the License. --> 1.0 + 1.1 diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index d864df8331e19..9be24def0da47 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.RecentsTaskLoader; 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 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener boolean mCanReuseTaskStackViews = true; boolean mDraggingInRecents; boolean mLaunchedWhileDocking; + private boolean mIsRunningOnTv; // Task launching Rect mSearchBarBounds = new Rect(); @@ -230,8 +232,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener 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 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } } + /** + * 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 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener 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. @@ -946,6 +971,90 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener mLastToggleTime = SystemClock.elapsedRealtime(); } + /** + * 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. */ 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 48a1904c03b11..365b29d676762 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 @@ import com.android.systemui.R; 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 @@ public class ViewFocusAnimator implements View.OnFocusChangeListener { 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 ef8d48e7f2cf3..bd3143f688cc2 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 @@ public class RecentsTvTransitionHelper { }; } 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 7d8a3ce32f450..5775b60ab3082 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 @@ public class TaskCardView extends LinearLayout { 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); } }