diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 8a7f90bf4a146..12c3a5d8cb501 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 d7c12ba329f35..a2934d7434413 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 aa1437b28ee8b..ec4820a349647 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 9e43bb46d7d1e..eec0411f3590f 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 cd643230a167b..6feda81bc60a1 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 86b03c850da47..58219bf6eeaa0 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 0000000000000..0ad46817154fe --- /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 95aa10f4876e2..574ea03ac9bba 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 0c48cf7483161..4ba9efada9de2 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 43591013868a3..72b914c6874e9 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 37b2859de411a..e5022a48cd078 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 5dde92698f789..10f491eb2bdcb 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 d152010c71c83..758f4d82336b1 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 261b6f6ae6459..b60fca8c19234 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) { - 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 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 e1a81c8c15f25..c2bfc28175456 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 333df9dd5b11f..ad46abd74f7d9 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 20933ee3cf6fd..52f8fc89f4534 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 2e7c7f2e640c5..e9c7ac6ccbb52 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -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 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. @@ -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, 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 05a85278db169..b2a7d902f0022 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); }