18ae4198a448ab308aed95756e82da82ce42735a7Winson Chung/*
28ae4198a448ab308aed95756e82da82ce42735a7Winson Chung * Copyright (C) 2017 The Android Open Source Project
38ae4198a448ab308aed95756e82da82ce42735a7Winson Chung *
48ae4198a448ab308aed95756e82da82ce42735a7Winson Chung * Licensed under the Apache License, Version 2.0 (the "License");
58ae4198a448ab308aed95756e82da82ce42735a7Winson Chung * you may not use this file except in compliance with the License.
68ae4198a448ab308aed95756e82da82ce42735a7Winson Chung * You may obtain a copy of the License at
78ae4198a448ab308aed95756e82da82ce42735a7Winson Chung *
88ae4198a448ab308aed95756e82da82ce42735a7Winson Chung *      http://www.apache.org/licenses/LICENSE-2.0
98ae4198a448ab308aed95756e82da82ce42735a7Winson Chung *
108ae4198a448ab308aed95756e82da82ce42735a7Winson Chung * Unless required by applicable law or agreed to in writing, software
118ae4198a448ab308aed95756e82da82ce42735a7Winson Chung * distributed under the License is distributed on an "AS IS" BASIS,
128ae4198a448ab308aed95756e82da82ce42735a7Winson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138ae4198a448ab308aed95756e82da82ce42735a7Winson Chung * See the License for the specific language governing permissions and
148ae4198a448ab308aed95756e82da82ce42735a7Winson Chung * limitations under the License.
158ae4198a448ab308aed95756e82da82ce42735a7Winson Chung */
168ae4198a448ab308aed95756e82da82ce42735a7Winson Chung
17f633ef5f4310b6f79087797a2dc215812f841b70Sunny Goyalpackage com.android.quickstep.views;
188ae4198a448ab308aed95756e82da82ce42735a7Winson Chung
196dceb7755a40de149ee1548d1ebf728ab4ea8318Winson Chungimport static android.widget.Toast.LENGTH_SHORT;
20783cd3cf213ddb37920d1e88ddb9ce83352e8754Vadim Tryshev
21d58c2d5a48f163d7f6837cef3415562a81582df9Tony Wickhamimport static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA_MULTIPLIER;
22c879dbf7646b244c32df99ad0f04c0e4e67af2baTony Wickham
23c879dbf7646b244c32df99ad0f04c0e4e67af2baTony Wickhamimport android.animation.Animator;
24c879dbf7646b244c32df99ad0f04c0e4e67af2baTony Wickhamimport android.animation.AnimatorListenerAdapter;
25c879dbf7646b244c32df99ad0f04c0e4e67af2baTony Wickhamimport android.animation.ObjectAnimator;
26e15e2a8267c677a41bd91eac4d79ee36d467d8d4Sunny Goyalimport android.animation.TimeInterpolator;
27b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chungimport android.app.ActivityOptions;
288ae4198a448ab308aed95756e82da82ce42735a7Winson Chungimport android.content.Context;
29bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyalimport android.content.res.Resources;
30bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyalimport android.graphics.Outline;
31ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshevimport android.os.Bundle;
329c70e7e220b8ffebc15d3cc1fed89163d4724abfTonyimport android.os.Handler;
338ae4198a448ab308aed95756e82da82ce42735a7Winson Chungimport android.util.AttributeSet;
34b271ad89728d9af582022a07fd190c3f3d685b97Tonyimport android.util.FloatProperty;
3580602a94ec225e26e39c4054d71da711bf17a531Winson Chungimport android.util.Log;
36b271ad89728d9af582022a07fd190c3f3d685b97Tonyimport android.util.Property;
37bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyalimport android.view.View;
38bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyalimport android.view.ViewOutlineProvider;
39ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshevimport android.view.accessibility.AccessibilityNodeInfo;
408ae4198a448ab308aed95756e82da82ce42735a7Winson Chungimport android.widget.FrameLayout;
416dceb7755a40de149ee1548d1ebf728ab4ea8318Winson Chungimport android.widget.Toast;
42b271ad89728d9af582022a07fd190c3f3d685b97Tony
439bd862e588aad4971f0f4383412b20ddeb0ff4b4Tony Wickhamimport com.android.launcher3.BaseActivity;
440b0847b272a37ed115504956be5ce44a96b5784cSunny Goyalimport com.android.launcher3.BaseDraggingActivity;
458ae4198a448ab308aed95756e82da82ce42735a7Winson Chungimport com.android.launcher3.R;
469bd862e588aad4971f0f4383412b20ddeb0ff4b4Tony Wickhamimport com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
479bd862e588aad4971f0f4383412b20ddeb0ff4b4Tony Wickhamimport com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
48ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshevimport com.android.quickstep.TaskSystemShortcut;
499bd862e588aad4971f0f4383412b20ddeb0ff4b4Tony Wickhamimport com.android.quickstep.TaskUtils;
50f633ef5f4310b6f79087797a2dc215812f841b70Sunny Goyalimport com.android.quickstep.views.RecentsView.PageCallbacks;
51f633ef5f4310b6f79087797a2dc215812f841b70Sunny Goyalimport com.android.quickstep.views.RecentsView.ScrollState;
528ae4198a448ab308aed95756e82da82ce42735a7Winson Chungimport com.android.systemui.shared.recents.model.Task;
538ae4198a448ab308aed95756e82da82ce42735a7Winson Chungimport com.android.systemui.shared.recents.model.Task.TaskCallbacks;
548ae4198a448ab308aed95756e82da82ce42735a7Winson Chungimport com.android.systemui.shared.recents.model.ThumbnailData;
558ae4198a448ab308aed95756e82da82ce42735a7Winson Chungimport com.android.systemui.shared.system.ActivityManagerWrapper;
568ae4198a448ab308aed95756e82da82ce42735a7Winson Chung
579c70e7e220b8ffebc15d3cc1fed89163d4724abfTonyimport java.util.function.Consumer;
58b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung
598ae4198a448ab308aed95756e82da82ce42735a7Winson Chung/**
608ae4198a448ab308aed95756e82da82ce42735a7Winson Chung * A task in the Recents view.
618ae4198a448ab308aed95756e82da82ce42735a7Winson Chung */
6205a3bbdef8c328370a51e045db12d67e62956b3fSunny Goyalpublic class TaskView extends FrameLayout implements TaskCallbacks, PageCallbacks {
63e15e2a8267c677a41bd91eac4d79ee36d467d8d4Sunny Goyal
6480602a94ec225e26e39c4054d71da711bf17a531Winson Chung    private static final String TAG = TaskView.class.getSimpleName();
6580602a94ec225e26e39c4054d71da711bf17a531Winson Chung
6659a38e67885cceae10649f19f822bfde84c5ed57Tony Wickham    /** A curve of x from 0 to 1, where 0 is the center of the screen and 1 is the edge. */
675cd8ab938c7439c3cfabee5293be35c35d121f2fTony    private static final TimeInterpolator CURVE_INTERPOLATOR
6859a38e67885cceae10649f19f822bfde84c5ed57Tony Wickham            = x -> (float) -Math.cos(x * Math.PI) / 2f + .5f;
69e15e2a8267c677a41bd91eac4d79ee36d467d8d4Sunny Goyal
70e15e2a8267c677a41bd91eac4d79ee36d467d8d4Sunny Goyal    /**
71e15e2a8267c677a41bd91eac4d79ee36d467d8d4Sunny Goyal     * The alpha of a black scrim on a page in the carousel as it leaves the screen.
72e15e2a8267c677a41bd91eac4d79ee36d467d8d4Sunny Goyal     * In the resting position of the carousel, the adjacent pages have about half this scrim.
73e15e2a8267c677a41bd91eac4d79ee36d467d8d4Sunny Goyal     */
7459a38e67885cceae10649f19f822bfde84c5ed57Tony Wickham    private static final float MAX_PAGE_SCRIM_ALPHA = 0.4f;
758643cd4ef492ba5257eb5cebc4aaef8333275a21Tony Wickham
765eb4a1e90d9eb168f4d31a58b43130aff5afeb28Tony Wickham    /**
775eb4a1e90d9eb168f4d31a58b43130aff5afeb28Tony Wickham     * How much to scale down pages near the edge of the screen.
785eb4a1e90d9eb168f4d31a58b43130aff5afeb28Tony Wickham     */
795eb4a1e90d9eb168f4d31a58b43130aff5afeb28Tony Wickham    private static final float EDGE_SCALE_DOWN_FACTOR = 0.03f;
805eb4a1e90d9eb168f4d31a58b43130aff5afeb28Tony Wickham
81b271ad89728d9af582022a07fd190c3f3d685b97Tony    public static final long SCALE_ICON_DURATION = 120;
82d58c2d5a48f163d7f6837cef3415562a81582df9Tony Wickham    private static final long DIM_ANIM_DURATION = 700;
83b271ad89728d9af582022a07fd190c3f3d685b97Tony
84b271ad89728d9af582022a07fd190c3f3d685b97Tony    public static final Property<TaskView, Float> ZOOM_SCALE =
85b271ad89728d9af582022a07fd190c3f3d685b97Tony            new FloatProperty<TaskView>("zoomScale") {
86b271ad89728d9af582022a07fd190c3f3d685b97Tony                @Override
87b271ad89728d9af582022a07fd190c3f3d685b97Tony                public void setValue(TaskView taskView, float v) {
88b271ad89728d9af582022a07fd190c3f3d685b97Tony                    taskView.setZoomScale(v);
89b271ad89728d9af582022a07fd190c3f3d685b97Tony                }
90b271ad89728d9af582022a07fd190c3f3d685b97Tony
91b271ad89728d9af582022a07fd190c3f3d685b97Tony                @Override
92b271ad89728d9af582022a07fd190c3f3d685b97Tony                public Float get(TaskView taskView) {
93b271ad89728d9af582022a07fd190c3f3d685b97Tony                    return taskView.mZoomScale;
94b271ad89728d9af582022a07fd190c3f3d685b97Tony                }
95b271ad89728d9af582022a07fd190c3f3d685b97Tony            };
960349b6c01c360c77a475a309b7c946ba2c779170Tony Wickham
978ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    private Task mTask;
988ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    private TaskThumbnailView mSnapshotView;
9985c53f2af562f0b4a2ec50d1bf83bbaf64fd57ebSunny Goyal    private IconView mIconView;
1000c95559cbc65dee86feba07261b24f4541a05066Tony    private float mCurveScale;
101b271ad89728d9af582022a07fd190c3f3d685b97Tony    private float mZoomScale;
102c879dbf7646b244c32df99ad0f04c0e4e67af2baTony Wickham    private Animator mDimAlphaAnim;
1038ae4198a448ab308aed95756e82da82ce42735a7Winson Chung
1048ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    public TaskView(Context context) {
1058ae4198a448ab308aed95756e82da82ce42735a7Winson Chung        this(context, null);
1068ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    }
1078ae4198a448ab308aed95756e82da82ce42735a7Winson Chung
1088ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    public TaskView(Context context, AttributeSet attrs) {
1098ae4198a448ab308aed95756e82da82ce42735a7Winson Chung        this(context, attrs, 0);
1108ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    }
1118ae4198a448ab308aed95756e82da82ce42735a7Winson Chung
1128ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    public TaskView(Context context, AttributeSet attrs, int defStyleAttr) {
1138ae4198a448ab308aed95756e82da82ce42735a7Winson Chung        super(context, attrs, defStyleAttr);
11427289bbe409643a0e673350304a28da20f0e1644Hyunyoung Song        setOnClickListener((view) -> {
11527289bbe409643a0e673350304a28da20f0e1644Hyunyoung Song            if (getTask() == null) {
11627289bbe409643a0e673350304a28da20f0e1644Hyunyoung Song                return;
11727289bbe409643a0e673350304a28da20f0e1644Hyunyoung Song            }
11827289bbe409643a0e673350304a28da20f0e1644Hyunyoung Song            launchTask(true /* animate */);
11927289bbe409643a0e673350304a28da20f0e1644Hyunyoung Song            BaseActivity.fromContext(context).getUserEventDispatcher().logTaskLaunchOrDismiss(
120783cd3cf213ddb37920d1e88ddb9ce83352e8754Vadim Tryshev                    Touch.TAP, Direction.NONE, getRecentsView().indexOfChild(this),
12127289bbe409643a0e673350304a28da20f0e1644Hyunyoung Song                    TaskUtils.getComponentKeyForTask(getTask().key));
12227289bbe409643a0e673350304a28da20f0e1644Hyunyoung Song        });
123bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyal        setOutlineProvider(new TaskOutlineProvider(getResources()));
1248ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    }
1258ae4198a448ab308aed95756e82da82ce42735a7Winson Chung
1268ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    @Override
1278ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    protected void onFinishInflate() {
1280607cf03eae90e22fb05d8938b597c72d356c395Sunny Goyal        super.onFinishInflate();
1298ae4198a448ab308aed95756e82da82ce42735a7Winson Chung        mSnapshotView = findViewById(R.id.snapshot);
1308ae4198a448ab308aed95756e82da82ce42735a7Winson Chung        mIconView = findViewById(R.id.icon);
1318ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    }
1328ae4198a448ab308aed95756e82da82ce42735a7Winson Chung
1338ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    /**
1348ae4198a448ab308aed95756e82da82ce42735a7Winson Chung     * Updates this task view to the given {@param task}.
1358ae4198a448ab308aed95756e82da82ce42735a7Winson Chung     */
1368ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    public void bind(Task task) {
137b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung        if (mTask != null) {
138b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung            mTask.removeCallback(this);
139b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung        }
1408ae4198a448ab308aed95756e82da82ce42735a7Winson Chung        mTask = task;
1410ea5006cbaa9a15ae333cc3e09b4e68ebbdc8dd2Sunny Goyal        mSnapshotView.bind();
1428ae4198a448ab308aed95756e82da82ce42735a7Winson Chung        task.addCallback(this);
1434ba5e6046fea22699f9608c6fc644dcec477dcbeVadim Tryshev        setContentDescription(task.titleDescription);
1448ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    }
1458ae4198a448ab308aed95756e82da82ce42735a7Winson Chung
146b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung    public Task getTask() {
147b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung        return mTask;
148b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung    }
149b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung
150b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung    public TaskThumbnailView getThumbnail() {
151b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung        return mSnapshotView;
152b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung    }
153b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung
15485c53f2af562f0b4a2ec50d1bf83bbaf64fd57ebSunny Goyal    public IconView getIconView() {
1557d2e40912eb7007e8378f106556b4cbcbc24d661Sunny Goyal        return mIconView;
1567d2e40912eb7007e8378f106556b4cbcbc24d661Sunny Goyal    }
1577d2e40912eb7007e8378f106556b4cbcbc24d661Sunny Goyal
158b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung    public void launchTask(boolean animate) {
15980602a94ec225e26e39c4054d71da711bf17a531Winson Chung        launchTask(animate, (result) -> {
16080602a94ec225e26e39c4054d71da711bf17a531Winson Chung            if (!result) {
1616dceb7755a40de149ee1548d1ebf728ab4ea8318Winson Chung                notifyTaskLaunchFailed(TAG);
16280602a94ec225e26e39c4054d71da711bf17a531Winson Chung            }
16380602a94ec225e26e39c4054d71da711bf17a531Winson Chung        }, getHandler());
1649c70e7e220b8ffebc15d3cc1fed89163d4724abfTony    }
1659c70e7e220b8ffebc15d3cc1fed89163d4724abfTony
1669c70e7e220b8ffebc15d3cc1fed89163d4724abfTony    public void launchTask(boolean animate, Consumer<Boolean> resultCallback,
1679c70e7e220b8ffebc15d3cc1fed89163d4724abfTony            Handler resultCallbackHandler) {
168b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung        if (mTask != null) {
169b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung            final ActivityOptions opts;
170b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung            if (animate) {
1710b0847b272a37ed115504956be5ce44a96b5784cSunny Goyal                opts = BaseDraggingActivity.fromContext(getContext())
17273c27ec176270cb2dff8f0c974a64eddb383b377Jon Miranda                        .getActivityLaunchOptions(this);
173b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung            } else {
174b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung                opts = ActivityOptions.makeCustomAnimation(getContext(), 0, 0);
175b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung            }
176b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung            ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(mTask.key,
1779c70e7e220b8ffebc15d3cc1fed89163d4724abfTony                    opts, resultCallback, resultCallbackHandler);
178b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung        }
179b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung    }
180b63b44c3d55cc49423b9c70d37f2e1d9a0799ea4Winson Chung
1818ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    @Override
1828ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    public void onTaskDataLoaded(Task task, ThumbnailData thumbnailData) {
183bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyal        mSnapshotView.setThumbnail(task, thumbnailData);
18485c53f2af562f0b4a2ec50d1bf83bbaf64fd57ebSunny Goyal        mIconView.setDrawable(task.icon);
1859c70e7e220b8ffebc15d3cc1fed89163d4724abfTony        mIconView.setOnClickListener(icon -> TaskMenuView.showForTask(this));
186f3c10bf15f18d20657e980ba801268238aea8298Tony Wickham        mIconView.setOnLongClickListener(icon -> {
187f3c10bf15f18d20657e980ba801268238aea8298Tony Wickham            requestDisallowInterceptTouchEvent(true);
188f3c10bf15f18d20657e980ba801268238aea8298Tony Wickham            return TaskMenuView.showForTask(this);
189f3c10bf15f18d20657e980ba801268238aea8298Tony Wickham        });
1908ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    }
1918ae4198a448ab308aed95756e82da82ce42735a7Winson Chung
1928ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    @Override
1938ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    public void onTaskDataUnloaded() {
194bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyal        mSnapshotView.setThumbnail(null, null);
19585c53f2af562f0b4a2ec50d1bf83bbaf64fd57ebSunny Goyal        mIconView.setDrawable(null);
1962fae2a0e9c337d217a63980f19eaae198720f86aTony Wickham        mIconView.setOnLongClickListener(null);
1978ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    }
1988ae4198a448ab308aed95756e82da82ce42735a7Winson Chung
1998ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    @Override
2008ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    public void onTaskWindowingModeChanged() {
2018ae4198a448ab308aed95756e82da82ce42735a7Winson Chung        // Do nothing
2028ae4198a448ab308aed95756e82da82ce42735a7Winson Chung    }
2038643cd4ef492ba5257eb5cebc4aaef8333275a21Tony Wickham
204c879dbf7646b244c32df99ad0f04c0e4e67af2baTony Wickham    public void animateIconToScaleAndDim(float scale) {
20560876ac0d77cbf3abda9eb609f6cd49ea3081cfaSunny Goyal        mIconView.animate().scaleX(scale).scaleY(scale).setDuration(SCALE_ICON_DURATION).start();
206d58c2d5a48f163d7f6837cef3415562a81582df9Tony Wickham        mDimAlphaAnim = ObjectAnimator.ofFloat(mSnapshotView, DIM_ALPHA_MULTIPLIER, 1 - scale,
207d58c2d5a48f163d7f6837cef3415562a81582df9Tony Wickham                scale);
208d58c2d5a48f163d7f6837cef3415562a81582df9Tony Wickham        mDimAlphaAnim.setDuration(DIM_ANIM_DURATION);
209c879dbf7646b244c32df99ad0f04c0e4e67af2baTony Wickham        mDimAlphaAnim.addListener(new AnimatorListenerAdapter() {
210c879dbf7646b244c32df99ad0f04c0e4e67af2baTony Wickham            @Override
211c879dbf7646b244c32df99ad0f04c0e4e67af2baTony Wickham            public void onAnimationEnd(Animator animation) {
212c879dbf7646b244c32df99ad0f04c0e4e67af2baTony Wickham                mDimAlphaAnim = null;
213c879dbf7646b244c32df99ad0f04c0e4e67af2baTony Wickham            }
214c879dbf7646b244c32df99ad0f04c0e4e67af2baTony Wickham        });
215c879dbf7646b244c32df99ad0f04c0e4e67af2baTony Wickham        mDimAlphaAnim.start();
2160349b6c01c360c77a475a309b7c946ba2c779170Tony Wickham    }
2170349b6c01c360c77a475a309b7c946ba2c779170Tony Wickham
218c879dbf7646b244c32df99ad0f04c0e4e67af2baTony Wickham    protected void setIconScaleAndDim(float iconScale) {
21960876ac0d77cbf3abda9eb609f6cd49ea3081cfaSunny Goyal        mIconView.animate().cancel();
22060876ac0d77cbf3abda9eb609f6cd49ea3081cfaSunny Goyal        mIconView.setScaleX(iconScale);
22160876ac0d77cbf3abda9eb609f6cd49ea3081cfaSunny Goyal        mIconView.setScaleY(iconScale);
222c879dbf7646b244c32df99ad0f04c0e4e67af2baTony Wickham        if (mDimAlphaAnim != null) {
223c879dbf7646b244c32df99ad0f04c0e4e67af2baTony Wickham            mDimAlphaAnim.cancel();
224c879dbf7646b244c32df99ad0f04c0e4e67af2baTony Wickham        }
225d58c2d5a48f163d7f6837cef3415562a81582df9Tony Wickham        mSnapshotView.setDimAlphaMultipler(iconScale);
2260349b6c01c360c77a475a309b7c946ba2c779170Tony Wickham    }
227e15e2a8267c677a41bd91eac4d79ee36d467d8d4Sunny Goyal
228005df0ba69e38aa94a9f55eb43819a426c0cd3ccTony Wickham    public void resetVisualProperties() {
229b271ad89728d9af582022a07fd190c3f3d685b97Tony        setZoomScale(1);
230005df0ba69e38aa94a9f55eb43819a426c0cd3ccTony Wickham        setTranslationX(0f);
231005df0ba69e38aa94a9f55eb43819a426c0cd3ccTony Wickham        setTranslationY(0f);
23220a13ff54e5579a5d4efcdcb822df7a39f05de4aSunny Goyal        setTranslationZ(0);
233005df0ba69e38aa94a9f55eb43819a426c0cd3ccTony Wickham        setAlpha(1f);
23428254eec60526f27768a928c142f584b78965970Sunny Goyal        setIconScaleAndDim(1);
235005df0ba69e38aa94a9f55eb43819a426c0cd3ccTony Wickham    }
236005df0ba69e38aa94a9f55eb43819a426c0cd3ccTony Wickham
237e15e2a8267c677a41bd91eac4d79ee36d467d8d4Sunny Goyal    @Override
2385cd8ab938c7439c3cfabee5293be35c35d121f2fTony    public void onPageScroll(ScrollState scrollState) {
239e15e2a8267c677a41bd91eac4d79ee36d467d8d4Sunny Goyal        float curveInterpolation =
240e15e2a8267c677a41bd91eac4d79ee36d467d8d4Sunny Goyal                CURVE_INTERPOLATOR.getInterpolation(scrollState.linearInterpolation);
241e15e2a8267c677a41bd91eac4d79ee36d467d8d4Sunny Goyal
242d58c2d5a48f163d7f6837cef3415562a81582df9Tony Wickham        mSnapshotView.setDimAlpha(curveInterpolation * MAX_PAGE_SCRIM_ALPHA);
243b271ad89728d9af582022a07fd190c3f3d685b97Tony        setCurveScale(getCurveScaleForCurveInterpolation(curveInterpolation));
2440c95559cbc65dee86feba07261b24f4541a05066Tony    }
2450c95559cbc65dee86feba07261b24f4541a05066Tony
2465fdd300e8a6481502bb3728fea500270d6d4722aSunny Goyal    @Override
2475fdd300e8a6481502bb3728fea500270d6d4722aSunny Goyal    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
2485fdd300e8a6481502bb3728fea500270d6d4722aSunny Goyal        super.onLayout(changed, left, top, right, bottom);
2495fdd300e8a6481502bb3728fea500270d6d4722aSunny Goyal        setPivotX((right - left) * 0.5f);
2505fdd300e8a6481502bb3728fea500270d6d4722aSunny Goyal        setPivotY(mSnapshotView.getTop() + mSnapshotView.getHeight() * 0.5f);
2515fdd300e8a6481502bb3728fea500270d6d4722aSunny Goyal    }
2525fdd300e8a6481502bb3728fea500270d6d4722aSunny Goyal
2539bb8ffb5e303597bd65ee4cae957c64c1f532d10Sunny Goyal    public static float getCurveScaleForInterpolation(float linearInterpolation) {
25478595cd7dea011bcfc9b40791a5f85bdaa122c23Tony Wickham        float curveInterpolation = CURVE_INTERPOLATOR.getInterpolation(linearInterpolation);
25578595cd7dea011bcfc9b40791a5f85bdaa122c23Tony Wickham        return getCurveScaleForCurveInterpolation(curveInterpolation);
25678595cd7dea011bcfc9b40791a5f85bdaa122c23Tony Wickham    }
25778595cd7dea011bcfc9b40791a5f85bdaa122c23Tony Wickham
2589bb8ffb5e303597bd65ee4cae957c64c1f532d10Sunny Goyal    private static float getCurveScaleForCurveInterpolation(float curveInterpolation) {
25978595cd7dea011bcfc9b40791a5f85bdaa122c23Tony Wickham        return 1 - curveInterpolation * EDGE_SCALE_DOWN_FACTOR;
26078595cd7dea011bcfc9b40791a5f85bdaa122c23Tony Wickham    }
26178595cd7dea011bcfc9b40791a5f85bdaa122c23Tony Wickham
262b271ad89728d9af582022a07fd190c3f3d685b97Tony    private void setCurveScale(float curveScale) {
263b271ad89728d9af582022a07fd190c3f3d685b97Tony        mCurveScale = curveScale;
264b271ad89728d9af582022a07fd190c3f3d685b97Tony        onScaleChanged();
265b271ad89728d9af582022a07fd190c3f3d685b97Tony    }
266b271ad89728d9af582022a07fd190c3f3d685b97Tony
2670c95559cbc65dee86feba07261b24f4541a05066Tony    public float getCurveScale() {
2680c95559cbc65dee86feba07261b24f4541a05066Tony        return mCurveScale;
269e15e2a8267c677a41bd91eac4d79ee36d467d8d4Sunny Goyal    }
270bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyal
271b271ad89728d9af582022a07fd190c3f3d685b97Tony    public void setZoomScale(float adjacentScale) {
272b271ad89728d9af582022a07fd190c3f3d685b97Tony        mZoomScale = adjacentScale;
273b271ad89728d9af582022a07fd190c3f3d685b97Tony        onScaleChanged();
274b271ad89728d9af582022a07fd190c3f3d685b97Tony    }
275b271ad89728d9af582022a07fd190c3f3d685b97Tony
276b271ad89728d9af582022a07fd190c3f3d685b97Tony    private void onScaleChanged() {
277b271ad89728d9af582022a07fd190c3f3d685b97Tony        float scale = mCurveScale * mZoomScale;
278b271ad89728d9af582022a07fd190c3f3d685b97Tony        setScaleX(scale);
279b271ad89728d9af582022a07fd190c3f3d685b97Tony        setScaleY(scale);
280b271ad89728d9af582022a07fd190c3f3d685b97Tony    }
281b271ad89728d9af582022a07fd190c3f3d685b97Tony
282a9f554681d13bcc88eacea73f715e1c608fdb527Sunny Goyal    @Override
283a9f554681d13bcc88eacea73f715e1c608fdb527Sunny Goyal    public boolean hasOverlappingRendering() {
284a9f554681d13bcc88eacea73f715e1c608fdb527Sunny Goyal        // TODO: Clip-out the icon region from the thumbnail, since they are overlapping.
285a9f554681d13bcc88eacea73f715e1c608fdb527Sunny Goyal        return false;
286a9f554681d13bcc88eacea73f715e1c608fdb527Sunny Goyal    }
287a9f554681d13bcc88eacea73f715e1c608fdb527Sunny Goyal
288bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyal    private static final class TaskOutlineProvider extends ViewOutlineProvider {
289bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyal
290bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyal        private final int mMarginTop;
291bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyal        private final float mRadius;
292bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyal
293bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyal        TaskOutlineProvider(Resources res) {
294bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyal            mMarginTop = res.getDimensionPixelSize(R.dimen.task_thumbnail_top_margin);
295bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyal            mRadius = res.getDimension(R.dimen.task_corner_radius);
296bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyal        }
297bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyal
298bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyal        @Override
299bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyal        public void getOutline(View view, Outline outline) {
300bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyal            outline.setRoundRect(0, mMarginTop, view.getWidth(),
301bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyal                    view.getHeight(), mRadius);
302bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyal        }
303bac7f64fccb8856e7f4a45cf78c811743a3def26Sunny Goyal    }
304ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev
305ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev    @Override
306ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
307ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev        super.onInitializeAccessibilityNodeInfo(info);
308ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev
309ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev        info.addAction(
310ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev                new AccessibilityNodeInfo.AccessibilityAction(R.string.accessibility_close_task,
311ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev                        getContext().getText(R.string.accessibility_close_task)));
312ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev
313ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev        final Context context = getContext();
314ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev        final BaseDraggingActivity activity = BaseDraggingActivity.fromContext(context);
315ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev        for (TaskSystemShortcut menuOption : TaskMenuView.MENU_OPTIONS) {
316ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev            OnClickListener onClickListener = menuOption.getOnClickListener(activity, this);
317ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev            if (onClickListener != null) {
318ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev                info.addAction(new AccessibilityNodeInfo.AccessibilityAction(menuOption.labelResId,
319ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev                        context.getText(menuOption.labelResId)));
320ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev            }
321ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev        }
322783cd3cf213ddb37920d1e88ddb9ce83352e8754Vadim Tryshev
32379141a1236ebf9d540b72cd1bf1bc56d4b5fe954Hyunyoung Song        final RecentsView recentsView = getRecentsView();
32479141a1236ebf9d540b72cd1bf1bc56d4b5fe954Hyunyoung Song        final AccessibilityNodeInfo.CollectionItemInfo itemInfo =
32579141a1236ebf9d540b72cd1bf1bc56d4b5fe954Hyunyoung Song                AccessibilityNodeInfo.CollectionItemInfo.obtain(
326d5ccb6978dbf458280bbea17af4df655510f68d0Vadim Tryshev                        0, 1, recentsView.getChildCount() - recentsView.indexOfChild(this) - 1, 1,
327d5ccb6978dbf458280bbea17af4df655510f68d0Vadim Tryshev                        false);
32879141a1236ebf9d540b72cd1bf1bc56d4b5fe954Hyunyoung Song        info.setCollectionItemInfo(itemInfo);
329ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev    }
330ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev
331ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev    @Override
332ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev    public boolean performAccessibilityAction(int action, Bundle arguments) {
333ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev        if (action == R.string.accessibility_close_task) {
334783cd3cf213ddb37920d1e88ddb9ce83352e8754Vadim Tryshev            getRecentsView().dismissTask(this, true /*animateTaskView*/,
335ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev                    true /*removeTask*/);
336ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev            return true;
337ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev        }
338ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev
339ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev        for (TaskSystemShortcut menuOption : TaskMenuView.MENU_OPTIONS) {
340ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev            if (action == menuOption.labelResId) {
341ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev                OnClickListener onClickListener = menuOption.getOnClickListener(
342ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev                        BaseDraggingActivity.fromContext(getContext()), this);
343ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev                if (onClickListener != null) {
344ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev                    onClickListener.onClick(this);
345ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev                }
346ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev                return true;
347ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev            }
348ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev        }
349ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev
350783cd3cf213ddb37920d1e88ddb9ce83352e8754Vadim Tryshev        if (getRecentsView().performTaskAccessibilityActionExtra(action)) return true;
351783cd3cf213ddb37920d1e88ddb9ce83352e8754Vadim Tryshev
352ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev        return super.performAccessibilityAction(action, arguments);
353ac2042a40a42fcdc483cad512c40291d7f41070aVadim Tryshev    }
35480602a94ec225e26e39c4054d71da711bf17a531Winson Chung
355783cd3cf213ddb37920d1e88ddb9ce83352e8754Vadim Tryshev    private RecentsView getRecentsView() {
356783cd3cf213ddb37920d1e88ddb9ce83352e8754Vadim Tryshev        return (RecentsView) getParent();
357783cd3cf213ddb37920d1e88ddb9ce83352e8754Vadim Tryshev    }
358783cd3cf213ddb37920d1e88ddb9ce83352e8754Vadim Tryshev
3596dceb7755a40de149ee1548d1ebf728ab4ea8318Winson Chung    public void notifyTaskLaunchFailed(String tag) {
36080602a94ec225e26e39c4054d71da711bf17a531Winson Chung        String msg = "Failed to launch task";
36180602a94ec225e26e39c4054d71da711bf17a531Winson Chung        if (mTask != null) {
36280602a94ec225e26e39c4054d71da711bf17a531Winson Chung            msg += " (task=" + mTask.key.baseIntent + " userId=" + mTask.key.userId + ")";
36380602a94ec225e26e39c4054d71da711bf17a531Winson Chung        }
3646dceb7755a40de149ee1548d1ebf728ab4ea8318Winson Chung        Log.w(tag, msg);
3656dceb7755a40de149ee1548d1ebf728ab4ea8318Winson Chung        Toast.makeText(getContext(), R.string.activity_not_available, LENGTH_SHORT).show();
36680602a94ec225e26e39c4054d71da711bf17a531Winson Chung    }
3678ae4198a448ab308aed95756e82da82ce42735a7Winson Chung}
368