Improve Animation Calculations to remove Jank

Add animations to back button press path.

Add scroll for launches of unfocused apps.

Part 1 of 2 to fix:

b/27876144

Change-Id: I1ac345dffb06d7926558a4087b07061ee4be731b
This commit is contained in:
Sid Soundararajan
2016-04-05 18:00:38 -07:00
parent 15971223dc
commit c81082b7ee
5 changed files with 66 additions and 29 deletions

View File

@@ -31,8 +31,10 @@ import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsImpl;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.model.ThumbnailData;
import com.android.systemui.recents.tv.views.TaskCardView;
public class RecentsTvImpl extends RecentsImpl{
@@ -124,12 +126,15 @@ public class RecentsTvImpl extends RecentsImpl{
*/
private ActivityOptions getThumbnailTransitionActivityOptionsForTV(
ActivityManager.RunningTaskInfo topTask) {
Bitmap thumbnail = mThumbTransitionBitmapCache;
Rect rect = TaskCardView.getStartingCardThumbnailRect(mContext);
if (thumbnail != null) {
SystemServicesProxy ssp = Recents.getSystemServices();
ThumbnailData thumbnailData = ssp.getTaskThumbnail(topTask.id);
if (thumbnailData.thumbnail != null) {
Bitmap thumbnail = Bitmap.createScaledBitmap(thumbnailData.thumbnail, rect.width(),
rect.height(), false);
return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
null, (int) rect.left, (int) rect.top,
(int) rect.width(), (int) rect.height(), mHandler, null);
thumbnail, (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();

View File

@@ -16,8 +16,10 @@
package com.android.systemui.recents.tv.views;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityOptions;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
@@ -120,8 +122,10 @@ public class RecentsTvTransitionHelper {
}
try {
Rect taskRect = taskView.getFocusedThumbnailRect();
Bitmap thumbnail = Bitmap.createScaledBitmap(task.thumbnail, taskRect.width(),
taskRect.height(), false);
WindowManagerGlobal.getWindowManagerService()
.overridePendingAppTransitionAspectScaledThumb(task.thumbnail, taskRect.left,
.overridePendingAppTransitionAspectScaledThumb(thumbnail, taskRect.left,
taskRect.top, taskRect.width(), taskRect.height(), callback, true);
} catch (RemoteException e) {
Log.w(TAG, "Failed to override transition: " + e);

View File

@@ -18,7 +18,10 @@ package com.android.systemui.recents.tv.views;
import android.content.Context;
import android.graphics.Rect;
import android.os.Handler;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowInsets;
@@ -32,15 +35,15 @@ import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
import com.android.systemui.recents.events.activity.ExitRecentsWindowFirstAnimationFrameEvent;
import com.android.systemui.recents.events.activity.LaunchTvTaskEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.tv.animations.RecentsRowFocusAnimationHolder;
import java.util.ArrayList;
import java.util.List;
import android.support.v7.widget.RecyclerView.OnScrollListener;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
/**
* Top level layout of recents for TV. This will show the TaskStacks using a HorizontalGridView.
@@ -58,7 +61,7 @@ public class RecentsTvView extends FrameLayout {
private Rect mSystemInsets = new Rect();
private RecentsTvTransitionHelper mTransitionHelper;
private Handler mHandler;
private OnScrollListener mScrollListener;
public RecentsTvView(Context context) {
this(context, null);
}
@@ -111,8 +114,7 @@ public class RecentsTvView extends FrameLayout {
if (mTaskStackHorizontalView != null) {
Task task = mTaskStackHorizontalView.getFocusedTask();
if (task != null) {
SystemServicesProxy ssp = Recents.getSystemServices();
ssp.startActivityFromRecents(getContext(), task.key, task.title, null);
launchTaskFomRecents(task);
return true;
}
}
@@ -125,25 +127,53 @@ public class RecentsTvView extends FrameLayout {
TaskStack stack = mTaskStackHorizontalView.getStack();
Task task = stack.getLaunchTarget();
if (task != null) {
SystemServicesProxy ssp = Recents.getSystemServices();
ssp.startActivityFromRecents(getContext(), task.key, task.title, null);
launchTaskFomRecents(task);
return true;
}
}
return false;
}
/** Launches a given task. */
public boolean launchTask(Task task, Rect taskBounds, int destinationStack) {
if (mTaskStackHorizontalView != null) {
// Iterate the stack views and try and find the given task.
if (mTaskStackHorizontalView.getChildViewForTask(task) != null) {
SystemServicesProxy ssp = Recents.getSystemServices();
ssp.startActivityFromRecents(getContext(), task.key, task.title, null);
return true;
/**
* Launch the given task from recents with animation. If the task is not focused, this will
* attempt to scroll to focus the task before launching.
* @param task
*/
private void launchTaskFomRecents(final Task task) {
if(task != mTaskStackHorizontalView.getFocusedTask()) {
if(mScrollListener != null) {
mTaskStackHorizontalView.removeOnScrollListener(mScrollListener);
}
mScrollListener = new OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if(newState == RecyclerView.SCROLL_STATE_IDLE) {
TaskCardView cardView = mTaskStackHorizontalView.getChildViewForTask(task);
if(cardView != null) {
mTransitionHelper.launchTaskFromRecents(mStack, task,
mTaskStackHorizontalView, cardView, null, INVALID_STACK_ID);
} else {
// This should not happen normally. If this happens then the data in
// the grid view was altered during the scroll. Log error and launch
// task with no animation.
Log.e(TAG, "Card view for task : " + task + ", returned null.");
SystemServicesProxy ssp = Recents.getSystemServices();
ssp.startActivityFromRecents(getContext(), task.key, task.title, null);
}
mTaskStackHorizontalView.removeOnScrollListener(mScrollListener);
}
}
};
mTaskStackHorizontalView.addOnScrollListener(mScrollListener);
mTaskStackHorizontalView.setSelectedPositionSmooth(
((TaskStackHorizontalViewAdapter) mTaskStackHorizontalView.getAdapter())
.getPositionOfTask(task));
} else {
mTransitionHelper.launchTaskFromRecents(mStack, task, mTaskStackHorizontalView,
mTaskStackHorizontalView.getChildViewForTask(task), null,
INVALID_STACK_ID);
}
return false;
}
/**

View File

@@ -91,13 +91,6 @@ public class TaskCardView extends LinearLayout {
public Rect getFocusedThumbnailRect() {
Rect r = new Rect();
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;
}

View File

@@ -131,4 +131,9 @@ public class TaskStackHorizontalViewAdapter extends
mTaskList.remove(position);
notifyItemRemoved(position);
}
public int getPositionOfTask(Task task) {
int position = mTaskList.indexOf(task);
return (position >= 0) ? position : 0;
}
}