blob: 7d4629e89357055897e49c18861c465cdbbe6765 [file] [log] [blame]
Jim Millere6ad1a82010-08-20 19:25:39 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
Joe Onorato013cfc12010-09-08 15:23:18 -040018package com.android.systemui.recent;
19
20import com.android.systemui.R;
Jim Millere6ad1a82010-08-20 19:25:39 -070021
Jim Miller783cb602010-09-02 18:08:05 -070022import com.android.ex.carousel.CarouselView;
Jim Millerc4cf1302010-09-24 18:29:03 -070023import com.android.ex.carousel.CarouselViewHelper;
Jim Miller783cb602010-09-02 18:08:05 -070024import com.android.ex.carousel.CarouselRS.CarouselCallback;
Jim Millerc4cf1302010-09-24 18:29:03 -070025import com.android.ex.carousel.CarouselViewHelper.DetailTextureParameters;
Jim Millere6ad1a82010-08-20 19:25:39 -070026
27import java.util.ArrayList;
28import java.util.List;
29
Jim Millere6ad1a82010-08-20 19:25:39 -070030import android.app.Activity;
31import android.app.ActivityManager;
Dianne Hackbornb6777462010-11-12 12:43:22 -080032import android.app.ActivityManagerNative;
33import android.app.IActivityManager;
Jim Millere6ad1a82010-08-20 19:25:39 -070034import android.app.IThumbnailReceiver;
35import android.app.ActivityManager.RunningTaskInfo;
36import android.content.ActivityNotFoundException;
37import android.content.Context;
38import android.content.Intent;
39import android.content.pm.ActivityInfo;
40import android.content.pm.PackageManager;
41import android.content.pm.ResolveInfo;
42import android.content.res.Configuration;
43import android.content.res.Resources;
44import android.graphics.Bitmap;
Jim Millerc4cf1302010-09-24 18:29:03 -070045import android.graphics.BitmapFactory;
46import android.graphics.Canvas;
Jim Millere6ad1a82010-08-20 19:25:39 -070047import android.graphics.Matrix;
Jim Millerc4cf1302010-09-24 18:29:03 -070048import android.graphics.Paint;
49import android.graphics.PaintFlagsDrawFilter;
50import android.graphics.PorterDuffXfermode;
51import android.graphics.PorterDuff;
Jim Millere6ad1a82010-08-20 19:25:39 -070052import android.graphics.Bitmap.Config;
53import android.graphics.drawable.Drawable;
54import android.graphics.PixelFormat;
55import android.os.Bundle;
56import android.os.RemoteException;
57import android.util.Log;
58import android.view.View;
Jim Millerc4cf1302010-09-24 18:29:03 -070059import android.view.View.MeasureSpec;
60import android.widget.TextView;
Jim Millere6ad1a82010-08-20 19:25:39 -070061
62public class RecentApplicationsActivity extends Activity {
63 private static final String TAG = "RecentApplicationsActivity";
Jim Millerc4cf1302010-09-24 18:29:03 -070064 private static boolean DBG = false;
Jim Millere6ad1a82010-08-20 19:25:39 -070065 private static final int CARD_SLOTS = 56;
66 private static final int VISIBLE_SLOTS = 7;
67 private static final int MAX_TASKS = VISIBLE_SLOTS * 2;
Jim Millerc4cf1302010-09-24 18:29:03 -070068
69 // TODO: these should be configurable
70 private static final int DETAIL_TEXTURE_MAX_WIDTH = 200;
71 private static final int DETAIL_TEXTURE_MAX_HEIGHT = 80;
72 private static final int TEXTURE_WIDTH = 256;
73 private static final int TEXTURE_HEIGHT = 256;
74
Jim Millere6ad1a82010-08-20 19:25:39 -070075 private ActivityManager mActivityManager;
76 private List<RunningTaskInfo> mRunningTaskList;
77 private boolean mPortraitMode = true;
78 private ArrayList<ActivityDescription> mActivityDescriptions
79 = new ArrayList<ActivityDescription>();
80 private CarouselView mCarouselView;
Jim Millerc4cf1302010-09-24 18:29:03 -070081 private LocalCarouselViewHelper mHelper;
Jim Millere6ad1a82010-08-20 19:25:39 -070082 private View mNoRecentsView;
Jim Millerc4cf1302010-09-24 18:29:03 -070083 private Bitmap mLoadingBitmap;
84 private Bitmap mRecentOverlay;
85 private boolean mHidden = false;
86 private boolean mHiding = false;
87 private DetailInfo mDetailInfo;
88
89 /**
90 * This class is a container for all items associated with the DetailView we'll
91 * be drawing to a bitmap and sending to Carousel.
92 *
93 */
94 static final class DetailInfo {
95 public DetailInfo(View _view, TextView _title, TextView _desc) {
96 view = _view;
97 title = _title;
98 description = _desc;
99 }
100
101 /**
102 * Draws view into the given bitmap, if provided
103 * @param bitmap
104 */
105 public Bitmap draw(Bitmap bitmap) {
106 resizeView(view, DETAIL_TEXTURE_MAX_WIDTH, DETAIL_TEXTURE_MAX_HEIGHT);
107 int desiredWidth = view.getWidth();
108 int desiredHeight = view.getHeight();
109 if (bitmap == null || desiredWidth != bitmap.getWidth()
110 || desiredHeight != bitmap.getHeight()) {
111 bitmap = Bitmap.createBitmap(desiredWidth, desiredHeight, Config.ARGB_8888);
112 }
113 Canvas canvas = new Canvas(bitmap);
114 view.draw(canvas);
115 return bitmap;
116 }
117
118 /**
119 * Force a layout pass on the given view.
120 */
121 private void resizeView(View view, int maxWidth, int maxHeight) {
122 int widthSpec = MeasureSpec.getMode(MeasureSpec.AT_MOST)
123 | MeasureSpec.getSize(maxWidth);
124 int heightSpec = MeasureSpec.getMode(MeasureSpec.AT_MOST)
125 | MeasureSpec.getSize(maxHeight);
126 view.measure(widthSpec, heightSpec);
127 view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
128 Log.v(TAG, "RESIZED VIEW: " + view.getWidth() + ", " + view.getHeight());
129 }
130
131 public View view;
132 public TextView title;
133 public TextView description;
134 }
Jim Millere6ad1a82010-08-20 19:25:39 -0700135
136 static class ActivityDescription {
137 int id;
138 Bitmap thumbnail; // generated by Activity.onCreateThumbnail()
139 Drawable icon; // application package icon
140 String label; // application package label
Jim Millerc4cf1302010-09-24 18:29:03 -0700141 CharSequence description; // generated by Activity.onCreateDescription()
Jim Millere6ad1a82010-08-20 19:25:39 -0700142 Intent intent; // launch intent for application
143 Matrix matrix; // arbitrary rotation matrix to correct orientation
144 int position; // position in list
145
146 public ActivityDescription(Bitmap _thumbnail,
147 Drawable _icon, String _label, String _desc, int _id, int _pos)
148 {
149 thumbnail = _thumbnail;
150 icon = _icon;
151 label = _label;
152 description = _desc;
153 id = _id;
154 position = _pos;
155 }
156
157 public void clear() {
158 icon = null;
159 thumbnail = null;
160 label = null;
161 description = null;
162 intent = null;
163 matrix = null;
164 id = -1;
165 position = -1;
166 }
167 };
168
169 private ActivityDescription findActivityDescription(int id) {
170 for (int i = 0; i < mActivityDescriptions.size(); i++) {
171 ActivityDescription item = mActivityDescriptions.get(i);
172 if (item != null && item.id == id) {
173 return item;
174 }
175 }
176 return null;
177 }
178
Jim Millerc4cf1302010-09-24 18:29:03 -0700179 private class LocalCarouselViewHelper extends CarouselViewHelper {
Jim Millerc4cf1302010-09-24 18:29:03 -0700180 private DetailTextureParameters mDetailParams = new DetailTextureParameters(10.0f, 20.0f);
Jim Millere6ad1a82010-08-20 19:25:39 -0700181
Jim Millerc4cf1302010-09-24 18:29:03 -0700182 public LocalCarouselViewHelper(Context context) {
183 super(context);
Jim Millere6ad1a82010-08-20 19:25:39 -0700184 }
185
Jim Millerc4cf1302010-09-24 18:29:03 -0700186 @Override
187 public DetailTextureParameters getDetailTextureParameters(int id) {
188 return mDetailParams;
Jim Millere6ad1a82010-08-20 19:25:39 -0700189 }
190
191 public void onCardSelected(int n) {
192 if (n < mActivityDescriptions.size()) {
193 ActivityDescription item = mActivityDescriptions.get(n);
Dianne Hackbornb6777462010-11-12 12:43:22 -0800194 if (item.id >= 0) {
195 // This is an active task; it should just go to the foreground.
Dianne Hackborn621e17d2010-11-22 15:59:56 -0800196 final ActivityManager am = (ActivityManager)
197 getSystemService(Context.ACTIVITY_SERVICE);
198 am.moveTaskToFront(item.id, ActivityManager.MOVE_TASK_WITH_HOME);
Dianne Hackbornb6777462010-11-12 12:43:22 -0800199 } else if (item.intent != null) {
200 // prepare a launch intent and send it
Dianne Hackborn621e17d2010-11-22 15:59:56 -0800201 item.intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
202 | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
Jim Millere6ad1a82010-08-20 19:25:39 -0700203 try {
204 if (DBG) Log.v(TAG, "Starting intent " + item.intent);
205 startActivity(item.intent);
Jim Millerc4cf1302010-09-24 18:29:03 -0700206 overridePendingTransition(R.anim.recent_app_enter, R.anim.recent_app_leave);
Jim Millere6ad1a82010-08-20 19:25:39 -0700207 } catch (ActivityNotFoundException e) {
208 if (DBG) Log.w("Recent", "Unable to launch recent task", e);
209 }
210 finish();
211 }
212 }
213 }
214
Jim Millerc4cf1302010-09-24 18:29:03 -0700215 @Override
216 public Bitmap getTexture(final int id) {
217 if (DBG) Log.v(TAG, "onRequestTexture(" + id + ")");
218 ActivityDescription info;
219 synchronized(mActivityDescriptions) {
220 info = mActivityDescriptions.get(id);
Jim Millere6ad1a82010-08-20 19:25:39 -0700221 }
Jim Millerc4cf1302010-09-24 18:29:03 -0700222 Bitmap bitmap = null;
223 if (info != null) {
224 bitmap = compositeBitmap(info);
225 }
226 return bitmap;
Jim Millere6ad1a82010-08-20 19:25:39 -0700227 }
Joe Onorato32f2f5d2010-09-15 15:34:17 -0400228
Jim Millerc4cf1302010-09-24 18:29:03 -0700229 @Override
230 public Bitmap getDetailTexture(int n) {
231 Bitmap bitmap = null;
232 if (n < mActivityDescriptions.size()) {
233 ActivityDescription item = mActivityDescriptions.get(n);
234 mDetailInfo.title.setText(item.label);
235 mDetailInfo.description.setText(item.description);
236 bitmap = mDetailInfo.draw(null);
237 }
238 return bitmap;
Joe Onorato32f2f5d2010-09-15 15:34:17 -0400239 }
Jim Millere6ad1a82010-08-20 19:25:39 -0700240 };
241
Jim Millerc4cf1302010-09-24 18:29:03 -0700242 private Bitmap compositeBitmap(ActivityDescription info) {
243 final int targetWidth = TEXTURE_WIDTH;
244 final int targetHeight = TEXTURE_HEIGHT;
245 final int border = 3; // inset along the edge for thumnnail content
246 final int overlap = 1; // how many pixels of overlap between border and thumbnail
247 final Resources res = getResources();
248 if (mRecentOverlay == null) {
249 mRecentOverlay = BitmapFactory.decodeResource(res, R.drawable.recent_overlay);
250 }
251
252 // Create a bitmap of the proper size/format and set the canvas to draw to it
253 final Bitmap result = Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_8888);
254 final Canvas canvas = new Canvas(result);
255 canvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG, Paint.FILTER_BITMAP_FLAG));
256 Paint paint = new Paint();
257 paint.setFilterBitmap(false);
258
259 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
260 canvas.save();
261 if (info.thumbnail != null) {
262 // Draw the thumbnail
263 int sourceWidth = targetWidth - 2 * (border - overlap);
264 int sourceHeight = targetHeight - 2 * (border - overlap);
265 final float scaleX = (float) sourceWidth / info.thumbnail.getWidth();
266 final float scaleY = (float) sourceHeight / info.thumbnail.getHeight();
267 canvas.translate(border * 0.5f, border * 0.5f);
268 canvas.scale(scaleX, scaleY);
269 canvas.drawBitmap(info.thumbnail, 0, 0, paint);
270 } else {
271 // Draw the Loading bitmap placeholder, TODO: Remove when RS handles blending
272 final float scaleX = (float) targetWidth / mLoadingBitmap.getWidth();
273 final float scaleY = (float) targetHeight / mLoadingBitmap.getHeight();
274 canvas.scale(scaleX, scaleY);
275 canvas.drawBitmap(mLoadingBitmap, 0, 0, paint);
276 }
277 canvas.restore();
278
279 // Draw overlay
280 canvas.save();
281 final float scaleOverlayX = (float) targetWidth / mRecentOverlay.getWidth();
282 final float scaleOverlayY = (float) targetHeight / mRecentOverlay.getHeight();
283 canvas.scale(scaleOverlayX, scaleOverlayY);
284 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
285 canvas.drawBitmap(mRecentOverlay, 0, 0, paint);
286 canvas.restore();
287
288 // Draw icon
289 if (info.icon != null) {
290 canvas.save();
291 info.icon.draw(canvas);
292 canvas.restore();
293 }
294
295 return result;
296 }
297
Jim Millere6ad1a82010-08-20 19:25:39 -0700298 private final IThumbnailReceiver mThumbnailReceiver = new IThumbnailReceiver.Stub() {
299
300 public void finished() throws RemoteException {
301
302 }
303
304 public void newThumbnail(final int id, final Bitmap bitmap, CharSequence description)
305 throws RemoteException {
306 int w = bitmap.getWidth();
307 int h = bitmap.getHeight();
308 if (DBG) Log.v(TAG, "New thumbnail for id=" + id + ", dimensions=" + w + "x" + h
309 + " description '" + description + "'");
310 ActivityDescription info = findActivityDescription(id);
311 if (info != null) {
312 info.thumbnail = bitmap;
Jim Millerc4cf1302010-09-24 18:29:03 -0700313 info.description = description;
Jim Millere6ad1a82010-08-20 19:25:39 -0700314 final int thumbWidth = bitmap.getWidth();
315 final int thumbHeight = bitmap.getHeight();
316 if ((mPortraitMode && thumbWidth > thumbHeight)
317 || (!mPortraitMode && thumbWidth < thumbHeight)) {
318 Matrix matrix = new Matrix();
319 matrix.setRotate(90.0f, (float) thumbWidth / 2, (float) thumbHeight / 2);
320 info.matrix = matrix;
321 } else {
322 info.matrix = null;
323 }
Jim Millerc3a44b62010-10-06 17:13:12 -0700324 // Force Carousel to request new textures for this item.
325 mCarouselView.setTextureForItem(info.position, null);
326 mCarouselView.setDetailTextureForItem(info.position, 0, 0, 0, 0, null);
Jim Millere6ad1a82010-08-20 19:25:39 -0700327 } else {
328 if (DBG) Log.v(TAG, "Can't find view for id " + id);
329 }
330 }
331 };
332
Jim Millerc4cf1302010-09-24 18:29:03 -0700333 /**
334 * We never really finish() RecentApplicationsActivity, since we don't want to
335 * get destroyed and pay the start-up cost to restart it.
336 */
337 @Override
338 public void finish() {
339 moveTaskToBack(true);
340 }
341
342 @Override
343 protected void onNewIntent(Intent intent) {
344 mHidden = !mHidden;
345 if (mHidden) {
346 mHiding = true;
347 moveTaskToBack(true);
348 } else {
349 mHiding = false;
350 }
351 super.onNewIntent(intent);
352 }
353
Jim Millere6ad1a82010-08-20 19:25:39 -0700354 @Override
355 protected void onCreate(Bundle savedInstanceState) {
356 super.onCreate(savedInstanceState);
357
358 final Resources res = getResources();
359 final View decorView = getWindow().getDecorView();
360
361 getWindow().getDecorView().setBackgroundColor(0x80000000);
Jim Millere6ad1a82010-08-20 19:25:39 -0700362
Jim Millerc4cf1302010-09-24 18:29:03 -0700363 if (mCarouselView == null) {
Jim Millerc3a44b62010-10-06 17:13:12 -0700364 long t = System.currentTimeMillis();
365 setContentView(R.layout.recent_apps_activity);
366 long elapsed = System.currentTimeMillis() - t;
367 Log.v(TAG, "Recents layout took " + elapsed + "ms to load");
Jim Millerc4cf1302010-09-24 18:29:03 -0700368 mLoadingBitmap = BitmapFactory.decodeResource(res, R.drawable.recent_rez_border);
369 mCarouselView = (CarouselView)findViewById(R.id.carousel);
370 mHelper = new LocalCarouselViewHelper(this);
371 mHelper.setCarouselView(mCarouselView);
372
373 mCarouselView.setSlotCount(CARD_SLOTS);
374 mCarouselView.setVisibleSlots(VISIBLE_SLOTS);
375 mCarouselView.createCards(0);
376 mCarouselView.setStartAngle((float) -(2.0f*Math.PI * 5 / CARD_SLOTS));
377 mCarouselView.setDefaultBitmap(mLoadingBitmap);
378 mCarouselView.setLoadingBitmap(mLoadingBitmap);
Jim Miller5fd395e2010-09-30 13:53:06 -0700379 mCarouselView.setRezInCardCount(3.0f);
Jim Millerc4cf1302010-09-24 18:29:03 -0700380 mCarouselView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
381
382 mNoRecentsView = (View) findViewById(R.id.no_applications_message);
383
384 mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
385 mPortraitMode = decorView.getHeight() > decorView.getWidth();
386
387 // Load detail view which will be used to render text
388 View detail = getLayoutInflater().inflate(R.layout.recents_detail_view, null);
389 TextView title = (TextView) detail.findViewById(R.id.app_title);
390 TextView description = (TextView) detail.findViewById(R.id.app_description);
391 mDetailInfo = new DetailInfo(detail, title, description);
392
393 refresh();
394 }
Jim Millere6ad1a82010-08-20 19:25:39 -0700395 }
396
397 @Override
398 protected void onResume() {
399 super.onResume();
400 refresh();
401 }
402
403 @Override
404 public void onConfigurationChanged(Configuration newConfig) {
405 super.onConfigurationChanged(newConfig);
406 mPortraitMode = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT;
407 if (DBG) Log.v(TAG, "CONFIG CHANGE, mPortraitMode = " + mPortraitMode);
408 refresh();
409 }
410
411 void updateRunningTasks() {
Dianne Hackbornd2835932010-12-13 16:28:46 -0800412 mRunningTaskList = mActivityManager.getRunningTasks(MAX_TASKS,
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700413 0, mThumbnailReceiver);
Jim Millere6ad1a82010-08-20 19:25:39 -0700414 if (DBG) Log.v(TAG, "Portrait: " + mPortraitMode);
415 for (RunningTaskInfo r : mRunningTaskList) {
416 if (r.thumbnail != null) {
417 int thumbWidth = r.thumbnail.getWidth();
418 int thumbHeight = r.thumbnail.getHeight();
419 if (DBG) Log.v(TAG, "Got thumbnail " + thumbWidth + "x" + thumbHeight);
420 ActivityDescription desc = findActivityDescription(r.id);
421 if (desc != null) {
422 desc.thumbnail = r.thumbnail;
Jim Millerc4cf1302010-09-24 18:29:03 -0700423 desc.description = r.description;
Jim Millere6ad1a82010-08-20 19:25:39 -0700424 if ((mPortraitMode && thumbWidth > thumbHeight)
425 || (!mPortraitMode && thumbWidth < thumbHeight)) {
426 Matrix matrix = new Matrix();
427 matrix.setRotate(90.0f, (float) thumbWidth / 2, (float) thumbHeight / 2);
428 desc.matrix = matrix;
429 }
430 } else {
431 if (DBG) Log.v(TAG, "Couldn't find ActivityDesc for id=" + r.id);
432 }
433 } else {
434 if (DBG) Log.v(TAG, "*** RUNNING THUMBNAIL WAS NULL ***");
435 }
436 }
Jim Millere6ad1a82010-08-20 19:25:39 -0700437 }
438
439 private void updateRecentTasks() {
440 final PackageManager pm = getPackageManager();
441 final ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
442
443 final List<ActivityManager.RecentTaskInfo> recentTasks =
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700444 am.getRecentTasks(MAX_TASKS, ActivityManager.RECENT_IGNORE_UNAVAILABLE);
Jim Millere6ad1a82010-08-20 19:25:39 -0700445
446 ActivityInfo homeInfo = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME)
447 .resolveActivityInfo(pm, 0);
448
449 // IconUtilities iconUtilities = new IconUtilities(this); // FIXME
450
451 int numTasks = recentTasks.size();
452 mActivityDescriptions.clear();
453 for (int i = 0, index = 0; i < numTasks && (index < MAX_TASKS); ++i) {
454 final ActivityManager.RecentTaskInfo recentInfo = recentTasks.get(i);
455
456 Intent intent = new Intent(recentInfo.baseIntent);
457 if (recentInfo.origActivity != null) {
458 intent.setComponent(recentInfo.origActivity);
459 }
460
461 // Skip the current home activity.
462 if (homeInfo != null
463 && homeInfo.packageName.equals(intent.getComponent().getPackageName())
464 && homeInfo.name.equals(intent.getComponent().getClassName())) {
465 continue;
466 }
467
468 intent.setFlags((intent.getFlags()&~Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
469 | Intent.FLAG_ACTIVITY_NEW_TASK);
470 final ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
471 if (resolveInfo != null) {
472 final ActivityInfo info = resolveInfo.activityInfo;
473 final String title = info.loadLabel(pm).toString();
474 Drawable icon = info.loadIcon(pm);
475
476 int id = recentTasks.get(i).id;
477 if (id != -1 && title != null && title.length() > 0 && icon != null) {
478 // icon = null; FIXME: iconUtilities.createIconDrawable(icon);
479 ActivityDescription item = new ActivityDescription(
480 null, icon, title, null, id, index);
481 item.intent = intent;
482 mActivityDescriptions.add(item);
483 if (DBG) Log.v(TAG, "Added item[" + index
484 + "], id=" + item.id
485 + ", title=" + item.label);
486 ++index;
487 } else {
488 if (DBG) Log.v(TAG, "SKIPPING item " + id);
489 }
490 }
491 }
492 }
493
Jim Millerc4cf1302010-09-24 18:29:03 -0700494 private final Runnable mRefreshRunnable = new Runnable() {
495 public void run() {
496 updateRecentTasks();
497 updateRunningTasks();
498 showCarousel(mActivityDescriptions.size() > 0);
499 }
500 };
501
502 private void showCarousel(boolean show) {
503 if (show) {
Jim Millerc3a44b62010-10-06 17:13:12 -0700504 mCarouselView.createCards(mActivityDescriptions.size());
505 for (int i = 1; i < mActivityDescriptions.size(); i++) {
506 // Force Carousel to update textures. Note we don't do this for the first item,
507 // since it will be updated when mThumbnailReceiver returns a thumbnail.
508 // TODO: only do this for apps that have changed.
509 mCarouselView.setTextureForItem(i, null);
510 mCarouselView.setDetailTextureForItem(i, 0, 0, 0, 0, null);
511 }
Jim Millerc4cf1302010-09-24 18:29:03 -0700512 // Make carousel visible
Jim Millere6ad1a82010-08-20 19:25:39 -0700513 mNoRecentsView.setVisibility(View.GONE);
514 mCarouselView.setVisibility(View.VISIBLE);
515 mCarouselView.createCards(mActivityDescriptions.size());
Jim Millerc4cf1302010-09-24 18:29:03 -0700516 } else {
517 // show "No Recent Tasks"
518 mNoRecentsView.setVisibility(View.VISIBLE);
519 mCarouselView.setVisibility(View.GONE);
520 }
521 }
522
523 private void refresh() {
524 if (!mHiding && mCarouselView != null) {
525 // Don't update the view now. Instead, post a request so it happens next time
526 // we reach the looper after a delay. This way we can fold multiple refreshes
527 // into just the latest.
528 mCarouselView.removeCallbacks(mRefreshRunnable);
529 mCarouselView.postDelayed(mRefreshRunnable, 50);
Jim Millere6ad1a82010-08-20 19:25:39 -0700530 }
531 }
532}