Ensure that loading and unloading of tasks happen symmetrically with lifecycle events. (Bug 18574950)
Since we were unloading tasks when the activity was stopped, but only reloading tasks on the next onCreate()/onNewIntent(), there were cases where the system would create the activity but then immediately stop and start it (ie. when the screen is turned off while the activity has resumeWhilePausing=True set in its manifest). This CL ensures that we reload the tasks with the same state used the last time the Recents activity was started. The CL also cleans up some visibility state that was confusing and is no longer necessary, fixes a small issue with the dismiss button flashing when toggling Recents quickly, and fixes some cases where the initial stack scroll is set incorrectly.
This commit is contained in:
@@ -61,15 +61,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
/** A proxy implementation for the recents component */
|
||||
public class AlternateRecentsComponent implements ActivityOptions.OnAnimationStartedListener {
|
||||
|
||||
final public static String EXTRA_FROM_HOME = "recents.triggeredOverHome";
|
||||
final public static String EXTRA_FROM_SEARCH_HOME = "recents.triggeredOverSearchHome";
|
||||
final public static String EXTRA_FROM_APP_THUMBNAIL = "recents.animatingWithThumbnail";
|
||||
final public static String EXTRA_FROM_TASK_ID = "recents.activeTaskId";
|
||||
final public static String EXTRA_TRIGGERED_FROM_ALT_TAB = "recents.triggeredFromAltTab";
|
||||
final public static String EXTRA_TRIGGERED_FROM_HOME_KEY = "recents.triggeredFromHomeKey";
|
||||
final public static String EXTRA_REUSE_TASK_STACK_VIEWS = "recents.reuseTaskStackViews";
|
||||
final public static String EXTRA_NUM_VISIBLE_TASKS = "recents.numVisibleTasks";
|
||||
final public static String EXTRA_NUM_VISIBLE_THUMBNAILS = "recents.numVisibleThumbnails";
|
||||
|
||||
final public static String ACTION_START_ENTER_ANIMATION = "action_start_enter_animation";
|
||||
final public static String ACTION_TOGGLE_RECENTS_ACTIVITY = "action_toggle_recents_activity";
|
||||
@@ -550,7 +543,8 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
|
||||
ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask, stack,
|
||||
mDummyStackView);
|
||||
if (opts != null) {
|
||||
startAlternateRecentsActivity(topTask, opts, EXTRA_FROM_APP_THUMBNAIL, stackVr);
|
||||
startAlternateRecentsActivity(topTask, opts, false /* fromHome */,
|
||||
false /* fromSearchHome */, true /* fromThumbnail */, stackVr);
|
||||
} else {
|
||||
// Fall through below to the non-thumbnail transition
|
||||
useThumbnailTransition = false;
|
||||
@@ -583,12 +577,13 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
|
||||
}
|
||||
|
||||
ActivityOptions opts = getHomeTransitionActivityOptions(fromSearchHome);
|
||||
startAlternateRecentsActivity(topTask, opts,
|
||||
fromSearchHome ? EXTRA_FROM_SEARCH_HOME : EXTRA_FROM_HOME, stackVr);
|
||||
startAlternateRecentsActivity(topTask, opts, true /* fromHome */, fromSearchHome,
|
||||
false /* fromThumbnail */, stackVr);
|
||||
} else {
|
||||
// Otherwise we do the normal fade from an unknown source
|
||||
ActivityOptions opts = getUnknownTransitionActivityOptions();
|
||||
startAlternateRecentsActivity(topTask, opts, EXTRA_FROM_HOME, stackVr);
|
||||
startAlternateRecentsActivity(topTask, opts, true /* fromHome */,
|
||||
false /* fromSearchHome */, false /* fromThumbnail */, stackVr);
|
||||
}
|
||||
}
|
||||
mLastToggleTime = SystemClock.elapsedRealtime();
|
||||
@@ -596,21 +591,24 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
|
||||
|
||||
/** Starts the recents activity */
|
||||
void startAlternateRecentsActivity(ActivityManager.RunningTaskInfo topTask,
|
||||
ActivityOptions opts, String extraFlag,
|
||||
ActivityOptions opts, boolean fromHome, boolean fromSearchHome, boolean fromThumbnail,
|
||||
TaskStackViewLayoutAlgorithm.VisibilityReport vr) {
|
||||
// Update the configuration based on the launch options
|
||||
mConfig.launchedFromHome = fromSearchHome || fromHome;
|
||||
mConfig.launchedFromSearchHome = fromSearchHome;
|
||||
mConfig.launchedFromAppWithThumbnail = fromThumbnail;
|
||||
mConfig.launchedToTaskId = (topTask != null) ? topTask.id : -1;
|
||||
mConfig.launchedWithAltTab = mTriggeredFromAltTab;
|
||||
mConfig.launchedReuseTaskStackViews = mCanReuseTaskStackViews;
|
||||
mConfig.launchedNumVisibleTasks = vr.numVisibleTasks;
|
||||
mConfig.launchedNumVisibleThumbnails = vr.numVisibleThumbnails;
|
||||
mConfig.launchedHasConfigurationChanged = false;
|
||||
|
||||
Intent intent = new Intent(sToggleRecentsAction);
|
||||
intent.setClassName(sRecentsPackage, sRecentsActivity);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
|
||||
| Intent.FLAG_ACTIVITY_TASK_ON_HOME);
|
||||
if (extraFlag != null) {
|
||||
intent.putExtra(extraFlag, true);
|
||||
}
|
||||
intent.putExtra(EXTRA_TRIGGERED_FROM_ALT_TAB, mTriggeredFromAltTab);
|
||||
intent.putExtra(EXTRA_FROM_TASK_ID, (topTask != null) ? topTask.id : -1);
|
||||
intent.putExtra(EXTRA_REUSE_TASK_STACK_VIEWS, mCanReuseTaskStackViews);
|
||||
intent.putExtra(EXTRA_NUM_VISIBLE_TASKS, vr.numVisibleTasks);
|
||||
intent.putExtra(EXTRA_NUM_VISIBLE_THUMBNAILS, vr.numVisibleThumbnails);
|
||||
if (opts != null) {
|
||||
mContext.startActivityAsUser(intent, opts.toBundle(), UserHandle.CURRENT);
|
||||
} else {
|
||||
|
||||
@@ -108,8 +108,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// Mark Recents as no longer visible
|
||||
onRecentsActivityVisibilityChanged(false);
|
||||
// Finish Recents
|
||||
if (mLaunchIntent != null) {
|
||||
if (mLaunchOpts != null) {
|
||||
@@ -133,8 +131,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (action.equals(AlternateRecentsComponent.ACTION_HIDE_RECENTS_ACTIVITY)) {
|
||||
// Mark Recents as no longer visible
|
||||
AlternateRecentsComponent.notifyVisibilityChanged(false);
|
||||
if (intent.getBooleanExtra(AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_ALT_TAB, false)) {
|
||||
// If we are hiding from releasing Alt-Tab, dismiss Recents to the focused app
|
||||
dismissRecentsToFocusedTaskOrHome(false);
|
||||
@@ -186,24 +182,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
||||
|
||||
/** Updates the set of recent tasks */
|
||||
void updateRecentsTasks(Intent launchIntent) {
|
||||
// Update the configuration based on the launch intent
|
||||
boolean fromSearchHome = launchIntent.getBooleanExtra(
|
||||
AlternateRecentsComponent.EXTRA_FROM_SEARCH_HOME, false);
|
||||
int numVisibleTasks = launchIntent.getIntExtra(
|
||||
AlternateRecentsComponent.EXTRA_NUM_VISIBLE_TASKS, 0);
|
||||
int numVisibleThumbnails = launchIntent.getIntExtra(
|
||||
AlternateRecentsComponent.EXTRA_NUM_VISIBLE_THUMBNAILS, 0);
|
||||
mConfig.launchedFromHome = fromSearchHome || launchIntent.getBooleanExtra(
|
||||
AlternateRecentsComponent.EXTRA_FROM_HOME, false);
|
||||
mConfig.launchedFromAppWithThumbnail = launchIntent.getBooleanExtra(
|
||||
AlternateRecentsComponent.EXTRA_FROM_APP_THUMBNAIL, false);
|
||||
mConfig.launchedToTaskId = launchIntent.getIntExtra(
|
||||
AlternateRecentsComponent.EXTRA_FROM_TASK_ID, -1);
|
||||
mConfig.launchedWithAltTab = launchIntent.getBooleanExtra(
|
||||
AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_ALT_TAB, false);
|
||||
mConfig.launchedReuseTaskStackViews = launchIntent.getBooleanExtra(
|
||||
AlternateRecentsComponent.EXTRA_REUSE_TASK_STACK_VIEWS, false);
|
||||
|
||||
// If AlternateRecentsComponent has preloaded a load plan, then use that to prevent
|
||||
// reconstructing the task stack
|
||||
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
|
||||
@@ -218,8 +196,8 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
||||
}
|
||||
RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
|
||||
loadOpts.runningTaskId = mConfig.launchedToTaskId;
|
||||
loadOpts.numVisibleTasks = numVisibleTasks;
|
||||
loadOpts.numVisibleTaskThumbnails = numVisibleThumbnails;
|
||||
loadOpts.numVisibleTasks = mConfig.launchedNumVisibleTasks;
|
||||
loadOpts.numVisibleTaskThumbnails = mConfig.launchedNumVisibleThumbnails;
|
||||
loader.loadTasks(this, plan, loadOpts);
|
||||
|
||||
SpaceNode root = plan.getSpaceNode();
|
||||
@@ -237,9 +215,9 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
||||
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
|
||||
mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent,
|
||||
ActivityOptions.makeCustomAnimation(this,
|
||||
fromSearchHome ? R.anim.recents_to_search_launcher_enter :
|
||||
mConfig.launchedFromSearchHome ? R.anim.recents_to_search_launcher_enter :
|
||||
R.anim.recents_to_launcher_enter,
|
||||
fromSearchHome ? R.anim.recents_to_search_launcher_exit :
|
||||
mConfig.launchedFromSearchHome ? R.anim.recents_to_search_launcher_exit :
|
||||
R.anim.recents_to_launcher_exit));
|
||||
|
||||
// Mark the task that is the launch target
|
||||
@@ -403,12 +381,12 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
||||
mEmptyViewStub = (ViewStub) findViewById(R.id.empty_view_stub);
|
||||
mDebugOverlayStub = (ViewStub) findViewById(R.id.debug_overlay_stub);
|
||||
mScrimViews = new SystemBarScrimViews(this, mConfig);
|
||||
mStatusBar = ((SystemUIApplication) getApplication())
|
||||
.getComponent(PhoneStatusBar.class);
|
||||
inflateDebugOverlay();
|
||||
|
||||
// Bind the search app widget when we first start up
|
||||
bindSearchBarAppWidget();
|
||||
// Update the recent tasks
|
||||
updateRecentsTasks(getIntent());
|
||||
|
||||
// Register the broadcast receiver to handle messages when the screen is turned off
|
||||
IntentFilter filter = new IntentFilter();
|
||||
@@ -424,17 +402,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// Update if we are getting a configuration change
|
||||
if (savedInstanceState != null) {
|
||||
// Update RecentsConfiguration
|
||||
mConfig.updateOnConfigurationChange();
|
||||
// Trigger the enter animation
|
||||
onEnterAnimationTriggered();
|
||||
}
|
||||
|
||||
mStatusBar = ((SystemUIApplication) getApplication())
|
||||
.getComponent(PhoneStatusBar.class);
|
||||
}
|
||||
|
||||
/** Inflates the debug overlay if debug mode is enabled. */
|
||||
@@ -449,14 +416,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
||||
}
|
||||
}
|
||||
|
||||
/** Handles changes to the activity visibility. */
|
||||
void onRecentsActivityVisibilityChanged(boolean visible) {
|
||||
if (!visible) {
|
||||
AlternateRecentsComponent.notifyVisibilityChanged(visible);
|
||||
}
|
||||
mVisible = visible;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
@@ -469,14 +428,13 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
||||
if (mDebugOverlay != null) {
|
||||
mDebugOverlay.clear();
|
||||
}
|
||||
|
||||
// Update the recent tasks
|
||||
updateRecentsTasks(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mVisible = true;
|
||||
AlternateRecentsComponent.notifyVisibilityChanged(true);
|
||||
|
||||
// Register the broadcast receiver to handle messages from our service
|
||||
IntentFilter filter = new IntentFilter();
|
||||
@@ -487,19 +445,16 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
||||
|
||||
// Register any broadcast receivers for the task loader
|
||||
RecentsTaskLoader.getInstance().registerReceivers(this, mRecentsView);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
// Mark Recents as visible
|
||||
onRecentsActivityVisibilityChanged(true);
|
||||
// Update the recent tasks
|
||||
updateRecentsTasks(getIntent());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mVisible = false;
|
||||
AlternateRecentsComponent.notifyVisibilityChanged(false);
|
||||
|
||||
// Notify the views that we are no longer visible
|
||||
mRecentsView.onRecentsHidden();
|
||||
@@ -641,8 +596,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
||||
|
||||
@Override
|
||||
public void onTaskViewClicked() {
|
||||
// Mark recents as no longer visible
|
||||
onRecentsActivityVisibilityChanged(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -124,8 +124,12 @@ public class RecentsConfiguration {
|
||||
public boolean launchedWithNoRecentTasks;
|
||||
public boolean launchedFromAppWithThumbnail;
|
||||
public boolean launchedFromHome;
|
||||
public boolean launchedFromSearchHome;
|
||||
public boolean launchedReuseTaskStackViews;
|
||||
public boolean launchedHasConfigurationChanged;
|
||||
public int launchedToTaskId;
|
||||
public int launchedNumVisibleTasks;
|
||||
public int launchedNumVisibleThumbnails;
|
||||
|
||||
/** Misc **/
|
||||
public boolean useHardwareLayers;
|
||||
@@ -308,12 +312,10 @@ public class RecentsConfiguration {
|
||||
/** Called when the configuration has changed, and we want to reset any configuration specific
|
||||
* members. */
|
||||
public void updateOnConfigurationChange() {
|
||||
launchedWithAltTab = false;
|
||||
launchedWithNoRecentTasks = false;
|
||||
launchedFromAppWithThumbnail = false;
|
||||
launchedFromHome = false;
|
||||
// Reset this flag on configuration change to ensure that we recreate new task views
|
||||
launchedReuseTaskStackViews = false;
|
||||
launchedToTaskId = -1;
|
||||
// Set this flag to indicate that the configuration has changed since Recents last launched
|
||||
launchedHasConfigurationChanged = true;
|
||||
}
|
||||
|
||||
/** Returns whether the search bar app widget exists. */
|
||||
|
||||
@@ -715,14 +715,20 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
mStartEnterAnimationContext = null;
|
||||
}
|
||||
|
||||
// When Alt-Tabbing, we scroll to and focus the previous task
|
||||
// When Alt-Tabbing, focus the previous task (but leave the animation until we finish the
|
||||
// enter animation).
|
||||
if (mConfig.launchedWithAltTab) {
|
||||
if (mConfig.launchedFromHome) {
|
||||
focusTask(Math.max(0, mStack.getTaskCount() - 1), false, true);
|
||||
if (mConfig.launchedFromAppWithThumbnail) {
|
||||
focusTask(Math.max(0, mStack.getTaskCount() - 2), false,
|
||||
mConfig.launchedHasConfigurationChanged);
|
||||
} else {
|
||||
focusTask(Math.max(0, mStack.getTaskCount() - 2), false, true);
|
||||
focusTask(Math.max(0, mStack.getTaskCount() - 1), false,
|
||||
mConfig.launchedHasConfigurationChanged);
|
||||
}
|
||||
}
|
||||
|
||||
// Start dozing
|
||||
mUIDozeTrigger.startDozing();
|
||||
}
|
||||
|
||||
/** Requests this task stacks to start it's enter-recents animation */
|
||||
@@ -767,16 +773,27 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
@Override
|
||||
public void run() {
|
||||
mStartEnterAnimationCompleted = true;
|
||||
// Start dozing
|
||||
mUIDozeTrigger.startDozing();
|
||||
// Focus the first view if accessibility is enabled
|
||||
// Poke the dozer to restart the trigger after the animation completes
|
||||
mUIDozeTrigger.poke();
|
||||
|
||||
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
|
||||
SystemServicesProxy ssp = loader.getSystemServicesProxy();
|
||||
int childCount = getChildCount();
|
||||
if (childCount > 0 && ssp.isTouchExplorationEnabled()) {
|
||||
TaskView tv = ((TaskView) getChildAt(childCount - 1));
|
||||
tv.requestAccessibilityFocus();
|
||||
mPrevAccessibilityFocusedIndex = mStack.indexOfTask(tv.getTask());
|
||||
if (childCount > 0) {
|
||||
// Focus the first view if accessibility is enabled
|
||||
if (ssp.isTouchExplorationEnabled()) {
|
||||
TaskView tv = ((TaskView) getChildAt(childCount - 1));
|
||||
tv.requestAccessibilityFocus();
|
||||
mPrevAccessibilityFocusedIndex = mStack.indexOfTask(tv.getTask());
|
||||
}
|
||||
}
|
||||
|
||||
// Start the focus animation when alt-tabbing
|
||||
if (mConfig.launchedWithAltTab && !mConfig.launchedHasConfigurationChanged) {
|
||||
View tv = getChildAt(mFocusedTaskIndex);
|
||||
if (tv != null) {
|
||||
((TaskView) tv).setFocusedTask(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -135,7 +135,6 @@ public class TaskStackViewLayoutAlgorithm {
|
||||
// Update the task offsets
|
||||
float pAtBackMostCardTop = 0.5f;
|
||||
float pAtFrontMostCardTop = pAtBackMostCardTop;
|
||||
float pAtSecondFrontMostCardTop = pAtBackMostCardTop;
|
||||
int taskCount = tasks.size();
|
||||
for (int i = 0; i < taskCount; i++) {
|
||||
Task task = tasks.get(i);
|
||||
@@ -145,25 +144,19 @@ public class TaskStackViewLayoutAlgorithm {
|
||||
// Increment the peek height
|
||||
float pPeek = task.group.isFrontMostTask(task) ?
|
||||
pBetweenAffiliateOffset : pWithinAffiliateOffset;
|
||||
pAtSecondFrontMostCardTop = pAtFrontMostCardTop;
|
||||
pAtFrontMostCardTop += pPeek;
|
||||
}
|
||||
}
|
||||
|
||||
mMaxScrollP = pAtFrontMostCardTop - ((1f - pTaskHeightOffset - pNavBarOffset));
|
||||
mMinScrollP = tasks.size() == 1 ? Math.max(mMaxScrollP, 0f) : 0f;
|
||||
if (launchedWithAltTab) {
|
||||
if (launchedFromHome) {
|
||||
// Center the top most task, since that will be focused first
|
||||
mInitialScrollP = pAtSecondFrontMostCardTop - 0.5f;
|
||||
} else {
|
||||
// Center the second top most task, since that will be focused first
|
||||
mInitialScrollP = pAtSecondFrontMostCardTop - 0.5f;
|
||||
}
|
||||
if (launchedWithAltTab && launchedFromHome) {
|
||||
// Center the top most task, since that will be focused first
|
||||
mInitialScrollP = mMaxScrollP;
|
||||
} else {
|
||||
mInitialScrollP = pAtFrontMostCardTop - 0.825f;
|
||||
}
|
||||
mInitialScrollP = Math.max(0, mInitialScrollP);
|
||||
mInitialScrollP = Math.min(mMaxScrollP, Math.max(0, mInitialScrollP));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -235,7 +235,9 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
|
||||
void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask,
|
||||
boolean occludesLaunchTarget, int offscreenY) {
|
||||
int initialDim = getDim();
|
||||
if (mConfig.launchedFromAppWithThumbnail) {
|
||||
if (mConfig.launchedHasConfigurationChanged) {
|
||||
// Just load the views as-is
|
||||
} else if (mConfig.launchedFromAppWithThumbnail) {
|
||||
if (isTaskViewLaunchTargetTask) {
|
||||
// Set the dim to 0 so we can animate it in
|
||||
initialDim = 0;
|
||||
|
||||
@@ -237,15 +237,17 @@ public class TaskViewHeader extends FrameLayout {
|
||||
|
||||
/** Animates this task bar if the user does not interact with the stack after a certain time. */
|
||||
void startNoUserInteractionAnimation() {
|
||||
mDismissButton.setVisibility(View.VISIBLE);
|
||||
mDismissButton.setAlpha(0f);
|
||||
mDismissButton.animate()
|
||||
.alpha(1f)
|
||||
.setStartDelay(0)
|
||||
.setInterpolator(mConfig.fastOutLinearInInterpolator)
|
||||
.setDuration(mConfig.taskViewEnterFromAppDuration)
|
||||
.withLayer()
|
||||
.start();
|
||||
if (mDismissButton.getVisibility() != View.VISIBLE) {
|
||||
mDismissButton.setVisibility(View.VISIBLE);
|
||||
mDismissButton.setAlpha(0f);
|
||||
mDismissButton.animate()
|
||||
.alpha(1f)
|
||||
.setStartDelay(0)
|
||||
.setInterpolator(mConfig.fastOutLinearInInterpolator)
|
||||
.setDuration(mConfig.taskViewEnterFromAppDuration)
|
||||
.withLayer()
|
||||
.start();
|
||||
}
|
||||
}
|
||||
|
||||
/** Mark this task view that the user does has not interacted with the stack after a certain time. */
|
||||
|
||||
Reference in New Issue
Block a user