[go: nahoru, domu]

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