1 /* 2 * Copyright (C) 2013 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 package com.android.systemui.recent; 18 19 import android.app.ActivityOptions; 20 import android.content.ActivityNotFoundException; 21 import android.content.Intent; 22 import android.content.res.Configuration; 23 import android.content.res.Resources; 24 import android.graphics.Bitmap; 25 import android.graphics.Canvas; 26 import android.graphics.Paint; 27 import android.graphics.drawable.BitmapDrawable; 28 import android.graphics.drawable.Drawable; 29 import android.os.UserHandle; 30 import android.util.DisplayMetrics; 31 import android.util.Log; 32 import android.view.Display; 33 import android.view.View; 34 35 import com.android.systemui.R; 36 import com.android.systemui.RecentsComponent; 37 import com.android.systemui.SystemUI; 38 39 public class Recents extends SystemUI implements RecentsComponent { 40 private static final String TAG = "Recents"; 41 private static final boolean DEBUG = false; 42 43 @Override 44 public void start() { 45 putComponent(RecentsComponent.class, this); 46 } 47 48 @Override 49 public void toggleRecents(Display display, int layoutDirection, View statusBarView) { 50 if (DEBUG) Log.d(TAG, "toggle recents panel"); 51 try { 52 TaskDescription firstTask = RecentTasksLoader.getInstance(mContext).getFirstTask(); 53 54 Intent intent = new Intent(RecentsActivity.TOGGLE_RECENTS_INTENT); 55 intent.setClassName("com.android.systemui", 56 "com.android.systemui.recent.RecentsActivity"); 57 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 58 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 59 60 if (firstTask == null) { 61 if (RecentsActivity.forceOpaqueBackground(mContext)) { 62 ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, 63 R.anim.recents_launch_from_launcher_enter, 64 R.anim.recents_launch_from_launcher_exit); 65 mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle( 66 UserHandle.USER_CURRENT)); 67 } else { 68 // The correct window animation will be applied via the activity's style 69 mContext.startActivityAsUser(intent, new UserHandle( 70 UserHandle.USER_CURRENT)); 71 } 72 73 } else { 74 Bitmap first = null; 75 if (firstTask.getThumbnail() instanceof BitmapDrawable) { 76 first = ((BitmapDrawable) firstTask.getThumbnail()).getBitmap(); 77 } else { 78 first = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); 79 Drawable d = RecentTasksLoader.getInstance(mContext).getDefaultThumbnail(); 80 d.draw(new Canvas(first)); 81 } 82 final Resources res = mContext.getResources(); 83 84 float thumbWidth = res 85 .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_width); 86 float thumbHeight = res 87 .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_height); 88 if (first == null) { 89 throw new RuntimeException("Recents thumbnail is null"); 90 } 91 if (first.getWidth() != thumbWidth || first.getHeight() != thumbHeight) { 92 first = Bitmap.createScaledBitmap(first, (int) thumbWidth, (int) thumbHeight, 93 true); 94 if (first == null) { 95 throw new RuntimeException("Recents thumbnail is null"); 96 } 97 } 98 99 100 DisplayMetrics dm = new DisplayMetrics(); 101 display.getMetrics(dm); 102 // calculate it here, but consider moving it elsewhere 103 // first, determine which orientation you're in. 104 final Configuration config = res.getConfiguration(); 105 int x, y; 106 107 if (config.orientation == Configuration.ORIENTATION_PORTRAIT) { 108 float appLabelLeftMargin = res.getDimensionPixelSize( 109 R.dimen.status_bar_recents_app_label_left_margin); 110 float appLabelWidth = res.getDimensionPixelSize( 111 R.dimen.status_bar_recents_app_label_width); 112 float thumbLeftMargin = res.getDimensionPixelSize( 113 R.dimen.status_bar_recents_thumbnail_left_margin); 114 float thumbBgPadding = res.getDimensionPixelSize( 115 R.dimen.status_bar_recents_thumbnail_bg_padding); 116 117 float width = appLabelLeftMargin + 118 +appLabelWidth 119 + thumbLeftMargin 120 + thumbWidth 121 + 2 * thumbBgPadding; 122 123 x = (int) ((dm.widthPixels - width) / 2f + appLabelLeftMargin + appLabelWidth 124 + thumbBgPadding + thumbLeftMargin); 125 y = (int) (dm.heightPixels 126 - res.getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_height) 127 - thumbBgPadding); 128 if (layoutDirection == View.LAYOUT_DIRECTION_RTL) { 129 x = dm.widthPixels - x - res.getDimensionPixelSize( 130 R.dimen.status_bar_recents_thumbnail_width); 131 } 132 133 } else { // if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) { 134 float thumbTopMargin = res.getDimensionPixelSize( 135 R.dimen.status_bar_recents_thumbnail_top_margin); 136 float thumbBgPadding = res.getDimensionPixelSize( 137 R.dimen.status_bar_recents_thumbnail_bg_padding); 138 float textPadding = res.getDimensionPixelSize( 139 R.dimen.status_bar_recents_text_description_padding); 140 float labelTextSize = res.getDimensionPixelSize( 141 R.dimen.status_bar_recents_app_label_text_size); 142 Paint p = new Paint(); 143 p.setTextSize(labelTextSize); 144 float labelTextHeight = p.getFontMetricsInt().bottom 145 - p.getFontMetricsInt().top; 146 float descriptionTextSize = res.getDimensionPixelSize( 147 R.dimen.status_bar_recents_app_description_text_size); 148 p.setTextSize(descriptionTextSize); 149 float descriptionTextHeight = p.getFontMetricsInt().bottom 150 - p.getFontMetricsInt().top; 151 152 float statusBarHeight = res.getDimensionPixelSize( 153 com.android.internal.R.dimen.status_bar_height); 154 float recentsItemTopPadding = statusBarHeight; 155 156 float height = thumbTopMargin 157 + thumbHeight 158 + 2 * thumbBgPadding + textPadding + labelTextHeight 159 + recentsItemTopPadding + textPadding + descriptionTextHeight; 160 float recentsItemRightPadding = res 161 .getDimensionPixelSize(R.dimen.status_bar_recents_item_padding); 162 float recentsScrollViewRightPadding = res 163 .getDimensionPixelSize(R.dimen.status_bar_recents_right_glow_margin); 164 x = (int) (dm.widthPixels - res 165 .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_width) 166 - thumbBgPadding - recentsItemRightPadding 167 - recentsScrollViewRightPadding); 168 y = (int) ((dm.heightPixels - statusBarHeight - height) / 2f + thumbTopMargin 169 + recentsItemTopPadding + thumbBgPadding + statusBarHeight); 170 } 171 172 ActivityOptions opts = ActivityOptions.makeThumbnailScaleDownAnimation( 173 statusBarView, 174 first, x, y, 175 new ActivityOptions.OnAnimationStartedListener() { 176 public void onAnimationStarted() { 177 Intent intent = 178 new Intent(RecentsActivity.WINDOW_ANIMATION_START_INTENT); 179 intent.setPackage("com.android.systemui"); 180 mContext.sendBroadcastAsUser(intent, 181 new UserHandle(UserHandle.USER_CURRENT)); 182 } 183 }); 184 intent.putExtra(RecentsActivity.WAITING_FOR_WINDOW_ANIMATION_PARAM, true); 185 mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle( 186 UserHandle.USER_CURRENT)); 187 } 188 } catch (ActivityNotFoundException e) { 189 Log.e(TAG, "Failed to launch RecentAppsIntent", e); 190 } 191 } 192 193 @Override 194 public void preloadRecentTasksList() { 195 if (DEBUG) Log.d(TAG, "preloading recents"); 196 Intent intent = new Intent(RecentsActivity.PRELOAD_INTENT); 197 intent.setClassName("com.android.systemui", 198 "com.android.systemui.recent.RecentsPreloadReceiver"); 199 mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT)); 200 201 RecentTasksLoader.getInstance(mContext).preloadFirstTask(); 202 } 203 204 @Override 205 public void cancelPreloadingRecentTasksList() { 206 if (DEBUG) Log.d(TAG, "cancel preloading recents"); 207 Intent intent = new Intent(RecentsActivity.CANCEL_PRELOAD_INTENT); 208 intent.setClassName("com.android.systemui", 209 "com.android.systemui.recent.RecentsPreloadReceiver"); 210 mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT)); 211 212 RecentTasksLoader.getInstance(mContext).cancelPreloadingFirstTask(); 213 } 214 215 @Override 216 public void closeRecents() { 217 if (DEBUG) Log.d(TAG, "closing recents panel"); 218 Intent intent = new Intent(RecentsActivity.CLOSE_RECENTS_INTENT); 219 intent.setPackage("com.android.systemui"); 220 mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT)); 221 } 222 } 223