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