diff options
author | Michael Jurka <mikejurka@google.com> | 2011-06-13 10:54:40 -0700 |
---|---|---|
committer | Michael Jurka <mikejurka@google.com> | 2011-06-15 16:50:04 -0700 |
commit | 3b1fc47d004f6b29af8f40d181baa3460b1e3b15 (patch) | |
tree | 920a9fe99b800ada9f13e7e5482d0c3c6f0df393 /packages/SystemUI/src/com/android | |
parent | f71e5469441286c6f466043e64a7f6492557cbd9 (diff) | |
download | frameworks_base-3b1fc47d004f6b29af8f40d181baa3460b1e3b15.zip frameworks_base-3b1fc47d004f6b29af8f40d181baa3460b1e3b15.tar.gz frameworks_base-3b1fc47d004f6b29af8f40d181baa3460b1e3b15.tar.bz2 |
Port recent apps from tablet to phone
- wire up to long press on home
- remove unused recents activity
- remove duplicate recents resources in -large directories (using -sw600dp instead)
- fix issue with zoom/scale translation when recents was brought up
Change-Id: I45538ccaff49b46ac3659c4828f9e2b0cd075241
Diffstat (limited to 'packages/SystemUI/src/com/android')
10 files changed, 211 insertions, 611 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java index b876075..49a65d8 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java +++ b/packages/SystemUI/src/com/android/systemui/recent/Choreographer.java @@ -36,14 +36,16 @@ import android.view.View; View mScrimView; View mContentView; AnimatorSet mContentAnim; + Animator.AnimatorListener mListener; // the panel will start to appear this many px from the end final int HYPERSPACE_OFFRAMP = 200; - public Choreographer(View root, View scrim, View content) { + public Choreographer(View root, View scrim, View content, Animator.AnimatorListener listener) { mRootView = root; mScrimView = scrim; mContentView = content; + mListener = listener; } void createAnimation(boolean appearing) { @@ -86,6 +88,9 @@ import android.view.View; .with(posAnim); mContentAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION); mContentAnim.addListener(this); + if (mListener != null) { + mContentAnim.addListener(mListener); + } } void startAnimation(boolean appearing) { diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java index 194c9d1..3dbcc59 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java @@ -16,7 +16,7 @@ package com.android.systemui.recent; -import com.android.systemui.recent.RecentsPanelView.ActvityDescriptionAdapter; +import com.android.systemui.recent.RecentsPanelView.ActivityDescriptionAdapter; import android.animation.Animator; import android.animation.Animator.AnimatorListener; @@ -49,7 +49,7 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView private static final float THRESHHOLD = 50; private static final boolean DEBUG_INVALIDATE = false; private LinearLayout mLinearLayout; - private ActvityDescriptionAdapter mAdapter; + private ActivityDescriptionAdapter mAdapter; private RecentsCallback mCallback; protected int mLastScrollPosition; private View mCurrentView; @@ -273,7 +273,7 @@ public class RecentsHorizontalScrollView extends HorizontalScrollView } } - public void setAdapter(ActvityDescriptionAdapter adapter) { + public void setAdapter(ActivityDescriptionAdapter adapter) { mAdapter = adapter; mAdapter.registerDataSetObserver(new DataSetObserver() { public void onChanged() { diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java index e2b3446..b8dc63d 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java @@ -19,6 +19,7 @@ package com.android.systemui.recent; import java.util.ArrayList; import java.util.List; +import android.animation.Animator; import android.animation.LayoutTransition; import android.app.ActivityManager; import android.content.Context; @@ -52,27 +53,33 @@ import android.widget.RelativeLayout; import android.widget.TextView; import com.android.systemui.R; +import com.android.systemui.statusbar.StatusBar; +import com.android.systemui.statusbar.phone.PhoneStatusBar; import com.android.systemui.statusbar.tablet.StatusBarPanel; import com.android.systemui.statusbar.tablet.TabletStatusBar; public class RecentsPanelView extends RelativeLayout - implements OnItemClickListener, RecentsCallback, StatusBarPanel { - private static final int GLOW_PADDING = 15; + implements OnItemClickListener, RecentsCallback, StatusBarPanel, Animator.AnimatorListener { static final String TAG = "RecentsListView"; - static final boolean DEBUG = TabletStatusBar.DEBUG; + static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG; private static final int DISPLAY_TASKS = 20; private static final int MAX_TASKS = DISPLAY_TASKS + 1; // allow extra for non-apps - private TabletStatusBar mBar; + private StatusBar mBar; private ArrayList<ActivityDescription> mActivityDescriptions; private int mIconDpi; private View mRecentsScrim; private View mRecentsGlowView; private View mRecentsContainer; private Bitmap mGlowBitmap; + // TODO: add these widgets attributes to the layout file + private int mGlowBitmapPaddingLeftPx; + private int mGlowBitmapPaddingTopPx; + private int mGlowBitmapPaddingRightPx; + private int mGlowBitmapPaddingBottomPx; private boolean mShowing; private Choreographer mChoreo; private View mRecentsDismissButton; - private ActvityDescriptionAdapter mListAdapter; + private ActivityDescriptionAdapter mListAdapter; /* package */ final static class ActivityDescription { int taskId; // application task id for curating apps @@ -108,10 +115,10 @@ public class RecentsPanelView extends RelativeLayout ActivityDescription activityDescription; } - /* package */ final class ActvityDescriptionAdapter extends BaseAdapter { + /* package */ final class ActivityDescriptionAdapter extends BaseAdapter { private LayoutInflater mInflater; - public ActvityDescriptionAdapter(Context context) { + public ActivityDescriptionAdapter(Context context) { mInflater = LayoutInflater.from(context); } @@ -183,6 +190,26 @@ public class RecentsPanelView extends RelativeLayout } } + public void onAnimationCancel(Animator animation) { + } + + public void onAnimationEnd(Animator animation) { + if (mShowing) { + final LayoutTransition transitioner = new LayoutTransition(); + ((ViewGroup)mRecentsContainer).setLayoutTransition(transitioner); + createCustomAnimations(transitioner); + } else { + ((ViewGroup)mRecentsContainer).setLayoutTransition(null); + } + } + + public void onAnimationRepeat(Animator animation) { + } + + public void onAnimationStart(Animator animation) { + } + + /** * We need to be aligned at the bottom. LinearLayout can't do this, so instead, * let LinearLayout do all the hard work, and then shift everything down to the bottom. @@ -201,7 +228,7 @@ public class RecentsPanelView extends RelativeLayout return mShowing; } - public void setBar(TabletStatusBar bar) { + public void setBar(StatusBar bar) { mBar = bar; } @@ -217,7 +244,16 @@ public class RecentsPanelView extends RelativeLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE; mIconDpi = xlarge ? DisplayMetrics.DENSITY_HIGH : res.getDisplayMetrics().densityDpi; + mGlowBitmap = BitmapFactory.decodeResource(res, R.drawable.recents_thumbnail_bg); + mGlowBitmapPaddingLeftPx = + res.getDimensionPixelSize(R.dimen.recents_thumbnail_bg_padding_left); + mGlowBitmapPaddingTopPx = + res.getDimensionPixelSize(R.dimen.recents_thumbnail_bg_padding_top); + mGlowBitmapPaddingRightPx = + res.getDimensionPixelSize(R.dimen.recents_thumbnail_bg_padding_right); + mGlowBitmapPaddingBottomPx = + res.getDimensionPixelSize(R.dimen.recents_thumbnail_bg_padding_bottom); } @Override @@ -225,7 +261,7 @@ public class RecentsPanelView extends RelativeLayout super.onFinishInflate(); mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mRecentsContainer = findViewById(R.id.recents_container); - mListAdapter = new ActvityDescriptionAdapter(mContext); + mListAdapter = new ActivityDescriptionAdapter(mContext); if (mRecentsContainer instanceof RecentsListView) { RecentsListView listView = (RecentsListView) mRecentsContainer; listView.setAdapter(mListAdapter); @@ -246,13 +282,10 @@ public class RecentsPanelView extends RelativeLayout throw new IllegalArgumentException("missing RecentsListView/RecentsScrollView"); } - final LayoutTransition transitioner = new LayoutTransition(); - ((ViewGroup)mRecentsContainer).setLayoutTransition(transitioner); - createCustomAnimations(transitioner); mRecentsGlowView = findViewById(R.id.recents_glow); mRecentsScrim = (View) findViewById(R.id.recents_bg_protect); - mChoreo = new Choreographer(this, mRecentsScrim, mRecentsGlowView); + mChoreo = new Choreographer(this, mRecentsScrim, mRecentsGlowView, this); mRecentsDismissButton = findViewById(R.id.recents_dismiss_button); mRecentsDismissButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { @@ -402,10 +435,9 @@ public class RecentsPanelView extends RelativeLayout Log.v(TAG, "Source thumb: " + srcWidth + "x" + srcHeight); canvas.drawBitmap(thumbnail, new Rect(0, 0, srcWidth-1, srcHeight-1), - new RectF(GLOW_PADDING, - GLOW_PADDING - 7.0f, - outBitmap.getWidth() - GLOW_PADDING + 3.0f, - outBitmap.getHeight() - GLOW_PADDING + 7.0f), paint); + new RectF(mGlowBitmapPaddingLeftPx, mGlowBitmapPaddingTopPx, + outBitmap.getWidth() - mGlowBitmapPaddingRightPx, + outBitmap.getHeight() - mGlowBitmapPaddingBottomPx), paint); } return outBitmap; } diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java index 54ec6b5..6a962cb 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java @@ -16,7 +16,7 @@ package com.android.systemui.recent; -import com.android.systemui.recent.RecentsPanelView.ActvityDescriptionAdapter; +import com.android.systemui.recent.RecentsPanelView.ActivityDescriptionAdapter; import android.animation.Animator; import android.animation.Animator.AnimatorListener; @@ -49,7 +49,7 @@ public class RecentsVerticalScrollView extends ScrollView private static final float THRESHHOLD = 50; private static final boolean DEBUG_INVALIDATE = false; private LinearLayout mLinearLayout; - private ActvityDescriptionAdapter mAdapter; + private ActivityDescriptionAdapter mAdapter; private RecentsCallback mCallback; protected int mLastScrollPosition; private View mCurrentView; @@ -275,7 +275,7 @@ public class RecentsVerticalScrollView extends ScrollView } } - public void setAdapter(ActvityDescriptionAdapter adapter) { + public void setAdapter(ActivityDescriptionAdapter adapter) { mAdapter = adapter; mAdapter.registerDataSetObserver(new DataSetObserver() { public void onChanged() { diff --git a/packages/SystemUI/src/com/android/systemui/recent/carousel/RecentApplicationsActivity.java b/packages/SystemUI/src/com/android/systemui/recent/carousel/RecentApplicationsActivity.java deleted file mode 100644 index 45e230f..0000000 --- a/packages/SystemUI/src/com/android/systemui/recent/carousel/RecentApplicationsActivity.java +++ /dev/null @@ -1,532 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package com.android.systemui.recent.carousel; - -import com.android.systemui.R; - -import com.android.ex.carousel.CarouselView; -import com.android.ex.carousel.CarouselViewHelper; -import com.android.ex.carousel.CarouselRS.CarouselCallback; -import com.android.ex.carousel.CarouselViewHelper.DetailTextureParameters; - -import java.util.ArrayList; -import java.util.List; - -import android.app.Activity; -import android.app.ActivityManager; -import android.app.ActivityManagerNative; -import android.app.IActivityManager; -import android.app.IThumbnailReceiver; -import android.app.ActivityManager.RunningTaskInfo; -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.PaintFlagsDrawFilter; -import android.graphics.PorterDuffXfermode; -import android.graphics.PorterDuff; -import android.graphics.Bitmap.Config; -import android.graphics.drawable.Drawable; -import android.graphics.PixelFormat; -import android.os.Bundle; -import android.os.RemoteException; -import android.util.Log; -import android.view.View; -import android.view.View.MeasureSpec; -import android.widget.TextView; - -public class RecentApplicationsActivity extends Activity { - private static final String TAG = "RecentApplicationsActivity"; - private static boolean DBG = false; - private static final int CARD_SLOTS = 56; - private static final int VISIBLE_SLOTS = 7; - private static final int MAX_TASKS = VISIBLE_SLOTS * 2; - - // TODO: these should be configurable - private static final int DETAIL_TEXTURE_MAX_WIDTH = 200; - private static final int DETAIL_TEXTURE_MAX_HEIGHT = 80; - private static final int TEXTURE_WIDTH = 256; - private static final int TEXTURE_HEIGHT = 256; - - private ActivityManager mActivityManager; - private List<RunningTaskInfo> mRunningTaskList; - private boolean mPortraitMode = true; - private ArrayList<ActivityDescription> mActivityDescriptions - = new ArrayList<ActivityDescription>(); - private CarouselView mCarouselView; - private LocalCarouselViewHelper mHelper; - private View mNoRecentsView; - private Bitmap mLoadingBitmap; - private Bitmap mRecentOverlay; - private boolean mHidden = false; - private boolean mHiding = false; - private DetailInfo mDetailInfo; - - /** - * This class is a container for all items associated with the DetailView we'll - * be drawing to a bitmap and sending to Carousel. - * - */ - static final class DetailInfo { - public DetailInfo(View _view, TextView _title, TextView _desc) { - view = _view; - title = _title; - description = _desc; - } - - /** - * Draws view into the given bitmap, if provided - * @param bitmap - */ - public Bitmap draw(Bitmap bitmap) { - resizeView(view, DETAIL_TEXTURE_MAX_WIDTH, DETAIL_TEXTURE_MAX_HEIGHT); - int desiredWidth = view.getWidth(); - int desiredHeight = view.getHeight(); - if (bitmap == null || desiredWidth != bitmap.getWidth() - || desiredHeight != bitmap.getHeight()) { - bitmap = Bitmap.createBitmap(desiredWidth, desiredHeight, Config.ARGB_8888); - } - Canvas canvas = new Canvas(bitmap); - view.draw(canvas); - return bitmap; - } - - /** - * Force a layout pass on the given view. - */ - private void resizeView(View view, int maxWidth, int maxHeight) { - int widthSpec = MeasureSpec.getMode(MeasureSpec.AT_MOST) - | MeasureSpec.getSize(maxWidth); - int heightSpec = MeasureSpec.getMode(MeasureSpec.AT_MOST) - | MeasureSpec.getSize(maxHeight); - view.measure(widthSpec, heightSpec); - view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); - Log.v(TAG, "RESIZED VIEW: " + view.getWidth() + ", " + view.getHeight()); - } - - public View view; - public TextView title; - public TextView description; - } - - static class ActivityDescription { - int id; - Bitmap thumbnail; // generated by Activity.onCreateThumbnail() - Drawable icon; // application package icon - String label; // application package label - CharSequence description; // generated by Activity.onCreateDescription() - Intent intent; // launch intent for application - Matrix matrix; // arbitrary rotation matrix to correct orientation - int position; // position in list - - public ActivityDescription(Bitmap _thumbnail, - Drawable _icon, String _label, String _desc, int _id, int _pos) - { - thumbnail = _thumbnail; - icon = _icon; - label = _label; - description = _desc; - id = _id; - position = _pos; - } - - public void clear() { - icon = null; - thumbnail = null; - label = null; - description = null; - intent = null; - matrix = null; - id = -1; - position = -1; - } - }; - - private ActivityDescription findActivityDescription(int id) { - for (int i = 0; i < mActivityDescriptions.size(); i++) { - ActivityDescription item = mActivityDescriptions.get(i); - if (item != null && item.id == id) { - return item; - } - } - return null; - } - - private class LocalCarouselViewHelper extends CarouselViewHelper { - private DetailTextureParameters mDetailParams = new DetailTextureParameters(10.0f, 20.0f); - - public LocalCarouselViewHelper(Context context) { - super(context); - } - - @Override - public DetailTextureParameters getDetailTextureParameters(int id) { - return mDetailParams; - } - - public void onCardSelected(int n) { - if (n < mActivityDescriptions.size()) { - ActivityDescription item = mActivityDescriptions.get(n); - if (item.id >= 0) { - // This is an active task; it should just go to the foreground. - final ActivityManager am = (ActivityManager) - getSystemService(Context.ACTIVITY_SERVICE); - am.moveTaskToFront(item.id, ActivityManager.MOVE_TASK_WITH_HOME); - } else if (item.intent != null) { - // prepare a launch intent and send it - item.intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY - | Intent.FLAG_ACTIVITY_TASK_ON_HOME); - try { - if (DBG) Log.v(TAG, "Starting intent " + item.intent); - startActivity(item.intent); - overridePendingTransition(R.anim.recent_app_enter, R.anim.recent_app_leave); - } catch (ActivityNotFoundException e) { - if (DBG) Log.w("Recent", "Unable to launch recent task", e); - } - finish(); - } - } - } - - @Override - public Bitmap getTexture(final int id) { - if (DBG) Log.v(TAG, "onRequestTexture(" + id + ")"); - ActivityDescription info; - synchronized(mActivityDescriptions) { - info = mActivityDescriptions.get(id); - } - Bitmap bitmap = null; - if (info != null) { - bitmap = compositeBitmap(info); - } - return bitmap; - } - - @Override - public Bitmap getDetailTexture(int n) { - Bitmap bitmap = null; - if (n < mActivityDescriptions.size()) { - ActivityDescription item = mActivityDescriptions.get(n); - mDetailInfo.title.setText(item.label); - mDetailInfo.description.setText(item.description); - bitmap = mDetailInfo.draw(null); - } - return bitmap; - } - }; - - private Bitmap compositeBitmap(ActivityDescription info) { - final int targetWidth = TEXTURE_WIDTH; - final int targetHeight = TEXTURE_HEIGHT; - final int border = 3; // inset along the edge for thumnnail content - final int overlap = 1; // how many pixels of overlap between border and thumbnail - final Resources res = getResources(); - if (mRecentOverlay == null) { - mRecentOverlay = BitmapFactory.decodeResource(res, R.drawable.recent_overlay); - } - - // Create a bitmap of the proper size/format and set the canvas to draw to it - final Bitmap result = Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_8888); - final Canvas canvas = new Canvas(result); - canvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG, Paint.FILTER_BITMAP_FLAG)); - Paint paint = new Paint(); - paint.setFilterBitmap(false); - - paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); - canvas.save(); - if (info.thumbnail != null) { - // Draw the thumbnail - int sourceWidth = targetWidth - 2 * (border - overlap); - int sourceHeight = targetHeight - 2 * (border - overlap); - final float scaleX = (float) sourceWidth / info.thumbnail.getWidth(); - final float scaleY = (float) sourceHeight / info.thumbnail.getHeight(); - canvas.translate(border * 0.5f, border * 0.5f); - canvas.scale(scaleX, scaleY); - canvas.drawBitmap(info.thumbnail, 0, 0, paint); - } else { - // Draw the Loading bitmap placeholder, TODO: Remove when RS handles blending - final float scaleX = (float) targetWidth / mLoadingBitmap.getWidth(); - final float scaleY = (float) targetHeight / mLoadingBitmap.getHeight(); - canvas.scale(scaleX, scaleY); - canvas.drawBitmap(mLoadingBitmap, 0, 0, paint); - } - canvas.restore(); - - // Draw overlay - canvas.save(); - final float scaleOverlayX = (float) targetWidth / mRecentOverlay.getWidth(); - final float scaleOverlayY = (float) targetHeight / mRecentOverlay.getHeight(); - canvas.scale(scaleOverlayX, scaleOverlayY); - paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD)); - canvas.drawBitmap(mRecentOverlay, 0, 0, paint); - canvas.restore(); - - // Draw icon - if (info.icon != null) { - canvas.save(); - info.icon.draw(canvas); - canvas.restore(); - } - - return result; - } - - private final IThumbnailReceiver mThumbnailReceiver = new IThumbnailReceiver.Stub() { - - public void finished() throws RemoteException { - - } - - public void newThumbnail(final int id, final Bitmap bitmap, CharSequence description) - throws RemoteException { - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - if (DBG) Log.v(TAG, "New thumbnail for id=" + id + ", dimensions=" + w + "x" + h - + " description '" + description + "'"); - ActivityDescription info = findActivityDescription(id); - if (info != null) { - info.thumbnail = bitmap; - info.description = description; - final int thumbWidth = bitmap.getWidth(); - final int thumbHeight = bitmap.getHeight(); - if ((mPortraitMode && thumbWidth > thumbHeight) - || (!mPortraitMode && thumbWidth < thumbHeight)) { - Matrix matrix = new Matrix(); - matrix.setRotate(90.0f, (float) thumbWidth / 2, (float) thumbHeight / 2); - info.matrix = matrix; - } else { - info.matrix = null; - } - // Force Carousel to request new textures for this item. - mCarouselView.setTextureForItem(info.position, null); - mCarouselView.setDetailTextureForItem(info.position, 0, 0, 0, 0, null); - } else { - if (DBG) Log.v(TAG, "Can't find view for id " + id); - } - } - }; - - /** - * We never really finish() RecentApplicationsActivity, since we don't want to - * get destroyed and pay the start-up cost to restart it. - */ - @Override - public void finish() { - moveTaskToBack(true); - } - - @Override - protected void onNewIntent(Intent intent) { - mHidden = !mHidden; - if (mHidden) { - mHiding = true; - moveTaskToBack(true); - } else { - mHiding = false; - } - super.onNewIntent(intent); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - final Resources res = getResources(); - final View decorView = getWindow().getDecorView(); - - getWindow().getDecorView().setBackgroundColor(0x80000000); - - if (mCarouselView == null) { - long t = System.currentTimeMillis(); - setContentView(R.layout.recent_apps_activity); - long elapsed = System.currentTimeMillis() - t; - Log.v(TAG, "Recents layout took " + elapsed + "ms to load"); - mLoadingBitmap = BitmapFactory.decodeResource(res, R.drawable.recent_rez_border); - mCarouselView = (CarouselView)findViewById(R.id.carousel); - mHelper = new LocalCarouselViewHelper(this); - mHelper.setCarouselView(mCarouselView); - - mCarouselView.setSlotCount(CARD_SLOTS); - mCarouselView.setVisibleSlots(VISIBLE_SLOTS); - mCarouselView.createCards(0); - mCarouselView.setStartAngle((float) -(2.0f*Math.PI * 5 / CARD_SLOTS)); - mCarouselView.setDefaultBitmap(mLoadingBitmap); - mCarouselView.setLoadingBitmap(mLoadingBitmap); - mCarouselView.setRezInCardCount(3.0f); - mCarouselView.getHolder().setFormat(PixelFormat.TRANSLUCENT); - - mNoRecentsView = (View) findViewById(R.id.no_applications_message); - - mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); - mPortraitMode = decorView.getHeight() > decorView.getWidth(); - - // Load detail view which will be used to render text - View detail = getLayoutInflater().inflate(R.layout.recents_detail_view, null); - TextView title = (TextView) detail.findViewById(R.id.app_title); - TextView description = (TextView) detail.findViewById(R.id.app_description); - mDetailInfo = new DetailInfo(detail, title, description); - - refresh(); - } - } - - @Override - protected void onResume() { - super.onResume(); - refresh(); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - mPortraitMode = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT; - if (DBG) Log.v(TAG, "CONFIG CHANGE, mPortraitMode = " + mPortraitMode); - refresh(); - } - - void updateRunningTasks() { - mRunningTaskList = mActivityManager.getRunningTasks(MAX_TASKS, - 0, mThumbnailReceiver); - if (DBG) Log.v(TAG, "Portrait: " + mPortraitMode); - for (RunningTaskInfo r : mRunningTaskList) { - if (r.thumbnail != null) { - int thumbWidth = r.thumbnail.getWidth(); - int thumbHeight = r.thumbnail.getHeight(); - if (DBG) Log.v(TAG, "Got thumbnail " + thumbWidth + "x" + thumbHeight); - ActivityDescription desc = findActivityDescription(r.id); - if (desc != null) { - desc.thumbnail = r.thumbnail; - desc.description = r.description; - if ((mPortraitMode && thumbWidth > thumbHeight) - || (!mPortraitMode && thumbWidth < thumbHeight)) { - Matrix matrix = new Matrix(); - matrix.setRotate(90.0f, (float) thumbWidth / 2, (float) thumbHeight / 2); - desc.matrix = matrix; - } - } else { - if (DBG) Log.v(TAG, "Couldn't find ActivityDesc for id=" + r.id); - } - } else { - if (DBG) Log.v(TAG, "*** RUNNING THUMBNAIL WAS NULL ***"); - } - } - } - - private void updateRecentTasks() { - final PackageManager pm = getPackageManager(); - final ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); - - final List<ActivityManager.RecentTaskInfo> recentTasks = - am.getRecentTasks(MAX_TASKS, ActivityManager.RECENT_IGNORE_UNAVAILABLE); - - ActivityInfo homeInfo = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME) - .resolveActivityInfo(pm, 0); - - // IconUtilities iconUtilities = new IconUtilities(this); // FIXME - - int numTasks = recentTasks.size(); - mActivityDescriptions.clear(); - for (int i = 0, index = 0; i < numTasks && (index < MAX_TASKS); ++i) { - final ActivityManager.RecentTaskInfo recentInfo = recentTasks.get(i); - - Intent intent = new Intent(recentInfo.baseIntent); - if (recentInfo.origActivity != null) { - intent.setComponent(recentInfo.origActivity); - } - - // Skip the current home activity. - if (homeInfo != null - && homeInfo.packageName.equals(intent.getComponent().getPackageName()) - && homeInfo.name.equals(intent.getComponent().getClassName())) { - continue; - } - - intent.setFlags((intent.getFlags()&~Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) - | Intent.FLAG_ACTIVITY_NEW_TASK); - final ResolveInfo resolveInfo = pm.resolveActivity(intent, 0); - if (resolveInfo != null) { - final ActivityInfo info = resolveInfo.activityInfo; - final String title = info.loadLabel(pm).toString(); - Drawable icon = info.loadIcon(pm); - - int id = recentTasks.get(i).id; - if (id != -1 && title != null && title.length() > 0 && icon != null) { - // icon = null; FIXME: iconUtilities.createIconDrawable(icon); - ActivityDescription item = new ActivityDescription( - null, icon, title, null, id, index); - item.intent = intent; - mActivityDescriptions.add(item); - if (DBG) Log.v(TAG, "Added item[" + index - + "], id=" + item.id - + ", title=" + item.label); - ++index; - } else { - if (DBG) Log.v(TAG, "SKIPPING item " + id); - } - } - } - } - - private final Runnable mRefreshRunnable = new Runnable() { - public void run() { - updateRecentTasks(); - updateRunningTasks(); - showCarousel(mActivityDescriptions.size() > 0); - } - }; - - private void showCarousel(boolean show) { - if (show) { - mCarouselView.createCards(mActivityDescriptions.size()); - for (int i = 1; i < mActivityDescriptions.size(); i++) { - // Force Carousel to update textures. Note we don't do this for the first item, - // since it will be updated when mThumbnailReceiver returns a thumbnail. - // TODO: only do this for apps that have changed. - mCarouselView.setTextureForItem(i, null); - mCarouselView.setDetailTextureForItem(i, 0, 0, 0, 0, null); - } - // Make carousel visible - mNoRecentsView.setVisibility(View.GONE); - mCarouselView.setVisibility(View.VISIBLE); - mCarouselView.createCards(mActivityDescriptions.size()); - } else { - // show "No Recent Tasks" - mNoRecentsView.setVisibility(View.VISIBLE); - mCarouselView.setVisibility(View.GONE); - } - } - - private void refresh() { - if (!mHiding && mCarouselView != null) { - // Don't update the view now. Instead, post a request so it happens next time - // we reach the looper after a delay. This way we can fold multiple refreshes - // into just the latest. - mCarouselView.removeCallbacks(mRefreshRunnable); - mCarouselView.postDelayed(mRefreshRunnable, 50); - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/recent/carousel/RecentApplicationsCarouselView.java b/packages/SystemUI/src/com/android/systemui/recent/carousel/RecentApplicationsCarouselView.java deleted file mode 100644 index 1afb086..0000000 --- a/packages/SystemUI/src/com/android/systemui/recent/carousel/RecentApplicationsCarouselView.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.recent.carousel; - -import android.content.Context; -import android.util.AttributeSet; - -import com.android.ex.carousel.CarouselView; -import com.android.systemui.R; - -public class RecentApplicationsCarouselView extends CarouselView { - - public RecentApplicationsCarouselView(Context context) { - this(context, null); - } - - public RecentApplicationsCarouselView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public Info getRenderScriptInfo() { - return new Info(R.raw.carousel); - } - -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index f81820e..62d7500 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -61,6 +61,7 @@ public class CommandQueue extends IStatusBar.Stub { private static final int MSG_SET_HARD_KEYBOARD_STATUS = 10 << MSG_SHIFT; private static final int MSG_USER_ACTIVITY = 11 << MSG_SHIFT; + private static final int MSG_TOGGLE_RECENT_APPS = 12 << MSG_SHIFT; private StatusBarIconList mList; private Callbacks mCallbacks; @@ -90,6 +91,7 @@ public class CommandQueue extends IStatusBar.Stub { public void setImeWindowStatus(IBinder token, int vis, int backDisposition); public void setHardKeyboardStatus(boolean available, boolean enabled); public void userActivity(); + public void toggleRecentApps(); } public CommandQueue(Callbacks callbacks, StatusBarIconList list) { @@ -196,6 +198,13 @@ public class CommandQueue extends IStatusBar.Stub { } } + public void toggleRecentApps() { + synchronized (mList) { + mHandler.removeMessages(MSG_TOGGLE_RECENT_APPS); + mHandler.obtainMessage(MSG_TOGGLE_RECENT_APPS, 0, 0, null).sendToTarget(); + } + } + private final class H extends Handler { public void handleMessage(Message msg) { final int what = msg.what & MSG_MASK; @@ -265,6 +274,9 @@ public class CommandQueue extends IStatusBar.Stub { case MSG_USER_ACTIVITY: mCallbacks.userActivity(); break; + case MSG_TOGGLE_RECENT_APPS: + mCallbacks.toggleRecentApps(); + break; } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java index e567dc7..ca75138 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java @@ -53,6 +53,7 @@ public abstract class StatusBar extends SystemUI implements CommandQueue.Callbac protected abstract View makeStatusBarView(); protected abstract int getStatusBarGravity(); public abstract int getStatusBarHeight(); + public abstract void animateCollapse(); private DoNotDisturb mDoNotDisturb; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index cc8358e..0b82123 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -28,10 +28,12 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; +import android.content.res.Configuration; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.net.Uri; +import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.os.Handler; @@ -74,6 +76,7 @@ import com.android.internal.statusbar.StatusBarIconList; import com.android.internal.statusbar.StatusBarNotification; import com.android.systemui.R; +import com.android.systemui.recent.RecentsPanelView; import com.android.systemui.statusbar.NotificationData; import com.android.systemui.statusbar.StatusBar; import com.android.systemui.statusbar.StatusBarIconView; @@ -83,6 +86,7 @@ import com.android.systemui.statusbar.policy.DateView; public class PhoneStatusBar extends StatusBar { static final String TAG = "PhoneStatusBar"; static final boolean SPEW = false; + public static final boolean DEBUG = false; public static final String ACTION_STATUSBAR_START = "com.android.internal.policy.statusbar.START"; @@ -94,6 +98,8 @@ public class PhoneStatusBar extends StatusBar { private static final int MSG_ANIMATE_REVEAL = 1001; private static final int MSG_SHOW_INTRUDER = 1002; private static final int MSG_HIDE_INTRUDER = 1003; + private static final int MSG_OPEN_RECENTS_PANEL = 1020; + private static final int MSG_CLOSE_RECENTS_PANEL = 1021; // will likely move to a resource or other tunable param at some point private static final int INTRUDER_ALERT_DECAY_MS = 10000; @@ -160,6 +166,9 @@ public class PhoneStatusBar extends StatusBar { private View mTickerView; private boolean mTicking; + // Recent applications + private RecentsPanelView mRecentsPanel; + // Tracking finger for opening/closing. int mEdgeBorder; // corresponds to R.dimen.status_bar_edge_ignore boolean mTracking; @@ -296,6 +305,9 @@ public class PhoneStatusBar extends StatusBar { setAreThereNotifications(); mDateView.setVisibility(View.INVISIBLE); + // Recents Panel + initializeRecentsPanel(); + // receive broadcasts IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); @@ -306,6 +318,51 @@ public class PhoneStatusBar extends StatusBar { return sb; } + protected WindowManager.LayoutParams getRecentsLayoutParams() { + boolean translucent = false; + WindowManager.LayoutParams lp = new WindowManager.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT, + WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, + WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM + | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH + | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, + (translucent ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT)); + lp.gravity = Gravity.BOTTOM | Gravity.LEFT; + lp.setTitle("RecentsPanel"); + lp.windowAnimations = R.style.Animation_RecentPanel; + lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED + | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; + return lp; + } + + protected void initializeRecentsPanel() { + // Recents Panel + boolean visible = false; + if (mRecentsPanel != null) { + visible = mRecentsPanel.getVisibility() == View.VISIBLE; + WindowManagerImpl.getDefault().removeView(mRecentsPanel); + } + mRecentsPanel = (RecentsPanelView) View.inflate(mContext, + R.layout.status_bar_recent_panel, null); + + mRecentsPanel.setOnTouchListener(new TouchOutsideListener(MSG_CLOSE_RECENTS_PANEL, + mRecentsPanel)); + mRecentsPanel.setVisibility(View.GONE); + WindowManager.LayoutParams lp = getRecentsLayoutParams(); + + WindowManagerImpl.getDefault().addView(mRecentsPanel, lp); + mRecentsPanel.setBar(this); + if (visible) { + // need to set visibility to View.GONE earlier since that + // triggers refreshing application list + mRecentsPanel.setVisibility(View.VISIBLE); + mRecentsPanel.show(true, false); + } + + } + protected int getStatusBarGravity() { return Gravity.TOP | Gravity.FILL_HORIZONTAL; } @@ -581,6 +638,12 @@ public class PhoneStatusBar extends StatusBar { } } + @Override + protected void onConfigurationChanged(Configuration newConfig) { + initializeRecentsPanel(); + } + + View[] makeNotificationView(StatusBarNotification notification, ViewGroup parent) { Notification n = notification.notification; RemoteViews remoteViews = n.contentView; @@ -789,6 +852,21 @@ public class PhoneStatusBar extends StatusBar { case MSG_HIDE_INTRUDER: setIntruderAlertVisibility(false); break; + case MSG_OPEN_RECENTS_PANEL: + if (DEBUG) Slog.d(TAG, "opening recents panel"); + if (mRecentsPanel != null) { + disable(StatusBarManager.DISABLE_BACK); + mRecentsPanel.setVisibility(View.VISIBLE); + mRecentsPanel.show(true, true); + } + break; + case MSG_CLOSE_RECENTS_PANEL: + if (DEBUG) Slog.d(TAG, "closing recents panel"); + if (mRecentsPanel != null && mRecentsPanel.isShowing()) { + disable(StatusBarManager.DISABLE_NONE); + mRecentsPanel.show(false, true); + } + break; } } } @@ -835,6 +913,10 @@ public class PhoneStatusBar extends StatusBar { } public void animateCollapse() { + animateCollapse(false); + } + + public void animateCollapse(boolean excludeRecents) { if (SPEW) { Slog.d(TAG, "animateCollapse(): mExpanded=" + mExpanded + " mExpandedVisible=" + mExpandedVisible @@ -844,6 +926,11 @@ public class PhoneStatusBar extends StatusBar { + " mAnimVel=" + mAnimVel); } + if (!excludeRecents) { + mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL); + mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL); + } + if (!mExpandedVisible) { return; } @@ -1557,6 +1644,13 @@ public class PhoneStatusBar extends StatusBar { } catch (RemoteException ex) { } } + public void toggleRecentApps() { + int msg = (mRecentsPanel.getVisibility() == View.GONE) + ? MSG_OPEN_RECENTS_PANEL : MSG_CLOSE_RECENTS_PANEL; + mHandler.removeMessages(msg); + mHandler.sendEmptyMessage(msg); + } + /** * The LEDs are turned o)ff when the notification panel is shown, even just a little bit. * This was added last-minute and is inconsistent with the way the rest of the notifications @@ -1625,7 +1719,14 @@ public class PhoneStatusBar extends StatusBar { String action = intent.getAction(); if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action) || Intent.ACTION_SCREEN_OFF.equals(action)) { - animateCollapse(); + boolean excludeRecents = false; + if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) { + String reason = intent.getExtras().getString("reason"); + if (reason != null) { + excludeRecents = reason.equals("recentapps"); + } + } + animateCollapse(excludeRecents); } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) { repositionNavigationBar(); @@ -1690,5 +1791,27 @@ public class PhoneStatusBar extends StatusBar { vibrate(); } }; + + public class TouchOutsideListener implements View.OnTouchListener { + private int mMsg; + private RecentsPanelView mPanel; + + public TouchOutsideListener(int msg, RecentsPanelView panel) { + mMsg = msg; + mPanel = panel; + } + + public boolean onTouch(View v, MotionEvent ev) { + final int action = ev.getAction(); + if (action == MotionEvent.ACTION_OUTSIDE + || (action == MotionEvent.ACTION_DOWN + && !mPanel.isInContentArea((int)ev.getX(), (int)ev.getY()))) { + mHandler.removeMessages(mMsg); + mHandler.sendEmptyMessage(mMsg); + return true; + } + return false; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java index a7af30d..9bd6983 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java @@ -76,7 +76,6 @@ import com.android.systemui.statusbar.policy.LocationController; import com.android.systemui.statusbar.policy.NetworkController; import com.android.systemui.statusbar.policy.Prefs; import com.android.systemui.recent.RecentsPanelView; -import com.android.systemui.recent.carousel.RecentApplicationsActivity; public class TabletStatusBar extends StatusBar implements HeightReceiver.OnBarHeightChangedListener, @@ -1156,20 +1155,12 @@ public class TabletStatusBar extends StatusBar implements public void onClickRecentButton() { if (DEBUG) Slog.d(TAG, "clicked recent apps; disabled=" + mDisabled); - if (mRecentsPanel == null) { - Intent intent = new Intent(); - intent.setClass(mContext, RecentApplicationsActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); - mContext.startActivity(intent); - } else { - if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) { - int msg = (mRecentsPanel.getVisibility() == View.GONE) - ? MSG_OPEN_RECENTS_PANEL - : MSG_CLOSE_RECENTS_PANEL; - mHandler.removeMessages(msg); - mHandler.sendEmptyMessage(msg); - } + if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) { + int msg = (mRecentsPanel.getVisibility() == View.GONE) + ? MSG_OPEN_RECENTS_PANEL + : MSG_CLOSE_RECENTS_PANEL; + mHandler.removeMessages(msg); + mHandler.sendEmptyMessage(msg); } } @@ -1681,6 +1672,13 @@ public class TabletStatusBar extends StatusBar implements public void userActivity() { } + public void toggleRecentApps() { + int msg = (mRecentsPanel.getVisibility() == View.GONE) + ? MSG_OPEN_RECENTS_PANEL : MSG_CLOSE_RECENTS_PANEL; + mHandler.removeMessages(msg); + mHandler.sendEmptyMessage(msg); + } + public class TouchOutsideListener implements View.OnTouchListener { private int mMsg; private StatusBarPanel mPanel; |