diff options
author | Michael Jurka <mikejurka@google.com> | 2012-02-14 13:57:14 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-02-14 13:57:14 -0800 |
commit | a17a7953f9385155e2d0d7b24d1395ed49147da3 (patch) | |
tree | 23333a8afd9849756fbc42828a6fb6c62b767d5e /packages | |
parent | 0599d6ede37304bf8f9ecd90dadea7707c160cd8 (diff) | |
parent | 99a9655b9333c3bff6e462b12baa56a5fcd4cb20 (diff) | |
download | frameworks_base-a17a7953f9385155e2d0d7b24d1395ed49147da3.zip frameworks_base-a17a7953f9385155e2d0d7b24d1395ed49147da3.tar.gz frameworks_base-a17a7953f9385155e2d0d7b24d1395ed49147da3.tar.bz2 |
Merge "Making recents faster"
Diffstat (limited to 'packages')
11 files changed, 518 insertions, 220 deletions
diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml index 2d76455..aa27861 100644 --- a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml +++ b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml @@ -58,6 +58,7 @@ android:maxHeight="@dimen/status_bar_recents_app_icon_max_height" android:scaleType="centerInside" android:adjustViewBounds="true" + android:visibility="invisible" /> <TextView android:id="@+id/app_label" diff --git a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml b/packages/SystemUI/res/layout-port/status_bar_recent_item.xml index b653fcd..bc389f9 100644 --- a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml +++ b/packages/SystemUI/res/layout-port/status_bar_recent_item.xml @@ -81,6 +81,7 @@ android:maxHeight="@dimen/status_bar_recents_app_icon_max_height" android:scaleType="centerInside" android:adjustViewBounds="true" + android:visibility="invisible" /> <TextView android:id="@+id/app_description" diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml index cb26db00..333fcda 100644 --- a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml +++ b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml @@ -65,6 +65,7 @@ android:maxHeight="@dimen/status_bar_recents_app_icon_max_height" android:scaleType="centerInside" android:adjustViewBounds="true" + android:visibility="invisible" /> diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java index 14ce266..cd8bd4e 100644 --- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java @@ -236,6 +236,10 @@ public class SwipeHelper { public void onAnimationEnd(Animator animation) { mCallback.onChildDismissed(view); animView.setLayerType(View.LAYER_TYPE_NONE, null); + // Restore the alpha/translation parameters to what they were before swiping + // (for when these items are recycled) + animView.setAlpha(1f); + setTranslation(animView, 0f); } }); anim.addUpdateListener(new AnimatorUpdateListener() { diff --git a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java index ad38a11..f8a4592 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java +++ b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java @@ -134,6 +134,7 @@ import android.view.View; void jumpTo(boolean appearing) { mContentView.setTranslationY(appearing ? 0 : mPanelHeight); + mScrimView.getBackground().setAlpha(appearing ? 255 : 0); } public void setPanelHeight(int h) { diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java index 4145fc4..92f4ca9 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java @@ -16,12 +16,6 @@ package com.android.systemui.recent; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - import android.app.ActivityManager; import android.content.ComponentName; import android.content.Context; @@ -36,15 +30,17 @@ import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.Handler; import android.os.Process; -import android.os.SystemClock; -import android.util.DisplayMetrics; import android.util.Log; -import android.util.LruCache; import com.android.systemui.R; import com.android.systemui.statusbar.phone.PhoneStatusBar; import com.android.systemui.statusbar.tablet.TabletStatusBar; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + public class RecentTasksLoader { static final String TAG = "RecentTasksLoader"; static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false; @@ -55,11 +51,14 @@ public class RecentTasksLoader { private Context mContext; private RecentsPanelView mRecentsPanel; - private AsyncTask<Void, Integer, Void> mThumbnailLoader; + private AsyncTask<Void, ArrayList<TaskDescription>, Void> mTaskLoader; + private AsyncTask<Void, TaskDescription, Void> mThumbnailLoader; private final Handler mHandler; private int mIconDpi; private Bitmap mDefaultThumbnailBackground; + private Bitmap mDefaultIconBackground; + private int mNumTasksInFirstScreenful; public RecentTasksLoader(Context context) { mContext = context; @@ -76,12 +75,20 @@ public class RecentTasksLoader { mIconDpi = res.getDisplayMetrics().densityDpi; } + // Render default icon (just a blank image) + int defaultIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.app_icon_size); + int iconSize = (int) (defaultIconSize * mIconDpi / res.getDisplayMetrics().densityDpi); + mDefaultIconBackground = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888); + // Render the default thumbnail background - int width = (int) res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width); - int height = (int) res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height); + int thumbnailWidth = + (int) res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width); + int thumbnailHeight = + (int) res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height); int color = res.getColor(R.drawable.status_bar_recents_app_thumbnail_background); - mDefaultThumbnailBackground = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + mDefaultThumbnailBackground = + Bitmap.createBitmap(thumbnailWidth, thumbnailHeight, Bitmap.Config.ARGB_8888); Canvas c = new Canvas(mDefaultThumbnailBackground); c.drawColor(color); @@ -95,12 +102,17 @@ public class RecentTasksLoader { public void setRecentsPanel(RecentsPanelView recentsPanel) { mRecentsPanel = recentsPanel; + mNumTasksInFirstScreenful = mRecentsPanel.numItemsInOneScreenful(); } public Bitmap getDefaultThumbnail() { return mDefaultThumbnailBackground; } + public Bitmap getDefaultIcon() { + return mDefaultIconBackground; + } + // Create an TaskDescription, returning null if the title or icon is null, or if it's the // home activity TaskDescription createTaskDescription(int taskId, int persistentTaskId, Intent baseIntent, @@ -114,6 +126,12 @@ public class RecentTasksLoader { homeInfo = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME) .resolveActivityInfo(pm, 0); } + // Don't load the current home activity. + if (homeInfo != null + && homeInfo.packageName.equals(intent.getComponent().getPackageName()) + && homeInfo.name.equals(intent.getComponent().getClassName())) { + return null; + } intent.setFlags((intent.getFlags()&~Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) | Intent.FLAG_ACTIVITY_NEW_TASK); @@ -121,9 +139,8 @@ public class RecentTasksLoader { if (resolveInfo != null) { final ActivityInfo info = resolveInfo.activityInfo; final String title = info.loadLabel(pm).toString(); - Drawable icon = getFullResIcon(resolveInfo, pm); - if (title != null && title.length() > 0 && icon != null) { + if (title != null && title.length() > 0) { if (DEBUG) Log.v(TAG, "creating activity desc for id=" + persistentTaskId + ", label=" + title); @@ -131,14 +148,6 @@ public class RecentTasksLoader { persistentTaskId, resolveInfo, baseIntent, info.packageName, description); item.setLabel(title); - item.setIcon(icon); - - // Don't load the current home activity. - if (homeInfo != null - && homeInfo.packageName.equals(intent.getComponent().getPackageName()) - && homeInfo.name.equals(intent.getComponent().getClassName())) { - return null; - } return item; } else { @@ -148,10 +157,12 @@ public class RecentTasksLoader { return null; } - void loadThumbnail(TaskDescription td) { + void loadThumbnailAndIcon(TaskDescription td) { final ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); + final PackageManager pm = mContext.getPackageManager(); ActivityManager.TaskThumbnails thumbs = am.getTaskThumbnails(td.persistentTaskId); + Drawable icon = getFullResIcon(td.resolveInfo, pm); if (DEBUG) Log.v(TAG, "Loaded bitmap for task " + td + ": " + thumbs.mainThumbnail); @@ -161,6 +172,10 @@ public class RecentTasksLoader { } else { td.setThumbnail(mDefaultThumbnailBackground); } + if (icon != null) { + td.setIcon(icon); + } + td.setLoaded(true); } } @@ -194,111 +209,149 @@ public class RecentTasksLoader { return getFullResDefaultActivityIcon(); } - public void cancelLoadingThumbnails() { + public void cancelLoadingThumbnailsAndIcons() { + if (mTaskLoader != null) { + mTaskLoader.cancel(false); + mTaskLoader = null; + } if (mThumbnailLoader != null) { mThumbnailLoader.cancel(false); mThumbnailLoader = null; } } - // return a snapshot of the current list of recent apps - ArrayList<TaskDescription> getRecentTasks() { - cancelLoadingThumbnails(); - - ArrayList<TaskDescription> tasks = new ArrayList<TaskDescription>(); - final PackageManager pm = mContext.getPackageManager(); - final ActivityManager am = (ActivityManager) + public void loadTasksInBackground() { + // cancel all previous loading of tasks and thumbnails + cancelLoadingThumbnailsAndIcons(); + final LinkedBlockingQueue<TaskDescription> tasksWaitingForThumbnails = + new LinkedBlockingQueue<TaskDescription>(); + final ArrayList<TaskDescription> taskDescriptionsWaitingToLoad = + new ArrayList<TaskDescription>(); + mTaskLoader = new AsyncTask<Void, ArrayList<TaskDescription>, Void>() { + @Override + protected void onProgressUpdate(ArrayList<TaskDescription>... values) { + if (!isCancelled()) { + ArrayList<TaskDescription> newTasks = values[0]; + // do a callback to RecentsPanelView to let it know we have more values + // how do we let it know we're all done? just always call back twice + mRecentsPanel.onTasksLoaded(newTasks); + } + } + @Override + protected Void doInBackground(Void... params) { + // We load in two stages: first, we update progress with just the first screenful + // of items. Then, we update with the rest of the items + final int origPri = Process.getThreadPriority(Process.myTid()); + Process.setThreadPriority(Process.THREAD_GROUP_BG_NONINTERACTIVE); + final PackageManager pm = mContext.getPackageManager(); + final ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); - final List<ActivityManager.RecentTaskInfo> recentTasks = - am.getRecentTasks(MAX_TASKS, ActivityManager.RECENT_IGNORE_UNAVAILABLE); + final List<ActivityManager.RecentTaskInfo> recentTasks = + am.getRecentTasks(MAX_TASKS, ActivityManager.RECENT_IGNORE_UNAVAILABLE); + int numTasks = recentTasks.size(); + ActivityInfo homeInfo = new Intent(Intent.ACTION_MAIN) + .addCategory(Intent.CATEGORY_HOME).resolveActivityInfo(pm, 0); - ActivityInfo homeInfo = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME) - .resolveActivityInfo(pm, 0); + boolean firstScreenful = true; + ArrayList<TaskDescription> tasks = new ArrayList<TaskDescription>(); - HashSet<Integer> recentTasksToKeepInCache = new HashSet<Integer>(); - int numTasks = recentTasks.size(); + // skip the first task - assume it's either the home screen or the current activity. + final int first = 1; + for (int i = first, index = 0; i < numTasks && (index < MAX_TASKS); ++i) { + if (isCancelled()) { + break; + } + final ActivityManager.RecentTaskInfo recentInfo = recentTasks.get(i); + TaskDescription item = createTaskDescription(recentInfo.id, + recentInfo.persistentId, recentInfo.baseIntent, + recentInfo.origActivity, recentInfo.description, homeInfo); + + if (item != null) { + while (true) { + try { + tasksWaitingForThumbnails.put(item); + break; + } catch (InterruptedException e) { + } + } + tasks.add(item); + if (firstScreenful && tasks.size() == mNumTasksInFirstScreenful) { + publishProgress(tasks); + tasks = new ArrayList<TaskDescription>(); + firstScreenful = false; + //break; + } + ++index; + } + } - // skip the first task - assume it's either the home screen or the current activity. - final int first = 1; - recentTasksToKeepInCache.add(recentTasks.get(0).persistentId); - for (int i = first, index = 0; i < numTasks && (index < MAX_TASKS); ++i) { - final ActivityManager.RecentTaskInfo recentInfo = recentTasks.get(i); + if (!isCancelled()) { + publishProgress(tasks); + if (firstScreenful) { + // always should publish two updates + publishProgress(new ArrayList<TaskDescription>()); + } + } - TaskDescription item = createTaskDescription(recentInfo.id, - recentInfo.persistentId, recentInfo.baseIntent, - recentInfo.origActivity, recentInfo.description, homeInfo); + while (true) { + try { + tasksWaitingForThumbnails.put(new TaskDescription()); + break; + } catch (InterruptedException e) { + } + } - if (item != null) { - tasks.add(item); - ++index; + Process.setThreadPriority(origPri); + return null; } - } - - // when we're not using the TaskDescription cache, we load the thumbnails in the - // background - loadThumbnailsInBackground(new ArrayList<TaskDescription>(tasks)); - return tasks; + }; + mTaskLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + loadThumbnailsAndIconsInBackground(tasksWaitingForThumbnails); } - private void loadThumbnailsInBackground(final ArrayList<TaskDescription> descriptions) { - if (descriptions.size() > 0) { - if (DEBUG) Log.v(TAG, "Showing " + descriptions.size() + " tasks"); - loadThumbnail(descriptions.get(0)); - if (descriptions.size() > 1) { - mThumbnailLoader = new AsyncTask<Void, Integer, Void>() { - @Override - protected void onProgressUpdate(Integer... values) { - final TaskDescription td = descriptions.get(values[0]); - if (!isCancelled()) { - mRecentsPanel.onTaskThumbnailLoaded(td); - } - // This is to prevent the loader thread from getting ahead - // of our UI updates. - mHandler.post(new Runnable() { - @Override public void run() { - synchronized (td) { - td.notifyAll(); - } - } - }); + private void loadThumbnailsAndIconsInBackground( + final BlockingQueue<TaskDescription> tasksWaitingForThumbnails) { + // continually read items from tasksWaitingForThumbnails and load + // thumbnails and icons for them. finish thread when cancelled or there + // is a null item in tasksWaitingForThumbnails + mThumbnailLoader = new AsyncTask<Void, TaskDescription, Void>() { + @Override + protected void onProgressUpdate(TaskDescription... values) { + if (!isCancelled()) { + TaskDescription td = values[0]; + mRecentsPanel.onTaskThumbnailLoaded(td); + } + } + @Override + protected Void doInBackground(Void... params) { + final int origPri = Process.getThreadPriority(Process.myTid()); + Process.setThreadPriority(Process.THREAD_GROUP_BG_NONINTERACTIVE); + + while (true) { + if (isCancelled()) { + break; } - - @Override - protected Void doInBackground(Void... params) { - final int origPri = Process.getThreadPriority(Process.myTid()); - Process.setThreadPriority(Process.THREAD_GROUP_BG_NONINTERACTIVE); - long nextTime = SystemClock.uptimeMillis(); - for (int i=1; i<descriptions.size(); i++) { - TaskDescription td = descriptions.get(i); - loadThumbnail(td); - long now = SystemClock.uptimeMillis(); - nextTime += 0; - if (nextTime > now) { - try { - Thread.sleep(nextTime-now); - } catch (InterruptedException e) { - } - } - - if (isCancelled()) { - break; - } - synchronized (td) { - publishProgress(i); - try { - td.wait(500); - } catch (InterruptedException e) { - } - } + TaskDescription td = null; + while (td == null) { + try { + td = tasksWaitingForThumbnails.take(); + } catch (InterruptedException e) { } - Process.setThreadPriority(origPri); - return null; } - }; - mThumbnailLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + if (td.isNull()) { + break; + } + loadThumbnailAndIcon(td); + synchronized(td) { + publishProgress(td); + } + } + + Process.setThreadPriority(origPri); + return null; } - } + }; + mThumbnailLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } - } diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java index f971d2d..4718a17 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java @@ -22,11 +22,18 @@ import android.content.res.Configuration; import android.database.DataSetObserver; import android.graphics.Canvas; import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.util.FloatMath; import android.util.Log; import android.view.MotionEvent; import android.view.View; -import android.view.ViewConfiguration; +import android.view.View.MeasureSpec; +import android.view.View.OnClickListener; +import android.view.View.OnLongClickListener; import android.view.View.OnTouchListener; +import android.view.ViewConfiguration; +import android.view.ViewTreeObserver; +import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.widget.HorizontalScrollView; import android.widget.LinearLayout; @@ -34,6 +41,8 @@ import com.android.systemui.R; import com.android.systemui.SwipeHelper; import com.android.systemui.recent.RecentsPanelView.TaskDescriptionAdapter; +import java.util.ArrayList; + public class RecentsHorizontalScrollView extends HorizontalScrollView implements SwipeHelper.Callback { private static final String TAG = RecentsPanelView.TAG; @@ -44,6 +53,8 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView protected int mLastScrollPosition; private SwipeHelper mSwipeHelper; private RecentsScrollViewPerformanceHelper mPerformanceHelper; + private ArrayList<View> mRecycledViews; + private int mNumItemsInOneScreenful; public RecentsHorizontalScrollView(Context context, AttributeSet attrs) { super(context, attrs, 0); @@ -51,6 +62,7 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop(); mSwipeHelper = new SwipeHelper(SwipeHelper.Y, this, densityScale, pagingTouchSlop); mPerformanceHelper = RecentsScrollViewPerformanceHelper.create(context, attrs, this, false); + mRecycledViews = new ArrayList<View>(); } private int scrollPositionOfMostRecent() { @@ -58,9 +70,23 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView } private void update() { + for (int i = 0; i < mLinearLayout.getChildCount(); i++) { + View v = mLinearLayout.getChildAt(i); + mRecycledViews.add(v); + mAdapter.recycleView(v); + } + LayoutTransition transitioner = getLayoutTransition(); + setLayoutTransition(null); + mLinearLayout.removeAllViews(); for (int i = 0; i < mAdapter.getCount(); i++) { - final View view = mAdapter.getView(i, null, mLinearLayout); + View old = null; + if (mRecycledViews.size() != 0) { + old = mRecycledViews.remove(mRecycledViews.size() - 1); + old.setVisibility(VISIBLE); + } + + final View view = mAdapter.getView(i, old, mLinearLayout); if (mPerformanceHelper != null) { mPerformanceHelper.addViewCallback(view); @@ -87,7 +113,8 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView } }; - final View thumbnailView = view.findViewById(R.id.app_thumbnail); + RecentsPanelView.ViewHolder holder = (RecentsPanelView.ViewHolder) view.getTag(); + final View thumbnailView = holder.thumbnailView; OnLongClickListener longClickListener = new OnLongClickListener() { public boolean onLongClick(View v) { final View anchorView = view.findViewById(R.id.app_description); @@ -107,13 +134,21 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView appTitle.setOnTouchListener(noOpListener); mLinearLayout.addView(view); } + setLayoutTransition(transitioner); + // Scroll to end after layout. - post(new Runnable() { - public void run() { - mLastScrollPosition = scrollPositionOfMostRecent(); - scrollTo(mLastScrollPosition, 0); - } - }); + final ViewTreeObserver observer = getViewTreeObserver(); + + final OnGlobalLayoutListener updateScroll = new OnGlobalLayoutListener() { + public void onGlobalLayout() { + mLastScrollPosition = scrollPositionOfMostRecent(); + scrollTo(mLastScrollPosition, 0); + if (observer.isAlive()) { + observer.removeOnGlobalLayoutListener(this); + } + } + }; + observer.addOnGlobalLayoutListener(updateScroll); } @Override @@ -142,8 +177,10 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView } public void onChildDismissed(View v) { + mRecycledViews.add(v); mLinearLayout.removeView(v); mCallback.handleSwipe(v); + v.setActivated(false); } public void onBeginDrag(View v) { @@ -315,6 +352,24 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView update(); } }); + DisplayMetrics dm = getResources().getDisplayMetrics(); + int childWidthMeasureSpec = + MeasureSpec.makeMeasureSpec(dm.widthPixels, MeasureSpec.AT_MOST); + int childheightMeasureSpec = + MeasureSpec.makeMeasureSpec(dm.heightPixels, MeasureSpec.AT_MOST); + View child = mAdapter.createView(mLinearLayout); + child.measure(childWidthMeasureSpec, childheightMeasureSpec); + mNumItemsInOneScreenful = + (int) FloatMath.ceil(dm.widthPixels / (float) child.getMeasuredWidth()); + mRecycledViews.add(child); + + for (int i = 0; i < mNumItemsInOneScreenful - 1; i++) { + mRecycledViews.add(mAdapter.createView(mLinearLayout)); + } + } + + public int numItemsInOneScreenful() { + return mNumItemsInOneScreenful; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java index a10e363..8706f10 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java @@ -27,6 +27,7 @@ import android.graphics.Bitmap; import android.graphics.Matrix; import android.graphics.Shader.TileMode; import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.provider.Settings; import android.util.AttributeSet; @@ -36,18 +37,18 @@ import android.view.LayoutInflater; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; -import android.view.ViewConfiguration; import android.view.ViewGroup; +import android.view.ViewRootImpl; import android.view.accessibility.AccessibilityEvent; import android.view.animation.AnimationUtils; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; +import android.widget.FrameLayout; import android.widget.HorizontalScrollView; import android.widget.ImageView; import android.widget.ImageView.ScaleType; import android.widget.PopupMenu; -import android.widget.RelativeLayout; import android.widget.ScrollView; import android.widget.TextView; @@ -59,7 +60,7 @@ import com.android.systemui.statusbar.tablet.TabletStatusBar; import java.util.ArrayList; -public class RecentsPanelView extends RelativeLayout implements OnItemClickListener, RecentsCallback, +public class RecentsPanelView extends FrameLayout implements OnItemClickListener, RecentsCallback, StatusBarPanel, Animator.AnimatorListener, View.OnTouchListener { static final String TAG = "RecentsPanelView"; static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false; @@ -71,6 +72,10 @@ public class RecentsPanelView extends RelativeLayout implements OnItemClickListe private StatusBarTouchProxy mStatusBarTouchProxy; private boolean mShowing; + private boolean mWaitingToShow; + private boolean mWaitingToShowAnimated; + private boolean mReadyToShow; + private int mNumItemsWaitingForThumbnailsAndIcons; private Choreographer mChoreo; OnRecentsPanelVisibilityChangedListener mVisibilityChangedListener; @@ -104,6 +109,7 @@ public class RecentsPanelView extends RelativeLayout implements OnItemClickListe TextView labelView; TextView descriptionView; TaskDescription taskDescription; + boolean loadedThumbnailAndIcon; } /* package */ final class TaskDescriptionAdapter extends BaseAdapter { @@ -125,42 +131,82 @@ public class RecentsPanelView extends RelativeLayout implements OnItemClickListe return position; // we just need something unique for this position } - public View getView(int position, View convertView, ViewGroup parent) { - ViewHolder holder; - if (convertView == null) { - convertView = mInflater.inflate(R.layout.status_bar_recent_item, parent, false); - holder = new ViewHolder(); - holder.thumbnailView = convertView.findViewById(R.id.app_thumbnail); - holder.thumbnailViewImage = (ImageView) convertView.findViewById( - R.id.app_thumbnail_image); - // If we set the default thumbnail now, we avoid an onLayout when we update - // the thumbnail later (if they both have the same dimensions) + public View createView(ViewGroup parent) { + View convertView = mInflater.inflate(R.layout.status_bar_recent_item, parent, false); + ViewHolder holder = new ViewHolder(); + holder.thumbnailView = convertView.findViewById(R.id.app_thumbnail); + holder.thumbnailViewImage = + (ImageView) convertView.findViewById(R.id.app_thumbnail_image); + // If we set the default thumbnail now, we avoid an onLayout when we update + // the thumbnail later (if they both have the same dimensions) + if (mRecentTasksLoader != null) { updateThumbnail(holder, mRecentTasksLoader.getDefaultThumbnail(), false, false); + } + holder.iconView = (ImageView) convertView.findViewById(R.id.app_icon); + if (mRecentTasksLoader != null) { + holder.iconView.setImageBitmap(mRecentTasksLoader.getDefaultIcon()); + } + holder.labelView = (TextView) convertView.findViewById(R.id.app_label); + holder.descriptionView = (TextView) convertView.findViewById(R.id.app_description); - holder.iconView = (ImageView) convertView.findViewById(R.id.app_icon); - holder.labelView = (TextView) convertView.findViewById(R.id.app_label); - holder.descriptionView = (TextView) convertView.findViewById(R.id.app_description); + convertView.setTag(holder); + return convertView; + } - convertView.setTag(holder); - } else { - holder = (ViewHolder) convertView.getTag(); + public View getView(int position, View convertView, ViewGroup parent) { + if (convertView == null) { + convertView = createView(parent); } + ViewHolder holder = (ViewHolder) convertView.getTag(); // index is reverse since most recent appears at the bottom... final int index = mRecentTaskDescriptions.size() - position - 1; final TaskDescription td = mRecentTaskDescriptions.get(index); - holder.iconView.setImageDrawable(td.getIcon()); + holder.labelView.setText(td.getLabel()); holder.thumbnailView.setContentDescription(td.getLabel()); - updateThumbnail(holder, td.getThumbnail(), true, false); + holder.loadedThumbnailAndIcon = td.isLoaded(); + if (td.isLoaded()) { + updateThumbnail(holder, td.getThumbnail(), true, false); + updateIcon(holder, td.getIcon(), true, false); + mNumItemsWaitingForThumbnailsAndIcons--; + } holder.thumbnailView.setTag(td); holder.thumbnailView.setOnLongClickListener(new OnLongClickDelegate(convertView)); holder.taskDescription = td; - return convertView; } + + public void recycleView(View v) { + ViewHolder holder = (ViewHolder) v.getTag(); + updateThumbnail(holder, mRecentTasksLoader.getDefaultThumbnail(), false, false); + holder.iconView.setImageBitmap(mRecentTasksLoader.getDefaultIcon()); + holder.iconView.setVisibility(INVISIBLE); + holder.labelView.setText(null); + holder.thumbnailView.setContentDescription(null); + holder.thumbnailView.setTag(null); + holder.thumbnailView.setOnLongClickListener(null); + holder.thumbnailView.setVisibility(INVISIBLE); + holder.taskDescription = null; + holder.loadedThumbnailAndIcon = false; + } + } + + public int numItemsInOneScreenful() { + if (mRecentsContainer instanceof RecentsHorizontalScrollView){ + RecentsHorizontalScrollView scrollView + = (RecentsHorizontalScrollView) mRecentsContainer; + return scrollView.numItemsInOneScreenful(); + } else if (mRecentsContainer instanceof RecentsVerticalScrollView){ + RecentsVerticalScrollView scrollView + = (RecentsVerticalScrollView) mRecentsContainer; + return scrollView.numItemsInOneScreenful(); + } + else { + throw new IllegalArgumentException("missing Recents[Horizontal]ScrollView"); + } } @Override @@ -192,15 +238,31 @@ public class RecentsPanelView extends RelativeLayout implements OnItemClickListe } public void show(boolean show, boolean animate) { - show(show, animate, null); + if (show) { + mWaitingToShow = true; + mWaitingToShowAnimated = animate; + showIfReady(); + } else { + show(show, animate, null, false); + } + } + + private void showIfReady() { + // mWaitingToShow = there was a touch up on the recents button + // mReadyToShow = we've created views for the first screenful of items + if (mWaitingToShow && mReadyToShow) { // && mNumItemsWaitingForThumbnailsAndIcons <= 0 + show(true, mWaitingToShowAnimated, null, false); + } } public void show(boolean show, boolean animate, - ArrayList<TaskDescription> recentTaskDescriptions) { + ArrayList<TaskDescription> recentTaskDescriptions, boolean firstScreenful) { + // For now, disable animations. We may want to re-enable in the future + animate = false; if (show) { // Need to update list of recent apps before we set visibility so this view's // content description is updated before it gets focus for TalkBack mode - refreshRecentTasksList(recentTaskDescriptions); + refreshRecentTasksList(recentTaskDescriptions, firstScreenful); // if there are no apps, either bring up a "No recent apps" message, or just // quit early @@ -209,19 +271,24 @@ public class RecentsPanelView extends RelativeLayout implements OnItemClickListe mRecentsNoApps.setVisibility(noApps ? View.VISIBLE : View.INVISIBLE); } else { if (noApps) { - if (DEBUG) Log.v(TAG, "Nothing to show"); + if (DEBUG) Log.v(TAG, "Nothing to show"); // Need to set recent tasks to dirty so that next time we load, we // refresh the list of tasks - mRecentTasksLoader.cancelLoadingThumbnails(); + mRecentTasksLoader.cancelLoadingThumbnailsAndIcons(); mRecentTasksDirty = true; + + mWaitingToShow = false; + mReadyToShow = false; return; } } } else { // Need to set recent tasks to dirty so that next time we load, we // refresh the list of tasks - mRecentTasksLoader.cancelLoadingThumbnails(); + mRecentTasksLoader.cancelLoadingThumbnailsAndIcons(); mRecentTasksDirty = true; + mWaitingToShow = false; + mReadyToShow = false; } if (animate) { if (mShowing != show) { @@ -385,7 +452,6 @@ public class RecentsPanelView extends RelativeLayout implements OnItemClickListe throw new IllegalArgumentException("missing Recents[Horizontal]ScrollView"); } - mRecentsScrim = findViewById(R.id.recents_bg_protect); mRecentsNoApps = findViewById(R.id.recents_no_apps); mChoreo = new Choreographer(this, mRecentsScrim, mRecentsContainer, mRecentsNoApps, this); @@ -425,6 +491,20 @@ public class RecentsPanelView extends RelativeLayout implements OnItemClickListe } } + + private void updateIcon(ViewHolder h, Drawable icon, boolean show, boolean anim) { + if (icon != null) { + h.iconView.setImageDrawable(icon); + if (show && h.iconView.getVisibility() != View.VISIBLE) { + if (anim) { + h.iconView.setAnimation( + AnimationUtils.loadAnimation(mContext, R.anim.recent_appear)); + } + h.iconView.setVisibility(View.VISIBLE); + } + } + } + private void updateThumbnail(ViewHolder h, Bitmap thumbnail, boolean show, boolean anim) { if (thumbnail != null) { // Should remove the default image in the frame @@ -458,31 +538,36 @@ public class RecentsPanelView extends RelativeLayout implements OnItemClickListe } } - void onTaskThumbnailLoaded(TaskDescription ad) { - synchronized (ad) { + void onTaskThumbnailLoaded(TaskDescription td) { + synchronized (td) { if (mRecentsContainer != null) { ViewGroup container = mRecentsContainer; if (container instanceof HorizontalScrollView || container instanceof ScrollView) { - container = (ViewGroup)container.findViewById( + container = (ViewGroup) container.findViewById( R.id.recents_linear_layout); } // Look for a view showing this thumbnail, to update. - for (int i=0; i<container.getChildCount(); i++) { + for (int i=0; i < container.getChildCount(); i++) { View v = container.getChildAt(i); if (v.getTag() instanceof ViewHolder) { ViewHolder h = (ViewHolder)v.getTag(); - if (h.taskDescription == ad) { + if (!h.loadedThumbnailAndIcon && h.taskDescription == td) { // only fade in the thumbnail if recents is already visible-- we // show it immediately otherwise - boolean animateShow = mShowing && - mRecentsContainer.getAlpha() > ViewConfiguration.ALPHA_THRESHOLD; - updateThumbnail(h, ad.getThumbnail(), true, animateShow); + //boolean animateShow = mShowing && + // mRecentsContainer.getAlpha() > ViewConfiguration.ALPHA_THRESHOLD; + boolean animateShow = false; + updateIcon(h, td.getIcon(), true, animateShow); + updateThumbnail(h, td.getThumbnail(), true, animateShow); + h.loadedThumbnailAndIcon = true; + mNumItemsWaitingForThumbnailsAndIcons--; } } } } - } + } + showIfReady(); } // additional optimization when we have sofware system buttons - start loading the recent @@ -516,7 +601,7 @@ public class RecentsPanelView extends RelativeLayout implements OnItemClickListe public void clearRecentTasksList() { // Clear memory used by screenshots if (mRecentTaskDescriptions != null) { - mRecentTasksLoader.cancelLoadingThumbnails(); + mRecentTasksLoader.cancelLoadingThumbnailsAndIcons(); mRecentTaskDescriptions.clear(); mListAdapter.notifyDataSetInvalidated(); mRecentTasksDirty = true; @@ -524,26 +609,50 @@ public class RecentsPanelView extends RelativeLayout implements OnItemClickListe } public void refreshRecentTasksList() { - refreshRecentTasksList(null); + refreshRecentTasksList(null, false); } - private void refreshRecentTasksList(ArrayList<TaskDescription> recentTasksList) { + private void refreshRecentTasksList( + ArrayList<TaskDescription> recentTasksList, boolean firstScreenful) { if (mRecentTasksDirty) { if (recentTasksList != null) { - mRecentTaskDescriptions = recentTasksList; + mFirstScreenful = true; + onTasksLoaded(recentTasksList); } else { - mRecentTaskDescriptions = mRecentTasksLoader.getRecentTasks(); + mFirstScreenful = true; + mRecentTasksLoader.loadTasksInBackground(); } - mListAdapter.notifyDataSetInvalidated(); - updateUiElements(getResources().getConfiguration()); mRecentTasksDirty = false; } } + boolean mFirstScreenful; + public void onTasksLoaded(ArrayList<TaskDescription> tasks) { + if (!mFirstScreenful && tasks.size() == 0) { + return; + } + mNumItemsWaitingForThumbnailsAndIcons = + mFirstScreenful ? tasks.size() : mRecentTaskDescriptions.size(); + if (mRecentTaskDescriptions == null) { + mRecentTaskDescriptions = new ArrayList(tasks); + } else { + mRecentTaskDescriptions.addAll(tasks); + } + mListAdapter.notifyDataSetInvalidated(); + updateUiElements(getResources().getConfiguration()); + mReadyToShow = true; + mFirstScreenful = false; + showIfReady(); + } + public ArrayList<TaskDescription> getRecentTasksList() { return mRecentTaskDescriptions; } + public boolean getFirstScreenful() { + return mFirstScreenful; + } + private void updateUiElements(Configuration config) { final int items = mRecentTaskDescriptions.size(); diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java index dc13092..0605c4c 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java @@ -22,10 +22,18 @@ import android.content.res.Configuration; import android.database.DataSetObserver; import android.graphics.Canvas; import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.util.FloatMath; import android.util.Log; import android.view.MotionEvent; import android.view.View; +import android.view.View.MeasureSpec; +import android.view.View.OnClickListener; +import android.view.View.OnLongClickListener; +import android.view.View.OnTouchListener; import android.view.ViewConfiguration; +import android.view.ViewTreeObserver; +import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.widget.LinearLayout; import android.widget.ScrollView; @@ -33,6 +41,8 @@ import com.android.systemui.R; import com.android.systemui.SwipeHelper; import com.android.systemui.recent.RecentsPanelView.TaskDescriptionAdapter; +import java.util.ArrayList; + public class RecentsVerticalScrollView extends ScrollView implements SwipeHelper.Callback { private static final String TAG = RecentsPanelView.TAG; private static final boolean DEBUG = RecentsPanelView.DEBUG; @@ -42,6 +52,8 @@ public class RecentsVerticalScrollView extends ScrollView implements SwipeHelper protected int mLastScrollPosition; private SwipeHelper mSwipeHelper; private RecentsScrollViewPerformanceHelper mPerformanceHelper; + private ArrayList<View> mRecycledViews; + private int mNumItemsInOneScreenful; public RecentsVerticalScrollView(Context context, AttributeSet attrs) { super(context, attrs, 0); @@ -50,6 +62,7 @@ public class RecentsVerticalScrollView extends ScrollView implements SwipeHelper mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, pagingTouchSlop); mPerformanceHelper = RecentsScrollViewPerformanceHelper.create(context, attrs, this, true); + mRecycledViews = new ArrayList<View>(); } private int scrollPositionOfMostRecent() { @@ -57,77 +70,91 @@ public class RecentsVerticalScrollView extends ScrollView implements SwipeHelper } private void update() { + for (int i = 0; i < mLinearLayout.getChildCount(); i++) { + View v = mLinearLayout.getChildAt(i); + mRecycledViews.add(v); + mAdapter.recycleView(v); + } + LayoutTransition transitioner = getLayoutTransition(); + setLayoutTransition(null); + mLinearLayout.removeAllViews(); // Once we can clear the data associated with individual item views, // we can get rid of the removeAllViews() and the code below will // recycle them. for (int i = 0; i < mAdapter.getCount(); i++) { View old = null; - if (i < mLinearLayout.getChildCount()) { - old = mLinearLayout.getChildAt(i); - old.setVisibility(View.VISIBLE); + if (mRecycledViews.size() != 0) { + old = mRecycledViews.remove(mRecycledViews.size() - 1); + old.setVisibility(VISIBLE); } + final View view = mAdapter.getView(i, old, mLinearLayout); if (mPerformanceHelper != null) { mPerformanceHelper.addViewCallback(view); } - if (old == null) { - OnTouchListener noOpListener = new OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - return true; - } - }; + OnTouchListener noOpListener = new OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + return true; + } + }; - view.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - mCallback.dismiss(); - } - }); - // We don't want a click sound when we dimiss recents - view.setSoundEffectsEnabled(false); + view.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + mCallback.dismiss(); + } + }); + // We don't want a click sound when we dimiss recents + view.setSoundEffectsEnabled(false); - OnClickListener launchAppListener = new OnClickListener() { - public void onClick(View v) { - mCallback.handleOnClick(view); - } - }; - - final View thumbnailView = view.findViewById(R.id.app_thumbnail); - OnLongClickListener longClickListener = new OnLongClickListener() { - public boolean onLongClick(View v) { - final View anchorView = view.findViewById(R.id.app_description); - mCallback.handleLongPress(view, anchorView, thumbnailView); - return true; - } - }; - thumbnailView.setClickable(true); - thumbnailView.setOnClickListener(launchAppListener); - thumbnailView.setOnLongClickListener(longClickListener); - - // We don't want to dismiss recents if a user clicks on the app title - // (we also don't want to launch the app either, though, because the - // app title is a small target and doesn't have great click feedback) - final View appTitle = view.findViewById(R.id.app_label); - appTitle.setContentDescription(" "); - appTitle.setOnTouchListener(noOpListener); - final View calloutLine = view.findViewById(R.id.recents_callout_line); - calloutLine.setOnTouchListener(noOpListener); - mLinearLayout.addView(view); - } - } - for (int i = mAdapter.getCount(); i < mLinearLayout.getChildCount(); i++) { - mLinearLayout.getChildAt(i).setVisibility(View.GONE); + OnClickListener launchAppListener = new OnClickListener() { + public void onClick(View v) { + mCallback.handleOnClick(view); + } + }; + + RecentsPanelView.ViewHolder holder = (RecentsPanelView.ViewHolder) view.getTag(); + final View thumbnailView = holder.thumbnailView; + OnLongClickListener longClickListener = new OnLongClickListener() { + public boolean onLongClick(View v) { + final View anchorView = view.findViewById(R.id.app_description); + mCallback.handleLongPress(view, anchorView, thumbnailView); + return true; + } + }; + thumbnailView.setClickable(true); + thumbnailView.setOnClickListener(launchAppListener); + thumbnailView.setOnLongClickListener(longClickListener); + + // We don't want to dismiss recents if a user clicks on the app title + // (we also don't want to launch the app either, though, because the + // app title is a small target and doesn't have great click feedback) + final View appTitle = view.findViewById(R.id.app_label); + appTitle.setContentDescription(" "); + appTitle.setOnTouchListener(noOpListener); + final View calloutLine = view.findViewById(R.id.recents_callout_line); + calloutLine.setOnTouchListener(noOpListener); + + mLinearLayout.addView(view); } + setLayoutTransition(transitioner); + // Scroll to end after layout. - post(new Runnable() { - public void run() { - mLastScrollPosition = scrollPositionOfMostRecent(); - scrollTo(0, mLastScrollPosition); - } - }); + final ViewTreeObserver observer = getViewTreeObserver(); + + final OnGlobalLayoutListener updateScroll = new OnGlobalLayoutListener() { + public void onGlobalLayout() { + mLastScrollPosition = scrollPositionOfMostRecent(); + scrollTo(0, mLastScrollPosition); + if (observer.isAlive()) { + observer.removeOnGlobalLayoutListener(this); + } + } + }; + observer.addOnGlobalLayoutListener(updateScroll); } @Override @@ -156,8 +183,10 @@ public class RecentsVerticalScrollView extends ScrollView implements SwipeHelper } public void onChildDismissed(View v) { + mRecycledViews.add(v); mLinearLayout.removeView(v); mCallback.handleSwipe(v); + v.setActivated(false); } public void onBeginDrag(View v) { @@ -330,6 +359,25 @@ public class RecentsVerticalScrollView extends ScrollView implements SwipeHelper update(); } }); + + DisplayMetrics dm = getResources().getDisplayMetrics(); + int childWidthMeasureSpec = + MeasureSpec.makeMeasureSpec(dm.widthPixels, MeasureSpec.AT_MOST); + int childheightMeasureSpec = + MeasureSpec.makeMeasureSpec(dm.heightPixels, MeasureSpec.AT_MOST); + View child = mAdapter.createView(mLinearLayout); + child.measure(childWidthMeasureSpec, childheightMeasureSpec); + mNumItemsInOneScreenful = + (int) FloatMath.ceil(dm.heightPixels / (float) child.getMeasuredHeight()); + mRecycledViews.add(child); + + for (int i = 0; i < mNumItemsInOneScreenful - 1; i++) { + mRecycledViews.add(mAdapter.createView(mLinearLayout)); + } + } + + public int numItemsInOneScreenful() { + return mNumItemsInOneScreenful; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recent/TaskDescription.java b/packages/SystemUI/src/com/android/systemui/recent/TaskDescription.java index dcfd6d8..7e979b7 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/TaskDescription.java +++ b/packages/SystemUI/src/com/android/systemui/recent/TaskDescription.java @@ -32,6 +32,7 @@ public final class TaskDescription { private Bitmap mThumbnail; // generated by Activity.onCreateThumbnail() private Drawable mIcon; // application package icon private CharSequence mLabel; // application package label + private boolean mLoaded; public TaskDescription(int _taskId, int _persistentTaskId, ResolveInfo _resolveInfo, Intent _intent, @@ -45,6 +46,28 @@ public final class TaskDescription { packageName = _packageName; } + public TaskDescription() { + resolveInfo = null; + intent = null; + taskId = -1; + persistentTaskId = -1; + + description = null; + packageName = null; + } + + public void setLoaded(boolean loaded) { + mLoaded = loaded; + } + + public boolean isLoaded() { + return mLoaded; + } + + public boolean isNull() { + return resolveInfo == null; + } + // mark all these as locked? public CharSequence getLabel() { return mLabel; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 5a1e3f4..b3cef90 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -393,7 +393,7 @@ public class PhoneStatusBar extends StatusBar { } lp.gravity = Gravity.BOTTOM | Gravity.LEFT; lp.setTitle("RecentsPanel"); - lp.windowAnimations = R.style.Animation_RecentPanel; + lp.windowAnimations = com.android.internal.R.style.Animation_RecentApplications; lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; return lp; @@ -403,11 +403,13 @@ public class PhoneStatusBar extends StatusBar { // Recents Panel boolean visible = false; ArrayList<TaskDescription> recentTasksList = null; + boolean firstScreenful = false; if (mRecentsPanel != null) { visible = mRecentsPanel.isShowing(); WindowManagerImpl.getDefault().removeView(mRecentsPanel); if (visible) { recentTasksList = mRecentsPanel.getRecentTasksList(); + firstScreenful = mRecentsPanel.getFirstScreenful(); } } @@ -425,7 +427,7 @@ public class PhoneStatusBar extends StatusBar { WindowManagerImpl.getDefault().addView(mRecentsPanel, lp); mRecentsPanel.setBar(this); if (visible) { - mRecentsPanel.show(true, false, recentTasksList); + mRecentsPanel.show(true, false, recentTasksList, firstScreenful); } } |