diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index 0cc2a67a3be34..ece34fb8fb63a 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -6,7 +6,9 @@ LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-proto-files-under,src) $(call all-Iaidl-files-under, src) \
src/com/android/systemui/EventLogTags.logtags
-LOCAL_STATIC_JAVA_LIBRARIES := Keyguard
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ Keyguard \
+ android-support-v7-recyclerview
LOCAL_JAVA_LIBRARIES := telephony-common
LOCAL_PACKAGE_NAME := SystemUI
diff --git a/packages/SystemUI/res/layout/recents.xml b/packages/SystemUI/res/layout/recents.xml
index 064d2258150fe..2c010ddc6bddb 100644
--- a/packages/SystemUI/res/layout/recents.xml
+++ b/packages/SystemUI/res/layout/recents.xml
@@ -39,6 +39,12 @@
android:layout_width="match_parent"
android:layout_height="match_parent" />
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_history_button.xml b/packages/SystemUI/res/layout/recents_history_button.xml
new file mode 100644
index 0000000000000..38457c7b2a61b
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents_history_button.xml
@@ -0,0 +1,26 @@
+
+
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_history_date.xml b/packages/SystemUI/res/layout/recents_history_date.xml
new file mode 100644
index 0000000000000..6d6a9eed6187d
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents_history_date.xml
@@ -0,0 +1,28 @@
+
+
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_history_task.xml b/packages/SystemUI/res/layout/recents_history_task.xml
new file mode 100644
index 0000000000000..b9de15606bfb4
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents_history_task.xml
@@ -0,0 +1,27 @@
+
+
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index d8193abfa2dc5..902db26d21fae 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -177,6 +177,9 @@
225
+
+ 250
+
96
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index e0c0f6a5bb1bd..04233ba064bd3 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -698,6 +698,10 @@
search
Could not start %s.
+
+ More
+
+ History
Split Horizontal
@@ -1157,21 +1161,26 @@
Use the new Quick Settings
-
+
Enable paging
-
+
Enable paging via the Overview button
-
+
Enable fast toggle
-
+
Enable launch timeout while paging
-
+
Enable fullscreen screenshots
-
+
Enable fullscreen screenshots in Overview
+
+ Show History
+
+ Enables the history view to see more recent tasks
+
Experimental
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 4d07d5f2c9a34..f398af3d04c99 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -102,6 +102,11 @@
android:title="@string/overview_fullscreen_thumbnails"
android:summary="@string/overview_fullscreen_thumbnails_desc" />
+
+
{
+
+ private static final String TAG = "RecentsHistoryView";
+ private static final boolean DEBUG = false;
+
+ static final int DATE_ROW_VIEW_TYPE = 0;
+ static final int TASK_ROW_VIEW_TYPE = 1;
+
+ /**
+ * View holder implementation.
+ */
+ public static class ViewHolder extends RecyclerView.ViewHolder {
+ public View mContent;
+
+ public ViewHolder(View v) {
+ super(v);
+ mContent = v;
+ }
+ }
+
+ /**
+ * A single row of content.
+ */
+ private interface Row {
+ int getViewType();
+ }
+
+ /**
+ * A date row.
+ */
+ private static class DateRow implements Row {
+
+ public final String date;
+
+ public DateRow(String date) {
+ this.date = date;
+ }
+
+ @Override
+ public int getViewType() {
+ return RecentsHistoryAdapter.DATE_ROW_VIEW_TYPE;
+ }
+ }
+
+ /**
+ * A task row.
+ */
+ private static class TaskRow implements Row, View.OnClickListener {
+
+ public final String description;
+ private final int mTaskId;
+
+ public TaskRow(Task task) {
+ mTaskId = task.key.id;
+ description = task.activityLabel;
+ }
+
+ @Override
+ public void onClick(View v) {
+ SystemServicesProxy ssp = Recents.getSystemServices();
+ ssp.startActivityFromRecents(v.getContext(), mTaskId, description,
+ ActivityOptions.makeBasic());
+ }
+
+ @Override
+ public int getViewType() {
+ return RecentsHistoryAdapter.TASK_ROW_VIEW_TYPE;
+ }
+ }
+
+ private LayoutInflater mLayoutInflater;
+ private final List mRows = new ArrayList<>();
+
+ public RecentsHistoryAdapter(Context context, TaskStack stack) {
+ mLayoutInflater = LayoutInflater.from(context);
+ updateTasks(context, stack.getTasks());
+ }
+
+ /**
+ * Updates this adapter with the given tasks.
+ */
+ public void updateTasks(Context context, List tasks) {
+ final Locale l = context.getResources().getConfiguration().locale;
+ final String dateFormatStr = DateFormat.getBestDateTimePattern(l, "EEEEMMMMd");
+ final List tasksMostRecent = new ArrayList<>(tasks);
+ Collections.reverse(tasksMostRecent);
+ int prevDayKey = -1;
+ mRows.clear();
+ for (Task task : tasksMostRecent) {
+ if (SystemServicesProxy.isFreeformStack(task.key.stackId)) {
+ continue;
+ }
+
+ Calendar cal = Calendar.getInstance(l);
+ cal.setTimeInMillis(task.key.lastActiveTime);
+ int dayKey = Objects.hash(cal.get(Calendar.YEAR), cal.get(Calendar.DAY_OF_YEAR));
+ if (dayKey != prevDayKey) {
+ prevDayKey = dayKey;
+ mRows.add(new DateRow(DateFormat.format(dateFormatStr, cal).toString()));
+ }
+ mRows.add(new TaskRow(task));
+ }
+ }
+
+ @Override
+ public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ switch (viewType) {
+ case DATE_ROW_VIEW_TYPE:
+ return new ViewHolder(mLayoutInflater.inflate(R.layout.recents_history_date, parent,
+ false));
+ case TASK_ROW_VIEW_TYPE:
+ return new ViewHolder(mLayoutInflater.inflate(R.layout.recents_history_task, parent,
+ false));
+ default:
+ return new ViewHolder(null);
+ }
+ }
+
+ @Override
+ public void onBindViewHolder(ViewHolder holder, int position) {
+ Row row = mRows.get(position);
+ int viewType = mRows.get(position).getViewType();
+ switch (viewType) {
+ case DATE_ROW_VIEW_TYPE: {
+ TextView tv = (TextView) holder.mContent;
+ tv.setText(((DateRow) row).date);
+ break;
+ }
+ case TASK_ROW_VIEW_TYPE: {
+ TextView tv = (TextView) holder.mContent;
+ TaskRow taskRow = (TaskRow) row;
+ tv.setText(taskRow.description);
+ tv.setOnClickListener(taskRow);
+ break;
+ }
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ return mRows.size();
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ return mRows.get(position).getViewType();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java
new file mode 100644
index 0000000000000..1ad79aea56a94
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.history;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.WindowInsets;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+import android.widget.LinearLayout;
+
+import com.android.systemui.R;
+import com.android.systemui.recents.RecentsActivity;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.misc.ReferenceCountedTrigger;
+import com.android.systemui.recents.model.TaskStack;
+
+/**
+ * A list of the recent tasks that are not in the stack.
+ */
+public class RecentsHistoryView extends LinearLayout {
+
+ private static final String TAG = "RecentsHistoryView";
+ private static final boolean DEBUG = false;
+
+ private RecyclerView mRecyclerView;
+ private boolean mIsVisible;
+
+ private Interpolator mFastOutSlowInInterpolator;
+ private Interpolator mFastOutLinearInInterpolator;
+ private int mHistoryTransitionDuration;
+
+ public RecentsHistoryView(Context context) {
+ super(context);
+ }
+
+ public RecentsHistoryView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public RecentsHistoryView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public RecentsHistoryView(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ Resources res = context.getResources();
+ mHistoryTransitionDuration = res.getInteger(R.integer.recents_history_transition_duration);
+ mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
+ com.android.internal.R.interpolator.fast_out_slow_in);
+ mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context,
+ com.android.internal.R.interpolator.fast_out_linear_in);
+ }
+
+ /**
+ * Updates this history view with the recent tasks, and then shows it.
+ */
+ public void show(TaskStack stack) {
+ setVisibility(View.VISIBLE);
+ setAlpha(0f);
+ animate()
+ .alpha(1f)
+ .setDuration(mHistoryTransitionDuration)
+ .setInterpolator(mFastOutSlowInInterpolator)
+ .withLayer()
+ .start();
+
+ mRecyclerView.setAdapter(new RecentsHistoryAdapter(getContext(), stack));
+ mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
+ mIsVisible = true;
+ }
+
+ /**
+ * Hides this history view.
+ */
+ public void hide(boolean animate, final ReferenceCountedTrigger postAnimationTrigger) {
+ if (animate) {
+ animate()
+ .alpha(0f)
+ .setDuration(mHistoryTransitionDuration)
+ .setInterpolator(mFastOutLinearInInterpolator)
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ setVisibility(View.INVISIBLE);
+ if (postAnimationTrigger != null) {
+ postAnimationTrigger.decrement();
+ }
+ }
+ })
+ .withLayer()
+ .start();
+ if (postAnimationTrigger != null) {
+ postAnimationTrigger.increment();
+ }
+ } else {
+ setAlpha(0f);
+ setVisibility(View.INVISIBLE);
+ }
+ mIsVisible = false;
+ }
+
+ /**
+ * Updates the system insets of this history view to the provided values.
+ */
+ public void setSystemInsets(Rect systemInsets) {
+ setPadding(systemInsets.left, systemInsets.top, systemInsets.right, systemInsets.bottom);
+ }
+
+ /**
+ * Returns whether this view is visible.
+ */
+ public boolean isVisible() {
+ return mIsVisible;
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mRecyclerView = (RecyclerView) findViewById(R.id.list);
+ }
+
+ @Override
+ public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ setSystemInsets(insets.getSystemWindowInsets());
+ return insets;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 90456c0838d73..d700786086b0c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -17,6 +17,7 @@
package com.android.systemui.recents.views;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -25,20 +26,26 @@ import android.util.ArraySet;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
+import android.view.View;
import android.view.WindowInsets;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
-import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsActivity;
import com.android.systemui.recents.RecentsActivityLaunchState;
import com.android.systemui.recents.RecentsAppWidgetHostView;
import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.RecentsDebugFlags;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
+import com.android.systemui.recents.events.activity.DebugFlagsChangedEvent;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
+import com.android.systemui.recents.events.activity.HideHistoryButtonEvent;
+import com.android.systemui.recents.events.activity.HideHistoryEvent;
+import com.android.systemui.recents.events.activity.ShowHistoryButtonEvent;
+import com.android.systemui.recents.events.activity.ShowHistoryEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent;
import com.android.systemui.recents.events.ui.DraggingInRecentsEvent;
@@ -63,11 +70,12 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
private static final String TAG = "RecentsView";
private static final boolean DEBUG = false;
- LayoutInflater mInflater;
Handler mHandler;
+ TaskStack mStack;
TaskStackView mTaskStackView;
RecentsAppWidgetHostView mSearchBar;
+ View mHistoryButton;
boolean mAwaitingFirstLayout = true;
boolean mLastTaskLaunchedWasFreeform;
@@ -81,7 +89,9 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
TaskStack.DockState.BOTTOM,
};
- Interpolator mFastOutSlowInInterpolator;
+ private Interpolator mFastOutSlowInInterpolator;
+ private Interpolator mFastOutLinearInInterpolator;
+ private int mHistoryTransitionDuration;
Rect mSystemInsets = new Rect();
@@ -99,18 +109,31 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
public RecentsView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+ Resources res = context.getResources();
setWillNotDraw(false);
- mInflater = LayoutInflater.from(context);
mHandler = new Handler();
mTransitionHelper = new RecentsTransitionHelper(getContext(), mHandler);
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_slow_in);
+ mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context,
+ com.android.internal.R.interpolator.fast_out_linear_in);
+ mHistoryTransitionDuration = res.getInteger(R.integer.recents_history_transition_duration);
mTouchHandler = new RecentsViewTouchHandler(this);
+
+ LayoutInflater inflater = LayoutInflater.from(context);
+ mHistoryButton = inflater.inflate(R.layout.recents_history_button, this, false);
+ mHistoryButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ EventBus.getDefault().send(new ShowHistoryEvent());
+ }
+ });
}
/** Set/get the bsp root node */
public void setTaskStack(TaskStack stack) {
RecentsConfiguration config = Recents.getConfiguration();
+ mStack = stack;
if (config.getLaunchState().launchedReuseTaskStackViews) {
if (mTaskStackView != null) {
// If onRecentsHidden is not triggered, we need to the stack view again here
@@ -129,6 +152,11 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
mTaskStackView.setCallbacks(this);
addView(mTaskStackView);
}
+ if (indexOfChild(mHistoryButton) == -1) {
+ addView(mHistoryButton);
+ } else {
+ mHistoryButton.bringToFront();
+ }
// Trigger a new layout
requestLayout();
@@ -141,6 +169,13 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
return mLastTaskLaunchedWasFreeform;
}
+ /**
+ * Returns the currently set task stack.
+ */
+ public TaskStack getTaskStack() {
+ return mStack;
+ }
+
/** Gets the next task in the stack - or if the last - the top task */
public Task getNextTaskOrTopTask(Task taskToSearch) {
Task returnTask = null;
@@ -219,10 +254,15 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
}
ctx.postAnimationTrigger.decrement();
+ // Hide the history button
+ int taskViewExitToHomeDuration = getResources().getInteger(
+ R.integer.recents_task_exit_to_home_duration);
+ hideHistoryButton(taskViewExitToHomeDuration);
+
// If we are going home, cancel the previous task's window transition
EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(null));
- // Notify of the exit animation
+ // Notify sof the exit animation
EventBus.getDefault().send(new DismissRecentsToHomeAnimationStarted());
}
@@ -253,6 +293,13 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
}
}
+ /**
+ * Returns the last known system insets.
+ */
+ public Rect getSystemInsets() {
+ return mSystemInsets;
+ }
+
@Override
protected void onAttachedToWindow() {
EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
@@ -301,6 +348,10 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
MeasureSpec.makeMeasureSpec(taskRect.height(), MeasureSpec.AT_MOST));
}
+ Rect stackRect = mTaskStackView.mLayoutAlgorithm.mCurrentStackRect;
+ measureChild(mHistoryButton,
+ MeasureSpec.makeMeasureSpec(stackRect.width(), MeasureSpec.EXACTLY),
+ heightMeasureSpec);
setMeasuredDimension(width, height);
}
@@ -330,6 +381,11 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
top + mDragView.getMeasuredHeight());
}
+ Rect stackRect = mTaskStackView.mLayoutAlgorithm.mCurrentStackRect;
+ mHistoryButton.layout(stackRect.left, stackRect.top,
+ stackRect.left + mHistoryButton.getMeasuredWidth(),
+ stackRect.top + mHistoryButton.getMeasuredHeight());
+
if (mAwaitingFirstLayout) {
mAwaitingFirstLayout = false;
@@ -346,7 +402,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
mSystemInsets.set(insets.getSystemWindowInsets());
requestLayout();
- return insets.consumeSystemWindowInsets();
+ return insets;
}
@Override
@@ -492,6 +548,67 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
animate().translationY(0f);
}
+ public final void onBusEvent(ShowHistoryEvent event) {
+ // Hide the history button when the history view is shown
+ hideHistoryButton(mHistoryTransitionDuration);
+ }
+
+ public final void onBusEvent(HideHistoryEvent event) {
+ // Show the history button when the history view is hidden
+ showHistoryButton(mHistoryTransitionDuration);
+ }
+
+ public final void onBusEvent(ShowHistoryButtonEvent event) {
+ showHistoryButton(150);
+ }
+
+ public final void onBusEvent(HideHistoryButtonEvent event) {
+ hideHistoryButton(100);
+ }
+
+ public final void onBusEvent(DebugFlagsChangedEvent event) {
+ RecentsDebugFlags debugFlags = Recents.getDebugFlags();
+ if (!debugFlags.isHistoryEnabled()) {
+ hideHistoryButton(100);
+ }
+ }
+
+ /**
+ * Shows the history button.
+ */
+ private void showHistoryButton(int duration) {
+ RecentsDebugFlags debugFlags = Recents.getDebugFlags();
+ if (!debugFlags.isHistoryEnabled()) {
+ return;
+ }
+
+ mHistoryButton.setVisibility(View.VISIBLE);
+ mHistoryButton.animate()
+ .alpha(1f)
+ .setDuration(duration)
+ .setInterpolator(mFastOutSlowInInterpolator)
+ .withLayer()
+ .start();
+ }
+
+ /**
+ * Hides the history button.
+ */
+ private void hideHistoryButton(int duration) {
+ mHistoryButton.animate()
+ .alpha(0f)
+ .setDuration(duration)
+ .setInterpolator(mFastOutLinearInInterpolator)
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ mHistoryButton.setVisibility(View.INVISIBLE);
+ }
+ })
+ .withLayer()
+ .start();
+ }
+
/**
* Updates the dock region to match the specified dock state.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index 5d091b19e4e60..1acc9433b9fae 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -573,7 +573,7 @@ public class TaskStackLayoutAlgorithm {
(mCurrentStackRect.height() - mTaskRect.height()) / 2;
y = centerYOffset + getYForDeltaP(p, 0);
z = mMaxTranslationZ;
- relP = p;
+ relP = 1f;
} else {
// Otherwise, update the task to the stack layout
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 67710bfd6294f..04a14e4d31f3a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -42,8 +42,12 @@ import com.android.systemui.recents.RecentsDebugFlags;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
+import com.android.systemui.recents.events.activity.HideHistoryButtonEvent;
+import com.android.systemui.recents.events.activity.HideHistoryEvent;
import com.android.systemui.recents.events.activity.IterateRecentsEvent;
import com.android.systemui.recents.events.activity.PackagesChangedEvent;
+import com.android.systemui.recents.events.activity.ShowHistoryButtonEvent;
+import com.android.systemui.recents.events.activity.ShowHistoryEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
@@ -82,6 +86,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
private final static String TAG = "TaskStackView";
private final static boolean DEBUG = false;
+ // The thresholds at which to show/hide the history button.
+ private static final float SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD = 0.3f;
+ private static final float HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD = 0.3f;
+
/** The TaskView callbacks */
interface TaskStackViewCallbacks {
public void onTaskViewClicked(TaskStackView stackView, TaskView tv, TaskStack stack, Task t,
@@ -1017,6 +1025,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
false /* requestViewFocus */);
}
+ // Update the history button visibility
+ if (mStackScroller.getStackScroll() < SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD) {
+ EventBus.getDefault().send(new ShowHistoryButtonEvent());
+ }
+
// Start dozing
mUIDozeTrigger.startDozing();
}
@@ -1333,10 +1346,18 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/**** TaskStackViewScroller.TaskStackViewScrollerCallbacks ****/
@Override
- public void onScrollChanged(float p) {
+ public void onScrollChanged(float prevScroll, float curScroll) {
mUIDozeTrigger.poke();
requestSynchronizeStackViewsWithModel();
postInvalidateOnAnimation();
+
+ if (prevScroll > SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD &&
+ curScroll <= SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD) {
+ EventBus.getDefault().send(new ShowHistoryButtonEvent());
+ } else if (prevScroll < HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD &&
+ curScroll >= HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD) {
+ EventBus.getDefault().send(new HideHistoryButtonEvent());
+ }
}
/**** EventBus Events ****/
@@ -1496,15 +1517,30 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
}
+ public final void onBusEvent(ShowHistoryEvent event) {
+ List taskViews = getTaskViews();
+ int taskViewCount = taskViews.size();
+ for (int i = taskViewCount - 1; i >= 0; i--) {
+ TaskView tv = taskViews.get(i);
+ tv.animate().alpha(0f).setDuration(200).start();
+ }
+ }
+
+ public final void onBusEvent(HideHistoryEvent event) {
+ List taskViews = getTaskViews();
+ int taskViewCount = taskViews.size();
+ for (int i = taskViewCount - 1; i >= 0; i--) {
+ TaskView tv = taskViews.get(i);
+ tv.animate().alpha(1f).setDuration(200).start();
+ }
+ }
+
/**
* Removes the task from the stack, and updates the focus to the next task in the stack if the
* removed TaskView was focused.
*/
private void removeTaskViewFromStack(TaskView tv) {
- SystemServicesProxy ssp = Recents.getSystemServices();
Task task = tv.getTask();
- int taskIndex = mStack.indexOfTask(task);
- boolean taskWasFocused = tv.isFocusedTask();
// Reset the previously focused task before it is removed from the stack
resetFocusedTask();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
index 62b640ee36f92..90b73fe2757d5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
@@ -35,7 +35,7 @@ public class TaskStackViewScroller {
private static final boolean DEBUG = false;
public interface TaskStackViewScrollerCallbacks {
- void onScrollChanged(float p);
+ void onScrollChanged(float prevScroll, float curScroll);
}
Context mContext;
@@ -78,9 +78,10 @@ public class TaskStackViewScroller {
/** Sets the current stack scroll */
public void setStackScroll(float s) {
+ float prevStackScroll = mStackScrollP;
mStackScrollP = s;
if (mCb != null) {
- mCb.onScrollChanged(mStackScrollP);
+ mCb.onScrollChanged(prevStackScroll, mStackScrollP);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 523f84f4adb70..44985d44fc0f8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -71,7 +71,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
ObjectAnimator mTaskProgressAnimator;
float mMaxDimScale;
int mDimAlpha;
- AccelerateInterpolator mDimInterpolator = new AccelerateInterpolator(1f);
+ AccelerateInterpolator mDimInterpolator = new AccelerateInterpolator(3f);
PorterDuffColorFilter mDimColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_ATOP);
Paint mDimLayerPaint = new Paint();
float mActionButtonTranslationZ;
@@ -265,15 +265,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
toTransform.translationZ = 0;
}
- /**
- * When we are un/filtering, this method will setup the transform that we are animating from,
- * in order to show the task.
- */
- void prepareTaskTransformForFilterTaskVisible(TaskViewTransform fromTransform) {
- // Fade the view in
- fromTransform.alpha = 0f;
- }
-
/** Prepares this task view for the enter-recents animations. This is called earlier in the
* first layout because the actual animation into recents may take a long time. */
void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask, boolean hideTask,
@@ -617,12 +608,9 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
/** Compute the dim as a function of the scale of this view. */
int getDimFromTaskProgress() {
- // TODO: Temporarily disable the dim on the stack
- /*
- float dim = mMaxDimScale * mDimInterpolator.getInterpolation(1f - mTaskProgress);
+ float x = mTaskProgress < 0 ? 1f : mDimInterpolator.getInterpolation(1f - mTaskProgress);
+ float dim = mMaxDimScale * x;
return (int) (dim * 255);
- */
- return 0;
}
/** Update the dim as a function of the scale of this view. */
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index fdc2543121574..9cf64d347e4a9 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -37,7 +37,10 @@ LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
LOCAL_PACKAGE_NAME := SystemUITests
-LOCAL_STATIC_JAVA_LIBRARIES := mockito-target Keyguard
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ mockito-target \
+ Keyguard \
+ android-support-v7-recyclerview
# sign this with platform cert, so this test is allowed to inject key events into
# UI it doesn't own. This is necessary to allow screenshots to be taken