Merge "Disabling timer" into nyc-dev

This commit is contained in:
Winson Chung
2016-03-03 22:29:37 +00:00
committed by Android (Google) Code Review
19 changed files with 360 additions and 223 deletions

View File

@@ -292,6 +292,9 @@
<!-- The amount to allow the stack to overscroll. -->
<dimen name="recents_stack_overscroll">24dp</dimen>
<!-- The size of the initial peek area at the top of the stack (below the status bar). -->
<dimen name="recents_initial_top_peek_size">8dp</dimen>
<!-- The size of the peek area at the top of the stack (below the status bar). -->
<dimen name="recents_layout_focused_top_peek_size">@dimen/recents_history_button_height</dimen>

View File

@@ -43,6 +43,7 @@ import com.android.systemui.R;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.AppWidgetProviderChangedEvent;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
import com.android.systemui.recents.events.activity.DebugFlagsChangedEvent;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
@@ -107,7 +108,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
private RecentsAppWidgetHostView mSearchWidgetHostView;
// Runnables to finish the Recents activity
private FinishRecentsRunnable mFinishLaunchHomeRunnable;
private Intent mHomeIntent;
// The trigger to automatically launch the current task
private int mFocusTimerDuration;
@@ -119,7 +120,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
* last activity launch state. Generally we always launch home when we exit Recents rather than
* just finishing the activity since we don't know what is behind Recents in the task stack.
*/
class FinishRecentsRunnable implements Runnable {
class LaunchHomeRunnable implements Runnable {
Intent mLaunchIntent;
ActivityOptions mOpts;
@@ -127,7 +128,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
/**
* Creates a finish runnable that starts the specified intent.
*/
public FinishRecentsRunnable(Intent launchIntent, ActivityOptions opts) {
public LaunchHomeRunnable(Intent launchIntent, ActivityOptions opts) {
mLaunchIntent = launchIntent;
mOpts = opts;
}
@@ -215,7 +216,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
MetricsLogger.count(this, "overview_trigger_nav_btn", 1);
}
// Keep track of whether we launched from an app or from home
if (launchState.launchedFromAppWithThumbnail) {
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);
@@ -294,12 +295,8 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
void dismissRecentsToHome(boolean animateTaskViews, ActivityOptions overrideAnimation) {
DismissRecentsToHomeAnimationStarted dismissEvent =
new DismissRecentsToHomeAnimationStarted(animateTaskViews);
if (overrideAnimation != null) {
dismissEvent.addPostAnimationCallback(new FinishRecentsRunnable(
mFinishLaunchHomeRunnable.mLaunchIntent, overrideAnimation));
} else {
dismissEvent.addPostAnimationCallback(mFinishLaunchHomeRunnable);
}
dismissEvent.addPostAnimationCallback(new LaunchHomeRunnable(mHomeIntent,
overrideAnimation));
dismissEvent.addPostAnimationCallback(new Runnable() {
@Override
public void run() {
@@ -365,11 +362,10 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
});
// Create the home intent runnable
Intent homeIntent = new Intent(Intent.ACTION_MAIN, null);
homeIntent.addCategory(Intent.CATEGORY_HOME);
homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
mHomeIntent.addCategory(Intent.CATEGORY_HOME);
mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent, null);
// Bind the search app widget when we first start up
if (RecentsDebugFlags.Static.EnableSearchBar) {
@@ -404,7 +400,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
boolean wasLaunchedByAm = !launchState.launchedFromHome &&
!launchState.launchedFromAppWithThumbnail;
!launchState.launchedFromApp;
if (launchState.launchedHasConfigurationChanged || wasLaunchedByAm) {
EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
}
@@ -528,6 +524,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
@Override
public void onMultiWindowChanged(boolean inMultiWindow) {
super.onMultiWindowChanged(inMultiWindow);
EventBus.getDefault().send(new ConfigurationChangedEvent());
RecentsTaskLoader loader = Recents.getTaskLoader();
RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options();
launchOpts.loadIcons = false;

View File

@@ -28,7 +28,8 @@ package com.android.systemui.recents;
public class RecentsActivityLaunchState {
public boolean launchedWithAltTab;
public boolean launchedFromAppWithThumbnail;
public boolean launchedFromApp;
public boolean launchedFromAppDocked;
public boolean launchedFromHome;
public boolean launchedFromSearchHome;
public boolean launchedReuseTaskStackViews;
@@ -42,7 +43,8 @@ public class RecentsActivityLaunchState {
public void reset() {
launchedFromHome = false;
launchedFromSearchHome = false;
launchedFromAppWithThumbnail = false;
launchedFromApp = false;
launchedFromAppDocked = false;
launchedToTaskId = -1;
launchedWithAltTab = false;
launchedHasConfigurationChanged = false;
@@ -67,7 +69,7 @@ public class RecentsActivityLaunchState {
public int getInitialFocusTaskIndex(int numTasks) {
RecentsDebugFlags debugFlags = Recents.getDebugFlags();
RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
if (launchedFromAppWithThumbnail) {
if (launchedFromApp) {
if (!launchState.launchedWithAltTab && debugFlags.isFastToggleRecentsEnabled()) {
// If fast toggling, focus the front most task so that the next tap will focus the
// N-1 task

View File

@@ -69,7 +69,6 @@ public class RecentsConfiguration {
public final int smallestWidth;
/** Misc **/
public boolean useHardwareLayers;
public boolean fakeShadows;
public int svelteLevel;
public int searchBarSpaceHeightPx;
@@ -80,7 +79,6 @@ public class RecentsConfiguration {
SystemServicesProxy ssp = Recents.getSystemServices();
Context appContext = context.getApplicationContext();
Resources res = appContext.getResources();
useHardwareLayers = res.getBoolean(R.bool.config_recents_use_hardware_layers);
fakeShadows = res.getBoolean(R.bool.config_recents_fake_shadows);
svelteLevel = res.getInteger(R.integer.recents_svelte_level);

View File

@@ -39,8 +39,8 @@ public class RecentsDebugFlags implements TunerService.Tunable {
public static final boolean EnableAffiliatedTaskGroups = true;
// Enables the history
public static final boolean EnableHistory = false;
// Overrides the Tuner flags and enables the fast toggle and timeout
public static final boolean EnableFastToggleTimeoutOverride = true;
// Overrides the Tuner flags and enables the timeout
private static final boolean EnableFastToggleTimeout = false;
// Enables us to create mock recents tasks
public static final boolean EnableMockTasks = false;
@@ -54,9 +54,9 @@ public class RecentsDebugFlags implements TunerService.Tunable {
public static final int MockTaskGroupsTaskCount = 12;
}
private static final String KEY_DISABLE_FAST_TOGGLE = "overview_disable_fast_toggle_via_button";
private static final String KEY_ENABLE_PAGING = "overview_enable_paging";
private boolean mDisableFastToggleRecents;
private boolean mEnablePaging;
/**
* We read the prefs once when we start the activity, then update them as the tuner changes
@@ -65,31 +65,32 @@ public class RecentsDebugFlags implements TunerService.Tunable {
public RecentsDebugFlags(Context context) {
// Register all our flags, this will also call onTuningChanged() for each key, which will
// initialize the current state of each flag
TunerService.get(context).addTunable(this, KEY_DISABLE_FAST_TOGGLE);
TunerService.get(context).addTunable(this, KEY_ENABLE_PAGING);
}
/**
* @return whether we are enabling fast toggling.
*/
public boolean isFastToggleRecentsEnabled() {
// These checks EnableFastToggleTimeoutOverride
SystemServicesProxy ssp = Recents.getSystemServices();
if (mDisableFastToggleRecents || ssp.hasFreeformWorkspaceSupport() || ssp.hasDockedTask()
|| ssp.isTouchExplorationEnabled()) {
if (ssp.hasFreeformWorkspaceSupport() || ssp.isTouchExplorationEnabled()) {
return false;
}
if (Static.EnableFastToggleTimeoutOverride) {
return true;
}
return true;
return Static.EnableFastToggleTimeout;
}
/**
* @return whether we are enabling paging.
*/
public boolean isPagingEnabled() {
return mEnablePaging;
}
@Override
public void onTuningChanged(String key, String newValue) {
switch (key) {
case KEY_DISABLE_FAST_TOGGLE:
mDisableFastToggleRecents = (newValue != null) &&
(Integer.parseInt(newValue) != 0);
case KEY_ENABLE_PAGING:
mEnablePaging = (newValue != null) && (Integer.parseInt(newValue) != 0);
break;
}
EventBus.getDefault().send(new DebugFlagsChangedEvent());

View File

@@ -16,6 +16,8 @@
package com.android.systemui.recents;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.ITaskStackListener;
@@ -66,6 +68,7 @@ import com.android.systemui.recents.model.TaskGrouping;
import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
import com.android.systemui.recents.views.TaskStackView;
import com.android.systemui.recents.views.TaskStackViewScroller;
import com.android.systemui.recents.views.TaskViewHeader;
import com.android.systemui.recents.views.TaskViewTransform;
import com.android.systemui.statusbar.BaseStatusBar;
@@ -74,8 +77,6 @@ import com.android.systemui.statusbar.phone.PhoneStatusBar;
import java.util.ArrayList;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
/**
* An implementation of the Recents component for the current user. For secondary users, this can
* be called remotely from the system user.
@@ -98,6 +99,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
//Used to store tv or non-tv activty for use in creating intents.
private final String mRecentsIntentActivityName;
/**
* An implementation of ITaskStackListener, that allows us to listen for changes to the system
* task stacks and update recents accordingly.
@@ -276,28 +278,24 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
mTriggeredFromAltTab = triggeredFromAltTab;
mDraggingInRecents = draggingInRecents;
mLaunchedWhileDocking = launchedWhileDockingTask;
if (mFastAltTabTrigger.hasTriggered()) {
// We are calling this from the doze trigger, so just fall through to show Recents
mFastAltTabTrigger.resetTrigger();
if (mFastAltTabTrigger.isAsleep()) {
// Fast alt-tab duration has elapsed, fall through to showing Recents and reset
mFastAltTabTrigger.stopDozing();
} else if (mFastAltTabTrigger.isDozing()) {
// We are dozing but haven't yet triggered, ignore this if this is not another alt-tab,
// otherwise, this is an additional tab (alt-tab*), which means that we should trigger
// immediately (fall through and disable the pending trigger)
// TODO: This is tricky, we need to handle the tab key, but Recents has not yet started
// so we may actually additional signal to handle multiple quick tab cases. The
// severity of this is inversely proportional to the FAST_ALT_TAB_DELAY_MS
// duration though
// Fast alt-tab duration has not elapsed. If this is triggered by a different
// showRecents() call, then ignore that call for now.
// TODO: We can not handle quick tabs that happen between the initial showRecents() call
// that started the activity and the activity starting up. The severity of this
// is inversely proportional to the FAST_ALT_TAB_DELAY_MS duration though.
if (!triggeredFromAltTab) {
return;
}
mFastAltTabTrigger.stopDozing();
} else {
// Otherwise, the doze trigger is not running, and if this is an alt tab, we should
// start the trigger and then wait for the hide (or for it to elapse)
if (triggeredFromAltTab) {
mFastAltTabTrigger.startDozing();
return;
}
} else if (triggeredFromAltTab) {
// The fast alt-tab detector is not yet running, so start the trigger and wait for the
// hideRecents() call, or for the fast alt-tab duration to elapse
mFastAltTabTrigger.startDozing();
return;
}
try {
@@ -321,7 +319,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
// Cancel the fast alt-tab trigger
mFastAltTabTrigger.stopDozing();
mFastAltTabTrigger.resetTrigger();
return;
}
@@ -348,12 +345,14 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
long elapsedTime = SystemClock.elapsedRealtime() - mLastToggleTime;
if (topTask != null && ssp.isRecentsTopMost(topTask, isTopTaskHome)) {
RecentsDebugFlags debugFlags = Recents.getDebugFlags();
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
if (!launchState.launchedWithAltTab) {
// If the user taps quickly
if (ViewConfiguration.getDoubleTapMinTime() < elapsedTime &&
elapsedTime < ViewConfiguration.getDoubleTapTimeout()) {
if (!debugFlags.isPagingEnabled() ||
(ViewConfiguration.getDoubleTapMinTime() < elapsedTime &&
elapsedTime < ViewConfiguration.getDoubleTapTimeout())) {
// Launch the next focused task
EventBus.getDefault().post(new LaunchNextTaskRequestEvent());
} else {
@@ -574,7 +573,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
false /* triggeredFromAltTab */,
dragMode == NavigationBarGestureHelper.DRAG_MODE_RECENTS,
false /* animate */,
true /* reloadTasks*/);
true /* launchedWhileDockingTask*/);
}
}
@@ -707,8 +706,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
// Update the destination rect
mDummyStackView.updateLayoutForStack(stack);
final Task toTask = new Task();
final TaskViewTransform toTransform = getThumbnailTransitionTransform(stack, stackView,
toTask);
final TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask);
ForegroundThread.getHandler().postAtFrontOfQueue(new Runnable() {
@Override
public void run() {
@@ -754,17 +752,20 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
* Creates the activity options for an app->recents transition.
*/
private ActivityOptions getThumbnailTransitionActivityOptions(
ActivityManager.RunningTaskInfo topTask, TaskStack stack, TaskStackView stackView) {
ActivityManager.RunningTaskInfo topTask, TaskStackView stackView) {
if (topTask.stackId == FREEFORM_WORKSPACE_STACK_ID) {
ArrayList<AppTransitionAnimationSpec> specs = new ArrayList<>();
stackView.getScroller().setStackScrollToInitialState();
ArrayList<Task> tasks = stack.getStackTasks();
ArrayList<Task> tasks = stackView.getStack().getStackTasks();
TaskStackLayoutAlgorithm stackLayout = stackView.getStackAlgorithm();
TaskStackViewScroller stackScroller = stackView.getScroller();
stackView.updateToInitialState();
for (int i = tasks.size() - 1; i >= 0; i--) {
Task task = tasks.get(i);
if (task.isFreeformTask()) {
mTmpTransform = stackView.getStackAlgorithm()
.getStackTransformScreenCoordinates(task,
stackView.getScroller().getStackScroll(), mTmpTransform, null);
mTmpTransform = stackLayout.getStackTransformScreenCoordinates(task,
stackScroller.getStackScroll(), mTmpTransform, null);
Rect toTaskRect = new Rect();
mTmpTransform.rect.round(toTaskRect);
Bitmap thumbnail = getThumbnailBitmap(topTask, task, mTmpTransform);
@@ -778,8 +779,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
} else {
// Update the destination rect
Task toTask = new Task();
TaskViewTransform toTransform = getThumbnailTransitionTransform(stack, stackView,
toTask);
TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask);
RectF toTaskRect = toTransform.rect;
Bitmap thumbnail = getThumbnailBitmap(topTask, toTask, toTransform);
if (thumbnail != null) {
@@ -811,9 +811,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
/**
* Returns the transition rect for the given task id.
*/
private TaskViewTransform getThumbnailTransitionTransform(TaskStack stack,
TaskStackView stackView, Task runningTaskOut) {
private TaskViewTransform getThumbnailTransitionTransform(TaskStackView stackView,
Task runningTaskOut) {
// Find the running task in the TaskStack
TaskStack stack = stackView.getStack();
Task launchTask = stack.getLaunchTarget();
if (launchTask != null) {
runningTaskOut.copyFrom(launchTask);
@@ -824,7 +825,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
}
// Get the transform for the running task
stackView.getScroller().setStackScrollToInitialState();
stackView.updateToInitialState();
mTmpTransform = stackView.getStackAlgorithm().getStackTransformScreenCoordinates(launchTask,
stackView.getScroller().getStackScroll(), mTmpTransform, null);
return mTmpTransform;
@@ -852,6 +853,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
c.scale(toTransform.scale, toTransform.scale);
mHeaderBar.rebindToTask(toTask, false /* touchExplorationEnabled */,
disabledInSafeMode);
mHeaderBar.setDimAlpha(toTransform.dimAlpha);
mHeaderBar.draw(c);
c.setBitmap(null);
}
@@ -900,8 +902,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
if (useThumbnailTransition) {
// Try starting with a thumbnail transition
ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask, stack,
mDummyStackView);
ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask, mDummyStackView);
if (opts != null) {
startRecentsActivity(topTask, opts, false /* fromHome */,
false /* fromSearchHome */, true /* fromThumbnail */, stackVr);
@@ -948,14 +949,15 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
* Starts the recents activity.
*/
private void startRecentsActivity(ActivityManager.RunningTaskInfo topTask,
ActivityOptions opts, boolean fromHome, boolean fromSearchHome, boolean fromThumbnail,
TaskStackLayoutAlgorithm.VisibilityReport vr) {
ActivityOptions opts, boolean fromHome, boolean fromSearchHome,
boolean fromThumbnail, TaskStackLayoutAlgorithm.VisibilityReport vr) {
// Update the configuration based on the launch options
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
launchState.launchedFromHome = fromSearchHome || fromHome;
launchState.launchedFromSearchHome = fromSearchHome;
launchState.launchedFromAppWithThumbnail = fromThumbnail;
launchState.launchedFromApp = fromThumbnail || mLaunchedWhileDocking;
launchState.launchedFromAppDocked = mLaunchedWhileDocking;
launchState.launchedToTaskId = (topTask != null) ? topTask.id : -1;
launchState.launchedWithAltTab = mTriggeredFromAltTab;
launchState.launchedReuseTaskStackViews = mCanReuseTaskStackViews;

View File

@@ -0,0 +1,26 @@
/*
* Copyright (C) 2016 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 when the Recents activity configuration has changed.
*/
public class ConfigurationChangedEvent extends EventBus.AnimatedEvent {
// Simple event
}

View File

@@ -30,7 +30,7 @@ public class DozeTrigger {
@ViewDebug.ExportedProperty(category="recents")
boolean mIsDozing;
@ViewDebug.ExportedProperty(category="recents")
boolean mHasTriggered;
boolean mIsAsleep;
@ViewDebug.ExportedProperty(category="recents")
int mDozeDurationMilliseconds;
Runnable mOnSleepRunnable;
@@ -40,7 +40,7 @@ public class DozeTrigger {
@Override
public void run() {
mIsDozing = false;
mHasTriggered = true;
mIsAsleep = true;
mOnSleepRunnable.run();
}
};
@@ -56,7 +56,7 @@ public class DozeTrigger {
*/
public void startDozing() {
forcePoke();
mHasTriggered = false;
mIsAsleep = false;
}
/**
@@ -65,6 +65,7 @@ public class DozeTrigger {
public void stopDozing() {
mHandler.removeCallbacks(mDozeRunnable);
mIsDozing = false;
mIsAsleep = false;
}
/**
@@ -99,12 +100,7 @@ public class DozeTrigger {
}
/** Returns whether the trigger has fired at least once. */
public boolean hasTriggered() {
return mHasTriggered;
}
/** Resets the doze trigger state. */
public void resetTrigger() {
mHasTriggered = false;
public boolean isAsleep() {
return mIsAsleep;
}
}

View File

@@ -40,7 +40,6 @@ import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationC
import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
import com.android.systemui.recents.events.activity.HideRecentsEvent;
import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
@@ -284,7 +283,7 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
boolean wasLaunchedByAm = !launchState.launchedFromHome &&
!launchState.launchedFromAppWithThumbnail;
!launchState.launchedFromApp;
if (launchState.launchedHasConfigurationChanged || wasLaunchedByAm) {
EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
}

View File

@@ -37,6 +37,13 @@ public class FreeformWorkspaceLayoutAlgorithm {
private int mTaskPadding;
public FreeformWorkspaceLayoutAlgorithm(Context context) {
reloadOnConfigurationChange(context);
}
/**
* Reloads the layout for the current configuration.
*/
public void reloadOnConfigurationChange(Context context) {
// This is applied to the edges of each task
mTaskPadding = context.getResources().getDimensionPixelSize(
R.dimen.recents_freeform_workspace_task_padding) / 2;
@@ -72,8 +79,7 @@ public class FreeformWorkspaceLayoutAlgorithm {
}
// Bound the task width to the workspace width so that at the worst case, it will
// fit its own row
normalizedTaskWidths[i] = Math.min(rowTaskWidth,
normalizedWorkspaceWidth);
normalizedTaskWidths[i] = Math.min(rowTaskWidth, normalizedWorkspaceWidth);
}
// Determine the scale to best fit each of the tasks in the workspace

View File

@@ -105,9 +105,6 @@ public class RecentsTransitionHelper {
animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
@Override
public void onAnimationStarted() {
// If we are launching into another task, cancel the previous task's
// window transition
EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
if (screenPinningRequested) {
@@ -149,6 +146,10 @@ public class RecentsTransitionHelper {
animStartedListener);
}
}
// If we are launching into another task, cancel the previous task's
// window transition
EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
}
/**

View File

@@ -192,7 +192,7 @@ public class RecentsView extends FrameLayout {
// 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.launchedFromAppWithThumbnail
if (launchState.launchedWhileDocking || launchState.launchedFromApp
|| mStack.getTaskCount() == 0) {
mBackgroundScrim.setAlpha((int) (DEFAULT_SCRIM_ALPHA * 255));
} else {
@@ -671,7 +671,7 @@ public class RecentsView extends FrameLayout {
public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
if (!launchState.launchedWhileDocking && !launchState.launchedFromAppWithThumbnail
if (!launchState.launchedWhileDocking && !launchState.launchedFromApp
&& mStack.getTaskCount() > 0) {
animateBackgroundScrim(DEFAULT_SCRIM_ALPHA,
TaskStackAnimationHelper.ENTER_FROM_HOME_TRANSLATION_DURATION);

View File

@@ -56,8 +56,8 @@ public class TaskStackAnimationHelper {
/**
* Callback to start the animation for the launch target {@link TaskView}.
*/
void onStartLaunchTargetEnterAnimation(int duration, boolean screenPinningEnabled,
ReferenceCountedTrigger postAnimationTrigger);
void onStartLaunchTargetEnterAnimation(TaskViewTransform transform, int duration,
boolean screenPinningEnabled, ReferenceCountedTrigger postAnimationTrigger);
/**
* Callback to start the animation for the launch target {@link TaskView} when it is
@@ -141,7 +141,7 @@ public class TaskStackAnimationHelper {
tv.setVisibility(View.INVISIBLE);
} else if (launchState.launchedHasConfigurationChanged) {
// Just load the views as-is
} else if (launchState.launchedFromAppWithThumbnail) {
} else if (launchState.launchedFromApp) {
if (task.isLaunchTarget) {
tv.onPrepareLaunchTargetForEnterAnimation();
} else if (currentTaskOccludesLaunchTarget) {
@@ -205,10 +205,11 @@ public class TaskStackAnimationHelper {
stackLayout.getStackTransform(task, stackScroller.getStackScroll(), mTmpTransform,
null);
if (launchState.launchedFromAppWithThumbnail) {
if (launchState.launchedFromApp) {
if (task.isLaunchTarget) {
tv.onStartLaunchTargetEnterAnimation(taskViewEnterFromAppDuration,
mStackView.mScreenPinningEnabled, postAnimationTrigger);
tv.onStartLaunchTargetEnterAnimation(mTmpTransform,
taskViewEnterFromAppDuration, mStackView.mScreenPinningEnabled,
postAnimationTrigger);
} else {
// Animate the task up if it was occluding the launch target
if (currentTaskOccludesLaunchTarget) {

View File

@@ -29,6 +29,7 @@ import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsActivityLaunchState;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsDebugFlags;
import com.android.systemui.recents.misc.FreePathInterpolator;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
@@ -36,6 +37,7 @@ import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
import java.util.ArrayList;
import java.util.List;
/**
* Used to describe a visible range that can be normalized to [0, 1].
@@ -220,6 +222,10 @@ public class TaskStackLayoutAlgorithm {
private Range mUnfocusedRange;
private Range mFocusedRange;
// The initial offset from the top of the stack
@ViewDebug.ExportedProperty(category="recents")
private int mInitialTopPeekHeight;
// The offset from the top when scrolled to the top of the stack
@ViewDebug.ExportedProperty(category="recents")
private int mFocusedTopPeekHeight;
@@ -231,6 +237,10 @@ public class TaskStackLayoutAlgorithm {
@ViewDebug.ExportedProperty(category="recents")
private int mStackTopOffset;
// The height of the header bar
@ViewDebug.ExportedProperty(category="recents")
private int mHeaderBarHeight;
// The offset from the bottom of the stack to the bottom of the bounds when the stack is
// scrolled to the front
@ViewDebug.ExportedProperty(category="recents")
@@ -249,6 +259,9 @@ public class TaskStackLayoutAlgorithm {
private FreePathInterpolator mUnfocusedDimCurveInterpolator;
private FreePathInterpolator mFocusedDimCurveInterpolator;
// Indexed from the front of the stack, the normalized x in the unfocused range for each task
private float[] mInitialNormX;
// The state of the stack focus (0..1), which controls the transition of the stack from the
// focused to non-focused state
@ViewDebug.ExportedProperty(category="recents")
@@ -292,23 +305,32 @@ public class TaskStackLayoutAlgorithm {
TaskViewTransform mFrontOfStackTransform = new TaskViewTransform();
public TaskStackLayoutAlgorithm(Context context, TaskStackLayoutAlgorithmCallbacks cb) {
Resources res = context.getResources();
mContext = context;
mCb = cb;
mFreeformLayoutAlgorithm = new FreeformWorkspaceLayoutAlgorithm(context);
reloadOnConfigurationChange(context);
}
/**
* Reloads the layout for the current configuration.
*/
public void reloadOnConfigurationChange(Context context) {
Resources res = context.getResources();
mFocusedRange = new Range(res.getFloat(R.integer.recents_layout_focused_range_min),
res.getFloat(R.integer.recents_layout_focused_range_max));
mUnfocusedRange = new Range(res.getFloat(R.integer.recents_layout_unfocused_range_min),
res.getFloat(R.integer.recents_layout_unfocused_range_max));
mFocusState = getDefaultFocusState();
mFocusState = getInitialFocusState();
mInitialTopPeekHeight = res.getDimensionPixelSize(R.dimen.recents_initial_top_peek_size);
mFocusedTopPeekHeight =
res.getDimensionPixelSize(R.dimen.recents_layout_focused_top_peek_size);
mFocusedBottomTaskPeekHeight =
res.getDimensionPixelSize(R.dimen.recents_layout_focused_bottom_task_peek_size);
mHeaderBarHeight = res.getDimensionPixelSize(R.dimen.recents_task_bar_height);
mMinTranslationZ = res.getDimensionPixelSize(R.dimen.recents_task_view_z_min);
mMaxTranslationZ = res.getDimensionPixelSize(R.dimen.recents_task_view_z_max);
mFreeformLayoutAlgorithm = new FreeformWorkspaceLayoutAlgorithm(context);
mFreeformLayoutAlgorithm.reloadOnConfigurationChange(context);
}
/**
@@ -316,7 +338,7 @@ public class TaskStackLayoutAlgorithm {
*/
public void reset() {
mTaskIndexOverrideMap.clear();
setFocusState(getDefaultFocusState());
setFocusState(getInitialFocusState());
}
/**
@@ -439,46 +461,87 @@ public class TaskStackLayoutAlgorithm {
mTaskIndexMap.put(task.key.id, i);
}
// Calculate the min/max scroll
if (getDefaultFocusState() > 0f) {
mMinScrollP = 0;
mMaxScrollP = Math.max(mMinScrollP, mNumStackTasks - 1);
} else {
if (!ssp.hasFreeformWorkspaceSupport() && mNumStackTasks == 1) {
mMinScrollP = mMaxScrollP = 0;
} else {
float bottomOffsetPct = (float) (mStackBottomOffset + mTaskRect.height()) /
mStackRect.height();
float normX = mUnfocusedCurveInterpolator.getX(bottomOffsetPct);
mMinScrollP = 0;
mMaxScrollP = Math.max(mMinScrollP, (mNumStackTasks - 1) -
Math.max(0, mUnfocusedRange.getAbsoluteX(normX)));
}
}
// Update the freeform tasks
if (!freeformTasks.isEmpty()) {
mFreeformLayoutAlgorithm.update(freeformTasks, this);
mInitialScrollP = mMaxScrollP;
} else {
Task launchTask = stack.getLaunchTarget();
int launchTaskIndex = launchTask != null
? stack.indexOfStackTask(launchTask)
: mNumStackTasks - 1;
if (!ssp.hasFreeformWorkspaceSupport() && mNumStackTasks == 1) {
mInitialScrollP = mMinScrollP;
} else if (getDefaultFocusState() > 0f) {
if (launchState.launchedFromHome) {
mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
} else {
mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP,
mMaxScrollP);
}
}
// Calculate the min/max/initial scroll
Task launchTask = stack.getLaunchTarget();
int launchTaskIndex = launchTask != null
? stack.indexOfStackTask(launchTask)
: mNumStackTasks - 1;
if (getInitialFocusState() == STATE_FOCUSED) {
mMinScrollP = 0;
mMaxScrollP = Math.max(mMinScrollP, mNumStackTasks - 1);
if (launchState.launchedFromHome) {
mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
} else {
float offsetPct = (float) (mTaskRect.height() / 3) / mStackRect.height();
float normX = mUnfocusedCurveInterpolator.getX(offsetPct);
mInitialScrollP = Utilities.clamp(launchTaskIndex -
mUnfocusedRange.getAbsoluteX(normX), mMinScrollP, mMaxScrollP);
mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP, mMaxScrollP);
}
} else if (!ssp.hasFreeformWorkspaceSupport() && mNumStackTasks == 1) {
// If there is one stack task, ignore the min/max/initial scroll positions
mMinScrollP = 0;
mMaxScrollP = 0;
mInitialScrollP = 0;
} else {
// Set the max scroll to be the point where the front most task is visible with the
// stack bottom offset
int maxBottomOffset = mStackBottomOffset + mTaskRect.height();
float maxBottomOffsetPct = (float) maxBottomOffset / mStackRect.height();
float maxBottomNormX = mUnfocusedCurveInterpolator.getX(maxBottomOffsetPct);
mUnfocusedRange.offset(0f);
mMinScrollP = 0;
mMaxScrollP = Math.max(mMinScrollP, (mNumStackTasks - 1) -
Math.max(0, mUnfocusedRange.getAbsoluteX(maxBottomNormX)));
boolean scrollToFront = launchState.launchedFromHome ||
launchState.launchedFromAppDocked;
if (scrollToFront) {
mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
} else {
mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP, mMaxScrollP);
}
// Set the initial scroll to the predefined state (which differs from the stack)
int initialPeekOffset = mStackRect.height() - mInitialTopPeekHeight;
float initialPeekOffsetPct = (float) initialPeekOffset / mStackRect.height();
float initialPeekOffsetNormX = mUnfocusedCurveInterpolator.getX(initialPeekOffsetPct);
float initialFocusedOffset = mStackRect.height() - mInitialTopPeekHeight -
(mHeaderBarHeight * 1f) + 1;
float initialFocusedOffsetPct = (float) initialFocusedOffset / mStackRect.height();
float initialFocusedNormX = mUnfocusedCurveInterpolator.getX(initialFocusedOffsetPct);
int initialBottomOffset = mStackBottomOffset + mHeaderBarHeight;
float initialBottomOffsetPct = (float) initialBottomOffset / mStackRect.height();
float initialBottomNormX = mUnfocusedCurveInterpolator.getX(initialBottomOffsetPct);
/*
// If we want to offset the top card slightly
mInitialNormX = scrollToFront
? new float[] { initialFocusedNormX, initialPeekOffsetNormX, 0f }
: new float[] { initialBottomNormX, initialFocusedNormX,
initialPeekOffsetNormX, 0f };
*/
mInitialNormX = scrollToFront
? new float[] { initialFocusedNormX, initialPeekOffsetNormX, 0f }
: new float[] { initialBottomNormX, 0.5f, 0f };
}
}
public void updateToInitialState(List<Task> tasks) {
if (mInitialNormX == null) {
return;
}
RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
mUnfocusedRange.offset(0f);
int taskCount = tasks.size();
for (int i = taskCount - 1; i >= 0; i--) {
int indexFromFront = taskCount - i - 1;
if (indexFromFront >= mInitialNormX.length) {
break;
}
float newTaskProgress = mInitialScrollP +
mUnfocusedRange.getAbsoluteX(mInitialNormX[indexFromFront]);
mTaskIndexOverrideMap.put(tasks.get(i).key.id, newTaskProgress);
}
}
@@ -500,6 +563,10 @@ public class TaskStackLayoutAlgorithm {
}
}
public void clearUnfocusedTaskOverrides() {
mTaskIndexOverrideMap.clear();
}
/**
* Updates this stack when a scroll happens.
*/
@@ -523,7 +590,7 @@ public class TaskStackLayoutAlgorithm {
} else {
// Scrolling override x away from x, we should still move the scroll towards x
float deltaX = overrideX - x;
newOverrideX = Math.signum(deltaX) * (Math.abs(deltaX) - deltaScroll);
newOverrideX = Math.signum(deltaX) * (Math.abs(deltaX) - Math.abs(deltaScroll));
mTaskIndexOverrideMap.put(taskId, x + newOverrideX);
}
}
@@ -532,8 +599,13 @@ public class TaskStackLayoutAlgorithm {
/**
* Returns the default focus state.
*/
public int getDefaultFocusState() {
return STATE_FOCUSED;
public int getInitialFocusState() {
RecentsDebugFlags debugFlags = Recents.getDebugFlags();
if (debugFlags.isPagingEnabled()) {
return STATE_FOCUSED;
} else {
return STATE_UNFOCUSED;
}
}
/**
@@ -577,7 +649,7 @@ public class TaskStackLayoutAlgorithm {
// Otherwise, walk backwards in the stack and count the number of tasks and visible
// thumbnails and add that to the total freeform task count
TaskViewTransform tmpTransform = new TaskViewTransform();
Range currentRange = getDefaultFocusState() > 0f ? mFocusedRange : mUnfocusedRange;
Range currentRange = getInitialFocusState() > 0f ? mFocusedRange : mUnfocusedRange;
currentRange.offset(mInitialScrollP);
int taskBarHeight = mContext.getResources().getDimensionPixelSize(
R.dimen.recents_task_bar_height);
@@ -635,11 +707,19 @@ public class TaskStackLayoutAlgorithm {
public TaskViewTransform getStackTransform(Task task, float stackScroll,
TaskViewTransform transformOut, TaskViewTransform frontTransform) {
return getStackTransform(task, stackScroll, mFocusState, transformOut, frontTransform,
false /* forceUpdate */);
false /* forceUpdate */, false /* ignoreTaskOverrides */);
}
public TaskViewTransform getStackTransform(Task task, float stackScroll,
TaskViewTransform transformOut, TaskViewTransform frontTransform,
boolean ignoreTaskOverrides) {
return getStackTransform(task, stackScroll, mFocusState, transformOut, frontTransform,
false /* forceUpdate */, ignoreTaskOverrides);
}
public TaskViewTransform getStackTransform(Task task, float stackScroll, int focusState,
TaskViewTransform transformOut, TaskViewTransform frontTransform, boolean forceUpdate) {
TaskViewTransform transformOut, TaskViewTransform frontTransform, boolean forceUpdate,
boolean ignoreTaskOverrides) {
if (mFreeformLayoutAlgorithm.isTransformAvailable(task, this)) {
mFreeformLayoutAlgorithm.getTransform(task, transformOut, this);
return transformOut;
@@ -649,7 +729,9 @@ public class TaskStackLayoutAlgorithm {
transformOut.reset();
return transformOut;
}
float taskProgress = getStackScrollForTask(task);
float taskProgress = ignoreTaskOverrides
? mTaskIndexMap.get(task.key.id, 0)
: getStackScrollForTask(task);
getStackTransform(taskProgress, stackScroll, focusState, transformOut,
frontTransform, false /* ignoreSingleTaskCase */, forceUpdate);
return transformOut;
@@ -851,8 +933,8 @@ public class TaskStackLayoutAlgorithm {
// The unfocused dim interpolator starts at max dim, reduces to zero at 0.5 (the focused
// task), then goes back to max dim towards the front of the stack
p.moveTo(0f, MAX_DIM);
p.cubicTo(0f, 0.1f, 0.4f, 0f, 0.5f, 0f);
p.cubicTo(0.6f, 0f, 0.9f, MAX_DIM - 0.1f, 1f, MAX_DIM / 2f);
p.cubicTo(0.1f, MAX_DIM, 0.4f, 0.0f, 0.5f, 0f);
p.cubicTo(0.6f, 0f, 0.9f, MAX_DIM / 2f, 1f, MAX_DIM / 2f);
return p;
}

View File

@@ -35,7 +35,6 @@ import android.provider.Settings;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.MutableBoolean;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@@ -56,6 +55,7 @@ import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsDebugFlags;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
import com.android.systemui.recents.events.activity.EnterRecentsTaskStackAnimationCompletedEvent;
import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
@@ -73,7 +73,6 @@ import com.android.systemui.recents.events.component.RecentsVisibilityChangedEve
import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
import com.android.systemui.recents.events.ui.StackViewScrolledEvent;
import com.android.systemui.recents.events.ui.TaskViewDismissedEvent;
import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent;
import com.android.systemui.recents.events.ui.UserInteractionEvent;
@@ -274,10 +273,18 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
/** Returns the task stack. */
TaskStack getStack() {
public TaskStack getStack() {
return mStack;
}
/**
* Updates this TaskStackView to the initial state.
*/
public void updateToInitialState() {
mStackScroller.setStackScrollToInitialState();
mLayoutAlgorithm.updateToInitialState(mStack.getStackTasks());
}
/** Updates the list of task views */
void updateTaskViewsList() {
mTaskViews.clear();
@@ -355,7 +362,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
mAwaitingFirstLayout = true;
mEnterAnimationComplete = false;
mUIDozeTrigger.stopDozing();
mUIDozeTrigger.resetTrigger();
mStackScroller.reset();
mLayoutAlgorithm.reset();
readSystemFlags();
@@ -410,7 +416,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
*/
int[] computeVisibleTaskTransforms(ArrayList<TaskViewTransform> taskTransforms,
ArrayList<Task> tasks, float curStackScroll, float targetStackScroll,
ArraySet<Task.TaskKey> ignoreTasksSet) {
ArraySet<Task.TaskKey> ignoreTasksSet, boolean ignoreTaskOverrides) {
int taskCount = tasks.size();
int[] visibleTaskRange = mTmpIntPair;
visibleTaskRange[0] = -1;
@@ -430,7 +436,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Calculate the current and (if necessary) the target transform for the task
transform = mLayoutAlgorithm.getStackTransform(task, curStackScroll,
taskTransforms.get(i), frontTransform);
taskTransforms.get(i), frontTransform, ignoreTaskOverrides);
if (useTargetStackScroll && !transform.visible) {
// If we have a target stack scroll and the task is not currently visible, then we
// just update the transform at the new scroll
@@ -468,11 +474,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/**
* Binds the visible {@link TaskView}s at the given target scroll.
*
* @see #bindVisibleTaskViews(float, ArraySet<Task.TaskKey>)
*/
void bindVisibleTaskViews(float targetStackScroll) {
bindVisibleTaskViews(targetStackScroll, mIgnoreTasks);
bindVisibleTaskViews(targetStackScroll, mIgnoreTasks, false /* ignoreTaskOverrides */);
}
void bindVisibleTaskViews(float targetStackScroll, boolean ignoreTaskOverrides) {
bindVisibleTaskViews(targetStackScroll, mIgnoreTasks, ignoreTaskOverrides);
}
/**
@@ -487,12 +495,16 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
* target stack scroll.
* @param ignoreTasksSet The set of tasks to ignore in this rebinding of the visible
* {@link TaskView}s
* @param ignoreTaskOverrides If set, the visible task computation will get the transforms for
* tasks at their non-overridden task progress
*/
void bindVisibleTaskViews(float targetStackScroll, ArraySet<Task.TaskKey> ignoreTasksSet) {
void bindVisibleTaskViews(float targetStackScroll, ArraySet<Task.TaskKey> ignoreTasksSet,
boolean ignoreTaskOverrides) {
// Get all the task transforms
ArrayList<Task> tasks = mStack.getStackTasks();
int[] visibleTaskRange = computeVisibleTaskTransforms(mCurrentTaskTransforms, tasks,
mStackScroller.getStackScroll(), targetStackScroll, ignoreTasksSet);
mStackScroller.getStackScroll(), targetStackScroll, ignoreTasksSet,
ignoreTaskOverrides);
// Return all the invisible children to the pool
mTmpTaskViewMap.clear();
@@ -605,7 +617,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
cancelAllTaskViewAnimations();
// Synchronize the current set of TaskViews
bindVisibleTaskViews(mStackScroller.getStackScroll(), ignoreTasksSet);
bindVisibleTaskViews(mStackScroller.getStackScroll(), ignoreTasksSet,
false /* ignoreTaskOverrides */);
// Animate them to their final transforms with the given animation
List<TaskView> taskViews = getTaskViews();
@@ -657,7 +670,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
transform.fillIn(tv);
} else {
mLayoutAlgorithm.getStackTransform(task, mStackScroller.getStackScroll(),
focusState, transform, null, true /* forceUpdate */);
focusState, transform, null, true /* forceUpdate */,
false /* ignoreTaskOverrides */);
}
transform.visible = true;
}
@@ -674,7 +688,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
Task task = tasks.get(i);
TaskViewTransform transform = transformsOut.get(i);
mLayoutAlgorithm.getStackTransform(task, stackScroll, focusState, transform, null,
true /* forceUpdate */);
true /* forceUpdate */, true /* ignoreTaskOverrides */);
transform.visible = true;
}
}
@@ -759,9 +773,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
}
tv.getViewBounds().setClipBottom(clipBottom);
if (!config.useHardwareLayers) {
tv.mThumbnailView.updateThumbnailVisibility(clipBottom - tv.getPaddingBottom());
}
tv.mThumbnailView.updateThumbnailVisibility(clipBottom - tv.getPaddingBottom());
prevVisibleTv = tv;
}
mTaskViewsClipDirty = false;
@@ -860,6 +872,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
cancelAllTaskViewAnimations();
}
mLayoutAlgorithm.clearUnfocusedTaskOverrides();
willScroll = mAnimationHelper.startScrollToFocusedTaskAnimation(newFocusedTask,
requestViewFocus);
} else {
@@ -1162,11 +1175,16 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// If this is the first layout, then scroll to the front of the stack, then update the
// TaskViews with the stack so that we can lay them out
if (mAwaitingFirstLayout) {
mStackScroller.setStackScrollToInitialState();
// TODO: The second check is a workaround for wacky layouts that we get while docking via
// long pressing the recents button
if (mAwaitingFirstLayout ||
(mStackScroller.getStackScroll() == mLayoutAlgorithm.mInitialScrollP)) {
updateToInitialState();
}
// Rebind all the views, including the ignore ones
bindVisibleTaskViews(mStackScroller.getStackScroll(), EMPTY_TASK_SET);
bindVisibleTaskViews(mStackScroller.getStackScroll(), EMPTY_TASK_SET,
false /* ignoreTaskOverrides */);
// Measure each of the TaskViews
mTmpTaskViews.clear();
@@ -1458,7 +1476,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
Recents.getTaskLoader().loadTaskData(task, true /* fetchAndInvalidateThumbnails */);
// If the doze trigger has already fired, then update the state for this task view
if (mUIDozeTrigger.hasTriggered()) {
if (mUIDozeTrigger.isAsleep()) {
tv.setNoUserInteractionState();
}
@@ -1859,6 +1877,12 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
});
}
public final void onBusEvent(ConfigurationChangedEvent event) {
mLayoutAlgorithm.reloadOnConfigurationChange(getContext());
mLayoutAlgorithm.initialize(mStackBounds,
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
}
/**
* Removes the task from the stack, and updates the focus to the next task in the stack if the
* removed TaskView was focused.

View File

@@ -115,13 +115,8 @@ public class TaskStackViewScroller {
* @return whether the stack progress changed.
*/
public boolean setStackScrollToInitialState() {
SystemServicesProxy ssp = Recents.getSystemServices();
float prevStackScrollP = mStackScrollP;
if (ssp.hasDockedTask()) {
setStackScroll(mLayoutAlgorithm.mMaxScrollP);
} else {
setStackScroll(mLayoutAlgorithm.mInitialScrollP);
}
setStackScroll(mLayoutAlgorithm.mInitialScrollP);
return Float.compare(prevStackScrollP, mStackScrollP) != 0;
}

View File

@@ -446,7 +446,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
}
// Pick up the newly visible views, not including the deleting tasks
mSv.bindVisibleTaskViews(newStackScroll);
mSv.bindVisibleTaskViews(newStackScroll, true /* ignoreTaskOverrides */);
// Get the final set of task transforms (with task removed)
mSv.getLayoutTaskTransforms(newStackScroll, TaskStackLayoutAlgorithm.STATE_UNFOCUSED,
@@ -486,6 +486,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
mSv.getScroller().setStackScroll(mTargetStackScroll, null);
// Update the focus state to the final focus state
mSv.getStackAlgorithm().setFocusState(TaskStackLayoutAlgorithm.STATE_UNFOCUSED);
mSv.getStackAlgorithm().clearUnfocusedTaskOverrides();
// Remove the task view from the stack
EventBus.getDefault().send(new TaskViewDismissedEvent(tv.getTask(), tv));
// Stop tracking this deletion animation

View File

@@ -75,6 +75,24 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
void onTaskViewClipStateChanged(TaskView tv);
}
/**
* The dim overlay is generally calculated from the task progress, but occasionally (like when
* launching) needs to be animated independently of the task progress. This call is only used
* when animating the task into Recents, when the header dim is already applied
*/
public static final Property<TaskView, Float> DIM_ALPHA_WITHOUT_HEADER =
new FloatProperty<TaskView>("dimAlphaWithoutHeader") {
@Override
public void setValue(TaskView tv, float dimAlpha) {
tv.setDimAlphaWithoutHeader(dimAlpha);
}
@Override
public Float get(TaskView tv) {
return tv.getDimAlpha();
}
};
/**
* The dim overlay is generally calculated from the task progress, but occasionally (like when
* launching) needs to be animated independently of the task progress.
@@ -388,21 +406,17 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
* Sets the current dim.
*/
public void setDimAlpha(float dimAlpha) {
RecentsConfiguration config = Recents.getConfiguration();
int dimAlphaInt = (int) (dimAlpha * 255);
mDimAlpha = dimAlpha;
if (config.useHardwareLayers) {
// Defer setting hardware layers if we have not yet measured, or there is no dim to draw
if (getMeasuredWidth() > 0 && getMeasuredHeight() > 0) {
mDimColorFilter.setColor(Color.argb(dimAlphaInt, 0, 0, 0));
mDimLayerPaint.setColorFilter(mDimColorFilter);
mContent.setLayerType(LAYER_TYPE_HARDWARE, mDimLayerPaint);
}
} else {
mThumbnailView.setDimAlpha(dimAlpha);
mHeaderView.setDimAlpha(dimAlpha);
}
mThumbnailView.setDimAlpha(dimAlpha);
mHeaderView.setDimAlpha(dimAlpha);
}
/**
* Sets the current dim without updating the header's dim.
*/
public void setDimAlphaWithoutHeader(float dimAlpha) {
mDimAlpha = dimAlpha;
mThumbnailView.setDimAlpha(dimAlpha);
}
/**
@@ -412,25 +426,6 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
return mDimAlpha;
}
/**
* Animates the dim to the given value.
*/
void animateDimAlpha(float toDimAlpha, AnimationProps animation) {
// Animate the dim into view as well
if (Float.compare(toDimAlpha, getDimAlpha()) != 0) {
Animator anim = animation.apply(AnimationProps.DIM_ALPHA, ObjectAnimator.ofFloat(this,
DIM_ALPHA, getDimAlpha(), toDimAlpha));
if (animation.getListener() != null) {
anim.addListener(animation.getListener());
}
anim.start();
} else {
if (animation.getListener() != null) {
animation.getListener().onAnimationEnd(null);
}
}
}
/**
* Explicitly sets the focused state of this task.
*/
@@ -517,18 +512,20 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
@Override
public void onPrepareLaunchTargetForEnterAnimation() {
// These values will be animated in when onStartLaunchTargetEnterAnimation() is called
setDimAlpha(0);
setDimAlphaWithoutHeader(0);
mActionButtonView.setAlpha(0f);
}
@Override
public void onStartLaunchTargetEnterAnimation(int duration, boolean screenPinningEnabled,
ReferenceCountedTrigger postAnimationTrigger) {
// Un-dim the view before/while launching the target
AnimationProps animation = new AnimationProps(duration, Interpolators.ALPHA_OUT)
.setListener(postAnimationTrigger.decrementOnAnimationEnd());
public void onStartLaunchTargetEnterAnimation(TaskViewTransform transform, int duration,
boolean screenPinningEnabled, ReferenceCountedTrigger postAnimationTrigger) {
// Dim the view after the app window transitions down into recents
postAnimationTrigger.increment();
animateDimAlpha(0, animation);
AnimationProps animation = new AnimationProps(duration, Interpolators.ALPHA_OUT);
Animator anim = animation.apply(AnimationProps.DIM_ALPHA, ObjectAnimator.ofFloat(this,
DIM_ALPHA_WITHOUT_HEADER, getDimAlpha(), transform.dimAlpha));
anim.addListener(postAnimationTrigger.decrementOnAnimationEnd());
anim.start();
if (screenPinningEnabled) {
showActionButton(true /* fadeIn */, duration /* fadeInDuration */);
@@ -540,7 +537,9 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
ReferenceCountedTrigger postAnimationTrigger) {
// Un-dim the view before/while launching the target
AnimationProps animation = new AnimationProps(duration, Interpolators.ALPHA_OUT);
animateDimAlpha(0, animation);
Animator anim = animation.apply(AnimationProps.DIM_ALPHA, ObjectAnimator.ofFloat(this,
DIM_ALPHA, getDimAlpha(), 0));
anim.start();
postAnimationTrigger.increment();
hideActionButton(true /* fadeOut */, duration,

View File

@@ -347,9 +347,11 @@ public class TaskViewHeader extends FrameLayout
* Sets the dim alpha, only used when we are not using hardware layers.
* (see RecentsConfiguration.useHardwareLayers)
*/
void setDimAlpha(float dimAlpha) {
mDimAlpha = dimAlpha;
updateBackgroundColor(mBackground.getColor(), dimAlpha);
public void setDimAlpha(float dimAlpha) {
if (Float.compare(mDimAlpha, dimAlpha) != 0) {
mDimAlpha = dimAlpha;
updateBackgroundColor(mBackground.getColor(), dimAlpha);
}
}
/**
@@ -377,7 +379,9 @@ public class TaskViewHeader extends FrameLayout
int primaryColor = disabledInSafeMode
? mDisabledTaskBarBackgroundColor
: t.colorPrimary;
updateBackgroundColor(primaryColor, mDimAlpha);
if (mBackground.getColor() != primaryColor) {
updateBackgroundColor(primaryColor, mDimAlpha);
}
if (t.icon != null) {
mIconView.setImageDrawable(t.icon);
}