blob: cd3bc425000047e9cc29c41ebc0e97da35baefb2 [file] [log] [blame]
Jim Miller44c66fe2010-10-20 18:32:52 -07001/*
Jim Miller9f0f0e02011-05-17 20:06:29 -07002 * Copyright (C) 2011 The Android Open Source Project
Jim Miller44c66fe2010-10-20 18:32:52 -07003 *
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
Jim Miller9f0f0e02011-05-17 20:06:29 -070017package com.android.systemui.recent;
Jim Miller44c66fe2010-10-20 18:32:52 -070018
Michael Jurka3b1fc472011-06-13 10:54:40 -070019import android.animation.Animator;
Jim Miller9f0f0e02011-05-17 20:06:29 -070020import android.animation.LayoutTransition;
Michael Jurka9bdaada2012-10-01 13:58:29 +020021import android.animation.TimeInterpolator;
Jim Miller44c66fe2010-10-20 18:32:52 -070022import android.app.ActivityManager;
Michael Jurka56a57832012-05-14 13:24:43 -070023import android.app.ActivityManagerNative;
Dianne Hackborn8078d8c2012-03-20 11:11:26 -070024import android.app.ActivityOptions;
Adam Powell0fc5b2b2012-07-18 18:20:29 -070025import android.app.TaskStackBuilder;
Jim Miller44c66fe2010-10-20 18:32:52 -070026import android.content.Context;
27import android.content.Intent;
Michael Jurka9bdaada2012-10-01 13:58:29 +020028import android.content.res.Configuration;
Michael Jurkabfd24ac2011-11-13 13:50:38 -080029import android.content.res.Resources;
Daniel Sandler4a066c52012-04-20 14:49:13 -040030import android.content.res.TypedArray;
Jim Miller44c66fe2010-10-20 18:32:52 -070031import android.graphics.Bitmap;
Jim Millerfefef312010-11-09 14:08:39 -080032import android.graphics.Matrix;
Jim Millere5c16ab2010-12-03 19:18:38 -080033import android.graphics.Shader.TileMode;
34import android.graphics.drawable.BitmapDrawable;
Michael Jurka99a96552012-01-27 17:23:38 -080035import android.graphics.drawable.Drawable;
Jim Millerc0d27312011-07-14 18:54:01 -070036import android.net.Uri;
Michael Jurka482f1592012-09-13 11:05:59 -070037import android.os.Bundle;
Michael Jurka56a57832012-05-14 13:24:43 -070038import android.os.RemoteException;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070039import android.os.UserHandle;
Jim Millerc0d27312011-07-14 18:54:01 -070040import android.provider.Settings;
Jim Miller44c66fe2010-10-20 18:32:52 -070041import android.util.AttributeSet;
42import android.util.Log;
Jim Miller5fda69c2011-02-16 15:17:11 -080043import android.view.LayoutInflater;
Jim Millerc0d27312011-07-14 18:54:01 -070044import android.view.MenuItem;
Svetoslav Ganov6179ea32011-06-28 01:12:41 -070045import android.view.MotionEvent;
Jim Miller44c66fe2010-10-20 18:32:52 -070046import android.view.View;
Jim Miller5fda69c2011-02-16 15:17:11 -080047import android.view.ViewGroup;
Jim Miller17377762011-10-11 15:33:34 -070048import android.view.accessibility.AccessibilityEvent;
Dianne Hackbornfc8fa632011-08-17 16:20:47 -070049import android.view.animation.AnimationUtils;
Michael Jurka9bdaada2012-10-01 13:58:29 +020050import android.view.animation.DecelerateInterpolator;
Jim Miller5fda69c2011-02-16 15:17:11 -080051import android.widget.AdapterView;
Michael Jurkabfd24ac2011-11-13 13:50:38 -080052import android.widget.AdapterView.OnItemClickListener;
Jim Miller5fda69c2011-02-16 15:17:11 -080053import android.widget.BaseAdapter;
Michael Jurka99a96552012-01-27 17:23:38 -080054import android.widget.FrameLayout;
Jim Miller44c66fe2010-10-20 18:32:52 -070055import android.widget.ImageView;
Michael Jurkabfd24ac2011-11-13 13:50:38 -080056import android.widget.ImageView.ScaleType;
Jim Millerc0d27312011-07-14 18:54:01 -070057import android.widget.PopupMenu;
Jim Miller44c66fe2010-10-20 18:32:52 -070058import android.widget.TextView;
Jim Miller44c66fe2010-10-20 18:32:52 -070059
60import com.android.systemui.R;
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -050061import com.android.systemui.statusbar.BaseStatusBar;
Michael Jurka3b1fc472011-06-13 10:54:40 -070062import com.android.systemui.statusbar.phone.PhoneStatusBar;
Jim Miller9f0f0e02011-05-17 20:06:29 -070063import com.android.systemui.statusbar.tablet.StatusBarPanel;
64import com.android.systemui.statusbar.tablet.TabletStatusBar;
Jim Miller44c66fe2010-10-20 18:32:52 -070065
Michael Jurkabfd24ac2011-11-13 13:50:38 -080066import java.util.ArrayList;
67
Michael Jurka99a96552012-01-27 17:23:38 -080068public class RecentsPanelView extends FrameLayout implements OnItemClickListener, RecentsCallback,
Michael Jurka80343f62012-10-18 13:13:46 +020069 StatusBarPanel, Animator.AnimatorListener {
Michael Jurka3cd0a592011-08-16 12:40:30 -070070 static final String TAG = "RecentsPanelView";
Dianne Hackbornfc8fa632011-08-17 16:20:47 -070071 static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false;
Michael Jurkacb466432012-04-03 05:22:45 -070072 private PopupMenu mPopup;
Jim Miller85babff2011-01-11 14:26:03 -080073 private View mRecentsScrim;
Michael Jurka6d667082011-09-16 17:04:40 -070074 private View mRecentsNoApps;
Jim Millerc0d27312011-07-14 18:54:01 -070075 private ViewGroup mRecentsContainer;
Daniel Sandler328310c2011-09-23 15:56:52 -040076 private StatusBarTouchProxy mStatusBarTouchProxy;
Peter Ng622a9762011-08-29 10:56:53 -070077
Jim Miller85babff2011-01-11 14:26:03 -080078 private boolean mShowing;
Michael Jurka99a96552012-01-27 17:23:38 -080079 private boolean mWaitingToShow;
Michael Jurka99a96552012-01-27 17:23:38 -080080 private int mNumItemsWaitingForThumbnailsAndIcons;
Michael Jurka9bdaada2012-10-01 13:58:29 +020081 private ViewHolder mItemToAnimateInWhenWindowAnimationIsFinished;
Michael Jurka80343f62012-10-18 13:13:46 +020082 private boolean mWaitingForWindowAnimation;
Michael Jurka21385cd2012-05-03 10:57:31 -070083
Michael Jurkaab48b682011-09-12 15:39:45 -070084 private RecentTasksLoader mRecentTasksLoader;
85 private ArrayList<TaskDescription> mRecentTaskDescriptions;
86 private TaskDescriptionAdapter mListAdapter;
87 private int mThumbnailWidth;
Michael Jurkabfd24ac2011-11-13 13:50:38 -080088 private boolean mFitThumbnailToXY;
Daniel Sandler4a066c52012-04-20 14:49:13 -040089 private int mRecentItemLayoutId;
Michael Jurkac016aaa2012-06-05 17:22:24 -070090 private boolean mHighEndGfx;
Dianne Hackborneeb1dca2011-09-08 13:30:11 -070091
Michael Jurka4eaa9832012-02-29 15:51:49 -080092 public static interface RecentsScrollView {
93 public int numItemsInOneScreenful();
94 public void setAdapter(TaskDescriptionAdapter adapter);
95 public void setCallback(RecentsCallback callback);
96 public void setMinSwipeAlpha(float minAlpha);
Michael Jurkae5923632012-10-03 15:29:36 +020097 public View findViewForTask(int persistentTaskId);
Michael Jurka4eaa9832012-02-29 15:51:49 -080098 }
99
Jim Millerc0d27312011-07-14 18:54:01 -0700100 private final class OnLongClickDelegate implements View.OnLongClickListener {
101 View mOtherView;
102 OnLongClickDelegate(View other) {
103 mOtherView = other;
104 }
105 public boolean onLongClick(View v) {
106 return mOtherView.performLongClick();
107 }
108 }
109
Jim Millerb5a2b292011-03-01 16:14:59 -0800110 /* package */ final static class ViewHolder {
Jim Millerc0d27312011-07-14 18:54:01 -0700111 View thumbnailView;
Dianne Hackbornfc8fa632011-08-17 16:20:47 -0700112 ImageView thumbnailViewImage;
Michael Jurka412cba82011-10-17 09:05:00 -0700113 Bitmap thumbnailViewImageBitmap;
Jim Miller9f0f0e02011-05-17 20:06:29 -0700114 ImageView iconView;
115 TextView labelView;
116 TextView descriptionView;
Michael Jurka9bdaada2012-10-01 13:58:29 +0200117 View calloutLine;
Michael Jurkaab48b682011-09-12 15:39:45 -0700118 TaskDescription taskDescription;
Michael Jurka99a96552012-01-27 17:23:38 -0800119 boolean loadedThumbnailAndIcon;
Jim Miller5fda69c2011-02-16 15:17:11 -0800120 }
121
Michael Jurkaab48b682011-09-12 15:39:45 -0700122 /* package */ final class TaskDescriptionAdapter extends BaseAdapter {
Jim Miller5fda69c2011-02-16 15:17:11 -0800123 private LayoutInflater mInflater;
124
Michael Jurkaab48b682011-09-12 15:39:45 -0700125 public TaskDescriptionAdapter(Context context) {
Jim Miller5fda69c2011-02-16 15:17:11 -0800126 mInflater = LayoutInflater.from(context);
127 }
128
129 public int getCount() {
Michael Jurkaab48b682011-09-12 15:39:45 -0700130 return mRecentTaskDescriptions != null ? mRecentTaskDescriptions.size() : 0;
Jim Miller5fda69c2011-02-16 15:17:11 -0800131 }
132
133 public Object getItem(int position) {
134 return position; // we only need the index
135 }
136
137 public long getItemId(int position) {
138 return position; // we just need something unique for this position
139 }
140
Michael Jurka99a96552012-01-27 17:23:38 -0800141 public View createView(ViewGroup parent) {
Daniel Sandler4a066c52012-04-20 14:49:13 -0400142 View convertView = mInflater.inflate(mRecentItemLayoutId, parent, false);
Michael Jurka99a96552012-01-27 17:23:38 -0800143 ViewHolder holder = new ViewHolder();
144 holder.thumbnailView = convertView.findViewById(R.id.app_thumbnail);
145 holder.thumbnailViewImage =
146 (ImageView) convertView.findViewById(R.id.app_thumbnail_image);
147 // If we set the default thumbnail now, we avoid an onLayout when we update
148 // the thumbnail later (if they both have the same dimensions)
Michael Jurka80343f62012-10-18 13:13:46 +0200149 updateThumbnail(holder, mRecentTasksLoader.getDefaultThumbnail(), false, false);
Michael Jurka99a96552012-01-27 17:23:38 -0800150 holder.iconView = (ImageView) convertView.findViewById(R.id.app_icon);
Michael Jurka80343f62012-10-18 13:13:46 +0200151 holder.iconView.setImageBitmap(mRecentTasksLoader.getDefaultIcon());
Michael Jurka99a96552012-01-27 17:23:38 -0800152 holder.labelView = (TextView) convertView.findViewById(R.id.app_label);
Michael Jurka9bdaada2012-10-01 13:58:29 +0200153 holder.calloutLine = convertView.findViewById(R.id.recents_callout_line);
Michael Jurka99a96552012-01-27 17:23:38 -0800154 holder.descriptionView = (TextView) convertView.findViewById(R.id.app_description);
155
156 convertView.setTag(holder);
157 return convertView;
158 }
159
160 public View getView(int position, View convertView, ViewGroup parent) {
161 if (convertView == null) {
162 convertView = createView(parent);
163 }
164 ViewHolder holder = (ViewHolder) convertView.getTag();
Jim Miller5fda69c2011-02-16 15:17:11 -0800165
Michael Jurkaab48b682011-09-12 15:39:45 -0700166 // index is reverse since most recent appears at the bottom...
167 final int index = mRecentTaskDescriptions.size() - position - 1;
Jim Miller5fda69c2011-02-16 15:17:11 -0800168
Michael Jurka412cba82011-10-17 09:05:00 -0700169 final TaskDescription td = mRecentTaskDescriptions.get(index);
Michael Jurka99a96552012-01-27 17:23:38 -0800170
Michael Jurka412cba82011-10-17 09:05:00 -0700171 holder.labelView.setText(td.getLabel());
172 holder.thumbnailView.setContentDescription(td.getLabel());
Michael Jurka99a96552012-01-27 17:23:38 -0800173 holder.loadedThumbnailAndIcon = td.isLoaded();
174 if (td.isLoaded()) {
175 updateThumbnail(holder, td.getThumbnail(), true, false);
176 updateIcon(holder, td.getIcon(), true, false);
177 mNumItemsWaitingForThumbnailsAndIcons--;
178 }
Michael Jurka9bdaada2012-10-01 13:58:29 +0200179 if (index == 0) {
Michael Jurka80343f62012-10-18 13:13:46 +0200180 if (mWaitingForWindowAnimation) {
Michael Jurkaa9240762012-10-17 13:02:55 +0200181 if (mItemToAnimateInWhenWindowAnimationIsFinished != null) {
Michael Jurkafe09ad82012-10-22 13:58:38 -0700182 holder.iconView.setAlpha(1f);
183 holder.iconView.setTranslationX(0f);
184 holder.iconView.setTranslationY(0f);
185 holder.labelView.setAlpha(1f);
186 holder.labelView.setTranslationX(0f);
187 holder.labelView.setTranslationY(0f);
188 if (holder.calloutLine != null) {
189 holder.calloutLine.setAlpha(1f);
190 holder.calloutLine.setTranslationX(0f);
191 holder.calloutLine.setTranslationY(0f);
Michael Jurkaa9240762012-10-17 13:02:55 +0200192 }
193 }
Michael Jurka9bdaada2012-10-01 13:58:29 +0200194 mItemToAnimateInWhenWindowAnimationIsFinished = holder;
195 final int translation = -getResources().getDimensionPixelSize(
196 R.dimen.status_bar_recents_app_icon_translate_distance);
197 final Configuration config = getResources().getConfiguration();
198 if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
Michael Jurkafe09ad82012-10-22 13:58:38 -0700199 holder.iconView.setAlpha(0f);
200 holder.iconView.setTranslationX(translation);
201 holder.labelView.setAlpha(0f);
202 holder.labelView.setTranslationX(translation);
203 holder.calloutLine.setAlpha(0f);
204 holder.calloutLine.setTranslationX(translation);
Michael Jurka9bdaada2012-10-01 13:58:29 +0200205 } else {
206 holder.iconView.setAlpha(0f);
207 holder.iconView.setTranslationY(translation);
208 }
209 }
210 }
Michael Jurkaab48b682011-09-12 15:39:45 -0700211
Michael Jurka412cba82011-10-17 09:05:00 -0700212 holder.thumbnailView.setTag(td);
Jim Millerc0d27312011-07-14 18:54:01 -0700213 holder.thumbnailView.setOnLongClickListener(new OnLongClickDelegate(convertView));
Michael Jurka412cba82011-10-17 09:05:00 -0700214 holder.taskDescription = td;
Jim Miller5fda69c2011-02-16 15:17:11 -0800215 return convertView;
216 }
Michael Jurka99a96552012-01-27 17:23:38 -0800217
218 public void recycleView(View v) {
219 ViewHolder holder = (ViewHolder) v.getTag();
220 updateThumbnail(holder, mRecentTasksLoader.getDefaultThumbnail(), false, false);
221 holder.iconView.setImageBitmap(mRecentTasksLoader.getDefaultIcon());
222 holder.iconView.setVisibility(INVISIBLE);
223 holder.labelView.setText(null);
224 holder.thumbnailView.setContentDescription(null);
225 holder.thumbnailView.setTag(null);
226 holder.thumbnailView.setOnLongClickListener(null);
227 holder.thumbnailView.setVisibility(INVISIBLE);
Michael Jurkafe09ad82012-10-22 13:58:38 -0700228 holder.iconView.setAlpha(1f);
229 holder.iconView.setTranslationX(0f);
230 holder.iconView.setTranslationY(0f);
231 holder.labelView.setAlpha(1f);
232 holder.labelView.setTranslationX(0f);
233 holder.labelView.setTranslationY(0f);
234 if (holder.calloutLine != null) {
235 holder.calloutLine.setAlpha(1f);
236 holder.calloutLine.setTranslationX(0f);
237 holder.calloutLine.setTranslationY(0f);
238 }
Michael Jurka99a96552012-01-27 17:23:38 -0800239 holder.taskDescription = null;
240 holder.loadedThumbnailAndIcon = false;
241 }
242 }
243
Michael Jurka8b2e37e2012-05-08 20:06:13 -0700244 public RecentsPanelView(Context context, AttributeSet attrs) {
245 this(context, attrs, 0);
246 }
247
248 public RecentsPanelView(Context context, AttributeSet attrs, int defStyle) {
249 super(context, attrs, defStyle);
Michael Jurka8b2e37e2012-05-08 20:06:13 -0700250 updateValuesFromResources();
251
252 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RecentsPanelView,
253 defStyle, 0);
254
255 mRecentItemLayoutId = a.getResourceId(R.styleable.RecentsPanelView_recentItemLayout, 0);
Michael Jurka80343f62012-10-18 13:13:46 +0200256 mRecentTasksLoader = RecentTasksLoader.getInstance(context);
Michael Jurka8b2e37e2012-05-08 20:06:13 -0700257 a.recycle();
258 }
259
Michael Jurka99a96552012-01-27 17:23:38 -0800260 public int numItemsInOneScreenful() {
Michael Jurka4eaa9832012-02-29 15:51:49 -0800261 if (mRecentsContainer instanceof RecentsScrollView){
262 RecentsScrollView scrollView
263 = (RecentsScrollView) mRecentsContainer;
Michael Jurka99a96552012-01-27 17:23:38 -0800264 return scrollView.numItemsInOneScreenful();
Michael Jurka4eaa9832012-02-29 15:51:49 -0800265 } else {
Michael Jurka99a96552012-01-27 17:23:38 -0800266 throw new IllegalArgumentException("missing Recents[Horizontal]ScrollView");
267 }
Jim Miller5fda69c2011-02-16 15:17:11 -0800268 }
269
Daniel Sandler328310c2011-09-23 15:56:52 -0400270 private boolean pointInside(int x, int y, View v) {
271 final int l = v.getLeft();
272 final int r = v.getRight();
273 final int t = v.getTop();
274 final int b = v.getBottom();
Jim Miller44c66fe2010-10-20 18:32:52 -0700275 return x >= l && x < r && y >= t && y < b;
276 }
277
Daniel Sandler328310c2011-09-23 15:56:52 -0400278 public boolean isInContentArea(int x, int y) {
Michael Jurkab144bd72012-01-12 06:56:39 -0800279 if (pointInside(x, y, mRecentsContainer)) {
280 return true;
281 } else if (mStatusBarTouchProxy != null &&
282 pointInside(x, y, mStatusBarTouchProxy)) {
283 return true;
284 } else {
285 return false;
286 }
Daniel Sandler328310c2011-09-23 15:56:52 -0400287 }
288
Michael Jurkacb2522c2012-04-13 09:32:47 -0700289 public void show(boolean show) {
Michael Jurka80343f62012-10-18 13:13:46 +0200290 show(show, null, false, false);
Michael Jurkacb2522c2012-04-13 09:32:47 -0700291 }
292
293 public void show(boolean show, ArrayList<TaskDescription> recentTaskDescriptions,
Michael Jurka80343f62012-10-18 13:13:46 +0200294 boolean firstScreenful, boolean waitingForWindowAnimation) {
295 mWaitingForWindowAnimation = waitingForWindowAnimation;
Michael Jurka99a96552012-01-27 17:23:38 -0800296 if (show) {
297 mWaitingToShow = true;
Michael Jurkacb2522c2012-04-13 09:32:47 -0700298 refreshRecentTasksList(recentTaskDescriptions, firstScreenful);
Michael Jurka99a96552012-01-27 17:23:38 -0800299 showIfReady();
300 } else {
Michael Jurkacb2522c2012-04-13 09:32:47 -0700301 showImpl(false);
Michael Jurka99a96552012-01-27 17:23:38 -0800302 }
303 }
304
305 private void showIfReady() {
Michael Jurkacb2522c2012-04-13 09:32:47 -0700306 // mWaitingToShow => there was a touch up on the recents button
307 // mRecentTaskDescriptions != null => we've created views for the first screenful of items
308 if (mWaitingToShow && mRecentTaskDescriptions != null) {
309 showImpl(true);
Michael Jurka99a96552012-01-27 17:23:38 -0800310 }
Michael Jurkaab48b682011-09-12 15:39:45 -0700311 }
312
Michael Jurka56a57832012-05-14 13:24:43 -0700313 static void sendCloseSystemWindows(Context context, String reason) {
314 if (ActivityManagerNative.isSystemReady()) {
315 try {
316 ActivityManagerNative.getDefault().closeSystemDialogs(reason);
317 } catch (RemoteException e) {
318 }
319 }
320 }
321
Michael Jurkacb2522c2012-04-13 09:32:47 -0700322 private void showImpl(boolean show) {
Michael Jurka56a57832012-05-14 13:24:43 -0700323 sendCloseSystemWindows(mContext, BaseStatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS);
324
Michael Jurkacb2522c2012-04-13 09:32:47 -0700325 mShowing = show;
326
Michael Jurka7daf95d2011-09-30 11:07:30 -0700327 if (show) {
Michael Jurkacb2522c2012-04-13 09:32:47 -0700328 // if there are no apps, bring up a "No recent apps" message
329 boolean noApps = mRecentTaskDescriptions != null
330 && (mRecentTaskDescriptions.size() == 0);
331 mRecentsNoApps.setAlpha(1f);
332 mRecentsNoApps.setVisibility(noApps ? View.VISIBLE : View.INVISIBLE);
Michael Jurka7daf95d2011-09-30 11:07:30 -0700333
Michael Jurkaab48b682011-09-12 15:39:45 -0700334 onAnimationEnd(null);
Michael Jurkae9166ed2011-07-27 18:23:18 -0700335 setFocusable(true);
336 setFocusableInTouchMode(true);
337 requestFocus();
Michael Jurkacb466432012-04-03 05:22:45 -0700338 } else {
Michael Jurkacb2522c2012-04-13 09:32:47 -0700339 mWaitingToShow = false;
340 // call onAnimationEnd() and clearRecentTasksList() in onUiHidden()
Michael Jurkacb466432012-04-03 05:22:45 -0700341 if (mPopup != null) {
342 mPopup.dismiss();
343 }
Michael Jurkae9166ed2011-07-27 18:23:18 -0700344 }
Jim Miller85babff2011-01-11 14:26:03 -0800345 }
346
Michael Jurkacb2522c2012-04-13 09:32:47 -0700347 public void onUiHidden() {
348 if (!mShowing && mRecentTaskDescriptions != null) {
349 onAnimationEnd(null);
350 clearRecentTasksList();
351 }
Michael Jurkac6461ca2011-09-02 12:12:15 -0700352 }
353
Michael Jurkacb2522c2012-04-13 09:32:47 -0700354 public void dismiss() {
355 ((RecentsActivity) mContext).dismissAndGoHome();
356 }
357
358 public void dismissAndGoBack() {
359 ((RecentsActivity) mContext).dismissAndGoBack();
Michael Jurka8b098662011-09-01 17:00:53 -0700360 }
361
Michael Jurka3b1fc472011-06-13 10:54:40 -0700362 public void onAnimationCancel(Animator animation) {
363 }
364
365 public void onAnimationEnd(Animator animation) {
366 if (mShowing) {
367 final LayoutTransition transitioner = new LayoutTransition();
368 ((ViewGroup)mRecentsContainer).setLayoutTransition(transitioner);
369 createCustomAnimations(transitioner);
370 } else {
371 ((ViewGroup)mRecentsContainer).setLayoutTransition(null);
372 }
373 }
374
375 public void onAnimationRepeat(Animator animation) {
376 }
377
378 public void onAnimationStart(Animator animation) {
379 }
380
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700381 @Override
382 public boolean dispatchHoverEvent(MotionEvent event) {
383 // Ignore hover events outside of this panel bounds since such events
384 // generate spurious accessibility events with the panel content when
385 // tapping outside of it, thus confusing the user.
386 final int x = (int) event.getX();
387 final int y = (int) event.getY();
388 if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) {
389 return super.dispatchHoverEvent(event);
390 }
391 return true;
392 }
393
Jim Miller85babff2011-01-11 14:26:03 -0800394 /**
395 * Whether the panel is showing, or, if it's animating, whether it will be
396 * when the animation is done.
397 */
398 public boolean isShowing() {
399 return mShowing;
400 }
401
Daniel Sandler328310c2011-09-23 15:56:52 -0400402 public void setStatusBarView(View statusBarView) {
403 if (mStatusBarTouchProxy != null) {
404 mStatusBarTouchProxy.setStatusBar(statusBarView);
405 }
406 }
407
408 public void setRecentTasksLoader(RecentTasksLoader loader) {
409 mRecentTasksLoader = loader;
410 }
411
Michael Jurkaab48b682011-09-12 15:39:45 -0700412 public void updateValuesFromResources() {
Michael Jurkabfd24ac2011-11-13 13:50:38 -0800413 final Resources res = mContext.getResources();
414 mThumbnailWidth = Math.round(res.getDimension(R.dimen.status_bar_recents_thumbnail_width));
415 mFitThumbnailToXY = res.getBoolean(R.bool.config_recents_thumbnail_image_fits_to_xy);
Jim Miller44c66fe2010-10-20 18:32:52 -0700416 }
417
418 @Override
419 protected void onFinishInflate() {
420 super.onFinishInflate();
Daniel Sandler4a066c52012-04-20 14:49:13 -0400421
Jim Millerc0d27312011-07-14 18:54:01 -0700422 mRecentsContainer = (ViewGroup) findViewById(R.id.recents_container);
Daniel Sandler328310c2011-09-23 15:56:52 -0400423 mStatusBarTouchProxy = (StatusBarTouchProxy) findViewById(R.id.status_bar_touch_proxy);
Michael Jurkaab48b682011-09-12 15:39:45 -0700424 mListAdapter = new TaskDescriptionAdapter(mContext);
Michael Jurka4eaa9832012-02-29 15:51:49 -0800425 if (mRecentsContainer instanceof RecentsScrollView){
426 RecentsScrollView scrollView
427 = (RecentsScrollView) mRecentsContainer;
Jim Miller9f0f0e02011-05-17 20:06:29 -0700428 scrollView.setAdapter(mListAdapter);
429 scrollView.setCallback(this);
Michael Jurka4eaa9832012-02-29 15:51:49 -0800430 } else {
Michael Jurka3cd0a592011-08-16 12:40:30 -0700431 throw new IllegalArgumentException("missing Recents[Horizontal]ScrollView");
Jim Miller9f0f0e02011-05-17 20:06:29 -0700432 }
Jim Miller5fda69c2011-02-16 15:17:11 -0800433
Michael Jurka6d667082011-09-16 17:04:40 -0700434 mRecentsScrim = findViewById(R.id.recents_bg_protect);
435 mRecentsNoApps = findViewById(R.id.recents_no_apps);
Jim Millere5c16ab2010-12-03 19:18:38 -0800436
Michael Jurkaf16fc512012-02-27 15:02:23 -0800437 if (mRecentsScrim != null) {
Jeff Brown98365d72012-08-19 20:30:52 -0700438 mHighEndGfx = ActivityManager.isHighEndGfx();
Michael Jurkac016aaa2012-06-05 17:22:24 -0700439 if (!mHighEndGfx) {
Michael Jurkad5895a72012-05-12 13:24:58 -0700440 mRecentsScrim.setBackground(null);
Michael Jurkaf16fc512012-02-27 15:02:23 -0800441 } else if (mRecentsScrim.getBackground() instanceof BitmapDrawable) {
442 // In order to save space, we make the background texture repeat in the Y direction
443 ((BitmapDrawable) mRecentsScrim.getBackground()).setTileModeY(TileMode.REPEAT);
444 }
Jim Millere5c16ab2010-12-03 19:18:38 -0800445 }
446 }
447
Michael Jurka4eaa9832012-02-29 15:51:49 -0800448 public void setMinSwipeAlpha(float minAlpha) {
449 if (mRecentsContainer instanceof RecentsScrollView){
450 RecentsScrollView scrollView
451 = (RecentsScrollView) mRecentsContainer;
452 scrollView.setMinSwipeAlpha(minAlpha);
453 }
454 }
455
Jim Miller9f0f0e02011-05-17 20:06:29 -0700456 private void createCustomAnimations(LayoutTransition transitioner) {
Chet Haase212f6252011-08-12 09:19:10 -0700457 transitioner.setDuration(200);
458 transitioner.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);
459 transitioner.setAnimator(LayoutTransition.DISAPPEARING, null);
Jim Miller9f0f0e02011-05-17 20:06:29 -0700460 }
461
Michael Jurka99a96552012-01-27 17:23:38 -0800462 private void updateIcon(ViewHolder h, Drawable icon, boolean show, boolean anim) {
463 if (icon != null) {
464 h.iconView.setImageDrawable(icon);
465 if (show && h.iconView.getVisibility() != View.VISIBLE) {
466 if (anim) {
467 h.iconView.setAnimation(
468 AnimationUtils.loadAnimation(mContext, R.anim.recent_appear));
469 }
470 h.iconView.setVisibility(View.VISIBLE);
471 }
472 }
473 }
474
Michael Jurka412cba82011-10-17 09:05:00 -0700475 private void updateThumbnail(ViewHolder h, Bitmap thumbnail, boolean show, boolean anim) {
Michael Jurkaab48b682011-09-12 15:39:45 -0700476 if (thumbnail != null) {
477 // Should remove the default image in the frame
478 // that this now covers, to improve scrolling speed.
479 // That can't be done until the anim is complete though.
480 h.thumbnailViewImage.setImageBitmap(thumbnail);
Michael Jurka412cba82011-10-17 09:05:00 -0700481
482 // scale the image to fill the full width of the ImageView. do this only if
483 // we haven't set a bitmap before, or if the bitmap size has changed
484 if (h.thumbnailViewImageBitmap == null ||
485 h.thumbnailViewImageBitmap.getWidth() != thumbnail.getWidth() ||
486 h.thumbnailViewImageBitmap.getHeight() != thumbnail.getHeight()) {
Michael Jurkabfd24ac2011-11-13 13:50:38 -0800487 if (mFitThumbnailToXY) {
488 h.thumbnailViewImage.setScaleType(ScaleType.FIT_XY);
489 } else {
490 Matrix scaleMatrix = new Matrix();
491 float scale = mThumbnailWidth / (float) thumbnail.getWidth();
492 scaleMatrix.setScale(scale, scale);
493 h.thumbnailViewImage.setScaleType(ScaleType.MATRIX);
494 h.thumbnailViewImage.setImageMatrix(scaleMatrix);
495 }
Jim Miller44c66fe2010-10-20 18:32:52 -0700496 }
Michael Jurka412cba82011-10-17 09:05:00 -0700497 if (show && h.thumbnailView.getVisibility() != View.VISIBLE) {
498 if (anim) {
499 h.thumbnailView.setAnimation(
500 AnimationUtils.loadAnimation(mContext, R.anim.recent_appear));
501 }
502 h.thumbnailView.setVisibility(View.VISIBLE);
503 }
504 h.thumbnailViewImageBitmap = thumbnail;
Jim Miller44c66fe2010-10-20 18:32:52 -0700505 }
Jim Millerfefef312010-11-09 14:08:39 -0800506 }
507
Michael Jurka99a96552012-01-27 17:23:38 -0800508 void onTaskThumbnailLoaded(TaskDescription td) {
509 synchronized (td) {
Dianne Hackbornfc8fa632011-08-17 16:20:47 -0700510 if (mRecentsContainer != null) {
511 ViewGroup container = mRecentsContainer;
Michael Jurka4eaa9832012-02-29 15:51:49 -0800512 if (container instanceof RecentsScrollView) {
Michael Jurka99a96552012-01-27 17:23:38 -0800513 container = (ViewGroup) container.findViewById(
Dianne Hackbornfc8fa632011-08-17 16:20:47 -0700514 R.id.recents_linear_layout);
515 }
516 // Look for a view showing this thumbnail, to update.
Michael Jurka99a96552012-01-27 17:23:38 -0800517 for (int i=0; i < container.getChildCount(); i++) {
Dianne Hackbornfc8fa632011-08-17 16:20:47 -0700518 View v = container.getChildAt(i);
519 if (v.getTag() instanceof ViewHolder) {
520 ViewHolder h = (ViewHolder)v.getTag();
Michael Jurka99a96552012-01-27 17:23:38 -0800521 if (!h.loadedThumbnailAndIcon && h.taskDescription == td) {
Michael Jurka412cba82011-10-17 09:05:00 -0700522 // only fade in the thumbnail if recents is already visible-- we
523 // show it immediately otherwise
Michael Jurka99a96552012-01-27 17:23:38 -0800524 //boolean animateShow = mShowing &&
525 // mRecentsContainer.getAlpha() > ViewConfiguration.ALPHA_THRESHOLD;
526 boolean animateShow = false;
527 updateIcon(h, td.getIcon(), true, animateShow);
528 updateThumbnail(h, td.getThumbnail(), true, animateShow);
529 h.loadedThumbnailAndIcon = true;
530 mNumItemsWaitingForThumbnailsAndIcons--;
Dianne Hackbornfc8fa632011-08-17 16:20:47 -0700531 }
532 }
533 }
534 }
Craig Mautnerca6da002012-09-20 14:54:37 -0700535 }
Michael Jurka99a96552012-01-27 17:23:38 -0800536 showIfReady();
Dianne Hackbornfc8fa632011-08-17 16:20:47 -0700537 }
538
Michael Jurka9bdaada2012-10-01 13:58:29 +0200539 public void onWindowAnimationStart() {
540 if (mItemToAnimateInWhenWindowAnimationIsFinished != null) {
Michael Jurka071316e2012-10-10 00:00:21 +0200541 final int startDelay = 150;
Michael Jurka9bdaada2012-10-01 13:58:29 +0200542 final int duration = 250;
543 final ViewHolder holder = mItemToAnimateInWhenWindowAnimationIsFinished;
544 final TimeInterpolator cubic = new DecelerateInterpolator(1.5f);
545 for (View v :
546 new View[] { holder.iconView, holder.labelView, holder.calloutLine }) {
547 if (v != null) {
548 v.animate().translationX(0).translationY(0).alpha(1f).setStartDelay(startDelay)
549 .setDuration(duration).setInterpolator(cubic);
550 }
551 }
552 mItemToAnimateInWhenWindowAnimationIsFinished = null;
Michael Jurka80343f62012-10-18 13:13:46 +0200553 mWaitingForWindowAnimation = false;
Michael Jurka9bdaada2012-10-01 13:58:29 +0200554 }
555 }
556
Michael Jurka412cba82011-10-17 09:05:00 -0700557 public void clearRecentTasksList() {
558 // Clear memory used by screenshots
Michael Jurkacb2522c2012-04-13 09:32:47 -0700559 if (mRecentTaskDescriptions != null) {
560 mRecentTasksLoader.cancelLoadingThumbnailsAndIcons(this);
561 onTaskLoadingCancelled();
562 }
563 }
564
565 public void onTaskLoadingCancelled() {
566 // Gets called by RecentTasksLoader when it's cancelled
567 if (mRecentTaskDescriptions != null) {
568 mRecentTaskDescriptions = null;
Michael Jurka412cba82011-10-17 09:05:00 -0700569 mListAdapter.notifyDataSetInvalidated();
Michael Jurka412cba82011-10-17 09:05:00 -0700570 }
571 }
572
Craig Mautnerca6da002012-09-20 14:54:37 -0700573 public void refreshViews() {
574 mListAdapter.notifyDataSetInvalidated();
575 updateUiElements();
576 showIfReady();
577 }
578
Michael Jurka412cba82011-10-17 09:05:00 -0700579 public void refreshRecentTasksList() {
Michael Jurka99a96552012-01-27 17:23:38 -0800580 refreshRecentTasksList(null, false);
Michael Jurka412cba82011-10-17 09:05:00 -0700581 }
582
Michael Jurka99a96552012-01-27 17:23:38 -0800583 private void refreshRecentTasksList(
584 ArrayList<TaskDescription> recentTasksList, boolean firstScreenful) {
Michael Jurkacb2522c2012-04-13 09:32:47 -0700585 if (mRecentTaskDescriptions == null && recentTasksList != null) {
586 onTasksLoaded(recentTasksList, firstScreenful);
587 } else {
588 mRecentTasksLoader.loadTasksInBackground();
Michael Jurka412cba82011-10-17 09:05:00 -0700589 }
Michael Jurkaab48b682011-09-12 15:39:45 -0700590 }
Michael Jurka7daf95d2011-09-30 11:07:30 -0700591
Michael Jurkacb2522c2012-04-13 09:32:47 -0700592 public void onTasksLoaded(ArrayList<TaskDescription> tasks, boolean firstScreenful) {
593 mNumItemsWaitingForThumbnailsAndIcons = firstScreenful
Michael Jurkae5923632012-10-03 15:29:36 +0200594 ? tasks.size() : mRecentTaskDescriptions == null
Craig Mautnerbb1449b2012-03-23 16:11:14 -0700595 ? 0 : mRecentTaskDescriptions.size();
Michael Jurka99a96552012-01-27 17:23:38 -0800596 if (mRecentTaskDescriptions == null) {
Craig Mautnerbb1449b2012-03-23 16:11:14 -0700597 mRecentTaskDescriptions = new ArrayList<TaskDescription>(tasks);
Michael Jurka99a96552012-01-27 17:23:38 -0800598 } else {
599 mRecentTaskDescriptions.addAll(tasks);
600 }
Michael Jurka7ed267f2012-10-09 17:03:30 +0200601 if (((RecentsActivity) mContext).isActivityShowing()) {
Craig Mautnerca6da002012-09-20 14:54:37 -0700602 refreshViews();
603 }
Michael Jurka99a96552012-01-27 17:23:38 -0800604 }
605
Craig Mautnerca6da002012-09-20 14:54:37 -0700606 private void updateUiElements() {
Dianne Hackborn8da429e2012-09-23 12:52:19 -0700607 final int items = mRecentTaskDescriptions != null
608 ? mRecentTaskDescriptions.size() : 0;
Michael Jurkaab48b682011-09-12 15:39:45 -0700609
610 mRecentsContainer.setVisibility(items > 0 ? View.VISIBLE : View.GONE);
Michael Jurkaab48b682011-09-12 15:39:45 -0700611
612 // Set description for accessibility
Dianne Hackborn8da429e2012-09-23 12:52:19 -0700613 int numRecentApps = mRecentTaskDescriptions != null
614 ? mRecentTaskDescriptions.size() : 0;
Michael Jurka7daf95d2011-09-30 11:07:30 -0700615 String recentAppsAccessibilityDescription;
616 if (numRecentApps == 0) {
617 recentAppsAccessibilityDescription =
618 getResources().getString(R.string.status_bar_no_recent_apps);
619 } else {
620 recentAppsAccessibilityDescription = getResources().getQuantityString(
621 R.plurals.status_bar_accessibility_recent_apps, numRecentApps, numRecentApps);
622 }
623 setContentDescription(recentAppsAccessibilityDescription);
Jim Miller44c66fe2010-10-20 18:32:52 -0700624 }
625
Michael Jurkae5923632012-10-03 15:29:36 +0200626 public boolean simulateClick(int persistentTaskId) {
Michael Jurkacb2522c2012-04-13 09:32:47 -0700627 if (mRecentsContainer instanceof RecentsScrollView){
628 RecentsScrollView scrollView
629 = (RecentsScrollView) mRecentsContainer;
Michael Jurkae5923632012-10-03 15:29:36 +0200630 View v = scrollView.findViewForTask(persistentTaskId);
Michael Jurkacb2522c2012-04-13 09:32:47 -0700631 if (v != null) {
632 handleOnClick(v);
633 return true;
634 }
635 }
636 return false;
637 }
Michael Jurkac016aaa2012-06-05 17:22:24 -0700638
Jim Miller9f0f0e02011-05-17 20:06:29 -0700639 public void handleOnClick(View view) {
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700640 ViewHolder holder = (ViewHolder)view.getTag();
641 TaskDescription ad = holder.taskDescription;
Jim Miller9f0f0e02011-05-17 20:06:29 -0700642 final Context context = view.getContext();
Jim Millere5c16ab2010-12-03 19:18:38 -0800643 final ActivityManager am = (ActivityManager)
Jim Miller9f0f0e02011-05-17 20:06:29 -0700644 context.getSystemService(Context.ACTIVITY_SERVICE);
Michael Jurkac016aaa2012-06-05 17:22:24 -0700645 Bitmap bm = holder.thumbnailViewImageBitmap;
646 boolean usingDrawingCache;
647 if (bm.getWidth() == holder.thumbnailViewImage.getWidth() &&
648 bm.getHeight() == holder.thumbnailViewImage.getHeight()) {
649 usingDrawingCache = false;
650 } else {
651 holder.thumbnailViewImage.setDrawingCacheEnabled(true);
652 bm = holder.thumbnailViewImage.getDrawingCache();
653 usingDrawingCache = true;
654 }
Michael Jurka482f1592012-09-13 11:05:59 -0700655 Bundle opts = (bm == null) ?
656 null :
657 ActivityOptions.makeThumbnailScaleUpAnimation(
658 holder.thumbnailViewImage, bm, 0, 0, null).toBundle();
Michael Jurkacb2522c2012-04-13 09:32:47 -0700659
660 show(false);
Jim Miller9f0f0e02011-05-17 20:06:29 -0700661 if (ad.taskId >= 0) {
Dianne Hackbornb6777462010-11-12 12:43:22 -0800662 // This is an active task; it should just go to the foreground.
Dianne Hackborn8078d8c2012-03-20 11:11:26 -0700663 am.moveTaskToFront(ad.taskId, ActivityManager.MOVE_TASK_WITH_HOME,
Michael Jurka482f1592012-09-13 11:05:59 -0700664 opts);
Dianne Hackbornb6777462010-11-12 12:43:22 -0800665 } else {
666 Intent intent = ad.intent;
Dianne Hackborn621e17d2010-11-22 15:59:56 -0800667 intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
Dianne Hackborn38cc8962011-10-13 11:33:55 -0700668 | Intent.FLAG_ACTIVITY_TASK_ON_HOME
669 | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackbornb6777462010-11-12 12:43:22 -0800670 if (DEBUG) Log.v(TAG, "Starting activity " + intent);
Michael Jurka482f1592012-09-13 11:05:59 -0700671 context.startActivityAsUser(intent, opts,
Dianne Hackborn79af1dd2012-08-16 16:42:52 -0700672 new UserHandle(UserHandle.USER_CURRENT));
Dianne Hackbornb6777462010-11-12 12:43:22 -0800673 }
Michael Jurkab9a38c52012-06-14 11:57:50 -0700674 if (usingDrawingCache) {
Michael Jurkac016aaa2012-06-05 17:22:24 -0700675 holder.thumbnailViewImage.setDrawingCacheEnabled(false);
676 }
Jim Millerf1e22e52011-01-26 15:39:51 -0800677 }
Jim Miller9f0f0e02011-05-17 20:06:29 -0700678
679 public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
680 handleOnClick(view);
681 }
682
Michael Jurka07d40462011-07-19 10:54:38 -0700683 public void handleSwipe(View view) {
Michael Jurkaab48b682011-09-12 15:39:45 -0700684 TaskDescription ad = ((ViewHolder) view.getTag()).taskDescription;
Michael Jurkaa8eac1d2012-04-30 15:54:19 -0700685 if (ad == null) {
Michael Jurka9d69b442012-05-04 15:46:32 -0700686 Log.v(TAG, "Not able to find activity description for swiped task; view=" + view +
687 " tag=" + view.getTag());
688 return;
Michael Jurkaa8eac1d2012-04-30 15:54:19 -0700689 }
Dianne Hackbornfc8fa632011-08-17 16:20:47 -0700690 if (DEBUG) Log.v(TAG, "Jettison " + ad.getLabel());
Michael Jurkaab48b682011-09-12 15:39:45 -0700691 mRecentTaskDescriptions.remove(ad);
Jim Miller9f0f0e02011-05-17 20:06:29 -0700692
693 // Handled by widget containers to enable LayoutTransitions properly
694 // mListAdapter.notifyDataSetChanged();
695
Michael Jurkaab48b682011-09-12 15:39:45 -0700696 if (mRecentTaskDescriptions.size() == 0) {
Michael Jurkacb2522c2012-04-13 09:32:47 -0700697 dismissAndGoBack();
Jim Miller9f0f0e02011-05-17 20:06:29 -0700698 }
699
700 // Currently, either direction means the same thing, so ignore direction and remove
701 // the task.
702 final ActivityManager am = (ActivityManager)
703 mContext.getSystemService(Context.ACTIVITY_SERVICE);
Michael Jurkaa8eac1d2012-04-30 15:54:19 -0700704 if (am != null) {
705 am.removeTask(ad.persistentTaskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
Jim Miller17377762011-10-11 15:33:34 -0700706
Michael Jurkaa8eac1d2012-04-30 15:54:19 -0700707 // Accessibility feedback
708 setContentDescription(
709 mContext.getString(R.string.accessibility_recents_item_dismissed, ad.getLabel()));
710 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
711 setContentDescription(null);
712 }
Jim Miller9f0f0e02011-05-17 20:06:29 -0700713 }
714
Jim Millerc0d27312011-07-14 18:54:01 -0700715 private void startApplicationDetailsActivity(String packageName) {
716 Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
717 Uri.fromParts("package", packageName, null));
Adam Powell0fc5b2b2012-07-18 18:20:29 -0700718 intent.setComponent(intent.resolveActivity(mContext.getPackageManager()));
719 TaskStackBuilder.create(getContext())
720 .addNextIntentWithParentStack(intent).startActivities();
Jim Millerc0d27312011-07-14 18:54:01 -0700721 }
722
Michael Jurkacb466432012-04-03 05:22:45 -0700723 public boolean onInterceptTouchEvent(MotionEvent ev) {
724 if (mPopup != null) {
725 return true;
726 } else {
727 return super.onInterceptTouchEvent(ev);
728 }
729 }
730
Michael Jurkafaa790c2011-09-02 17:35:02 -0700731 public void handleLongPress(
732 final View selectedView, final View anchorView, final View thumbnailView) {
733 thumbnailView.setSelected(true);
Michael Jurkacb466432012-04-03 05:22:45 -0700734 final PopupMenu popup =
735 new PopupMenu(mContext, anchorView == null ? selectedView : anchorView);
736 mPopup = popup;
Jim Millerc0d27312011-07-14 18:54:01 -0700737 popup.getMenuInflater().inflate(R.menu.recent_popup_menu, popup.getMenu());
738 popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
739 public boolean onMenuItemClick(MenuItem item) {
740 if (item.getItemId() == R.id.recent_remove_item) {
741 mRecentsContainer.removeViewInLayout(selectedView);
742 } else if (item.getItemId() == R.id.recent_inspect_item) {
743 ViewHolder viewHolder = (ViewHolder) selectedView.getTag();
744 if (viewHolder != null) {
Michael Jurkaab48b682011-09-12 15:39:45 -0700745 final TaskDescription ad = viewHolder.taskDescription;
Jim Millerc0d27312011-07-14 18:54:01 -0700746 startApplicationDetailsActivity(ad.packageName);
Michael Jurkacb2522c2012-04-13 09:32:47 -0700747 show(false);
Jim Millerc0d27312011-07-14 18:54:01 -0700748 } else {
749 throw new IllegalStateException("Oops, no tag on view " + selectedView);
750 }
751 } else {
752 return false;
753 }
754 return true;
755 }
756 });
Michael Jurkafaa790c2011-09-02 17:35:02 -0700757 popup.setOnDismissListener(new PopupMenu.OnDismissListener() {
758 public void onDismiss(PopupMenu menu) {
759 thumbnailView.setSelected(false);
Michael Jurkacb466432012-04-03 05:22:45 -0700760 mPopup = null;
Michael Jurkafaa790c2011-09-02 17:35:02 -0700761 }
762 });
Jim Millerc0d27312011-07-14 18:54:01 -0700763 popup.show();
Jim Miller9f0f0e02011-05-17 20:06:29 -0700764 }
Jim Miller44c66fe2010-10-20 18:32:52 -0700765}