This adds the ability to lock task in recents so they won't be cleared when removing all tasks
Ticket: NOUGAT-1
Drawables from material.io
Change-Id: I06ffe411e72d4e837cfec7b9b77fb2519e417bc7
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:width="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@color/recents_task_bar_dark_icon_color"
+ android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM15.1,8L8.9,8L8.9,6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2z" />
+</vector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:width="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@color/recents_task_bar_light_icon_color"
+ android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM15.1,8L8.9,8L8.9,6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2z" />
+</vector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:width="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@color/recents_task_bar_dark_icon_color"
+ android:pathData="M12,17c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6h1.9c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM18,20L6,20L6,10h12v10z" />
+</vector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:width="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@color/recents_task_bar_light_icon_color"
+ android:pathData="M12,17c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6h1.9c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM18,20L6,20L6,10h12v10z" />
+</vector>
android:background="?android:selectableItemBackground"
android:alpha="0"
android:visibility="gone" />
+ <com.android.systemui.recents.views.FixedSizeImageView
+ android:id="@+id/lock_task"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/recents_task_view_header_lock_button_padding"
+ android:layout_gravity="end|center"
+ android:padding="@dimen/recents_task_view_header_button_padding"
+ android:src="@drawable/recents_dismiss_light"
+ android:background="?android:selectableItemBackground"
+ android:alpha="0"
+ android:visibility="gone" />
<!-- The progress indicator shows if auto-paging is enabled -->
<ViewStub android:id="@+id/focus_timer_indicator_stub"
<dimen name="navbar_single_hand_mode_horizontal_threshhold">90dp</dimen>
<dimen name="navbar_single_hand_mode_vertical_threshhold">48dp</dimen>
+
+ <dimen name="recents_task_view_header_lock_button_padding">48dp</dimen>
</resources>
import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.model.RecentsTaskLoader;
+import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.tv.RecentsTvImpl;
import com.android.systemui.stackdivider.Divider;
RECENTS_ACTIVITIES.add(RecentsTvImpl.RECENTS_TV_ACTIVITY);
}
+ public final static Set<Task> sLockedTasks = new HashSet<>();
+
// Purely for experimentation
private final static String RECENTS_OVERRIDE_SYSPROP_KEY = "persist.recents_override_pkg";
private final static String ACTION_SHOW_RECENTS = "com.android.systemui.recents.ACTION_SHOW";
* how they should update themselves.
*/
public void removeTask(Task t, AnimationProps animation, boolean fromDockGesture) {
+ if (Recents.sLockedTasks.contains(t)) {
+ Recents.sLockedTasks.remove(t);
+ }
if (mStackTaskList.contains(t)) {
removeTaskImpl(mStackTaskList, t);
Task newFrontMostTask = getStackFrontMostTask(false /* includeFreeform */);
ArrayList<Task> tasks = mStackTaskList.getTasks();
for (int i = tasks.size() - 1; i >= 0; i--) {
Task t = tasks.get(i);
+ if (Recents.sLockedTasks.contains(t)) {
+ continue;
+ }
removeTaskImpl(mStackTaskList, t);
mRawTaskList.remove(t);
}
public final void onBusEvent(final DismissAllTaskViewsEvent event) {
// Keep track of the tasks which will have their data removed
ArrayList<Task> tasks = new ArrayList<>(mStack.getStackTasks());
+ ArrayList<TaskView> deletedTasks = new ArrayList<>();
+ ArrayList<TaskView> taskViews = new ArrayList<>(getTaskViews());
+ for (TaskView t : taskViews) {
+ if (Recents.sLockedTasks.contains(t.getTask())) {
+ deletedTasks.add(t);
+ }
+ }
+ taskViews.removeAll(deletedTasks);
mAnimationHelper.startDeleteAllTasksAnimation(
- getTaskViews(), useGridLayout(), event.getAnimationTrigger());
+ taskViews, useGridLayout(), event.getAnimationTrigger());
event.addPostAnimationCallback(new Runnable() {
@Override
public void run() {
// Remove all tasks and delete the task data for all tasks
mStack.removeAllTasks();
for (int i = tasks.size() - 1; i >= 0; i--) {
- EventBus.getDefault().send(new DeleteTaskDataEvent(tasks.get(i)));
+ Task t = tasks.get(i);
+ if (Recents.sLockedTasks.contains(t)) continue;
+ EventBus.getDefault().send(new DeleteTaskDataEvent(t));
}
MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_DISMISS_ALL);
// Disallow dismissing an already dismissed task
TaskView tv = (TaskView) v;
Task task = tv.getTask();
- return !mSwipeHelperAnimations.containsKey(v) &&
- (mSv.getStack().indexOfStackTask(task) != -1);
+ return !mSwipeHelperAnimations.containsKey(v) && !Recents.sLockedTasks.contains(task)
+ && (mSv.getStack().indexOfStackTask(task) != -1);
}
/**
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
+import com.android.systemui.recents.model.TaskStack;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
TextView mTitleView;
ImageView mMoveTaskButton;
ImageView mDismissButton;
+ ImageView mLockTaskButton;
FrameLayout mAppOverlayView;
ImageView mAppIconView;
ImageView mAppInfoView;
Drawable mDarkFullscreenIcon;
Drawable mLightInfoIcon;
Drawable mDarkInfoIcon;
+ Drawable mLightLockedDrawable;
+ Drawable mLightUnlockedDrawable;
+ Drawable mDarkLockedDrawable;
+ Drawable mDarkUnlockedDrawable;
int mTaskBarViewLightTextColor;
int mTaskBarViewDarkTextColor;
int mDisabledTaskBarBackgroundColor;
mDarkInfoIcon = context.getDrawable(R.drawable.recents_info_dark);
mDisabledTaskBarBackgroundColor =
context.getColor(R.color.recents_task_bar_disabled_background_color);
+ mLightLockedDrawable = context.getDrawable(R.drawable.recents_locked_light);
+ mLightUnlockedDrawable = context.getDrawable(R.drawable.recents_unlocked_light);
+ mDarkLockedDrawable = context.getDrawable(R.drawable.recents_locked_dark);
+ mDarkUnlockedDrawable = context.getDrawable(R.drawable.recents_unlocked_dark);
// Configure the background and dim
mBackground = new HighlightColorDrawable();
mIconView.setOnLongClickListener(this);
mTitleView = (TextView) findViewById(R.id.title);
mDismissButton = (ImageView) findViewById(R.id.dismiss_task);
+ mLockTaskButton = (ImageView) findViewById(R.id.lock_task);
if (ssp.hasFreeformWorkspaceSupport()) {
mMoveTaskButton = (ImageView) findViewById(R.id.move_task);
}
}
mDismissButton.setVisibility(showDismissIcon ? View.VISIBLE : View.INVISIBLE);
mDismissButton.setTranslationX(rightInset);
+ mLockTaskButton.setVisibility(showDismissIcon ? View.VISIBLE : View.INVISIBLE);
setLeftTopRightBottom(0, 0, width, getMeasuredHeight());
}
mShouldDarkenBackgroundColor = flag;
}
+ private void updateLockTaskDrawable() {
+ mLockTaskButton.setImageDrawable(mTask.useLightOnPrimaryColor ?
+ (Recents.sLockedTasks.contains(mTask) ? mLightLockedDrawable : mLightUnlockedDrawable) :
+ (Recents.sLockedTasks.contains(mTask) ? mDarkLockedDrawable : mDarkUnlockedDrawable));
+ }
+
/**
* Binds the bar view to the task.
*/
mDismissButton.setOnClickListener(this);
mDismissButton.setClickable(false);
((RippleDrawable) mDismissButton.getBackground()).setForceSoftware(true);
+ updateLockTaskDrawable();
+ mLockTaskButton.setOnClickListener(this);
+ mLockTaskButton.setClickable(false);
+ ((RippleDrawable) mLockTaskButton.getBackground()).setForceSoftware(true);
// When freeform workspaces are enabled, then update the move-task button depending on the
// current task
} else {
mDismissButton.setAlpha(1f);
}
+ mLockTaskButton.setVisibility(View.VISIBLE);
+ mLockTaskButton.setClickable(true);
+ if (mLockTaskButton.getVisibility() == VISIBLE) {
+ mLockTaskButton.animate()
+ .alpha(1f)
+ .setInterpolator(Interpolators.FAST_OUT_LINEAR_IN)
+ .setDuration(duration)
+ .start();
+ } else {
+ mLockTaskButton.setAlpha(1f);
+ }
if (mMoveTaskButton != null) {
if (mMoveTaskButton.getVisibility() == VISIBLE) {
mMoveTaskButton.setVisibility(View.VISIBLE);
mDismissButton.animate().cancel();
mDismissButton.setAlpha(1f);
mDismissButton.setClickable(true);
+ mLockTaskButton.setVisibility(View.VISIBLE);
+ mLockTaskButton.animate().cancel();
+ mLockTaskButton.setAlpha(1f);
+ mLockTaskButton.setClickable(true);
if (mMoveTaskButton != null) {
mMoveTaskButton.setVisibility(View.VISIBLE);
mMoveTaskButton.animate().cancel();
mDismissButton.setVisibility(View.INVISIBLE);
mDismissButton.setAlpha(0f);
mDismissButton.setClickable(false);
+ mLockTaskButton.setVisibility(View.INVISIBLE);
+ mLockTaskButton.setAlpha(0f);
+ mLockTaskButton.setClickable(false);
if (mMoveTaskButton != null) {
mMoveTaskButton.setVisibility(View.INVISIBLE);
mMoveTaskButton.setAlpha(0f);
EventBus.getDefault().send(new ShowApplicationInfoEvent(mTask));
} else if (v == mDismissButton) {
TaskView tv = Utilities.findParent(this, TaskView.class);
- tv.dismissTask();
+ if (!Recents.sLockedTasks.contains(tv.getTask())) {
+ tv.dismissTask();
- // Keep track of deletions by the dismiss button
- MetricsLogger.histogram(getContext(), "overview_task_dismissed_source",
- Constants.Metrics.DismissSourceHeaderButton);
+ // Keep track of deletions by the dismiss button
+ MetricsLogger.histogram(getContext(), "overview_task_dismissed_source",
+ Constants.Metrics.DismissSourceHeaderButton);
+ }
} else if (v == mMoveTaskButton) {
TaskView tv = Utilities.findParent(this, TaskView.class);
EventBus.getDefault().send(new LaunchTaskEvent(tv, mTask, null,
EventBus.getDefault().send(new ShowApplicationInfoEvent(mTask));
} else if (v == mAppIconView) {
hideAppOverlay(false /* immediate */);
+ } else if (v == mLockTaskButton) {
+ if (Recents.sLockedTasks.contains(mTask)) {
+ Recents.sLockedTasks.remove(mTask);
+ } else {
+ Recents.sLockedTasks.add(mTask);
+ }
+ updateLockTaskDrawable();
}
}