Refactoring to update stack in onResume.
This CL fixes a long-standing issue in which Recents is not updated correctly if it is not completely hidden and shown. In particular, it would cause animation issues when launching into a non-fullscreen activity or if the user quickly toggles between recent tasks. It contains several fixes: - The visual state in Recents is no longer reset until the activity is fully hidden (onStop() is called), and the task stack state is saved allowing us to return to the same initial state. When restarting the activity, we propagate whether the activity was hidden down the view hierarchy, so that each task can decide whether to reset itself. - When the recents activity is started, we now merge the new stack with the current stack instead of replacing it completely. This unifies the logic when dismissing multi-window while Recents is open, and this CL fixes an issue with the merging where onStackTaskAdded() was called before the stack was updated with the new task. As a result of this change, we can just rebind the task views without having to return and pick them up from the view pool. - This CL also fixes an issue with flashing when the screen turns off. The activity onStop() can be called before the activity is fully hidden, which would trigger a reset(), which would return all views to the pool. Bug: 23815609 Bug: 25411120 Bug: 27186407 Change-Id: I83d74c947f9b47766d6778b7f5c421bb6df833e9
This commit is contained in:
@@ -513,8 +513,9 @@ public class Recents extends SystemUI
|
||||
* Handle Recents activity visibility changed.
|
||||
*/
|
||||
public final void onBusEvent(final RecentsVisibilityChangedEvent event) {
|
||||
int processUser = event.systemServicesProxy.getProcessUser();
|
||||
if (event.systemServicesProxy.isSystemUser(processUser)) {
|
||||
SystemServicesProxy ssp = Recents.getSystemServices();
|
||||
int processUser = ssp.getProcessUser();
|
||||
if (ssp.isSystemUser(processUser)) {
|
||||
mImpl.onVisibilityChanged(event.applicationContext, event.visible);
|
||||
} else {
|
||||
postToSystemUser(new Runnable() {
|
||||
|
||||
@@ -55,7 +55,7 @@ import com.android.systemui.recents.events.activity.IterateRecentsEvent;
|
||||
import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
|
||||
import com.android.systemui.recents.events.activity.LaunchTaskSucceededEvent;
|
||||
import com.android.systemui.recents.events.activity.ShowHistoryEvent;
|
||||
import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
|
||||
import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
|
||||
import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
|
||||
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
|
||||
import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
|
||||
@@ -97,6 +97,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
|
||||
private long mLastTabKeyEventTime;
|
||||
private boolean mFinishedOnStartup;
|
||||
private boolean mIgnoreAltTabRelease;
|
||||
private boolean mIsVisible;
|
||||
|
||||
// Top level views
|
||||
private RecentsView mRecentsView;
|
||||
@@ -174,59 +175,6 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
|
||||
}
|
||||
};
|
||||
|
||||
/** Updates the set of recent tasks */
|
||||
void updateRecentsTasks() {
|
||||
// If AlternateRecentsComponent has preloaded a load plan, then use that to prevent
|
||||
// reconstructing the task stack
|
||||
RecentsTaskLoader loader = Recents.getTaskLoader();
|
||||
RecentsTaskLoadPlan plan = RecentsImpl.consumeInstanceLoadPlan();
|
||||
if (plan == null) {
|
||||
plan = loader.createLoadPlan(this);
|
||||
}
|
||||
|
||||
// Start loading tasks according to the load plan
|
||||
RecentsConfiguration config = Recents.getConfiguration();
|
||||
RecentsActivityLaunchState launchState = config.getLaunchState();
|
||||
if (!plan.hasTasks()) {
|
||||
loader.preloadTasks(plan, -1, launchState.launchedFromHome);
|
||||
}
|
||||
RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
|
||||
loadOpts.runningTaskId = launchState.launchedToTaskId;
|
||||
loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
|
||||
loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
|
||||
loader.loadTasks(this, plan, loadOpts);
|
||||
|
||||
TaskStack stack = plan.getTaskStack();
|
||||
mRecentsView.setTaskStack(stack);
|
||||
|
||||
// Animate the SystemUI scrims into view
|
||||
Task launchTarget = stack.getLaunchTarget();
|
||||
int taskCount = stack.getTaskCount();
|
||||
int launchTaskIndexInStack = launchTarget != null
|
||||
? stack.indexOfStackTask(launchTarget)
|
||||
: 0;
|
||||
boolean hasNavBarScrim = (taskCount > 0) && !config.hasTransposedNavBar;
|
||||
boolean animateNavBarScrim = !launchState.launchedWhileDocking;
|
||||
mScrimViews.prepareEnterRecentsAnimation(hasNavBarScrim, animateNavBarScrim);
|
||||
|
||||
// Keep track of whether we launched from the nav bar button or via alt-tab
|
||||
if (launchState.launchedWithAltTab) {
|
||||
MetricsLogger.count(this, "overview_trigger_alttab", 1);
|
||||
} else {
|
||||
MetricsLogger.count(this, "overview_trigger_nav_btn", 1);
|
||||
}
|
||||
// Keep track of whether we launched from an app or from home
|
||||
if (launchState.launchedFromApp) {
|
||||
MetricsLogger.count(this, "overview_source_app", 1);
|
||||
// If from an app, track the stack index of the app in the stack (for affiliated tasks)
|
||||
MetricsLogger.histogram(this, "overview_source_app_index", launchTaskIndexInStack);
|
||||
} else {
|
||||
MetricsLogger.count(this, "overview_source_home", 1);
|
||||
}
|
||||
// Keep track of the total stack task count
|
||||
MetricsLogger.histogram(this, "overview_task_count", taskCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismisses the history view back into the stack view.
|
||||
*/
|
||||
@@ -345,6 +293,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
|
||||
|
||||
// Set the Recents layout
|
||||
setContentView(R.layout.recents);
|
||||
takeKeyEvents(true);
|
||||
mRecentsView = (RecentsView) findViewById(R.id.recents_view);
|
||||
mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
|
||||
@@ -381,46 +330,13 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
|
||||
registerReceiver(mSystemBroadcastReceiver, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
setIntent(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
|
||||
// Update the recent tasks
|
||||
updateRecentsTasks();
|
||||
|
||||
// If this is a new instance from a configuration change, then we have to manually trigger
|
||||
// the enter animation state, or if recents was relaunched by AM, without going through
|
||||
// the normal mechanisms
|
||||
RecentsConfiguration config = Recents.getConfiguration();
|
||||
RecentsActivityLaunchState launchState = config.getLaunchState();
|
||||
boolean wasLaunchedByAm = !launchState.launchedFromHome &&
|
||||
!launchState.launchedFromApp;
|
||||
if (launchState.launchedHasConfigurationChanged || wasLaunchedByAm) {
|
||||
EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
|
||||
}
|
||||
|
||||
// Notify that recents is now visible
|
||||
SystemServicesProxy ssp = Recents.getSystemServices();
|
||||
EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, ssp, true));
|
||||
|
||||
EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, true));
|
||||
MetricsLogger.visible(this, MetricsEvent.OVERVIEW_ACTIVITY);
|
||||
|
||||
mRecentsView.getViewTreeObserver().addOnPreDrawListener(
|
||||
new ViewTreeObserver.OnPreDrawListener() {
|
||||
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
EventBus.getDefault().post(new RecentsDrawnEvent());
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -430,26 +346,91 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
// Stop the fast-toggle dozer
|
||||
mIterateTrigger.stopDozing();
|
||||
// If the Recents component has preloaded a load plan, then use that to prevent
|
||||
// reconstructing the task stack
|
||||
RecentsTaskLoader loader = Recents.getTaskLoader();
|
||||
RecentsTaskLoadPlan loadPlan = RecentsImpl.consumeInstanceLoadPlan();
|
||||
if (loadPlan == null) {
|
||||
loadPlan = loader.createLoadPlan(this);
|
||||
}
|
||||
|
||||
// Start loading tasks according to the load plan
|
||||
RecentsConfiguration config = Recents.getConfiguration();
|
||||
RecentsActivityLaunchState launchState = config.getLaunchState();
|
||||
if (!loadPlan.hasTasks()) {
|
||||
loader.preloadTasks(loadPlan, -1, launchState.launchedFromHome);
|
||||
}
|
||||
|
||||
RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
|
||||
loadOpts.runningTaskId = launchState.launchedToTaskId;
|
||||
loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
|
||||
loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
|
||||
loader.loadTasks(this, loadPlan, loadOpts);
|
||||
TaskStack stack = loadPlan.getTaskStack();
|
||||
mRecentsView.onResume(mIsVisible, stack);
|
||||
|
||||
// Animate the SystemUI scrims into view
|
||||
Task launchTarget = stack.getLaunchTarget();
|
||||
int taskCount = stack.getTaskCount();
|
||||
int launchTaskIndexInStack = launchTarget != null
|
||||
? stack.indexOfStackTask(launchTarget)
|
||||
: 0;
|
||||
boolean hasNavBarScrim = (taskCount > 0) && !config.hasTransposedNavBar;
|
||||
boolean animateNavBarScrim = !launchState.launchedWhileDocking;
|
||||
mScrimViews.prepareEnterRecentsAnimation(hasNavBarScrim, animateNavBarScrim);
|
||||
|
||||
// If this is a new instance from a configuration change, then we have to manually trigger
|
||||
// the enter animation state, or if recents was relaunched by AM, without going through
|
||||
// the normal mechanisms
|
||||
boolean wasLaunchedByAm = !launchState.launchedFromHome &&
|
||||
!launchState.launchedFromApp;
|
||||
if (launchState.launchedHasConfigurationChanged || wasLaunchedByAm) {
|
||||
EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
|
||||
}
|
||||
|
||||
mRecentsView.getViewTreeObserver().addOnPreDrawListener(
|
||||
new ViewTreeObserver.OnPreDrawListener() {
|
||||
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
EventBus.getDefault().post(new RecentsDrawnEvent());
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// Keep track of whether we launched from the nav bar button or via alt-tab
|
||||
if (launchState.launchedWithAltTab) {
|
||||
MetricsLogger.count(this, "overview_trigger_alttab", 1);
|
||||
} else {
|
||||
MetricsLogger.count(this, "overview_trigger_nav_btn", 1);
|
||||
}
|
||||
|
||||
// Keep track of whether we launched from an app or from home
|
||||
if (launchState.launchedFromApp) {
|
||||
MetricsLogger.count(this, "overview_source_app", 1);
|
||||
// If from an app, track the stack index of the app in the stack (for affiliated tasks)
|
||||
MetricsLogger.histogram(this, "overview_source_app_index", launchTaskIndexInStack);
|
||||
} else {
|
||||
MetricsLogger.count(this, "overview_source_home", 1);
|
||||
}
|
||||
|
||||
// Keep track of the total stack task count
|
||||
MetricsLogger.histogram(this, "overview_task_count", taskCount);
|
||||
|
||||
// After we have resumed, set the visible state until the next onStop() call
|
||||
mIsVisible = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
||||
// Reset some states
|
||||
mIgnoreAltTabRelease = false;
|
||||
if (RecentsDebugFlags.Static.EnableHistory && mRecentsView.isHistoryVisible()) {
|
||||
EventBus.getDefault().send(new HideHistoryEvent(false /* animate */));
|
||||
}
|
||||
|
||||
// Notify that recents is now hidden
|
||||
SystemServicesProxy ssp = Recents.getSystemServices();
|
||||
EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, ssp, false));
|
||||
mIterateTrigger.stopDozing();
|
||||
|
||||
// Workaround for b/22542869, if the RecentsActivity is started again, but without going
|
||||
// through SystemUI, we need to reset the config launch flags to ensure that we do not
|
||||
@@ -457,7 +438,20 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
|
||||
RecentsConfiguration config = Recents.getConfiguration();
|
||||
RecentsActivityLaunchState launchState = config.getLaunchState();
|
||||
launchState.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
|
||||
// Only hide the history if Recents is completely hidden
|
||||
if (RecentsDebugFlags.Static.EnableHistory && mRecentsView.isHistoryVisible()) {
|
||||
EventBus.getDefault().send(new HideHistoryEvent(false /* animate */));
|
||||
}
|
||||
|
||||
// Notify that recents is now hidden
|
||||
mIsVisible = false;
|
||||
EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, false));
|
||||
MetricsLogger.hidden(this, MetricsEvent.OVERVIEW_ACTIVITY);
|
||||
}
|
||||
|
||||
@@ -525,16 +519,22 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
|
||||
public void onMultiWindowChanged(boolean inMultiWindow) {
|
||||
super.onMultiWindowChanged(inMultiWindow);
|
||||
EventBus.getDefault().send(new ConfigurationChangedEvent());
|
||||
|
||||
// Reload the task stack completely
|
||||
RecentsConfiguration config = Recents.getConfiguration();
|
||||
RecentsActivityLaunchState launchState = config.getLaunchState();
|
||||
RecentsTaskLoader loader = Recents.getTaskLoader();
|
||||
RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options();
|
||||
launchOpts.loadIcons = false;
|
||||
launchOpts.loadThumbnails = false;
|
||||
launchOpts.onlyLoadForCache = true;
|
||||
RecentsTaskLoadPlan loadPlan = loader.createLoadPlan(this);
|
||||
loader.preloadTasks(loadPlan, -1, false);
|
||||
loader.loadTasks(this, loadPlan, launchOpts);
|
||||
EventBus.getDefault().send(new TaskStackUpdatedEvent(loadPlan.getTaskStack(),
|
||||
inMultiWindow));
|
||||
loader.preloadTasks(loadPlan, -1 /* topTaskId */, false /* isTopTaskHome */);
|
||||
|
||||
RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
|
||||
loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
|
||||
loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
|
||||
loader.loadTasks(this, loadPlan, loadOpts);
|
||||
|
||||
mRecentsView.onResume(mIsVisible, loadPlan.getTaskStack());
|
||||
|
||||
EventBus.getDefault().send(new MultiWindowStateChangedEvent(inMultiWindow));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -602,7 +602,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
|
||||
com.android.internal.R.dimen.navigation_bar_width);
|
||||
mTaskBarHeight = res.getDimensionPixelSize(
|
||||
R.dimen.recents_task_bar_height);
|
||||
mDummyStackView = new TaskStackView(mContext, new TaskStack());
|
||||
mDummyStackView = new TaskStackView(mContext);
|
||||
mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header,
|
||||
null, false);
|
||||
}
|
||||
@@ -615,8 +615,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
|
||||
* is not already bound (can be expensive)
|
||||
* @param stack the stack to initialize the stack layout with
|
||||
*/
|
||||
private void updateHeaderBarLayout(boolean tryAndBindSearchWidget,
|
||||
TaskStack stack) {
|
||||
private void updateHeaderBarLayout(boolean tryAndBindSearchWidget, TaskStack stack) {
|
||||
RecentsConfiguration config = Recents.getConfiguration();
|
||||
SystemServicesProxy ssp = Recents.getSystemServices();
|
||||
Rect systemInsets = new Rect();
|
||||
@@ -640,14 +639,15 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
|
||||
mSearchBarBounds, mTaskStackBounds);
|
||||
|
||||
// Rebind the header bar and draw it for the transition
|
||||
TaskStackLayoutAlgorithm algo = mDummyStackView.getStackAlgorithm();
|
||||
TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm();
|
||||
Rect taskStackBounds = new Rect(mTaskStackBounds);
|
||||
algo.setSystemInsets(systemInsets);
|
||||
stackLayout.setSystemInsets(systemInsets);
|
||||
if (stack != null) {
|
||||
algo.initialize(taskStackBounds,
|
||||
stackLayout.initialize(taskStackBounds,
|
||||
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(stack));
|
||||
mDummyStackView.setTasks(stack, false /* notifyStackChanges */);
|
||||
}
|
||||
Rect taskViewBounds = algo.getUntransformedTaskViewBounds();
|
||||
Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds();
|
||||
if (!taskViewBounds.equals(mLastTaskViewBounds)) {
|
||||
mLastTaskViewBounds.set(taskViewBounds);
|
||||
|
||||
@@ -705,7 +705,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
|
||||
updateHeaderBarLayout(false /* tryAndBindSearchWidget */, stack);
|
||||
|
||||
// Update the destination rect
|
||||
mDummyStackView.updateLayoutForStack(stack);
|
||||
final Task toTask = new Task();
|
||||
final TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask);
|
||||
ForegroundThread.getHandler().postAtFrontOfQueue(new Runnable() {
|
||||
@@ -887,7 +886,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
|
||||
updateHeaderBarLayout(false /* tryAndBindSearchWidget */, stack);
|
||||
|
||||
// Prepare the dummy stack for the transition
|
||||
mDummyStackView.updateLayoutForStack(stack);
|
||||
TaskStackLayoutAlgorithm.VisibilityReport stackVr =
|
||||
mDummyStackView.computeStackVisibilityReport();
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.events.activity;
|
||||
|
||||
import com.android.systemui.recents.events.EventBus;
|
||||
|
||||
/**
|
||||
* This is sent by the activity whenever the multi-window state has changed.
|
||||
*/
|
||||
public class MultiWindowStateChangedEvent extends EventBus.Event {
|
||||
|
||||
public final boolean inMultiWindow;
|
||||
|
||||
public MultiWindowStateChangedEvent(boolean inMultiWindow) {
|
||||
this.inMultiWindow = inMultiWindow;
|
||||
}
|
||||
}
|
||||
@@ -19,21 +19,18 @@ package com.android.systemui.recents.events.component;
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.systemui.recents.events.EventBus;
|
||||
import com.android.systemui.recents.misc.SystemServicesProxy;
|
||||
|
||||
/**
|
||||
* This is sent when the visibility of the RecentsActivity for the current user changes.
|
||||
* This is sent when the visibility of the RecentsActivity for the current user changes. Handlers
|
||||
* of this event should not alter the UI, as the activity may still be visible.
|
||||
*/
|
||||
public class RecentsVisibilityChangedEvent extends EventBus.Event {
|
||||
|
||||
public final Context applicationContext;
|
||||
public final SystemServicesProxy systemServicesProxy;
|
||||
public final boolean visible;
|
||||
|
||||
public RecentsVisibilityChangedEvent(Context context, SystemServicesProxy systemServicesProxy,
|
||||
boolean visible) {
|
||||
public RecentsVisibilityChangedEvent(Context context, boolean visible) {
|
||||
this.applicationContext = context.getApplicationContext();
|
||||
this.systemServicesProxy = systemServicesProxy;
|
||||
this.visible = visible;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,8 +212,7 @@ public class RecentsTaskLoadPlan {
|
||||
|
||||
// Initialize the stacks
|
||||
mStack = new TaskStack();
|
||||
mStack.setTasks(allTasks, false /* notifyStackChanges */);
|
||||
mStack.createAffiliatedGroupings(mContext);
|
||||
mStack.setTasks(mContext, allTasks, false /* notifyStackChanges */);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -100,11 +100,7 @@ public class Task {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Task.Key: " + id + ", "
|
||||
+ "s: " + stackId + ", "
|
||||
+ "u: " + userId + ", "
|
||||
+ "lat: " + lastActiveTime + ", "
|
||||
+ getComponent().getPackageName();
|
||||
return "t" + id + ", s" + stackId + ", u" + userId;
|
||||
}
|
||||
|
||||
private void updateHashCode() {
|
||||
@@ -204,7 +200,9 @@ public class Task {
|
||||
this.isDockable = isDockable;
|
||||
}
|
||||
|
||||
/** Copies the other task. */
|
||||
/**
|
||||
* Copies the metadata from another task, but retains the current callbacks.
|
||||
*/
|
||||
public void copyFrom(Task o) {
|
||||
this.key = o.key;
|
||||
this.group = o.group;
|
||||
@@ -300,11 +298,6 @@ public class Task {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String groupAffiliation = "no group";
|
||||
if (group != null) {
|
||||
groupAffiliation = Integer.toString(group.affiliation);
|
||||
}
|
||||
return "Task (" + groupAffiliation + "): " + key +
|
||||
" [" + super.toString() + "]";
|
||||
return "[" + key.toString() + "] " + title;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,15 +92,6 @@ class FilteredTaskList {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the task list, but does not remove the filter.
|
||||
*/
|
||||
void reset() {
|
||||
mTasks.clear();
|
||||
mFilteredTasks.clear();
|
||||
mTaskIndices.clear();
|
||||
}
|
||||
|
||||
/** Removes the task filter and returns the previous touch state */
|
||||
void removeFilter() {
|
||||
mFilter = null;
|
||||
@@ -481,15 +472,6 @@ public class TaskStack {
|
||||
mCb = cb;
|
||||
}
|
||||
|
||||
/** Resets this TaskStack. */
|
||||
public void reset() {
|
||||
mCb = null;
|
||||
mStackTaskList.reset();
|
||||
mHistoryTaskList.reset();
|
||||
mGroups.clear();
|
||||
mAffinitiesGroups.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the given task to either the front of the freeform workspace or the stack.
|
||||
*/
|
||||
@@ -556,12 +538,12 @@ public class TaskStack {
|
||||
* @param tasks the new set of tasks to replace the current set.
|
||||
* @param notifyStackChanges whether or not to callback on specific changes to the list of tasks.
|
||||
*/
|
||||
public void setTasks(List<Task> tasks, boolean notifyStackChanges) {
|
||||
public void setTasks(Context context, List<Task> tasks, boolean notifyStackChanges) {
|
||||
// Compute a has set for each of the tasks
|
||||
ArrayMap<Task.TaskKey, Task> currentTasksMap = createTaskKeyMapFromList(mRawTaskList);
|
||||
ArrayMap<Task.TaskKey, Task> newTasksMap = createTaskKeyMapFromList(tasks);
|
||||
|
||||
ArrayList<Task> newTasks = new ArrayList<>();
|
||||
ArrayList<Task> addedTasks = new ArrayList<>();
|
||||
ArrayList<Task> allTasks = new ArrayList<>();
|
||||
|
||||
// Disable notifications if there are no callbacks
|
||||
if (mCb == null) {
|
||||
@@ -570,10 +552,13 @@ public class TaskStack {
|
||||
|
||||
// Remove any tasks that no longer exist
|
||||
int taskCount = mRawTaskList.size();
|
||||
for (int i = 0; i < taskCount; i++) {
|
||||
for (int i = taskCount - 1; i >= 0; i--) {
|
||||
Task task = mRawTaskList.get(i);
|
||||
if (!newTasksMap.containsKey(task.key)) {
|
||||
if (notifyStackChanges) {
|
||||
// If we are notifying, then remove the task now, otherwise the raw task list
|
||||
// will be reset at the end of this method
|
||||
removeTask(task, AnimationProps.IMMEDIATE);
|
||||
mCb.onStackTaskRemoved(this, task, i == (taskCount - 1), null,
|
||||
AnimationProps.IMMEDIATE);
|
||||
}
|
||||
@@ -584,26 +569,28 @@ public class TaskStack {
|
||||
// Add any new tasks
|
||||
taskCount = tasks.size();
|
||||
for (int i = 0; i < taskCount; i++) {
|
||||
Task task = tasks.get(i);
|
||||
if (!currentTasksMap.containsKey(task.key)) {
|
||||
if (notifyStackChanges) {
|
||||
mCb.onStackTaskAdded(this, task);
|
||||
}
|
||||
newTasks.add(task);
|
||||
} else {
|
||||
newTasks.add(currentTasksMap.get(task.key));
|
||||
Task newTask = tasks.get(i);
|
||||
Task currentTask = currentTasksMap.get(newTask.key);
|
||||
if (currentTask == null && notifyStackChanges) {
|
||||
addedTasks.add(newTask);
|
||||
} else if (currentTask != null) {
|
||||
// The current task has bound callbacks, so just copy the data from the new task
|
||||
// state and add it back into the list
|
||||
currentTask.copyFrom(newTask);
|
||||
newTask = currentTask;
|
||||
}
|
||||
allTasks.add(newTask);
|
||||
}
|
||||
|
||||
// Sort all the tasks to ensure they are ordered correctly
|
||||
Collections.sort(newTasks, FREEFORM_LAST_ACTIVE_TIME_COMPARATOR);
|
||||
Collections.sort(allTasks, FREEFORM_LAST_ACTIVE_TIME_COMPARATOR);
|
||||
|
||||
// Filter out the historical tasks from this new list
|
||||
ArrayList<Task> stackTasks = new ArrayList<>();
|
||||
ArrayList<Task> historyTasks = new ArrayList<>();
|
||||
int newTaskCount = newTasks.size();
|
||||
int newTaskCount = allTasks.size();
|
||||
for (int i = 0; i < newTaskCount; i++) {
|
||||
Task task = newTasks.get(i);
|
||||
Task task = allTasks.get(i);
|
||||
if (task.isHistorical) {
|
||||
historyTasks.add(task);
|
||||
} else {
|
||||
@@ -613,10 +600,16 @@ public class TaskStack {
|
||||
|
||||
mStackTaskList.set(stackTasks);
|
||||
mHistoryTaskList.set(historyTasks);
|
||||
mRawTaskList.clear();
|
||||
mRawTaskList.addAll(newTasks);
|
||||
mGroups.clear();
|
||||
mAffinitiesGroups.clear();
|
||||
mRawTaskList = allTasks;
|
||||
|
||||
// Only callback for the newly added tasks after this stack has been updated
|
||||
int addedTaskCount = addedTasks.size();
|
||||
for (int i = 0; i < addedTaskCount; i++) {
|
||||
mCb.onStackTaskAdded(this, addedTasks.get(i));
|
||||
}
|
||||
|
||||
// Update the affiliated groupings
|
||||
createAffiliatedGroupings(context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -779,9 +772,12 @@ public class TaskStack {
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporary: This method will simulate affiliation groups by
|
||||
* Temporary: This method will simulate affiliation groups
|
||||
*/
|
||||
public void createAffiliatedGroupings(Context context) {
|
||||
void createAffiliatedGroupings(Context context) {
|
||||
mGroups.clear();
|
||||
mAffinitiesGroups.clear();
|
||||
|
||||
if (RecentsDebugFlags.Static.EnableMockTaskGroups) {
|
||||
ArrayMap<Task.TaskKey, Task> taskMap = new ArrayMap<>();
|
||||
// Sort all tasks by increasing firstActiveTime of the task
|
||||
@@ -926,13 +922,13 @@ public class TaskStack {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String str = "Stack Tasks:\n";
|
||||
String str = "Stack Tasks (" + mStackTaskList.size() + "):\n";
|
||||
for (Task t : mStackTaskList.getTasks()) {
|
||||
str += " " + t.toString() + "\n";
|
||||
str += " " + t.toString() + "\n";
|
||||
}
|
||||
str += "Historical Tasks:\n";
|
||||
str += "Historical Tasks(" + mHistoryTaskList.size() + "):\n";
|
||||
for (Task t : mHistoryTaskList.getTasks()) {
|
||||
str += " " + t.toString() + "\n";
|
||||
str += " " + t.toString() + "\n";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
@@ -294,7 +294,7 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
|
||||
|
||||
// Notify that recents is now visible
|
||||
SystemServicesProxy ssp = Recents.getSystemServices();
|
||||
EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, ssp, true));
|
||||
EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, true));
|
||||
|
||||
if (mPipManager.isPipShown()) {
|
||||
// Place mPipView at the PIP bounds for fine tuned focus handling.
|
||||
@@ -343,8 +343,7 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
|
||||
mPipManager.removeListener(mPipListener);
|
||||
mIgnoreAltTabRelease = false;
|
||||
// Notify that recents is now hidden
|
||||
SystemServicesProxy ssp = Recents.getSystemServices();
|
||||
EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, ssp, false));
|
||||
EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, false));
|
||||
|
||||
// Workaround for b/22542869, if the RecentsActivity is started again, but without going
|
||||
// through SystemUI, we need to reset the config launch flags to ensure that we do not
|
||||
|
||||
@@ -177,6 +177,7 @@ public class RecentsTransitionHelper {
|
||||
// Keep track of failed launches
|
||||
EventBus.getDefault().send(new LaunchTaskFailedEvent());
|
||||
}
|
||||
|
||||
if (transitionFuture != null) {
|
||||
IRemoteCallback.Stub callback = null;
|
||||
if (animStartedListener != null) {
|
||||
|
||||
@@ -60,9 +60,7 @@ import com.android.systemui.recents.events.activity.HideHistoryEvent;
|
||||
import com.android.systemui.recents.events.activity.LaunchTaskEvent;
|
||||
import com.android.systemui.recents.events.activity.ShowHistoryButtonEvent;
|
||||
import com.android.systemui.recents.events.activity.ShowHistoryEvent;
|
||||
import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
|
||||
import com.android.systemui.recents.events.activity.ToggleHistoryEvent;
|
||||
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
|
||||
import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent;
|
||||
import com.android.systemui.recents.events.ui.DraggingInRecentsEvent;
|
||||
import com.android.systemui.recents.events.ui.ResetBackgroundScrimEvent;
|
||||
@@ -168,35 +166,39 @@ public class RecentsView extends FrameLayout {
|
||||
}
|
||||
|
||||
/** Set/get the bsp root node */
|
||||
public void setTaskStack(TaskStack stack) {
|
||||
public void onResume(boolean isResumingFromVisible, TaskStack stack) {
|
||||
RecentsConfiguration config = Recents.getConfiguration();
|
||||
RecentsActivityLaunchState launchState = config.getLaunchState();
|
||||
mStack = stack;
|
||||
if (launchState.launchedReuseTaskStackViews) {
|
||||
if (mTaskStackView != null) {
|
||||
// If onRecentsHidden is not triggered, we need to the stack view again here
|
||||
mTaskStackView.reset();
|
||||
mTaskStackView.setStack(stack);
|
||||
} else {
|
||||
mTaskStackView = new TaskStackView(getContext(), stack);
|
||||
addView(mTaskStackView);
|
||||
}
|
||||
} else {
|
||||
if (mTaskStackView != null) {
|
||||
removeView(mTaskStackView);
|
||||
}
|
||||
mTaskStackView = new TaskStackView(getContext(), stack);
|
||||
|
||||
if (mTaskStackView == null || !launchState.launchedReuseTaskStackViews) {
|
||||
isResumingFromVisible = false;
|
||||
removeView(mTaskStackView);
|
||||
mTaskStackView = new TaskStackView(getContext());
|
||||
mStack = mTaskStackView.getStack();
|
||||
addView(mTaskStackView);
|
||||
}
|
||||
|
||||
// If we are already occluded by the app, then just set the default background scrim now.
|
||||
// Otherwise, defer until the enter animation completes to animate the scrim with the
|
||||
// tasks for the home animation.
|
||||
if (launchState.launchedWhileDocking || launchState.launchedFromApp
|
||||
|| mStack.getTaskCount() == 0) {
|
||||
mBackgroundScrim.setAlpha((int) (DEFAULT_SCRIM_ALPHA * 255));
|
||||
// Reset the state
|
||||
mAwaitingFirstLayout = !isResumingFromVisible;
|
||||
mLastTaskLaunchedWasFreeform = false;
|
||||
|
||||
// Update the stack
|
||||
mTaskStackView.onResume(isResumingFromVisible);
|
||||
mTaskStackView.setTasks(stack, isResumingFromVisible /* notifyStackChanges */);
|
||||
|
||||
if (isResumingFromVisible) {
|
||||
// If we are already visible, then restore the background scrim
|
||||
animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, DEFAULT_UPDATE_SCRIM_DURATION);
|
||||
} else {
|
||||
mBackgroundScrim.setAlpha(0);
|
||||
// If we are already occluded by the app, then set the final background scrim alpha now.
|
||||
// Otherwise, defer until the enter animation completes to animate the scrim alpha with
|
||||
// the tasks for the home animation.
|
||||
if (launchState.launchedWhileDocking || launchState.launchedFromApp
|
||||
|| mStack.getTaskCount() == 0) {
|
||||
mBackgroundScrim.setAlpha((int) (DEFAULT_SCRIM_ALPHA * 255));
|
||||
} else {
|
||||
mBackgroundScrim.setAlpha(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the top level view's visibilities
|
||||
@@ -205,9 +207,6 @@ public class RecentsView extends FrameLayout {
|
||||
} else {
|
||||
showEmptyView();
|
||||
}
|
||||
|
||||
// Trigger a new layout
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -662,13 +661,6 @@ public class RecentsView extends FrameLayout {
|
||||
animator.start();
|
||||
}
|
||||
|
||||
public final void onBusEvent(TaskStackUpdatedEvent event) {
|
||||
if (!event.inMultiWindow) {
|
||||
mStack.setTasks(event.stack.computeAllTasksList(), true /* notifyStackChanges */);
|
||||
mStack.createAffiliatedGroupings(getContext());
|
||||
}
|
||||
}
|
||||
|
||||
public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
|
||||
RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
|
||||
if (!launchState.launchedWhileDocking && !launchState.launchedFromApp
|
||||
@@ -686,17 +678,6 @@ public class RecentsView extends FrameLayout {
|
||||
animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, DEFAULT_UPDATE_SCRIM_DURATION);
|
||||
}
|
||||
|
||||
public final void onBusEvent(RecentsVisibilityChangedEvent event) {
|
||||
if (!event.visible) {
|
||||
// Reset the view state
|
||||
mAwaitingFirstLayout = true;
|
||||
mLastTaskLaunchedWasFreeform = false;
|
||||
if (RecentsDebugFlags.Static.EnableHistory) {
|
||||
hideHistoryButton(0, false /* translate */);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final void onBusEvent(ToggleHistoryEvent event) {
|
||||
if (!RecentsDebugFlags.Static.EnableHistory) {
|
||||
return;
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
|
||||
package com.android.systemui.recents.views;
|
||||
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewPropertyAnimator;
|
||||
|
||||
import com.android.systemui.Interpolators;
|
||||
import com.android.systemui.R;
|
||||
@@ -56,25 +58,41 @@ public class SystemBarScrimViews {
|
||||
View.VISIBLE : View.INVISIBLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Animates the nav bar scrim visibility.
|
||||
*/
|
||||
public void animateNavBarScrimVisibility(boolean visible, AnimationProps animation) {
|
||||
int toY = 0;
|
||||
if (visible) {
|
||||
mNavBarScrimView.setVisibility(View.VISIBLE);
|
||||
mNavBarScrimView.setTranslationY(mNavBarScrimView.getMeasuredHeight());
|
||||
} else {
|
||||
toY = mNavBarScrimView.getMeasuredHeight();
|
||||
}
|
||||
if (animation != AnimationProps.IMMEDIATE) {
|
||||
mNavBarScrimView.animate()
|
||||
.translationY(toY)
|
||||
.setDuration(animation.getDuration(AnimationProps.BOUNDS))
|
||||
.setInterpolator(animation.getInterpolator(AnimationProps.BOUNDS))
|
||||
.start();
|
||||
} else {
|
||||
mNavBarScrimView.setTranslationY(toY);
|
||||
}
|
||||
}
|
||||
|
||||
/**** EventBus events ****/
|
||||
|
||||
/**
|
||||
* Starts animating the scrim views when entering Recents.
|
||||
*/
|
||||
public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
|
||||
if (mHasNavBarScrim && mShouldAnimateNavBarScrim) {
|
||||
mNavBarScrimView.setTranslationY(mNavBarScrimView.getMeasuredHeight());
|
||||
mNavBarScrimView.animate()
|
||||
.translationY(0)
|
||||
.setDuration(mNavBarScrimEnterDuration)
|
||||
.setInterpolator(Interpolators.DECELERATE_QUINT)
|
||||
.withStartAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mNavBarScrimView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
})
|
||||
.start();
|
||||
if (mHasNavBarScrim) {
|
||||
AnimationProps animation = mShouldAnimateNavBarScrim
|
||||
? new AnimationProps()
|
||||
.setDuration(AnimationProps.BOUNDS, mNavBarScrimEnterDuration)
|
||||
.setInterpolator(AnimationProps.BOUNDS, Interpolators.DECELERATE_QUINT)
|
||||
: AnimationProps.IMMEDIATE;
|
||||
animateNavBarScrimVisibility(true, animation);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,13 +101,12 @@ public class SystemBarScrimViews {
|
||||
* going home).
|
||||
*/
|
||||
public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
|
||||
if (mHasNavBarScrim && mShouldAnimateNavBarScrim) {
|
||||
mNavBarScrimView.animate()
|
||||
.translationY(mNavBarScrimView.getMeasuredHeight())
|
||||
.setStartDelay(0)
|
||||
.setDuration(TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION)
|
||||
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
|
||||
.start();
|
||||
if (mHasNavBarScrim) {
|
||||
AnimationProps animation = new AnimationProps()
|
||||
.setDuration(AnimationProps.BOUNDS,
|
||||
TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION)
|
||||
.setInterpolator(AnimationProps.BOUNDS, Interpolators.FAST_OUT_SLOW_IN);
|
||||
animateNavBarScrimVisibility(false, animation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -531,7 +531,6 @@ public class TaskStackLayoutAlgorithm {
|
||||
return;
|
||||
}
|
||||
|
||||
RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
|
||||
mUnfocusedRange.offset(0f);
|
||||
int taskCount = tasks.size();
|
||||
for (int i = taskCount - 1; i >= 0; i--) {
|
||||
@@ -571,6 +570,10 @@ public class TaskStackLayoutAlgorithm {
|
||||
* Updates this stack when a scroll happens.
|
||||
*/
|
||||
public void updateFocusStateOnScroll(float stackScroll, float deltaScroll) {
|
||||
if (deltaScroll == 0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = mTaskIndexOverrideMap.size() - 1; i >= 0; i--) {
|
||||
int taskId = mTaskIndexOverrideMap.keyAt(i);
|
||||
float x = mTaskIndexMap.get(taskId);
|
||||
@@ -630,6 +633,13 @@ public class TaskStackLayoutAlgorithm {
|
||||
return mState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this stack layout has been initialized.
|
||||
*/
|
||||
public boolean isInitialized() {
|
||||
return !mStackRect.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the maximum number of visible tasks and thumbnails when the scroll is at the initial
|
||||
* stack scroll. Requires that update() is called first.
|
||||
|
||||
@@ -65,11 +65,10 @@ import com.android.systemui.recents.events.activity.IterateRecentsEvent;
|
||||
import com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent;
|
||||
import com.android.systemui.recents.events.activity.LaunchTaskEvent;
|
||||
import com.android.systemui.recents.events.activity.LaunchTaskStartedEvent;
|
||||
import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
|
||||
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.activity.TaskStackUpdatedEvent;
|
||||
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
|
||||
import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
|
||||
import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
|
||||
import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
|
||||
@@ -117,7 +116,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
private static final ArraySet<Task.TaskKey> EMPTY_TASK_SET = new ArraySet<>();
|
||||
|
||||
LayoutInflater mInflater;
|
||||
TaskStack mStack;
|
||||
TaskStack mStack = new TaskStack();
|
||||
@ViewDebug.ExportedProperty(deepExport=true, prefix="layout_")
|
||||
TaskStackLayoutAlgorithm mLayoutAlgorithm;
|
||||
@ViewDebug.ExportedProperty(deepExport=true, prefix="scroller_")
|
||||
@@ -206,13 +205,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
}
|
||||
};
|
||||
|
||||
public TaskStackView(Context context, TaskStack stack) {
|
||||
public TaskStackView(Context context) {
|
||||
super(context);
|
||||
SystemServicesProxy ssp = Recents.getSystemServices();
|
||||
Resources res = context.getResources();
|
||||
|
||||
// Set the stack first
|
||||
setStack(stack);
|
||||
mStack.setCallbacks(this);
|
||||
mViewPool = new ViewPool<>(context, this);
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mLayoutAlgorithm = new TaskStackLayoutAlgorithm(context, this);
|
||||
@@ -248,6 +247,41 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called only if we are resuming Recents.
|
||||
*/
|
||||
void onResume(boolean isResumingFromVisible) {
|
||||
if (!isResumingFromVisible) {
|
||||
// Reset the focused task
|
||||
resetFocusedTask(getFocusedTask());
|
||||
}
|
||||
|
||||
// Reset the state of each of the task views
|
||||
List<TaskView> taskViews = new ArrayList<>();
|
||||
taskViews.addAll(getTaskViews());
|
||||
taskViews.addAll(mViewPool.getViews());
|
||||
for (int i = taskViews.size() - 1; i >= 0; i--) {
|
||||
taskViews.get(i).onResume(isResumingFromVisible);
|
||||
}
|
||||
|
||||
// Reset the stack state
|
||||
readSystemFlags();
|
||||
mTaskViewsClipDirty = true;
|
||||
mEnterAnimationComplete = false;
|
||||
mUIDozeTrigger.stopDozing();
|
||||
if (isResumingFromVisible) {
|
||||
// Animate in the freeform workspace
|
||||
int ffBgAlpha = mLayoutAlgorithm.getStackState().freeformBackgroundAlpha;
|
||||
animateFreeformWorkspaceBackgroundAlpha(ffBgAlpha, new AnimationProps(150,
|
||||
Interpolators.FAST_OUT_SLOW_IN));
|
||||
} else {
|
||||
mStackScroller.reset();
|
||||
mLayoutAlgorithm.reset();
|
||||
mAwaitingFirstLayout = true;
|
||||
requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
|
||||
@@ -261,15 +295,20 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
|
||||
/** Sets the task stack */
|
||||
void setStack(TaskStack stack) {
|
||||
// Set the new stack
|
||||
mStack = stack;
|
||||
if (mStack != null) {
|
||||
mStack.setCallbacks(this);
|
||||
/**
|
||||
* Sets the stack tasks of this TaskStackView from the given TaskStack.
|
||||
*/
|
||||
public void setTasks(TaskStack stack, boolean notifyStackChanges) {
|
||||
boolean isInitialized = mLayoutAlgorithm.isInitialized();
|
||||
mStack.setTasks(getContext(), stack.computeAllTasksList(),
|
||||
notifyStackChanges && isInitialized);
|
||||
if (isInitialized) {
|
||||
// Only update the layout if we are notifying, otherwise, we will update it in the next
|
||||
// measure/layout pass
|
||||
updateLayoutAlgorithm(false /* boundScroll */, EMPTY_TASK_SET);
|
||||
updateToInitialState();
|
||||
relayoutTaskViewsOnNextFrame(AnimationProps.IMMEDIATE);
|
||||
}
|
||||
// Layout again with the new stack
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
/** Returns the task stack. */
|
||||
@@ -338,36 +377,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Resets this TaskStackView for reuse. */
|
||||
void reset() {
|
||||
// Reset the focused task
|
||||
resetFocusedTask(getFocusedTask());
|
||||
|
||||
// Return all the views to the pool
|
||||
List<TaskView> taskViews = getTaskViews();
|
||||
int taskViewCount = taskViews.size();
|
||||
for (int i = taskViewCount - 1; i >= 0; i--) {
|
||||
mViewPool.returnViewToPool(taskViews.get(i));
|
||||
}
|
||||
|
||||
// Mark each task view for relayout
|
||||
List<TaskView> poolViews = mViewPool.getViews();
|
||||
for (TaskView tv : poolViews) {
|
||||
tv.reset();
|
||||
}
|
||||
|
||||
// Reset the stack state
|
||||
mStack.reset();
|
||||
mTaskViewsClipDirty = true;
|
||||
mAwaitingFirstLayout = true;
|
||||
mEnterAnimationComplete = false;
|
||||
mUIDozeTrigger.stopDozing();
|
||||
mStackScroller.reset();
|
||||
mLayoutAlgorithm.reset();
|
||||
readSystemFlags();
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
/** Returns the stack algorithm for this task stack. */
|
||||
public TaskStackLayoutAlgorithm getStackAlgorithm() {
|
||||
return mLayoutAlgorithm;
|
||||
@@ -1119,15 +1128,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is ONLY used from the Recents component to update the dummy stack view for purposes
|
||||
* of getting the task rect to animate to.
|
||||
*/
|
||||
public void updateLayoutForStack(TaskStack stack) {
|
||||
mStack = stack;
|
||||
updateLayoutAlgorithm(false /* boundScroll */, EMPTY_TASK_SET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the maximum number of visible tasks and thumbnails. Requires that
|
||||
* updateLayoutForStack() is called first.
|
||||
@@ -1423,7 +1423,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
public void onReturnViewToPool(TaskView tv) {
|
||||
final Task task = tv.getTask();
|
||||
|
||||
// Report that this tasks's data is no longer being used
|
||||
// Report that this task's data is no longer being used
|
||||
Recents.getTaskLoader().unloadTaskData(task);
|
||||
|
||||
// Reset the view properties and view state
|
||||
@@ -1670,12 +1670,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
}
|
||||
}
|
||||
|
||||
public final void onBusEvent(RecentsVisibilityChangedEvent event) {
|
||||
if (!event.visible) {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
public final void onBusEvent(DragStartEvent event) {
|
||||
// Ensure that the drag task is not animated
|
||||
addIgnoreTask(event.task);
|
||||
@@ -1772,12 +1766,14 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
event.taskView.setLeftTopRightBottom(taskViewRect.left, taskViewRect.top,
|
||||
taskViewRect.right, taskViewRect.bottom);
|
||||
|
||||
// Animate all the TaskViews back into position
|
||||
// Animate the non-drag TaskViews back into position
|
||||
mLayoutAlgorithm.getStackTransform(event.task, getScroller().getStackScroll(),
|
||||
mTmpTransform, null);
|
||||
event.getAnimationTrigger().increment();
|
||||
relayoutTaskViews(new AnimationProps(DEFAULT_SYNC_STACK_DURATION,
|
||||
Interpolators.FAST_OUT_SLOW_IN));
|
||||
|
||||
// Animate the drag TaskView back into position
|
||||
updateTaskViewToTransform(event.taskView, mTmpTransform,
|
||||
new AnimationProps(DEFAULT_SYNC_STACK_DURATION, Interpolators.FAST_OUT_SLOW_IN,
|
||||
event.getAnimationTrigger().decrementOnAnimationEnd()));
|
||||
@@ -1850,31 +1846,22 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
mAnimationHelper.startHideHistoryAnimation();
|
||||
}
|
||||
|
||||
public final void onBusEvent(TaskStackUpdatedEvent event) {
|
||||
public final void onBusEvent(MultiWindowStateChangedEvent event) {
|
||||
if (!event.inMultiWindow) {
|
||||
// Scroll the stack to the front after it has been updated
|
||||
event.addPostAnimationCallback(new Runnable() {
|
||||
// Scroll the stack to the front to see the undocked task
|
||||
mStackScroller.animateScroll(mLayoutAlgorithm.mMaxScrollP, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mStackScroller.animateScroll(mLayoutAlgorithm.mMaxScrollP,
|
||||
null /* postScrollRunnable */);
|
||||
List<TaskView> taskViews = getTaskViews();
|
||||
int taskViewCount = taskViews.size();
|
||||
for (int i = 0; i < taskViewCount; i++) {
|
||||
TaskView tv = taskViews.get(i);
|
||||
tv.getHeaderView().rebindToTask(tv.getTask(), tv.mTouchExplorationEnabled,
|
||||
tv.mIsDisabledInSafeMode);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// When the multi-window state changes, rebind all task view headers again to update their
|
||||
// dockable state
|
||||
event.addPostAnimationCallback(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
List<TaskView> taskViews = getTaskViews();
|
||||
int taskViewCount = taskViews.size();
|
||||
for (int i = 0; i < taskViewCount; i++) {
|
||||
TaskView tv = taskViews.get(i);
|
||||
tv.getHeaderView().rebindToTask(tv.getTask(), tv.mTouchExplorationEnabled,
|
||||
tv.mIsDisabledInSafeMode);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public final void onBusEvent(ConfigurationChangedEvent event) {
|
||||
|
||||
@@ -193,11 +193,13 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
|
||||
}
|
||||
|
||||
/** Resets this TaskView for reuse. */
|
||||
void reset() {
|
||||
resetViewProperties();
|
||||
void onResume(boolean isResumingFromVisible) {
|
||||
resetNoUserInteractionState();
|
||||
readSystemFlags();
|
||||
setClipViewInStack(false);
|
||||
if (!isResumingFromVisible) {
|
||||
resetViewProperties();
|
||||
setClipViewInStack(false);
|
||||
}
|
||||
setCallbacks(null);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user