Merge "Don't reload the layout every time we enter Recents. (Bug 18160176)" into lmp-mr1-dev
This commit is contained in:
@@ -54,7 +54,7 @@ import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/** A proxy implementation for the recents component */
|
||||
public class AlternateRecentsComponent {
|
||||
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";
|
||||
@@ -62,7 +62,9 @@ public class AlternateRecentsComponent {
|
||||
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 ACTION_START_ENTER_ANIMATION = "action_start_enter_animation";
|
||||
final public static String ACTION_TOGGLE_RECENTS_ACTIVITY = "action_toggle_recents_activity";
|
||||
final public static String ACTION_HIDE_RECENTS_ACTIVITY = "action_hide_recents_activity";
|
||||
|
||||
@@ -77,7 +79,10 @@ public class AlternateRecentsComponent {
|
||||
Context mContext;
|
||||
LayoutInflater mInflater;
|
||||
SystemServicesProxy mSystemServicesProxy;
|
||||
Handler mHandler;
|
||||
boolean mBootCompleted;
|
||||
boolean mStartAnimationTriggered;
|
||||
boolean mCanReuseTaskStackViews = true;
|
||||
|
||||
// Task launching
|
||||
RecentsConfiguration mConfig;
|
||||
@@ -103,6 +108,7 @@ public class AlternateRecentsComponent {
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mContext = context;
|
||||
mSystemServicesProxy = new SystemServicesProxy(context);
|
||||
mHandler = new Handler();
|
||||
mTaskStackBounds = new Rect();
|
||||
}
|
||||
|
||||
@@ -128,7 +134,7 @@ public class AlternateRecentsComponent {
|
||||
}
|
||||
|
||||
// When we start, preload the metadata associated with the previous tasks
|
||||
RecentsTaskLoader.getInstance().preload(mContext);
|
||||
RecentsTaskLoader.getInstance().preload(mContext, RecentsTaskLoader.ALL_TASKS);
|
||||
}
|
||||
|
||||
public void onBootCompleted() {
|
||||
@@ -176,7 +182,9 @@ public class AlternateRecentsComponent {
|
||||
}
|
||||
|
||||
public void onPreloadRecents() {
|
||||
// Do nothing
|
||||
// When we start, preload the metadata associated with the previous tasks
|
||||
RecentsTaskLoader.getInstance().preload(mContext,
|
||||
Constants.Values.RecentsTaskLoader.PreloadFirstTasksCount);
|
||||
}
|
||||
|
||||
public void onCancelPreloadingRecents() {
|
||||
@@ -186,7 +194,7 @@ public class AlternateRecentsComponent {
|
||||
void showRelativeAffiliatedTask(boolean showNextTask) {
|
||||
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
|
||||
TaskStack stack = loader.getTaskStack(mSystemServicesProxy, mContext.getResources(),
|
||||
-1, -1, false, true, null, null);
|
||||
-1, -1, RecentsTaskLoader.ALL_TASKS, false, true, null, null);
|
||||
// Return early if there are no tasks
|
||||
if (stack.getTaskCount() == 0) return;
|
||||
|
||||
@@ -251,6 +259,8 @@ public class AlternateRecentsComponent {
|
||||
}
|
||||
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
// Don't reuse task stack views if the configuration changes
|
||||
mCanReuseTaskStackViews = false;
|
||||
// Reload the header bar layout
|
||||
reloadHeaderBarLayout();
|
||||
}
|
||||
@@ -364,23 +374,28 @@ public class AlternateRecentsComponent {
|
||||
* Creates the activity options for a unknown state->recents transition.
|
||||
*/
|
||||
ActivityOptions getUnknownTransitionActivityOptions() {
|
||||
mStartAnimationTriggered = false;
|
||||
return ActivityOptions.makeCustomAnimation(mContext,
|
||||
R.anim.recents_from_unknown_enter,
|
||||
R.anim.recents_from_unknown_exit);
|
||||
R.anim.recents_from_unknown_exit,
|
||||
mHandler, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the activity options for a home->recents transition.
|
||||
*/
|
||||
ActivityOptions getHomeTransitionActivityOptions(boolean fromSearchHome) {
|
||||
mStartAnimationTriggered = false;
|
||||
if (fromSearchHome) {
|
||||
return ActivityOptions.makeCustomAnimation(mContext,
|
||||
R.anim.recents_from_search_launcher_enter,
|
||||
R.anim.recents_from_search_launcher_exit);
|
||||
R.anim.recents_from_search_launcher_exit,
|
||||
mHandler, this);
|
||||
}
|
||||
return ActivityOptions.makeCustomAnimation(mContext,
|
||||
R.anim.recents_from_launcher_enter,
|
||||
R.anim.recents_from_launcher_exit);
|
||||
R.anim.recents_from_launcher_exit,
|
||||
mHandler, this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -408,9 +423,10 @@ public class AlternateRecentsComponent {
|
||||
c.setBitmap(null);
|
||||
}
|
||||
|
||||
mStartAnimationTriggered = false;
|
||||
return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mStatusBarView,
|
||||
thumbnail, toTaskRect.left, toTaskRect.top, toTaskRect.width(),
|
||||
toTaskRect.height(), null);
|
||||
toTaskRect.height(), this);
|
||||
}
|
||||
|
||||
// If both the screenshot and thumbnail fails, then just fall back to the default transition
|
||||
@@ -423,7 +439,7 @@ public class AlternateRecentsComponent {
|
||||
// Get the stack of tasks that we are animating into
|
||||
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
|
||||
TaskStack stack = loader.getTaskStack(mSystemServicesProxy, mContext.getResources(),
|
||||
runningTaskId, -1, false, isTopTaskHome, null, null);
|
||||
runningTaskId, -1, RecentsTaskLoader.ALL_TASKS, false, isTopTaskHome, null, null);
|
||||
if (stack.getTaskCount() == 0) {
|
||||
return null;
|
||||
}
|
||||
@@ -529,11 +545,13 @@ public class AlternateRecentsComponent {
|
||||
}
|
||||
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);
|
||||
if (opts != null) {
|
||||
mContext.startActivityAsUser(intent, opts.toBundle(), UserHandle.CURRENT);
|
||||
} else {
|
||||
mContext.startActivityAsUser(intent, UserHandle.CURRENT);
|
||||
}
|
||||
mCanReuseTaskStackViews = true;
|
||||
}
|
||||
|
||||
/** Sets the RecentsComponent callbacks. */
|
||||
@@ -547,4 +565,42 @@ public class AlternateRecentsComponent {
|
||||
sRecentsComponentCallbacks.onVisibilityChanged(visible);
|
||||
}
|
||||
}
|
||||
|
||||
/**** OnAnimationStartedListener Implementation ****/
|
||||
|
||||
@Override
|
||||
public void onAnimationStarted() {
|
||||
// Notify recents to start the enter animation
|
||||
if (!mStartAnimationTriggered) {
|
||||
// There can be a race condition between the start animation callback and
|
||||
// the start of the new activity (where we register the receiver that listens
|
||||
// to this broadcast, so we add our own receiver and if that gets called, then
|
||||
// we know the activity has not yet started and we can retry sending the broadcast.
|
||||
BroadcastReceiver fallbackReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (getResultCode() == Activity.RESULT_OK) {
|
||||
mStartAnimationTriggered = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Schedule for the broadcast to be sent again after some time
|
||||
mHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onAnimationStarted();
|
||||
}
|
||||
}, 25);
|
||||
}
|
||||
};
|
||||
|
||||
// Send the broadcast to notify Recents that the animation has started
|
||||
Intent intent = new Intent(ACTION_START_ENTER_ANIMATION);
|
||||
intent.setPackage(mContext.getPackageName());
|
||||
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
|
||||
Intent.FLAG_RECEIVER_FOREGROUND);
|
||||
mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null,
|
||||
fallbackReceiver, null, Activity.RESULT_CANCELED, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
@@ -142,6 +143,12 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
||||
} else if (action.equals(AlternateRecentsComponent.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
|
||||
// If we are toggling Recents, then first unfilter any filtered stacks first
|
||||
dismissRecentsToFocusedTaskOrHome(true);
|
||||
} else if (action.equals(AlternateRecentsComponent.ACTION_START_ENTER_ANIMATION)) {
|
||||
// Trigger the enter animation
|
||||
onEnterAnimationTriggered();
|
||||
// Notify the fallback receiver that we have successfully got the broadcast
|
||||
// See AlternateRecentsComponent.onAnimationStarted()
|
||||
setResultCode(Activity.RESULT_OK);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -157,7 +164,8 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
||||
// When the screen turns off, dismiss Recents to Home
|
||||
dismissRecentsToHome(false);
|
||||
// Start preloading some tasks in the background
|
||||
RecentsTaskLoader.getInstance().preload(RecentsActivity.this);
|
||||
RecentsTaskLoader.getInstance().preload(RecentsActivity.this,
|
||||
Constants.Values.RecentsTaskLoader.PreloadFirstTasksCount);
|
||||
} else if (action.equals(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED)) {
|
||||
// When the search activity changes, update the Search widget
|
||||
refreshSearchWidget();
|
||||
@@ -188,6 +196,8 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
||||
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);
|
||||
|
||||
// Load all the tasks
|
||||
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
|
||||
@@ -397,8 +407,12 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
||||
|
||||
// Update if we are getting a configuration change
|
||||
if (savedInstanceState != null) {
|
||||
// Update RecentsConfiguration
|
||||
mConfig = RecentsConfiguration.reinitialize(this,
|
||||
RecentsTaskLoader.getInstance().getSystemServicesProxy());
|
||||
mConfig.updateOnConfigurationChange();
|
||||
onConfigurationChange();
|
||||
// Trigger the enter animation
|
||||
onEnterAnimationTriggered();
|
||||
}
|
||||
|
||||
// Start listening for widget package changes if there is one bound, post it since we don't
|
||||
@@ -428,19 +442,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when the configuration changes. */
|
||||
void onConfigurationChange() {
|
||||
// Update RecentsConfiguration
|
||||
mConfig = RecentsConfiguration.reinitialize(this,
|
||||
RecentsTaskLoader.getInstance().getSystemServicesProxy());
|
||||
|
||||
// Try and start the enter animation (or restart it on configuration changed)
|
||||
ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
|
||||
mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
|
||||
// Animate the SystemUI scrim views
|
||||
mScrimViews.startEnterRecentsAnimation();
|
||||
}
|
||||
|
||||
/** Handles changes to the activity visibility. */
|
||||
void onRecentsActivityVisibilityChanged(boolean visible) {
|
||||
if (!visible) {
|
||||
@@ -474,6 +475,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(AlternateRecentsComponent.ACTION_HIDE_RECENTS_ACTIVITY);
|
||||
filter.addAction(AlternateRecentsComponent.ACTION_TOGGLE_RECENTS_ACTIVITY);
|
||||
filter.addAction(AlternateRecentsComponent.ACTION_START_ENTER_ANIMATION);
|
||||
registerReceiver(mServiceBroadcastReceiver, filter);
|
||||
|
||||
// Register any broadcast receivers for the task loader
|
||||
@@ -492,8 +494,8 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
|
||||
// Remove all the views
|
||||
mRecentsView.removeAllTaskStacks();
|
||||
// Notify the views that we are no longer visible
|
||||
mRecentsView.onRecentsHidden();
|
||||
|
||||
// Unregister the RecentsService receiver
|
||||
unregisterReceiver(mServiceBroadcastReceiver);
|
||||
@@ -515,8 +517,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnterAnimationComplete() {
|
||||
public void onEnterAnimationTriggered() {
|
||||
// Try and start the enter animation (or restart it on configuration changed)
|
||||
ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
|
||||
mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
|
||||
@@ -584,7 +585,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
||||
|
||||
/** Called when debug mode is triggered */
|
||||
public void onDebugModeTriggered() {
|
||||
|
||||
if (mConfig.developerOptionsEnabled) {
|
||||
SharedPreferences settings = getSharedPreferences(getPackageName(), 0);
|
||||
if (settings.getBoolean(Constants.Values.App.Key_DebugModeEnabled, false)) {
|
||||
|
||||
@@ -115,8 +115,8 @@ public class RecentsConfiguration {
|
||||
public boolean launchedWithAltTab;
|
||||
public boolean launchedWithNoRecentTasks;
|
||||
public boolean launchedFromAppWithThumbnail;
|
||||
public boolean launchedFromAppWithScreenshot;
|
||||
public boolean launchedFromHome;
|
||||
public boolean launchedReuseTaskStackViews;
|
||||
public int launchedToTaskId;
|
||||
|
||||
/** Misc **/
|
||||
@@ -308,6 +308,7 @@ public class RecentsConfiguration {
|
||||
launchedWithNoRecentTasks = false;
|
||||
launchedFromAppWithThumbnail = false;
|
||||
launchedFromHome = false;
|
||||
launchedReuseTaskStackViews = false;
|
||||
launchedToTaskId = -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -82,4 +82,9 @@ public class DozeTrigger {
|
||||
public boolean hasTriggered() {
|
||||
return mHasTriggered;
|
||||
}
|
||||
|
||||
/** Resets the doze trigger state. */
|
||||
public void resetTrigger() {
|
||||
mHasTriggered = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,6 +260,7 @@ public class RecentsTaskLoader {
|
||||
private static final String TAG = "RecentsTaskLoader";
|
||||
|
||||
static RecentsTaskLoader sInstance;
|
||||
public static final int ALL_TASKS = -1;
|
||||
|
||||
SystemServicesProxy mSystemServicesProxy;
|
||||
DrawableLruCache mApplicationIconCache;
|
||||
@@ -326,10 +327,9 @@ public class RecentsTaskLoader {
|
||||
|
||||
/** Gets the list of recent tasks, ordered from back to front. */
|
||||
private static List<ActivityManager.RecentTaskInfo> getRecentTasks(SystemServicesProxy ssp,
|
||||
boolean isTopTaskHome) {
|
||||
RecentsConfiguration config = RecentsConfiguration.getInstance();
|
||||
int numTasksToLoad, boolean isTopTaskHome) {
|
||||
List<ActivityManager.RecentTaskInfo> tasks =
|
||||
ssp.getRecentTasks(config.maxNumTasksToLoad, UserHandle.CURRENT.getIdentifier(),
|
||||
ssp.getRecentTasks(numTasksToLoad, UserHandle.CURRENT.getIdentifier(),
|
||||
isTopTaskHome);
|
||||
Collections.reverse(tasks);
|
||||
return tasks;
|
||||
@@ -416,7 +416,8 @@ public class RecentsTaskLoader {
|
||||
ArrayList<Task.TaskKey> taskKeys = new ArrayList<Task.TaskKey>();
|
||||
ArrayList<Task> tasksToLoad = new ArrayList<Task>();
|
||||
TaskStack stack = getTaskStack(mSystemServicesProxy, context.getResources(),
|
||||
-1, preloadCount, true, isTopTaskHome, taskKeys, tasksToLoad);
|
||||
-1, preloadCount, RecentsTaskLoader.ALL_TASKS, true, isTopTaskHome, taskKeys,
|
||||
tasksToLoad);
|
||||
SpaceNode root = new SpaceNode();
|
||||
root.setStack(stack);
|
||||
|
||||
@@ -428,10 +429,10 @@ public class RecentsTaskLoader {
|
||||
}
|
||||
|
||||
/** Preloads the set of recent tasks (not including thumbnails). */
|
||||
public void preload(Context context) {
|
||||
public void preload(Context context, int numTasksToPreload) {
|
||||
ArrayList<Task> tasksToLoad = new ArrayList<Task>();
|
||||
getTaskStack(mSystemServicesProxy, context.getResources(),
|
||||
-1, -1, true, true, null, tasksToLoad);
|
||||
-1, -1, numTasksToPreload, true, true, null, tasksToLoad);
|
||||
|
||||
// Start the task loader and add all the tasks we need to load
|
||||
mLoadQueue.addTasks(tasksToLoad);
|
||||
@@ -440,11 +441,13 @@ public class RecentsTaskLoader {
|
||||
|
||||
/** Creates a lightweight stack of the current recent tasks, without thumbnails and icons. */
|
||||
public synchronized TaskStack getTaskStack(SystemServicesProxy ssp, Resources res,
|
||||
int preloadTaskId, int preloadTaskCount,
|
||||
int preloadTaskId, int preloadTaskCount, int loadTaskCount,
|
||||
boolean loadTaskThumbnails, boolean isTopTaskHome,
|
||||
List<Task.TaskKey> taskKeysOut, List<Task> tasksToLoadOut) {
|
||||
RecentsConfiguration config = RecentsConfiguration.getInstance();
|
||||
List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(ssp, isTopTaskHome);
|
||||
List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(ssp,
|
||||
(loadTaskCount == ALL_TASKS ? config.maxNumTasksToLoad : loadTaskCount),
|
||||
isTopTaskHome);
|
||||
HashMap<Task.ComponentNameKey, ActivityInfoHandle> activityInfoCache =
|
||||
new HashMap<Task.ComponentNameKey, ActivityInfoHandle>();
|
||||
ArrayList<Task> tasksToAdd = new ArrayList<Task>();
|
||||
|
||||
@@ -95,42 +95,57 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
|
||||
|
||||
/** Set/get the bsp root node */
|
||||
public void setTaskStacks(ArrayList<TaskStack> stacks) {
|
||||
// Remove all TaskStackViews (but leave the search bar)
|
||||
int numStacks = stacks.size();
|
||||
|
||||
// Make a list of the stack view children only
|
||||
ArrayList<TaskStackView> stackViews = new ArrayList<TaskStackView>();
|
||||
int childCount = getChildCount();
|
||||
for (int i = childCount - 1; i >= 0; i--) {
|
||||
View v = getChildAt(i);
|
||||
if (v != mSearchBar) {
|
||||
removeViewAt(i);
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
View child = getChildAt(i);
|
||||
if (child != mSearchBar) {
|
||||
stackViews.add((TaskStackView) child);
|
||||
}
|
||||
}
|
||||
|
||||
// Create and add all the stacks for this partition of space.
|
||||
// Remove all/extra stack views
|
||||
int numTaskStacksToKeep = 0; // Keep no tasks if we are recreating the layout
|
||||
if (mConfig.launchedReuseTaskStackViews) {
|
||||
numTaskStacksToKeep = Math.min(childCount, numStacks);
|
||||
}
|
||||
for (int i = stackViews.size() - 1; i >= numTaskStacksToKeep; i--) {
|
||||
removeView(stackViews.get(i));
|
||||
stackViews.remove(i);
|
||||
}
|
||||
|
||||
// Update the stack views that we are keeping
|
||||
for (int i = 0; i < numTaskStacksToKeep; i++) {
|
||||
stackViews.get(i).setStack(stacks.get(i));
|
||||
}
|
||||
|
||||
// Add remaining/recreate stack views
|
||||
mStacks = stacks;
|
||||
int numStacks = mStacks.size();
|
||||
for (int i = 0; i < numStacks; i++) {
|
||||
TaskStack stack = mStacks.get(i);
|
||||
for (int i = stackViews.size(); i < numStacks; i++) {
|
||||
TaskStack stack = stacks.get(i);
|
||||
TaskStackView stackView = new TaskStackView(getContext(), stack);
|
||||
stackView.setCallbacks(this);
|
||||
// Enable debug mode drawing
|
||||
if (mConfig.debugModeEnabled) {
|
||||
stackView.setDebugOverlay(mDebugOverlay);
|
||||
}
|
||||
addView(stackView);
|
||||
}
|
||||
|
||||
// Enable debug mode drawing on all the stacks if necessary
|
||||
if (mConfig.debugModeEnabled) {
|
||||
for (int i = childCount - 1; i >= 0; i--) {
|
||||
View v = getChildAt(i);
|
||||
if (v != mSearchBar) {
|
||||
TaskStackView stackView = (TaskStackView) v;
|
||||
stackView.setDebugOverlay(mDebugOverlay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the launched state
|
||||
mAlreadyLaunchingTask = false;
|
||||
}
|
||||
|
||||
/** Removes all the task stack views from this recents view. */
|
||||
public void removeAllTaskStacks() {
|
||||
int childCount = getChildCount();
|
||||
for (int i = childCount - 1; i >= 0; i--) {
|
||||
View child = getChildAt(i);
|
||||
if (child != mSearchBar) {
|
||||
removeViewAt(i);
|
||||
}
|
||||
}
|
||||
// Trigger a new layout
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
/** Launches the focused task from the first stack if possible */
|
||||
@@ -529,6 +544,19 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
|
||||
mCb.onAllTaskViewsDismissed();
|
||||
}
|
||||
|
||||
/** Final callback after Recents is finally hidden. */
|
||||
public void onRecentsHidden() {
|
||||
// Notify each task stack view
|
||||
int childCount = getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
View child = getChildAt(i);
|
||||
if (child != mSearchBar) {
|
||||
TaskStackView stackView = (TaskStackView) child;
|
||||
stackView.onRecentsHidden();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskStackFilterTriggered() {
|
||||
// Hide the search bar
|
||||
|
||||
@@ -40,6 +40,7 @@ import com.android.systemui.recents.model.TaskStack;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/* The visual representation of a task stack view */
|
||||
@@ -99,25 +100,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
}
|
||||
};
|
||||
|
||||
// A convenience runnable to return all views to the pool
|
||||
Runnable mReturnAllViewsToPoolRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int childCount = getChildCount();
|
||||
for (int i = childCount - 1; i >= 0; i--) {
|
||||
TaskView tv = (TaskView) getChildAt(i);
|
||||
mViewPool.returnViewToPool(tv);
|
||||
// Also hide the view since we don't need it anymore
|
||||
tv.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public TaskStackView(Context context, TaskStack stack) {
|
||||
super(context);
|
||||
// Set the stack first
|
||||
setStack(stack);
|
||||
mConfig = RecentsConfiguration.getInstance();
|
||||
mStack = stack;
|
||||
mStack.setCallbacks(this);
|
||||
mViewPool = new ViewPool<TaskView, Task>(context, this);
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mLayoutAlgorithm = new TaskStackViewLayoutAlgorithm(mConfig);
|
||||
@@ -143,11 +130,62 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
mCb = cb;
|
||||
}
|
||||
|
||||
/** Sets the task stack */
|
||||
void setStack(TaskStack stack) {
|
||||
// Unset the old stack
|
||||
if (mStack != null) {
|
||||
mStack.setCallbacks(null);
|
||||
|
||||
// Return all existing views to the pool
|
||||
reset();
|
||||
// Layout again with the new stack
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
// Set the new stack
|
||||
mStack = stack;
|
||||
if (mStack != null) {
|
||||
mStack.setCallbacks(this);
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets the debug overlay */
|
||||
public void setDebugOverlay(DebugOverlayView overlay) {
|
||||
mDebugOverlay = overlay;
|
||||
}
|
||||
|
||||
/** Resets this TaskStackView for reuse. */
|
||||
void reset() {
|
||||
// Return all the views to the pool
|
||||
int childCount = getChildCount();
|
||||
for (int i = childCount - 1; i >= 0; i--) {
|
||||
TaskView tv = (TaskView) getChildAt(i);
|
||||
mViewPool.returnViewToPool(tv);
|
||||
}
|
||||
|
||||
// Mark each task view for relayout
|
||||
if (mViewPool != null) {
|
||||
Iterator<TaskView> iter = mViewPool.poolViewIterator();
|
||||
if (iter != null) {
|
||||
while (iter.hasNext()) {
|
||||
TaskView tv = iter.next();
|
||||
tv.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the stack state
|
||||
resetFocusedTask();
|
||||
mStackViewsDirty = true;
|
||||
mStackViewsClipDirty = true;
|
||||
mAwaitingFirstLayout = true;
|
||||
mPrevAccessibilityFocusedIndex = -1;
|
||||
if (mUIDozeTrigger != null) {
|
||||
mUIDozeTrigger.stopDozing();
|
||||
mUIDozeTrigger.resetTrigger();
|
||||
}
|
||||
}
|
||||
|
||||
/** Requests that the views be synchronized with the model */
|
||||
void requestSynchronizeStackViewsWithModel() {
|
||||
requestSynchronizeStackViewsWithModel(0);
|
||||
@@ -510,6 +548,16 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
tv.dismissTask();
|
||||
}
|
||||
|
||||
/** Resets the focused task. */
|
||||
void resetFocusedTask() {
|
||||
if (mFocusedTaskIndex > -1) {
|
||||
Task t = mStack.getTasks().get(mFocusedTaskIndex);
|
||||
TaskView tv = getChildViewForTask(t);
|
||||
tv.unsetFocusedTask();
|
||||
}
|
||||
mFocusedTaskIndex = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
|
||||
super.onInitializeAccessibilityEvent(event);
|
||||
@@ -543,6 +591,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
|
||||
@Override
|
||||
public void computeScroll() {
|
||||
if (mStack == null) return;
|
||||
|
||||
mStackScroller.computeScroll();
|
||||
// Synchronize the views
|
||||
synchronizeStackViewsWithModel();
|
||||
@@ -758,9 +808,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
TaskView tv = (TaskView) getChildAt(i);
|
||||
tv.startExitToHomeAnimation(ctx);
|
||||
}
|
||||
|
||||
// Add a runnable to the post animation ref counter to clear all the views
|
||||
ctx.postAnimationTrigger.addLastDecrementRunnable(mReturnAllViewsToPoolRunnable);
|
||||
}
|
||||
|
||||
/** Animates a task view in this stack as it launches. */
|
||||
@@ -780,6 +827,12 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
}
|
||||
}
|
||||
|
||||
/** Final callback after Recents is finally hidden. */
|
||||
void onRecentsHidden() {
|
||||
reset();
|
||||
setStack(null);
|
||||
}
|
||||
|
||||
public boolean isTransformedTouchPointInView(float x, float y, View child) {
|
||||
return isTransformedTouchPointInView(x, y, child, null);
|
||||
}
|
||||
@@ -944,20 +997,23 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
|
||||
// Reset the view properties
|
||||
tv.resetViewProperties();
|
||||
|
||||
// Reset the clip state of the task view
|
||||
tv.setClipViewInStack(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareViewToLeavePool(TaskView tv, Task task, boolean isNewView) {
|
||||
// It is possible for a view to be returned to the view pool before it is laid out,
|
||||
// which means that we will need to relayout the view when it is first used next.
|
||||
boolean requiresRelayout = tv.getWidth() <= 0 && !isNewView;
|
||||
|
||||
// Rebind the task and request that this task's data be filled into the TaskView
|
||||
tv.onTaskBound(task);
|
||||
|
||||
// Load the task data
|
||||
RecentsTaskLoader.getInstance().loadTaskData(task);
|
||||
|
||||
// Sanity check, the task view should always be clipping against the stack at this point,
|
||||
// but just in case, re-enable it here
|
||||
tv.setClipViewInStack(true);
|
||||
|
||||
// If the doze trigger has already fired, then update the state for this task view
|
||||
if (mUIDozeTrigger.hasTriggered()) {
|
||||
tv.setNoUserInteractionState();
|
||||
@@ -985,13 +1041,17 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
// Add/attach the view to the hierarchy
|
||||
if (isNewView) {
|
||||
addView(tv, insertIndex);
|
||||
|
||||
// Set the callbacks and listeners for this new view
|
||||
tv.setTouchEnabled(true);
|
||||
tv.setCallbacks(this);
|
||||
} else {
|
||||
attachViewToParent(tv, insertIndex, tv.getLayoutParams());
|
||||
if (requiresRelayout) {
|
||||
tv.requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
// Set the new state for this view, including the callbacks and view clipping
|
||||
tv.setCallbacks(this);
|
||||
tv.setTouchEnabled(true);
|
||||
tv.setClipViewInStack(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -112,6 +112,14 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
|
||||
mCb = cb;
|
||||
}
|
||||
|
||||
/** Resets this TaskView for reuse. */
|
||||
void reset() {
|
||||
resetViewProperties();
|
||||
resetNoUserInteractionState();
|
||||
setClipViewInStack(false);
|
||||
setCallbacks(null);
|
||||
}
|
||||
|
||||
/** Gets the task */
|
||||
Task getTask() {
|
||||
return mTask;
|
||||
@@ -191,6 +199,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
|
||||
/** Resets this view's properties */
|
||||
void resetViewProperties() {
|
||||
setDim(0);
|
||||
setLayerType(View.LAYER_TYPE_NONE, null);
|
||||
TaskViewTransform.reset(this);
|
||||
}
|
||||
|
||||
@@ -448,6 +457,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
|
||||
mHeaderView.setNoUserInteractionState();
|
||||
}
|
||||
|
||||
/** Resets the state tracking that the user has not interacted with the stack after a certain time. */
|
||||
void resetNoUserInteractionState() {
|
||||
mHeaderView.resetNoUserInteractionState();
|
||||
}
|
||||
|
||||
/** Dismisses this task. */
|
||||
void dismissTask() {
|
||||
// Animate out the view and call the callback
|
||||
|
||||
@@ -263,6 +263,11 @@ public class TaskViewHeader extends FrameLayout {
|
||||
}
|
||||
}
|
||||
|
||||
/** Resets the state tracking that the user has not interacted with the stack after a certain time. */
|
||||
void resetNoUserInteractionState() {
|
||||
mDismissButton.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int[] onCreateDrawableState(int extraSpace) {
|
||||
|
||||
|
||||
@@ -75,4 +75,12 @@ public class ViewPool<V, T> {
|
||||
mViewCreator.prepareViewToLeavePool(v, prepareData, isNewView);
|
||||
return v;
|
||||
}
|
||||
|
||||
/** Returns an iterator to the list of the views in the pool. */
|
||||
Iterator<V> poolViewIterator() {
|
||||
if (mPool != null) {
|
||||
return mPool.iterator();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user