TaskSwitcherActivity.java revision 7cb0068e59dde61ef0e649735199e5ba31c9c6af
1/* 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 18package com.android.carouseltest; 19 20import java.util.ArrayList; 21import java.util.List; 22import com.android.carouseltest.R; 23 24import com.android.ex.carousel.CarouselRS.CarouselCallback; 25 26import android.app.Activity; 27import android.app.ActivityManager; 28import android.app.IThumbnailReceiver; 29import android.app.ActivityManager.RunningTaskInfo; 30import android.content.ActivityNotFoundException; 31import android.content.Context; 32import android.content.Intent; 33import android.content.pm.ActivityInfo; 34import android.content.pm.PackageManager; 35import android.content.pm.ResolveInfo; 36import android.content.res.Configuration; 37import android.content.res.Resources; 38import android.graphics.Bitmap; 39import android.graphics.BitmapFactory; 40import android.graphics.Matrix; 41import android.graphics.Bitmap.Config; 42import android.graphics.drawable.Drawable; 43import android.os.Bundle; 44import android.os.RemoteException; 45import android.util.Log; 46import android.view.View; 47 48public class TaskSwitcherActivity extends Activity { 49 private static final String TAG = "TaskSwitcherActivity"; 50 private static final int CARD_SLOTS = 56; 51 private static final int MAX_TASKS = 20; 52 private static final int VISIBLE_SLOTS = 7; 53 protected static final boolean DBG = false; 54 private ActivityManager mActivityManager; 55 private List<RunningTaskInfo> mRunningTaskList; 56 private boolean mPortraitMode = true; 57 private ArrayList<ActivityDescription> mActivityDescriptions 58 = new ArrayList<ActivityDescription>(); 59 private MyCarouselView mView; 60 private Bitmap mBlankBitmap = Bitmap.createBitmap(128, 128, Config.RGB_565); 61 62 static class ActivityDescription { 63 int id; 64 Bitmap thumbnail; 65 Drawable icon; 66 String label; 67 String description; 68 Intent intent; 69 Matrix matrix; 70 71 public ActivityDescription(Bitmap _thumbnail, 72 Drawable _icon, String _label, String _desc, int _id) 73 { 74 thumbnail = _thumbnail; 75 icon = _icon; 76 label = _label; 77 description = _desc; 78 id = _id; 79 } 80 81 public void clear() { 82 icon = null; 83 thumbnail = null; 84 label = null; 85 description = null; 86 intent = null; 87 matrix = null; 88 id = -1; 89 } 90 }; 91 92 private ActivityDescription findActivityDescription(int id) { 93 for (int i = 0; i < mActivityDescriptions.size(); i++) { 94 ActivityDescription item = mActivityDescriptions.get(i); 95 if (item != null && item.id == id) { 96 return item; 97 } 98 } 99 return null; 100 } 101 102 final CarouselCallback mCarouselCallback = new CarouselCallback() { 103 104 public void onAnimationFinished() { 105 106 } 107 108 public void onAnimationStarted() { 109 110 } 111 112 public void onCardSelected(int n) { 113 if (n < mActivityDescriptions.size()) { 114 ActivityDescription item = mActivityDescriptions.get(n); 115 // prepare a launch intent and send it 116 if (item.intent != null) { 117 item.intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY); 118 try { 119 Log.v(TAG, "Starting intent " + item.intent); 120 startActivity(item.intent); 121 overridePendingTransition(R.anim.zoom_enter, R.anim.zoom_exit); 122 } catch (ActivityNotFoundException e) { 123 Log.w("Recent", "Unable to launch recent task", e); 124 } 125 finish(); 126 } 127 } 128 } 129 130 public void onInvalidateTexture(int n) { 131 132 } 133 134 public void onRequestDetailTexture(int n) { 135 if (DBG) Log.v(TAG, "onRequestDetailTexture(" + n + ")" ); 136 //mDetailTextureHandler.removeMessages(n); 137 //Message message = mDetailTextureHandler.obtainMessage(n, n, 0); 138 //mDetailTextureHandler.sendMessageDelayed(message, HOLDOFF_DELAY); 139 } 140 141 public void onInvalidateDetailTexture(int n) { 142 if (DBG) Log.v(TAG, "onInvalidateDetailTexture(" + n + ")"); 143 //mDetailTextureHandler.removeMessages(n); 144 } 145 146 public void onRequestGeometry(int n) { 147 148 } 149 150 public void onInvalidateGeometry(int n) { 151 152 } 153 154 public void onRequestTexture(final int n) { 155 Log.v(TAG, "onRequestTexture(" + n + ")"); 156 if (n < mActivityDescriptions.size()) { 157 mView.post(new Runnable() { 158 public void run() { 159 ActivityDescription desc = mActivityDescriptions.get(n); 160 if (desc != null) { 161 Log.v(TAG, "FOUND ACTIVITY THUMBNAIL " + desc.thumbnail); 162 Bitmap bitmap = desc.thumbnail == null ? mBlankBitmap : desc.thumbnail; 163 mView.setTextureForItem(n, bitmap); 164 } else { 165 Log.v(TAG, "FAILED TO GET ACTIVITY THUMBNAIL FOR ITEM " + n); 166 } 167 } 168 }); 169 } 170 } 171 172 public void onReportFirstCardPosition(int n) { 173 174 } 175 }; 176 177 private final IThumbnailReceiver mThumbnailReceiver = new IThumbnailReceiver.Stub() { 178 179 public void finished() throws RemoteException { 180 181 } 182 183 public void newThumbnail(final int id, final Bitmap bitmap, CharSequence description) 184 throws RemoteException { 185 int w = bitmap.getWidth(); 186 int h = bitmap.getHeight(); 187 Log.v(TAG, "New thumbnail for id=" + id + ", dimensions=" + w + "x" + h 188 + " description '" + description + "'"); 189 ActivityDescription info = findActivityDescription(id); 190 if (info != null) { 191 info.thumbnail = bitmap; 192 final int thumbWidth = bitmap.getWidth(); 193 final int thumbHeight = bitmap.getHeight(); 194 if ((mPortraitMode && thumbWidth > thumbHeight) 195 || (!mPortraitMode && thumbWidth < thumbHeight)) { 196 Matrix matrix = new Matrix(); 197 matrix.setRotate(90.0f, (float) thumbWidth / 2, (float) thumbHeight / 2); 198 info.matrix = matrix; 199 } else { 200 info.matrix = null; 201 } 202 } else { 203 Log.v(TAG, "Can't find view for id " + id); 204 } 205 } 206 }; 207 208 @Override 209 protected void onCreate(Bundle savedInstanceState) { 210 super.onCreate(savedInstanceState); 211 212 final Resources res = getResources(); 213 final View decorView = getWindow().getDecorView(); 214 215 mView = new MyCarouselView(this); 216 mView.setSlotCount(CARD_SLOTS); 217 mView.setVisibleSlots(VISIBLE_SLOTS); 218 mView.createCards(1); 219 mView.setStartAngle((float) -(2.0f*Math.PI * 5 / CARD_SLOTS)); 220 mView.setDefaultBitmap(BitmapFactory.decodeResource(res, R.drawable.wait)); 221 mView.setLoadingBitmap(BitmapFactory.decodeResource(res, R.drawable.wait)); 222 mView.setCallback(mCarouselCallback); 223 224 mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); 225 mPortraitMode = decorView.getHeight() > decorView.getWidth(); 226 227 refresh(); 228 229 setContentView(mView); 230 } 231 232 @Override 233 protected void onResume() { 234 super.onResume(); 235 refresh(); 236 } 237 238 @Override 239 public void onConfigurationChanged(Configuration newConfig) { 240 super.onConfigurationChanged(newConfig); 241 mPortraitMode = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT; 242 Log.v(TAG, "CONFIG CHANGE, mPortraitMode = " + mPortraitMode); 243 refresh(); 244 } 245 246 void updateRunningTasks() { 247 mRunningTaskList = mActivityManager.getRunningTasks(MAX_TASKS + 2, 0, mThumbnailReceiver); 248 Log.v(TAG, "Portrait: " + mPortraitMode); 249 for (RunningTaskInfo r : mRunningTaskList) { 250 if (r.thumbnail != null) { 251 int thumbWidth = r.thumbnail.getWidth(); 252 int thumbHeight = r.thumbnail.getHeight(); 253 Log.v(TAG, "Got thumbnail " + thumbWidth + "x" + thumbHeight); 254 ActivityDescription desc = findActivityDescription(r.id); 255 if (desc != null) { 256 desc.thumbnail = r.thumbnail; 257 desc.label = r.topActivity.flattenToShortString(); 258 if ((mPortraitMode && thumbWidth > thumbHeight) 259 || (!mPortraitMode && thumbWidth < thumbHeight)) { 260 Matrix matrix = new Matrix(); 261 matrix.setRotate(90.0f, (float) thumbWidth / 2, (float) thumbHeight / 2); 262 desc.matrix = matrix; 263 } 264 } else { 265 Log.v(TAG, "Couldn't find ActivityDesc for id=" + r.id); 266 } 267 } else { 268 Log.v(TAG, "*** RUNNING THUMBNAIL WAS NULL ***"); 269 } 270 } 271 // HACK refresh carousel 272 mView.createCards(mActivityDescriptions.size()); 273 } 274 275 private void updateRecentTasks() { 276 final PackageManager pm = getPackageManager(); 277 final ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); 278 279 final List<ActivityManager.RecentTaskInfo> recentTasks = 280 am.getRecentTasks(MAX_TASKS + 2, ActivityManager.RECENT_IGNORE_UNAVAILABLE); 281 282 ActivityInfo homeInfo = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME) 283 .resolveActivityInfo(pm, 0); 284 285 //IconUtilities iconUtilities = new IconUtilities(this); 286 287 int numTasks = recentTasks.size(); 288 mActivityDescriptions.clear(); 289 for (int i = 1, index = 0; i < numTasks && (index < MAX_TASKS + 2); ++i) { 290 final ActivityManager.RecentTaskInfo recentInfo = recentTasks.get(i); 291 292 Intent intent = new Intent(recentInfo.baseIntent); 293 if (recentInfo.origActivity != null) { 294 intent.setComponent(recentInfo.origActivity); 295 } 296 297 // Skip the current home activity. 298 if (homeInfo != null 299 && homeInfo.packageName.equals(intent.getComponent().getPackageName()) 300 && homeInfo.name.equals(intent.getComponent().getClassName())) { 301 continue; 302 } 303 304 intent.setFlags((intent.getFlags()&~Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) 305 | Intent.FLAG_ACTIVITY_NEW_TASK); 306 final ResolveInfo resolveInfo = pm.resolveActivity(intent, 0); 307 if (resolveInfo != null) { 308 final ActivityInfo info = resolveInfo.activityInfo; 309 final String title = info.loadLabel(pm).toString(); 310 Drawable icon = info.loadIcon(pm); 311 312 int id = recentTasks.get(i).id; 313 if (id != -1 && title != null && title.length() > 0 && icon != null) { 314 //icon = iconUtilities.createIconDrawable(icon); 315 ActivityDescription item = new ActivityDescription(null, icon, title, null, id); 316 item.intent = intent; 317 mActivityDescriptions.add(item); 318 Log.v(TAG, "Added item[" + index + "], id=" + item.id); 319 ++index; 320 } else { 321 Log.v(TAG, "SKIPPING item " + id); 322 } 323 } 324 } 325 } 326 327 private void refresh() { 328 updateRecentTasks(); 329 updateRunningTasks(); 330 mView.createCards(mActivityDescriptions.size()); 331 } 332} 333