1b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan/* 2b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan * Copyright (C) 2016 The Android Open Source Project 3b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan * 4b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan * Licensed under the Apache License, Version 2.0 (the "License"); 5b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan * you may not use this file except in compliance with the License. 6b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan * You may obtain a copy of the License at 7b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan * 8b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan * http://www.apache.org/licenses/LICENSE-2.0 9b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan * 10b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan * Unless required by applicable law or agreed to in writing, software 11b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan * distributed under the License is distributed on an "AS IS" BASIS, 12b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan * See the License for the specific language governing permissions and 14b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan * limitations under the License. 15b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan */ 16b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajanpackage com.android.systemui.recents.tv.views; 17b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan 184bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajanimport android.animation.Animator; 19b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajanimport android.content.Context; 20bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajanimport android.content.pm.PackageManager; 21bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajanimport android.content.res.Configuration; 22fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajanimport android.content.res.Resources; 23bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajanimport android.graphics.Bitmap; 243e3a35eb36c0be407c3d210dedf800ca47b082e7Sid Soundararajanimport android.graphics.Outline; 25fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajanimport android.graphics.Point; 261008cc25863be3d86e01c15eeabe9dfedb963224Sid Soundararajanimport android.graphics.Rect; 27bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajanimport android.graphics.drawable.Drawable; 28b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajanimport android.util.AttributeSet; 29bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajanimport android.util.Log; 30fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajanimport android.util.TypedValue; 31fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajanimport android.view.Display; 324bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajanimport android.view.KeyEvent; 3304cbe870ae6c8721d6322c248d40bb94a9cb5a09Jaewan Kimimport android.view.View; 343e3a35eb36c0be407c3d210dedf800ca47b082e7Sid Soundararajanimport android.view.ViewOutlineProvider; 35fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajanimport android.view.WindowManager; 36b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajanimport android.widget.ImageView; 371008cc25863be3d86e01c15eeabe9dfedb963224Sid Soundararajanimport android.widget.LinearLayout; 38b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajanimport android.widget.TextView; 39c0d7058b14c24cd07912f5629c26b39b7b4673d5Winson 40b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajanimport com.android.systemui.R; 411103bfca8d44150eebdfef50736c6e98455e8d3bSid Soundararajanimport com.android.systemui.recents.Recents; 421103bfca8d44150eebdfef50736c6e98455e8d3bSid Soundararajanimport com.android.systemui.recents.misc.SystemServicesProxy; 43a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kimimport com.android.systemui.recents.model.Task; 44a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kimimport com.android.systemui.recents.tv.RecentsTvActivity; 454bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajanimport com.android.systemui.recents.tv.animations.DismissAnimationsHolder; 4604cbe870ae6c8721d6322c248d40bb94a9cb5a09Jaewan Kimimport com.android.systemui.recents.tv.animations.RecentsRowFocusAnimationHolder; 47c0d7058b14c24cd07912f5629c26b39b7b4673d5Winsonimport com.android.systemui.recents.tv.animations.ViewFocusAnimator; 48b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan 491008cc25863be3d86e01c15eeabe9dfedb963224Sid Soundararajanpublic class TaskCardView extends LinearLayout { 50b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan 51bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan private static final String TAG = "TaskCardView"; 52bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan private View mThumbnailView; 532cc285e2677a567e72c7016693ccab81e27aadb4Sid Soundararajan private View mDismissIconView; 54a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim private View mInfoFieldView; 55b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan private TextView mTitleTextView; 56b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan private ImageView mBadgeView; 57b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan private Task mTask; 584bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan private boolean mDismissState; 596b822694d0d25010533292bd201318d333a6d392Sid Soundararajan private boolean mTouchExplorationEnabled; 603e3a35eb36c0be407c3d210dedf800ca47b082e7Sid Soundararajan private int mCornerRadius; 61b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan 62b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan private ViewFocusAnimator mViewFocusAnimator; 634bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan private DismissAnimationsHolder mDismissAnimationsHolder; 6404cbe870ae6c8721d6322c248d40bb94a9cb5a09Jaewan Kim private RecentsRowFocusAnimationHolder mRecentsRowFocusAnimationHolder; 65b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan 66b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan public TaskCardView(Context context) { 67b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan this(context, null); 68b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan } 69b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan 70b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan public TaskCardView(Context context, AttributeSet attrs) { 71b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan this(context, attrs, 0); 72b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan } 73b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan 74b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan public TaskCardView(Context context, AttributeSet attrs, int defStyleAttr) { 75b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan super(context, attrs, defStyleAttr); 764bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan mDismissState = false; 77bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan Configuration config = getResources().getConfiguration(); 78bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan setLayoutDirection(config.getLayoutDirection()); 79b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan } 80b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan 81b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan @Override 82b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan protected void onFinishInflate() { 8367ed54a724df258738062e60d7f702f396502b49Sid Soundararajan super.onFinishInflate(); 84bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan mThumbnailView = findViewById(R.id.card_view_thumbnail); 85a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim mInfoFieldView = findViewById(R.id.card_info_field); 86b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan mTitleTextView = (TextView) findViewById(R.id.card_title_text); 87b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan mBadgeView = (ImageView) findViewById(R.id.card_extra_badge); 882cc285e2677a567e72c7016693ccab81e27aadb4Sid Soundararajan mDismissIconView = findViewById(R.id.dismiss_icon); 894bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan mDismissAnimationsHolder = new DismissAnimationsHolder(this); 903e3a35eb36c0be407c3d210dedf800ca47b082e7Sid Soundararajan mCornerRadius = getResources().getDimensionPixelSize( 913e3a35eb36c0be407c3d210dedf800ca47b082e7Sid Soundararajan R.dimen.recents_task_view_rounded_corners_radius); 92a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim mRecentsRowFocusAnimationHolder = new RecentsRowFocusAnimationHolder(this, mInfoFieldView); 931103bfca8d44150eebdfef50736c6e98455e8d3bSid Soundararajan SystemServicesProxy ssp = Recents.getSystemServices(); 946b822694d0d25010533292bd201318d333a6d392Sid Soundararajan mTouchExplorationEnabled = ssp.isTouchExplorationEnabled(); 956b822694d0d25010533292bd201318d333a6d392Sid Soundararajan if (!mTouchExplorationEnabled) { 9617d29b6d70a23d56c55a50cce00ffa66ed58ac63Sid Soundararajan mDismissIconView.setVisibility(VISIBLE); 971103bfca8d44150eebdfef50736c6e98455e8d3bSid Soundararajan } else { 9817d29b6d70a23d56c55a50cce00ffa66ed58ac63Sid Soundararajan mDismissIconView.setVisibility(GONE); 991103bfca8d44150eebdfef50736c6e98455e8d3bSid Soundararajan } 100bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan mViewFocusAnimator = new ViewFocusAnimator(this); 101b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan } 102b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan 103b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan public void init(Task task) { 104b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan mTask = task; 105b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan mTitleTextView.setText(task.title); 106b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan mBadgeView.setImageDrawable(task.icon); 107bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan setThumbnailView(); 108caa611f88d374f18ca229749760d10947fdac61aSid Soundararajan setContentDescription(task.titleDescription); 109a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim mDismissState = false; 110a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim mDismissAnimationsHolder.reset(); 111a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim mRecentsRowFocusAnimationHolder.reset(); 112b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan } 113b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan 114b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan public Task getTask() { 115b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan return mTask; 116b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan } 1171008cc25863be3d86e01c15eeabe9dfedb963224Sid Soundararajan 1181008cc25863be3d86e01c15eeabe9dfedb963224Sid Soundararajan @Override 1191008cc25863be3d86e01c15eeabe9dfedb963224Sid Soundararajan public void getFocusedRect(Rect r) { 1201008cc25863be3d86e01c15eeabe9dfedb963224Sid Soundararajan mThumbnailView.getFocusedRect(r); 1211008cc25863be3d86e01c15eeabe9dfedb963224Sid Soundararajan } 1221008cc25863be3d86e01c15eeabe9dfedb963224Sid Soundararajan 123fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan public Rect getFocusedThumbnailRect() { 1241008cc25863be3d86e01c15eeabe9dfedb963224Sid Soundararajan Rect r = new Rect(); 125fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan mThumbnailView.getGlobalVisibleRect(r); 1261008cc25863be3d86e01c15eeabe9dfedb963224Sid Soundararajan return r; 1271008cc25863be3d86e01c15eeabe9dfedb963224Sid Soundararajan } 1281008cc25863be3d86e01c15eeabe9dfedb963224Sid Soundararajan 129ea347d3cafa7ab03dedeb5fe9c330adf6ff34b6aJaewan Kim public static Rect getStartingCardThumbnailRect( 130ea347d3cafa7ab03dedeb5fe9c330adf6ff34b6aJaewan Kim Context context, boolean hasFocus, int numberOfTasks) { 13118cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan if(numberOfTasks > 1) { 132ea347d3cafa7ab03dedeb5fe9c330adf6ff34b6aJaewan Kim return getStartingCardThumbnailRectForStartPosition(context, hasFocus); 13318cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan } else { 134ea347d3cafa7ab03dedeb5fe9c330adf6ff34b6aJaewan Kim return getStartingCardThumbnailRectForFocusedPosition(context, hasFocus); 13518cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan } 13618cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan } 13718cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan 138ea347d3cafa7ab03dedeb5fe9c330adf6ff34b6aJaewan Kim private static Rect getStartingCardThumbnailRectForStartPosition( 139ea347d3cafa7ab03dedeb5fe9c330adf6ff34b6aJaewan Kim Context context, boolean hasFocus) { 14018cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan Resources res = context.getResources(); 14118cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan 14218cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan int width = res.getDimensionPixelOffset(R.dimen.recents_tv_card_width); 143ea347d3cafa7ab03dedeb5fe9c330adf6ff34b6aJaewan Kim int totalSpacing = res.getDimensionPixelOffset(R.dimen.recents_tv_gird_card_spacing) * 2; 144ea347d3cafa7ab03dedeb5fe9c330adf6ff34b6aJaewan Kim if (hasFocus) { 145ea347d3cafa7ab03dedeb5fe9c330adf6ff34b6aJaewan Kim totalSpacing += res.getDimensionPixelOffset(R.dimen.recents_tv_gird_focused_card_delta); 146ea347d3cafa7ab03dedeb5fe9c330adf6ff34b6aJaewan Kim } 14718cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan int height = res.getDimensionPixelOffset(R.dimen.recents_tv_screenshot_height); 14818cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan int topMargin = res.getDimensionPixelOffset(R.dimen.recents_tv_gird_row_top_margin); 14918cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan int headerHeight = res.getDimensionPixelOffset(R.dimen.recents_tv_card_extra_badge_size) + 15018cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan res.getDimensionPixelOffset(R.dimen.recents_tv_icon_padding_bottom); 15118cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan 15218cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 15318cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan Display display = wm.getDefaultDisplay(); 15418cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan Point size = new Point(); 15518cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan display.getSize(size); 15618cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan int screenWidth = size.x; 15718cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan 15818cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan return new Rect(screenWidth / 2 + width / 2 + totalSpacing, 15918cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan topMargin + headerHeight, 16018cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan screenWidth / 2 + width / 2 + totalSpacing + width, 16118cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan topMargin + headerHeight + height); 16218cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan } 16318cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan 164ea347d3cafa7ab03dedeb5fe9c330adf6ff34b6aJaewan Kim private static Rect getStartingCardThumbnailRectForFocusedPosition( 165ea347d3cafa7ab03dedeb5fe9c330adf6ff34b6aJaewan Kim Context context, boolean hasFocus) { 166fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan Resources res = context.getResources(); 167fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan 168fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan TypedValue out = new TypedValue(); 169fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan res.getValue(R.integer.selected_scale, out, true); 170ea347d3cafa7ab03dedeb5fe9c330adf6ff34b6aJaewan Kim float scale = hasFocus ? out.getFloat() : 1; 171fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan 172fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan int width = res.getDimensionPixelOffset(R.dimen.recents_tv_card_width); 173fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan int widthDelta = (int) (width * scale - width); 1744bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan int height = res.getDimensionPixelOffset(R.dimen.recents_tv_screenshot_height); 1754bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan int heightDelta = (int) (height * scale - height); 1764bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan int topMargin = res.getDimensionPixelOffset(R.dimen.recents_tv_gird_row_top_margin); 177fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan 1784bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan int headerHeight = res.getDimensionPixelOffset(R.dimen.recents_tv_card_extra_badge_size) + 1794bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan res.getDimensionPixelOffset(R.dimen.recents_tv_icon_padding_bottom); 1804bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan int headerHeightDelta = (int) (headerHeight * scale - headerHeight); 1814bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan 1824bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan int dismissAreaHeight = 1834bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan res.getDimensionPixelOffset(R.dimen.recents_tv_dismiss_icon_top_margin) + 1844bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan res.getDimensionPixelOffset(R.dimen.recents_tv_dismiss_icon_bottom_margin) + 1854bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan res.getDimensionPixelOffset(R.dimen.recents_tv_dismiss_icon_size) + 1864bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan res.getDimensionPixelOffset(R.dimen.recents_tv_dismiss_text_size); 1874bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan 1884bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan int dismissAreaHeightDelta = (int) (dismissAreaHeight * scale - dismissAreaHeight); 1894bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan 1904bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan int totalHeightDelta = heightDelta + headerHeightDelta + dismissAreaHeightDelta; 191fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan 192fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 193fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan Display display = wm.getDefaultDisplay(); 194fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan Point size = new Point(); 195fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan display.getSize(size); 196fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan int screenWidth = size.x; 197fa61ce343e91e11bb06545eae00e0659a2942a7dSid Soundararajan 1984bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan return new Rect(screenWidth / 2 - width / 2 - widthDelta / 2, 1994bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan topMargin - totalHeightDelta / 2 + (int) (headerHeight * scale), 2004bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan screenWidth / 2 + width / 2 + widthDelta / 2, 2014bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan topMargin - totalHeightDelta / 2 + (int) (headerHeight * scale) + 2024bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan (int) (height * scale)); 2034bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan } 2044bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan 2054bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan @Override 206a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim public boolean dispatchKeyEvent(KeyEvent event) { 207a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim // Override dispatchKeyEvent() instead of onKeyDown() to prevent warning from ViewRootImpl. 208a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim switch (event.getKeyCode()) { 2094bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan case KeyEvent.KEYCODE_DPAD_DOWN : { 210a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim if (!isInDismissState() && event.getAction() == KeyEvent.ACTION_DOWN) { 2114bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan setDismissState(true); 2124bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan return true; 2134bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan } 2144bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan break; 2154bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan } 2164bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan case KeyEvent.KEYCODE_DPAD_UP : { 217a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim if (event.getAction() == KeyEvent.ACTION_DOWN) { 218a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim if (isInDismissState()) { 219a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim setDismissState(false); 220a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim } else { 221a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim ((RecentsTvActivity) getContext()).requestPipControlsFocus(); 222a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim } 2234bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan } 224a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim return true; 2254bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan } 2264bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan 227a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim // Eat right and left key presses when we are in dismiss state 228a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim case KeyEvent.KEYCODE_DPAD_LEFT : 2294bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan case KeyEvent.KEYCODE_DPAD_RIGHT : { 2304bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan if (isInDismissState()) { 2314bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan return true; 2324bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan } 2334bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan break; 2344bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan } 2354bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan } 236a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim return super.dispatchKeyEvent(event); 2374bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan } 2384bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan 2394bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan private void setDismissState(boolean dismissState) { 2404bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan if (mDismissState != dismissState) { 2414bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan mDismissState = dismissState; 2426b822694d0d25010533292bd201318d333a6d392Sid Soundararajan // Check for touch exploration to ensure dismiss icon/text do not 2436b822694d0d25010533292bd201318d333a6d392Sid Soundararajan // get animated. This should be removed based on decision from 2446b822694d0d25010533292bd201318d333a6d392Sid Soundararajan // b/29208918 2456b822694d0d25010533292bd201318d333a6d392Sid Soundararajan if (!mTouchExplorationEnabled) { 2466b822694d0d25010533292bd201318d333a6d392Sid Soundararajan if (dismissState) { 2476b822694d0d25010533292bd201318d333a6d392Sid Soundararajan mDismissAnimationsHolder.startEnterAnimation(); 2486b822694d0d25010533292bd201318d333a6d392Sid Soundararajan } else { 2496b822694d0d25010533292bd201318d333a6d392Sid Soundararajan mDismissAnimationsHolder.startExitAnimation(); 2506b822694d0d25010533292bd201318d333a6d392Sid Soundararajan } 2514bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan } 2524bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan } 2534bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan } 2544bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan 2554bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan public boolean isInDismissState() { 2564bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan return mDismissState; 2574bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan } 2584bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan 2594bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan public void startDismissTaskAnimation(Animator.AnimatorListener listener) { 26085b0a0f1eccc0c32a2032385f2f199c76c50a917Sid Soundararajan mDismissState = false; 2614bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan mDismissAnimationsHolder.startDismissAnimation(listener); 2624bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan } 2634bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan 264a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim public ViewFocusAnimator getViewFocusAnimator() { 265a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim return mViewFocusAnimator; 26604cbe870ae6c8721d6322c248d40bb94a9cb5a09Jaewan Kim } 26704cbe870ae6c8721d6322c248d40bb94a9cb5a09Jaewan Kim 268a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim public RecentsRowFocusAnimationHolder getRecentsRowFocusAnimationHolder() { 269a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim return mRecentsRowFocusAnimationHolder; 27085b0a0f1eccc0c32a2032385f2f199c76c50a917Sid Soundararajan } 271bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan 272bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan private void setThumbnailView() { 273bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan ImageView screenshotView = (ImageView) findViewById(R.id.card_view_banner_icon); 274bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan PackageManager pm = getContext().getPackageManager(); 275bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan if (mTask.thumbnail != null) { 276bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan setAsScreenShotView(mTask.thumbnail, screenshotView); 277bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan } else { 278bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan try { 279bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan Drawable banner = null; 280bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan if (mTask.key != null) { 281bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan banner = pm.getActivityBanner(mTask.key.baseIntent); 282bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan } 283bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan if (banner != null) { 284bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan setAsBannerView(banner, screenshotView); 285bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan } else { 286bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan setAsIconView(mTask.icon, screenshotView); 287bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan } 288bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan } catch (PackageManager.NameNotFoundException e) { 289bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan Log.e(TAG, "Package not found : " + e); 290bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan setAsIconView(mTask.icon, screenshotView); 291bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan } 292bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan } 293bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan } 294bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan 295bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan private void setAsScreenShotView(Bitmap screenshot, ImageView screenshotView) { 296bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan LayoutParams lp = (LayoutParams) screenshotView.getLayoutParams(); 2973e3a35eb36c0be407c3d210dedf800ca47b082e7Sid Soundararajan lp.width = LayoutParams.MATCH_PARENT; 2983e3a35eb36c0be407c3d210dedf800ca47b082e7Sid Soundararajan lp.height = LayoutParams.MATCH_PARENT; 299bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan 300bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan screenshotView.setLayoutParams(lp); 3013e3a35eb36c0be407c3d210dedf800ca47b082e7Sid Soundararajan screenshotView.setClipToOutline(true); 3023e3a35eb36c0be407c3d210dedf800ca47b082e7Sid Soundararajan screenshotView.setOutlineProvider(new ViewOutlineProvider() { 3033e3a35eb36c0be407c3d210dedf800ca47b082e7Sid Soundararajan @Override 3043e3a35eb36c0be407c3d210dedf800ca47b082e7Sid Soundararajan public void getOutline(View view, Outline outline) { 3053e3a35eb36c0be407c3d210dedf800ca47b082e7Sid Soundararajan outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), mCornerRadius); 3063e3a35eb36c0be407c3d210dedf800ca47b082e7Sid Soundararajan } 3073e3a35eb36c0be407c3d210dedf800ca47b082e7Sid Soundararajan }); 3084332dda9a76191b0f055dedbea8d509a20d5c455Sid Soundararajan screenshotView.setImageBitmap(screenshot); 309bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan } 310bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan 311bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan private void setAsBannerView(Drawable banner, ImageView bannerView) { 312bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan LayoutParams lp = (LayoutParams) bannerView.getLayoutParams(); 313bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan lp.width = getResources() 314bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan .getDimensionPixelSize(R.dimen.recents_tv_banner_width); 315bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan lp.height = getResources() 316bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan .getDimensionPixelSize(R.dimen.recents_tv_banner_height); 317bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan bannerView.setLayoutParams(lp); 318bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan bannerView.setImageDrawable(banner); 319bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan } 320bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan 321bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan private void setAsIconView(Drawable icon, ImageView iconView) { 322bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan LayoutParams lp = (LayoutParams) iconView.getLayoutParams(); 323bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan lp.width = getResources() 324bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan .getDimensionPixelSize(R.dimen.recents_tv_fallback_icon_width); 325bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan lp.height = getResources() 326bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan .getDimensionPixelSize(R.dimen.recents_tv_fallback_icon_height); 327bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan 328bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan iconView.setLayoutParams(lp); 329bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan iconView.setImageDrawable(icon); 330bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan } 331bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan 332bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan public View getThumbnailView() { 333bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan return mThumbnailView; 334bda1b17d45267c7e6efd9b03a5ec2b5356aa5eb7Sid Soundararajan } 3352cc285e2677a567e72c7016693ccab81e27aadb4Sid Soundararajan 336a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim public View getInfoFieldView() { 337a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim return mInfoFieldView; 338a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim } 339a9e0621f33233c43f29e876b6c1055cf1dc855fcJaewan Kim 3402cc285e2677a567e72c7016693ccab81e27aadb4Sid Soundararajan public View getDismissIconView() { 3412cc285e2677a567e72c7016693ccab81e27aadb4Sid Soundararajan return mDismissIconView; 3422cc285e2677a567e72c7016693ccab81e27aadb4Sid Soundararajan } 3434332dda9a76191b0f055dedbea8d509a20d5c455Sid Soundararajan 3444332dda9a76191b0f055dedbea8d509a20d5c455Sid Soundararajan public static int getNumberOfVisibleTasks(Context context) { 3454332dda9a76191b0f055dedbea8d509a20d5c455Sid Soundararajan Resources res = context.getResources(); 3464332dda9a76191b0f055dedbea8d509a20d5c455Sid Soundararajan WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 3474332dda9a76191b0f055dedbea8d509a20d5c455Sid Soundararajan Display display = wm.getDefaultDisplay(); 3484332dda9a76191b0f055dedbea8d509a20d5c455Sid Soundararajan Point size = new Point(); 3494332dda9a76191b0f055dedbea8d509a20d5c455Sid Soundararajan display.getSize(size); 3504332dda9a76191b0f055dedbea8d509a20d5c455Sid Soundararajan int screenWidth = size.x; 3514332dda9a76191b0f055dedbea8d509a20d5c455Sid Soundararajan int cardWidth = res.getDimensionPixelSize(R.dimen.recents_tv_card_width); 3524332dda9a76191b0f055dedbea8d509a20d5c455Sid Soundararajan int spacing = res.getDimensionPixelSize(R.dimen.recents_tv_gird_card_spacing); 3534332dda9a76191b0f055dedbea8d509a20d5c455Sid Soundararajan return (int) (1.0 + Math.ceil(screenWidth / (cardWidth + spacing * 2.0))); 3544332dda9a76191b0f055dedbea8d509a20d5c455Sid Soundararajan } 355b58c46acec2e270f24ca587a64298f06cefb09cbSid Soundararajan} 356