From e693aafe0511c2a7ffc571b22abeefba44046225 Mon Sep 17 00:00:00 2001 From: Winson Date: Tue, 1 Mar 2016 12:05:59 -0800 Subject: [PATCH] Disabling timer - Disabling the timer by default - Adding flag to enable/disable paging (disabled by default). When disabled, the second tap will just launch the next task. - Updating the initial state to put tasks at specific points on the curve. This allows us to allocate specific space for the front most tasks, as well as the tasks behind it. - Removing hardware layer config (no devices targeting N depend on it) - Fixing issue with the header not having the final dim applied when transitioning into recents. - Fixing issue where the stack range would not be reloaded after docking or undocking a task. Bug: 27409035 Change-Id: I13a03fba2b1a770f15d0033d43ef4c28415041c9 --- packages/SystemUI/res/values/dimens.xml | 3 + .../android/systemui/recents/RecentsActivity.java | 27 ++-- .../recents/RecentsActivityLaunchState.java | 8 +- .../systemui/recents/RecentsConfiguration.java | 2 - .../systemui/recents/RecentsDebugFlags.java | 31 ++-- .../com/android/systemui/recents/RecentsImpl.java | 84 +++++----- .../events/activity/ConfigurationChangedEvent.java | 26 ++++ .../android/systemui/recents/misc/DozeTrigger.java | 16 +- .../systemui/recents/tv/RecentsTvActivity.java | 3 +- .../views/FreeformWorkspaceLayoutAlgorithm.java | 10 +- .../recents/views/RecentsTransitionHelper.java | 7 +- .../systemui/recents/views/RecentsView.java | 4 +- .../recents/views/TaskStackAnimationHelper.java | 13 +- .../recents/views/TaskStackLayoutAlgorithm.java | 172 +++++++++++++++------ .../systemui/recents/views/TaskStackView.java | 66 +++++--- .../recents/views/TaskStackViewScroller.java | 7 +- .../recents/views/TaskStackViewTouchHandler.java | 3 +- .../android/systemui/recents/views/TaskView.java | 79 +++++----- .../systemui/recents/views/TaskViewHeader.java | 12 +- 19 files changed, 355 insertions(+), 218 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 8a7f90bf4a14..12c3a5d8cb50 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -292,6 +292,9 @@ 24dp + + 8dp + @dimen/recents_history_button_height diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index d7c12ba329f3..a2934d743441 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -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; diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java index aa1437b28ee8..ec4820a34964 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java @@ -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 diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java index 9e43bb46d7d1..eec0411f3590 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java @@ -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); diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java index cd643230a167..6feda81bc60a 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java @@ -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()); diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index 86b03c850da4..58219bf6eeaa 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java @@ -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 specs = new ArrayList<>(); - stackView.getScroller().setStackScrollToInitialState(); - ArrayList tasks = stack.getStackTasks(); + ArrayList 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; diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java new file mode 100644 index 000000000000..0ad46817154f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java @@ -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 +} diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java index 95aa10f4876e..574ea03ac9bb 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java @@ -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; } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java index 0c48cf748316..4ba9efada9de 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java @@ -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()); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java index 43591013868a..72b914c6874e 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java @@ -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 diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java index 37b2859de411..e5022a48cd07 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java @@ -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)); } /** diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index 5dde92698f78..10f491eb2bdc 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -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); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java index d152010c71c8..758f4d82336b 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java @@ -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) { diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java index 261b6f6ae645..b60fca8c1923 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java @@ -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) { + // Update the freeform tasks + if (!freeformTasks.isEmpty()) { + mFreeformLayoutAlgorithm.update(freeformTasks, this); + } + + // 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 { + 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 { - if (!ssp.hasFreeformWorkspaceSupport() && mNumStackTasks == 1) { - mMinScrollP = mMaxScrollP = 0; + // 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 { - 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))); + 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 }; } + } - 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); - } - } else { - float offsetPct = (float) (mTaskRect.height() / 3) / mStackRect.height(); - float normX = mUnfocusedCurveInterpolator.getX(offsetPct); - mInitialScrollP = Utilities.clamp(launchTaskIndex - - mUnfocusedRange.getAbsoluteX(normX), mMinScrollP, mMaxScrollP); + public void updateToInitialState(List 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; } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index e1a81c8c15f2..c2bfc2817545 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -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 taskTransforms, ArrayList tasks, float curStackScroll, float targetStackScroll, - ArraySet ignoreTasksSet) { + ArraySet 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) */ 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 ignoreTasksSet) { + void bindVisibleTaskViews(float targetStackScroll, ArraySet ignoreTasksSet, + boolean ignoreTaskOverrides) { // Get all the task transforms ArrayList 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 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. diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java index 333df9dd5b11..ad46abd74f7d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java @@ -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; } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java index 20933ee3cf6f..52f8fc89f453 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java @@ -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 diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java index 2e7c7f2e640c..e9c7ac6ccbb5 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -77,6 +77,24 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks /** * 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 DIM_ALPHA_WITHOUT_HEADER = + new FloatProperty("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. */ public static final Property DIM_ALPHA = @@ -388,47 +406,24 @@ 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); } /** - * Returns the current dim. + * Sets the current dim without updating the header's dim. */ - public float getDimAlpha() { - return mDimAlpha; + public void setDimAlphaWithoutHeader(float dimAlpha) { + mDimAlpha = dimAlpha; + mThumbnailView.setDimAlpha(dimAlpha); } /** - * Animates the dim to the given value. + * Returns the current dim. */ - 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); - } - } + public float getDimAlpha() { + return mDimAlpha; } /** @@ -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, diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java index 05a85278db16..b2a7d902f002 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java @@ -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); } -- 2.11.0