Fixing a few potential crashes, preparing for Task affiliations framework changes.
- Deferring widget host listening to speed up startup
- Ensuring that we animate to the right task position in the stack and not just the front-most
- Removing assumption that we can only get screenshots for the most recent task
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 0c28488..e375433 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -23,12 +23,10 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.os.Handler;
-import android.os.SystemClock;
import android.os.UserHandle;
import android.view.View;
import com.android.systemui.R;
@@ -317,6 +315,11 @@
Rect getThumbnailTransitionRect(int runningTaskId) {
// Get the stack of tasks that we are animating into
TaskStack stack = RecentsTaskLoader.getShallowTaskStack(mSystemServicesProxy);
+ if (stack.getTaskCount() == 0) {
+ return new Rect();
+ }
+
+ // Get the stack
TaskStackView tsv = new TaskStackView(mContext, stack);
TaskStackViewLayoutAlgorithm algo = tsv.getStackAlgorithm();
tsv.computeRects(mTaskStackBounds.width(), mTaskStackBounds.height() - mStatusBarHeight, 0, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index d1efb57..56de0be 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -48,6 +48,7 @@
import com.android.systemui.recents.views.SystemBarScrimViews;
import com.android.systemui.recents.views.ViewAnimation;
+import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
@@ -125,7 +126,7 @@
}
}
- // Broadcast receiver to handle messages from our RecentsService
+ // Broadcast receiver to handle messages from AlternateRecentsComponent
final BroadcastReceiver mServiceBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -458,11 +459,6 @@
filter.addAction(ACTION_START_ENTER_ANIMATION);
registerReceiver(mServiceBroadcastReceiver, filter);
- // Start listening for widget package changes if there is one bound
- if (mConfig.searchBarAppWidgetId >= 0) {
- mAppWidgetHost.startListening(this);
- }
-
mVisible = true;
}
@@ -473,6 +469,22 @@
Console.AnsiRed);
}
super.onResume();
+
+ // Start listening for widget package changes if there is one bound, post it since we don't
+ // want it stalling the startup
+ if (mConfig.searchBarAppWidgetId >= 0) {
+ final WeakReference<RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks> callback =
+ new WeakReference<RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks>(this);
+ mRecentsView.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks cb = callback.get();
+ if (cb != null) {
+ mAppWidgetHost.startListening(cb);
+ }
+ }
+ }, 1);
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index 29f1440..94474e9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -396,7 +396,7 @@
Resources res = context.getResources();
ArrayList<Task> tasksToForceLoad = new ArrayList<Task>();
TaskStack stack = new TaskStack();
- SpaceNode root = new SpaceNode(context);
+ SpaceNode root = new SpaceNode();
root.setStack(stack);
// Get the recent tasks
@@ -428,7 +428,7 @@
boolean isForemostTask = (i == (taskCount - 1));
// Create a new task
- Task task = new Task(t.persistentId, (t.id > -1), t.baseIntent, activityLabel,
+ Task task = new Task(t.persistentId, (t.id > -1), t.baseIntent, 0, activityLabel,
activityIcon, activityColor, t.userId, t.firstActiveTime, t.lastActiveTime);
// Preload the specified number of apps
@@ -522,7 +522,7 @@
ActivityInfo info = ssp.getActivityInfo(t.baseIntent.getComponent(), t.userId);
if (info == null) continue;
- stack.addTask(new Task(t.persistentId, true, t.baseIntent, null, null, 0, 0,
+ stack.addTask(new Task(t.persistentId, true, t.baseIntent, 0, null, null, 0, 0,
t.firstActiveTime, t.lastActiveTime));
}
stack.createSimulatedAffiliatedGroupings();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNode.java b/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNode.java
index 20be415..831698a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNode.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNode.java
@@ -16,7 +16,6 @@
package com.android.systemui.recents.model;
-import android.content.Context;
import android.graphics.Rect;
import java.util.ArrayList;
@@ -35,15 +34,13 @@
public void onSpaceNodeMeasured(SpaceNode node, Rect rect);
}
- Context mContext;
-
SpaceNode mStartNode;
SpaceNode mEndNode;
TaskStack mStack;
- public SpaceNode(Context context) {
- mContext = context;
+ public SpaceNode() {
+ // Do nothing
}
/** Sets the current stack for this space node */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index 002395f..0667e4c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -79,6 +79,7 @@
public TaskKey key;
public TaskGrouping group;
+ public int taskAffiliation;
public Drawable applicationIcon;
public Drawable activityIcon;
public String activityLabel;
@@ -94,10 +95,11 @@
// Only used by RecentsService for task rect calculations.
}
- public Task(int id, boolean isActive, Intent intent, String activityTitle,
- Drawable activityIcon, int colorPrimary, int userId, long firstActiveTime,
- long lastActiveTime) {
+ public Task(int id, boolean isActive, Intent intent, int taskAffiliation, String activityTitle,
+ Drawable activityIcon, int colorPrimary, int userId,
+ long firstActiveTime, long lastActiveTime) {
this.key = new TaskKey(id, intent, userId, firstActiveTime, lastActiveTime);
+ this.taskAffiliation = taskAffiliation;
this.activityLabel = activityTitle;
this.activityIcon = activityIcon;
this.colorPrimary = colorPrimary;
@@ -148,7 +150,7 @@
public String toString() {
String groupAffiliation = "no group";
if (group != null) {
- groupAffiliation = group.affiliation;
+ groupAffiliation = Integer.toString(group.affiliation);
}
return "Task (" + groupAffiliation + "): " + key.baseIntent.getComponent().getPackageName() +
" [" + super.toString() + "]";
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskGrouping.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskGrouping.java
index 7793549..9791038 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskGrouping.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskGrouping.java
@@ -6,20 +6,21 @@
/** Represents a grouping of tasks witihin a stack. */
public class TaskGrouping {
- String affiliation;
+ int affiliation;
long latestActiveTimeInGroup;
- ArrayList<Task.TaskKey> mTasks = new ArrayList<Task.TaskKey>();
- HashMap<Task.TaskKey, Integer> mTaskIndices = new HashMap<Task.TaskKey, Integer>();
+ Task.TaskKey mFrontMostTaskKey;
+ ArrayList<Task.TaskKey> mTaskKeys = new ArrayList<Task.TaskKey>();
+ HashMap<Task.TaskKey, Integer> mTaskKeyIndices = new HashMap<Task.TaskKey, Integer>();
/** Creates a group with a specified affiliation. */
- public TaskGrouping(String affiliation) {
+ public TaskGrouping(int affiliation) {
this.affiliation = affiliation;
}
/** Adds a new task to this group. */
void addTask(Task t) {
- mTasks.add(t.key);
+ mTaskKeys.add(t.key);
if (t.key.lastActiveTime > latestActiveTimeInGroup) {
latestActiveTimeInGroup = t.key.lastActiveTime;
}
@@ -29,11 +30,11 @@
/** Removes a task from this group. */
void removeTask(Task t) {
- mTasks.remove(t.key);
+ mTaskKeys.remove(t.key);
latestActiveTimeInGroup = 0;
- int taskCount = mTasks.size();
+ int taskCount = mTaskKeys.size();
for (int i = 0; i < taskCount; i++) {
- long lastActiveTime = mTasks.get(i).lastActiveTime;
+ long lastActiveTime = mTaskKeys.get(i).lastActiveTime;
if (lastActiveTime > latestActiveTimeInGroup) {
latestActiveTimeInGroup = lastActiveTime;
}
@@ -44,24 +45,31 @@
/** Gets the front task */
public boolean isFrontMostTask(Task t) {
- return t.key.equals(mTasks.get(mTasks.size() - 1));
+ return (t.key == mFrontMostTaskKey);
}
/** Finds the index of a given task in a group. */
public int indexOf(Task t) {
- return mTaskIndices.get(t.key);
+ return mTaskKeyIndices.get(t.key);
}
/** Returns the number of tasks in this group. */
- public int getTaskCount() { return mTasks.size(); }
+ public int getTaskCount() { return mTaskKeys.size(); }
/** Updates the mapping of tasks to indices. */
private void updateTaskIndices() {
- mTaskIndices.clear();
- int taskCount = mTasks.size();
+ if (mTaskKeys.isEmpty()) {
+ mFrontMostTaskKey = null;
+ mTaskKeyIndices.clear();
+ return;
+ }
+
+ mFrontMostTaskKey = mTaskKeys.get(mTaskKeys.size() - 1);
+ mTaskKeyIndices.clear();
+ int taskCount = mTaskKeys.size();
for (int i = 0; i < taskCount; i++) {
- Task.TaskKey k = mTasks.get(i);
- mTaskIndices.put(k, i);
+ Task.TaskKey k = mTaskKeys.get(i);
+ mTaskKeyIndices.put(k, i);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 6bc74a7..1ed0edd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -170,11 +170,14 @@
}
}
+ // The task offset to apply to a task id as a group affiliation
+ static final int IndividualTaskIdOffset = 1 << 16;
+
FilteredTaskList mTaskList = new FilteredTaskList();
TaskStackCallbacks mCb;
ArrayList<TaskGrouping> mGroups = new ArrayList<TaskGrouping>();
- HashMap<String, TaskGrouping> mAffinitiesGroups = new HashMap<String, TaskGrouping>();
+ HashMap<Integer, TaskGrouping> mAffinitiesGroups = new HashMap<Integer, TaskGrouping>();
/** Sets the callbacks for this task stack */
public void setCallbacks(TaskStackCallbacks cb) {
@@ -303,7 +306,7 @@
}
/** Returns the group with the specified affiliation. */
- public TaskGrouping getGroupWithAffiliation(String affiliation) {
+ public TaskGrouping getGroupWithAffiliation(int affiliation) {
return mAffinitiesGroups.get(affiliation);
}
@@ -325,9 +328,9 @@
NamedCounter counter = new NamedCounter("task-group", "");
int taskCount = tasks.size();
String prevPackage = "";
- String prevAffiliation = "";
+ int prevAffiliation = -1;
Random r = new Random();
- int groupCountDown = 1000;
+ int groupCountDown = 5;
for (int i = 0; i < taskCount; i++) {
Task t = tasks.get(i);
String packageName = t.key.baseIntent.getComponent().getPackageName();
@@ -337,12 +340,12 @@
group = getGroupWithAffiliation(prevAffiliation);
groupCountDown--;
} else {
- String affiliation = counter.nextName();
+ int affiliation = IndividualTaskIdOffset + t.key.id;
group = new TaskGrouping(affiliation);
addGroup(group);
prevAffiliation = affiliation;
prevPackage = packageName;
- groupCountDown = 1000;
+ groupCountDown = 5;
}
group.addTask(t);
taskMap.put(t.key, t);
@@ -361,13 +364,13 @@
int groupCount = mGroups.size();
for (int i = 0; i < groupCount; i++) {
TaskGrouping group = mGroups.get(i);
- Collections.sort(group.mTasks, new Comparator<Task.TaskKey>() {
+ Collections.sort(group.mTaskKeys, new Comparator<Task.TaskKey>() {
@Override
public int compare(Task.TaskKey taskKey, Task.TaskKey taskKey2) {
return (int) (taskKey.firstActiveTime - taskKey2.firstActiveTime);
}
});
- ArrayList<Task.TaskKey> groupTasks = group.mTasks;
+ ArrayList<Task.TaskKey> groupTasks = group.mTaskKeys;
int groupTaskCount = groupTasks.size();
for (int j = 0; j < groupTaskCount; j++) {
tasks.set(taskIndex, taskMap.get(groupTasks.get(j)));
@@ -376,14 +379,20 @@
}
mTaskList.set(tasks);
} else {
- // Create a group per task
- NamedCounter counter = new NamedCounter("task-group", "");
+ // Create the task groups
ArrayList<Task> tasks = mTaskList.getTasks();
int taskCount = tasks.size();
for (int i = 0; i < taskCount; i++) {
Task t = tasks.get(i);
- TaskGrouping group = new TaskGrouping(counter.nextName());
- addGroup(group);
+ TaskGrouping group;
+ int affiliation = t.taskAffiliation > 0 ? t.taskAffiliation :
+ IndividualTaskIdOffset + t.key.id;
+ if (mAffinitiesGroups.containsKey(affiliation)) {
+ group = getGroupWithAffiliation(affiliation);
+ } else {
+ group = new TaskGrouping(affiliation);
+ addGroup(group);
+ }
group.addTask(t);
}
}
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 f38c637..35cf8ab 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -773,14 +773,29 @@
// Mark that we have completely the first layout
mAwaitingFirstLayout = false;
+ // Find the target task with the specified id
+ ArrayList<Task> tasks = mStack.getTasks();
+ Task targetTask = null;
+ int targetTaskId = mConfig.launchedToTaskId;
+ if (targetTaskId != -1) {
+ int taskCount = tasks.size();
+ for (int i = 0; i < taskCount; i++) {
+ Task t = tasks.get(i);
+ if (t.key.id == targetTaskId) {
+ targetTask = t;
+ break;
+ }
+ }
+ }
+
// Prepare the first view for its enter animation
int offsetTopAlign = -mStackAlgorithm.mTaskRect.top;
int offscreenY = mStackAlgorithm.mRect.bottom -
(mStackAlgorithm.mTaskRect.top - mStackAlgorithm.mRect.top);
for (int i = childCount - 1; i >= 0; i--) {
TaskView tv = (TaskView) getChildAt(i);
- tv.prepareEnterRecentsAnimation((i == (getChildCount() - 1)), offsetTopAlign,
- offscreenY, mStackAlgorithm.mTaskRect);
+ tv.prepareEnterRecentsAnimation(tv.getTask() == targetTask, offsetTopAlign,
+ offscreenY);
}
// If the enter animation started already and we haven't completed a layout yet, do the
@@ -809,41 +824,40 @@
}
if (mStack.getTaskCount() > 0) {
- if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
- // Find the target task with the specified id
- ArrayList<Task> tasks = mStack.getTasks();
- Task targetTask = null;
- int targetTaskId = mConfig.launchedToTaskId;
- if (targetTaskId != -1) {
- int taskCount = tasks.size();
- for (int i = 0; i < taskCount; i++) {
- Task t = tasks.get(i);
- if (t.key.id == targetTaskId) {
- targetTask = t;
- break;
- }
+ // Find the target task with the specified id
+ ArrayList<Task> tasks = mStack.getTasks();
+ Task targetTask = null;
+ int targetTaskId = mConfig.launchedToTaskId;
+ if (targetTaskId != -1) {
+ int taskCount = tasks.size();
+ for (int i = 0; i < taskCount; i++) {
+ Task t = tasks.get(i);
+ if (t.key.id == targetTaskId) {
+ targetTask = t;
+ break;
}
}
+ }
- // Find the group and task index of the target task
- if (targetTask != null) {
- ctx.targetTaskTransform = new TaskViewTransform();
- mStackAlgorithm.getStackTransform(targetTask, getStackScroll(), ctx.targetTaskTransform);
- Rect taskStackBounds = new Rect();
- mConfig.getTaskStackBounds(getMeasuredWidth(), getMeasuredHeight(), taskStackBounds);
- ctx.targetTaskTransform.rect.offset(taskStackBounds.left, taskStackBounds.top);
- }
+ // Find the transform for the target task
+ if (targetTask != null) {
+ ctx.targetTaskTransform = new TaskViewTransform();
+ mStackAlgorithm.getStackTransform(targetTask, getStackScroll(), ctx.targetTaskTransform);
+ Rect taskStackBounds = new Rect();
+ mConfig.getTaskStackBounds(getMeasuredWidth(), getMeasuredHeight(), taskStackBounds);
+ ctx.targetTaskTransform.rect.offset(taskStackBounds.left, taskStackBounds.top);
}
// Animate all the task views into view
int childCount = getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
TaskView tv = (TaskView) getChildAt(i);
+ Task task = tv.getTask();
ctx.currentTaskTransform = new TaskViewTransform();
ctx.currentStackViewIndex = i;
ctx.currentStackViewCount = childCount;
- ctx.isCurrentTaskFrontMost = (i == (getChildCount() - 1));
- mStackAlgorithm.getStackTransform(tv.getTask(), getStackScroll(), ctx.currentTaskTransform);
+ ctx.isCurrentTaskLaunchTarget = (task == targetTask);
+ mStackAlgorithm.getStackTransform(task, getStackScroll(), ctx.currentTaskTransform);
tv.startEnterRecentsAnimation(ctx);
}
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 1ba0560..33e3f58 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -19,7 +19,6 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
-import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
@@ -242,10 +241,10 @@
/** 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. */
- public void prepareEnterRecentsAnimation(boolean isTaskViewFrontMost, int offsetY, int offscreenY,
- Rect taskRect) {
+ public void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask, int offsetY,
+ int offscreenY) {
if (mConfig.launchedFromAppWithScreenshot) {
- if (isTaskViewFrontMost) {
+ if (isTaskViewLaunchTargetTask) {
// Hide the task view as we are going to animate the full screenshot into view
// and then replace it with this view once we are done
setVisibility(View.INVISIBLE);
@@ -259,7 +258,7 @@
}
} else if (mConfig.launchedFromAppWithThumbnail) {
- if (isTaskViewFrontMost) {
+ if (isTaskViewLaunchTargetTask) {
// Hide the front most task bar view so we can animate it in
mBarView.prepareEnterRecentsAnimation();
// Set the dim to 0 so we can animate it in
@@ -282,7 +281,7 @@
TaskViewTransform transform = ctx.currentTaskTransform;
if (mConfig.launchedFromAppWithScreenshot) {
- if (ctx.isCurrentTaskFrontMost) {
+ if (ctx.isCurrentTaskLaunchTarget) {
// Animate the full screenshot down first, before swapping with this task view
ctx.fullScreenshotView.animateOnEnterRecents(ctx, new Runnable() {
@Override
@@ -318,7 +317,7 @@
ctx.postAnimationTrigger.increment();
} else if (mConfig.launchedFromAppWithThumbnail) {
- if (ctx.isCurrentTaskFrontMost) {
+ if (ctx.isCurrentTaskLaunchTarget) {
// Animate the task bar of the first task view
mBarView.startEnterRecentsAnimation(mConfig.taskBarEnterAnimDelay, mEnableThumbnailClip);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java b/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java
index a531583..e50a5cf 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java
@@ -36,7 +36,7 @@
// The transform of the current task view
TaskViewTransform currentTaskTransform;
// Whether this is the front most task view
- boolean isCurrentTaskFrontMost;
+ boolean isCurrentTaskLaunchTarget;
// The view index of the current task view
int currentStackViewIndex;
// The total number of task views