Fixing crash when trying to reset focused task after removing task.

- Moving the focused state back into the stack, since the task view
  is transient and can be rebound.  Also ensuring that we update the
  task view focus state as we return and pick up views from the view
  pool
- Fixing issue where going back from recents would not go back home
- Properly calculating the task visibility (regression)

Bug: 25975225

Change-Id: Ica861f0d8996e4e254e875199a2d704a65bf8e58
This commit is contained in:
Winson
2015-12-02 15:10:14 -08:00
parent 5b7dd536aa
commit a0731a1a26
8 changed files with 103 additions and 79 deletions

View File

@@ -283,6 +283,20 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
return false;
}
/**
* Dismisses recents back to the launch target task.
*/
boolean dismissRecentsToLaunchTargetTaskOrHome() {
SystemServicesProxy ssp = Recents.getSystemServices();
if (ssp.isRecentsTopMost(ssp.getTopMostTask(), null)) {
// If we have a focused Task, launch that Task now
if (mRecentsView.launchPreviousTask()) return true;
// If none of the other cases apply, then just go Home
dismissRecentsToHome(true);
}
return false;
}
/**
* Dismisses recents if we are already visible and the intent is to toggle the recents view.
*/
@@ -566,9 +580,8 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
@Override
public void onBackPressed() {
if (!dismissHistory()) {
dismissRecentsToFocusedTaskOrHome();
}
// Back behaves like the recents button so just trigger a toggle event
EventBus.getDefault().send(new ToggleRecentsEvent());
}
/**** RecentsResizeTaskDialog ****/
@@ -584,7 +597,12 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
public final void onBusEvent(ToggleRecentsEvent event) {
if (!dismissHistory()) {
dismissRecentsToFocusedTaskOrHome();
RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
if (launchState.launchedFromHome) {
dismissRecentsToHome(true);
} else {
dismissRecentsToLaunchTargetTaskOrHome();
}
}
}

View File

@@ -199,8 +199,11 @@ public class TaskStack {
/** Task stack callbacks */
public interface TaskStackCallbacks {
/* Notifies when a task has been removed from the stack */
void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask,
Task newFrontMostTask);
void onStackTaskRemoved(TaskStack stack, Task removedTask, int removedTaskIndex,
boolean wasFrontMostTask, Task newFrontMostTask);
/* Notifies when a task has been removed from the history */
void onHistoryTaskRemoved(TaskStack stack, Task removedTask);
}
/**
@@ -382,6 +385,7 @@ public class TaskStack {
public void removeTask(Task t) {
if (mStackTaskList.contains(t)) {
boolean wasFrontMostTask = (getStackFrontMostTask() == t);
int removedTaskIndex = indexOfStackTask(t);
removeTaskImpl(mStackTaskList, t);
Task newFrontMostTask = getStackFrontMostTask();
if (newFrontMostTask != null && newFrontMostTask.lockToTaskEnabled) {
@@ -389,13 +393,14 @@ public class TaskStack {
}
if (mCb != null) {
// Notify that a task has been removed
mCb.onStackTaskRemoved(this, t, wasFrontMostTask, newFrontMostTask);
mCb.onStackTaskRemoved(this, t, removedTaskIndex, wasFrontMostTask,
newFrontMostTask);
}
} else if (mHistoryTaskList.contains(t)) {
removeTaskImpl(mHistoryTaskList, t);
if (mCb != null) {
// Notify that a task has been removed
mCb.onStackTaskRemoved(this, t, false, null);
mCb.onHistoryTaskRemoved(this, t);
}
}
}

View File

@@ -308,12 +308,6 @@ public class RecentsTransitionHelper {
*/
private static AppTransitionAnimationSpec composeAnimationSpec(TaskView taskView,
TaskViewTransform transform, boolean addHeaderBitmap) {
// Disable any focused state before we draw the header
// Upfront the processing of the thumbnail
if (taskView.isFocusedTask()) {
taskView.setFocusedState(false, false /* animated */, false /* requestViewFocus */);
}
Bitmap b = null;
if (addHeaderBitmap) {
float scale = transform.scale;

View File

@@ -213,6 +213,21 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
return false;
}
/** Launches the task that recents was launched from if possible */
public boolean launchPreviousTask() {
if (mTaskStackView != null) {
TaskStack stack = mTaskStackView.getStack();
Task task = stack.getLaunchTarget();
if (task != null) {
TaskView taskView = mTaskStackView.getChildViewForTask(task);
onTaskViewClicked(mTaskStackView, taskView, stack, task, false, null,
INVALID_STACK_ID);
return true;
}
}
return false;
}
/** Launches a given task. */
public boolean launchTask(Task task, Rect taskBounds, int destinationStack) {
if (mTaskStackView != null) {
@@ -471,9 +486,6 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
final TaskStack.DockState dockState = (TaskStack.DockState) event.dropTarget;
// Remove the task after it is docked
if (event.taskView.isFocusedTask()) {
mTaskStackView.resetFocusedTask();
}
event.taskView.animate()
.alpha(0f)
.setDuration(150)

View File

@@ -658,7 +658,8 @@ public class TaskStackLayoutAlgorithm {
transformOut.rect.set(mTaskRect);
transformOut.rect.offset(transformOut.translationX, transformOut.translationY);
Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale);
transformOut.visible = true;
transformOut.visible = (transformOut.rect.top < mStackRect.bottom) &&
(frontTransform == null || transformOut.rect.top != frontTransform.rect.top);
transformOut.clipBottom = 0;
transformOut.clipRight = 0;
transformOut.thumbnailScale = 1f;

View File

@@ -280,7 +280,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/** Resets this TaskStackView for reuse. */
void reset() {
// Reset the focused task
resetFocusedTask();
resetFocusedTask(getFocusedTask());
// Return all the views to the pool
List<TaskView> taskViews = getTaskViews();
@@ -426,7 +426,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Return all the invisible children to the pool
mTmpTaskViewMap.clear();
List<TaskView> taskViews = getTaskViews();
boolean wasLastFocusedTaskAnimated = false;
int lastFocusedTaskIndex = -1;
int taskViewCount = taskViews.size();
for (int i = taskViewCount - 1; i >= 0; i--) {
@@ -437,10 +436,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
visibleStackRange[1] <= taskIndex && taskIndex <= visibleStackRange[0]) {
mTmpTaskViewMap.put(task, tv);
} else {
if (mTouchExplorationEnabled && tv.isFocusedTask()) {
wasLastFocusedTaskAnimated = tv.isFocusAnimated();
if (mTouchExplorationEnabled) {
lastFocusedTaskIndex = taskIndex;
resetFocusedTask();
resetFocusedTask(task);
}
if (DEBUG) {
Log.d(TAG, "returning to pool: " + task.key);
@@ -467,6 +465,21 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
if (mLayersDisabled) {
tv.disableLayersForOneFrame();
}
} else {
// Reattach it in the right z order
detachViewFromParent(tv);
int insertIndex = -1;
int taskIndex = mStack.indexOfStackTask(task);
taskViews = getTaskViews();
taskViewCount = taskViews.size();
for (int j = 0; j < taskViewCount; j++) {
Task tvTask = taskViews.get(j).getTask();
if (taskIndex <= mStack.indexOfStackTask(tvTask)) {
insertIndex = j;
break;
}
}
attachViewToParent(tv, insertIndex, tv.getLayoutParams());
}
// Animate the task into place
@@ -474,21 +487,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
mStackViewsAnimationDuration, mFastOutSlowInInterpolator,
mRequestUpdateClippingListener);
// Reattach it in the right z order
detachViewFromParent(tv);
int insertIndex = -1;
int taskIndex = mStack.indexOfStackTask(task);
taskViews = getTaskViews();
taskViewCount = taskViews.size();
for (int j = 0; j < taskViewCount; j++) {
Task tvTask = taskViews.get(j).getTask();
if (taskIndex < mStack.indexOfStackTask(tvTask)) {
insertIndex = j;
break;
}
}
attachViewToParent(tv, insertIndex, tv.getLayoutParams());
// Update the task views list after adding the new task view
updateTaskViewsList();
}
@@ -538,9 +536,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Update the focus if the previous focused task was returned to the view pool
if (lastFocusedTaskIndex != -1) {
if (lastFocusedTaskIndex < visibleStackRange[1]) {
setFocusedTask(visibleStackRange[1], false, wasLastFocusedTaskAnimated);
setFocusedTask(visibleStackRange[1], false /* animated */,
true /* requestViewFocus */);
} else {
setFocusedTask(visibleStackRange[0], false, wasLastFocusedTaskAnimated);
setFocusedTask(visibleStackRange[0], false /* animated */,
true /* requestViewFocus */);
}
}
@@ -653,7 +653,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
if (mFocusedTaskIndex != -1) {
Task focusedTask = mStack.getStackTasks().get(mFocusedTaskIndex);
if (focusedTask != newFocusedTask) {
resetFocusedTask();
resetFocusedTask(focusedTask);
}
}
@@ -777,10 +777,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/**
* Resets the focused task.
*/
void resetFocusedTask() {
if (mFocusedTaskIndex != -1) {
Task t = mStack.getStackTasks().get(mFocusedTaskIndex);
TaskView tv = getChildViewForTask(t);
void resetFocusedTask(Task task) {
if (task != null) {
TaskView tv = getChildViewForTask(task);
if (tv != null) {
tv.setFocusedState(false, false /* animated */, false /* requestViewFocus */);
}
@@ -1183,8 +1182,12 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/**** TaskStackCallbacks Implementation ****/
@Override
public void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask,
Task newFrontMostTask) {
public void onStackTaskRemoved(TaskStack stack, Task removedTask, int removedTaskIndex,
boolean wasFrontMostTask, Task newFrontMostTask) {
if (mFocusedTaskIndex == removedTaskIndex) {
resetFocusedTask(removedTask);
}
if (!removedTask.isFreeformTask()) {
// Remove the view associated with this task, we can't rely on updateTransforms
// to work here because the task is no longer in the list
@@ -1260,6 +1263,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
}
@Override
public void onHistoryTaskRemoved(TaskStack stack, Task removedTask) {
// To be implemented
}
/**** ViewPoolConsumer Implementation ****/
@Override
@@ -1282,6 +1290,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Reset the view properties
tv.resetViewProperties();
// Reset the focused view state
tv.setFocusedState(false, false /* animated */, false /* requestViewFocus */);
// Reset the clip state of the task view
tv.setClipViewInStack(false);
}
@@ -1332,6 +1343,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
tv.setCallbacks(this);
tv.setTouchEnabled(true);
tv.setClipViewInStack(true);
if (mFocusedTaskIndex == taskIndex) {
tv.setFocusedState(true, false /* animated */, false /* requestViewFocus */);
}
}
@Override
@@ -1553,11 +1567,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
private void removeTaskViewFromStack(TaskView tv) {
Task task = tv.getTask();
// Reset the previously focused task before it is removed from the stack
if (tv.isFocusedTask()) {
resetFocusedTask();
}
// Announce for accessibility
tv.announceForAccessibility(getContext().getString(
R.string.accessibility_recents_item_dismissed, tv.getTask().activityLabel));

View File

@@ -78,8 +78,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
Task mTask;
boolean mTaskDataLoaded;
boolean mIsFocused;
boolean mIsFocusAnimated;
boolean mClipViewInStack;
AnimateableViewBounds mViewBounds;
private AnimatorSet mClipAnimation;
@@ -640,14 +638,12 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
public void setFocusedState(boolean isFocused, boolean animated, boolean requestViewFocus) {
if (DEBUG) {
Log.d(TAG, "setFocusedState: " + mTask.activityLabel + " focused: " + isFocused +
" mIsFocused: " + mIsFocused + " animated: " + animated +
" requestViewFocus: " + requestViewFocus + " isFocused(): " + isFocused() +
" animated: " + animated + " requestViewFocus: " + requestViewFocus +
" isFocused(): " + isFocused() +
" isAccessibilityFocused(): " + isAccessibilityFocused());
}
SystemServicesProxy ssp = Recents.getSystemServices();
mIsFocused = isFocused;
mIsFocusAnimated = animated;
mHeaderView.onTaskViewFocusChanged(isFocused, animated);
if (isFocused) {
if (requestViewFocus && !isFocused()) {
@@ -663,20 +659,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
}
}
/**
* Returns whether we have explicitly been focused.
*/
public boolean isFocusedTask() {
return mIsFocused;
}
/**
* Returns whether this focused task is animated.
*/
public boolean isFocusAnimated() {
return mIsFocusAnimated;
}
public void disableLayersForOneFrame() {
mHeaderView.disableLayersForOneFrame();
}

View File

@@ -55,6 +55,8 @@ import com.android.systemui.recents.model.Task;
public class TaskViewHeader extends FrameLayout
implements View.OnClickListener, View.OnLongClickListener {
private static final float FOCUS_TRANSLATION_Z = 4f;
Task mTask;
// Header views
@@ -367,13 +369,14 @@ public class TaskViewHeader extends FrameLayout
Utilities.cancelAnimationWithoutCallbacks(mFocusAnimator);
if (focused) {
// If we are not animating the visible state, just return
if (!animateFocusedState) return;
// Bump up the translation
mFocusAnimator = ObjectAnimator.ofFloat(this, "translationZ", 8f);
mFocusAnimator.setDuration(200);
mFocusAnimator.start();
if (animateFocusedState) {
// Bump up the translation
mFocusAnimator = ObjectAnimator.ofFloat(this, "translationZ", FOCUS_TRANSLATION_Z);
mFocusAnimator.setDuration(200);
mFocusAnimator.start();
} else {
setTranslationZ(FOCUS_TRANSLATION_Z);
}
} else {
if (isRunning) {
// Restore the translation