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