14bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan/*
24bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan * Copyright (C) 2016 The Android Open Source Project
34bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan *
44bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan * Licensed under the Apache License, Version 2.0 (the "License");
54bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan * you may not use this file except in compliance with the License.
64bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan * You may obtain a copy of the License at
74bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan *
84bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan *      http://www.apache.org/licenses/LICENSE-2.0
94bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan *
104bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan * Unless required by applicable law or agreed to in writing, software
114bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan * distributed under the License is distributed on an "AS IS" BASIS,
124bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan * See the License for the specific language governing permissions and
144bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan * limitations under the License.
154bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan */
164bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan
174bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajanpackage com.android.systemui.recents.tv;
184bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan
194bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajanimport android.app.ActivityManager;
204bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajanimport android.app.ActivityOptions;
214bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajanimport android.content.Context;
224bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajanimport android.content.Intent;
234bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajanimport android.graphics.Bitmap;
244bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajanimport android.graphics.Rect;
254bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajanimport android.os.SystemClock;
264bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajanimport android.os.UserHandle;
27a1ededd056d51532ab18354f17f8065ec1134535Winson
2867ed54a724df258738062e60d7f702f396502b49Sid Soundararajanimport com.android.systemui.SystemUIApplication;
29a1ededd056d51532ab18354f17f8065ec1134535Winsonimport com.android.systemui.recents.Recents;
30a1ededd056d51532ab18354f17f8065ec1134535Winsonimport com.android.systemui.recents.RecentsActivityLaunchState;
31a1ededd056d51532ab18354f17f8065ec1134535Winsonimport com.android.systemui.recents.RecentsConfiguration;
32a1ededd056d51532ab18354f17f8065ec1134535Winsonimport com.android.systemui.recents.RecentsImpl;
334bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajanimport com.android.systemui.recents.events.EventBus;
344bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajanimport com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
35c81082b7ee925aeeb7edddbb181dc365a4600be1Sid Soundararajanimport com.android.systemui.recents.misc.SystemServicesProxy;
364bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajanimport com.android.systemui.recents.model.RecentsTaskLoader;
374bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajanimport com.android.systemui.recents.model.TaskStack;
38c81082b7ee925aeeb7edddbb181dc365a4600be1Sid Soundararajanimport com.android.systemui.recents.model.ThumbnailData;
394bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajanimport com.android.systemui.recents.tv.views.TaskCardView;
4067ed54a724df258738062e60d7f702f396502b49Sid Soundararajanimport com.android.systemui.statusbar.tv.TvStatusBar;
41ea347d3cafa7ab03dedeb5fe9c330adf6ff34b6aJaewan Kimimport com.android.systemui.tv.pip.PipManager;
424bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan
434bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajanpublic class RecentsTvImpl extends RecentsImpl{
444bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan    public final static String RECENTS_TV_ACTIVITY =
454bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan            "com.android.systemui.recents.tv.RecentsTvActivity";
464bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan
47ea347d3cafa7ab03dedeb5fe9c330adf6ff34b6aJaewan Kim    private static final PipManager mPipManager = PipManager.getInstance();
48ea347d3cafa7ab03dedeb5fe9c330adf6ff34b6aJaewan Kim
494bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan    public RecentsTvImpl(Context context) {
504bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        super(context);
514bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan    }
524bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan
534bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan    @Override
54d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson    protected void startRecentsActivity(ActivityManager.RunningTaskInfo runningTask,
55d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson            boolean isHomeStackVisible, boolean animate, int growTarget) {
564bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        RecentsTaskLoader loader = Recents.getTaskLoader();
574bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan
584bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        // In the case where alt-tab is triggered, we never get a preloadRecents() call, so we
594bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        // should always preload the tasks now. If we are dragging in recents, reload them as
604bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        // the stacks might have changed.
614bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        if (mTriggeredFromAltTab || sInstanceLoadPlan == null) {
624bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan            // Create a new load plan if preloadRecents() was never triggered
634bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan            sInstanceLoadPlan = loader.createLoadPlan(mContext);
644bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        }
654bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        if (mTriggeredFromAltTab || !sInstanceLoadPlan.hasTasks()) {
66dfd7be012b889f92d3e7e6d80ff7fe6b55c75901Winson            loader.preloadTasks(sInstanceLoadPlan, runningTask.id, !isHomeStackVisible);
674bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        }
684bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        TaskStack stack = sInstanceLoadPlan.getTaskStack();
694bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan
704bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        if (!animate) {
714bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan            ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, -1, -1);
72d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson            startRecentsActivity(runningTask, opts, false /* fromHome */, false /* fromThumbnail*/);
734bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan            return;
744bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        }
754bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan
764bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        boolean hasRecentTasks = stack.getTaskCount() > 0;
77d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson        boolean useThumbnailTransition = (runningTask != null) && !isHomeStackVisible && hasRecentTasks;
784bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan
794bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        if (useThumbnailTransition) {
804bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan            // Try starting with a thumbnail transition
81d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson            ActivityOptions opts = getThumbnailTransitionActivityOptionsForTV(runningTask,
8218cfc84f4814f87d660d04bad4f9941e6d503125Sid Soundararajan                    stack.getTaskCount());
834bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan            if (opts != null) {
84d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson                startRecentsActivity(runningTask, opts, false /* fromHome */, true /* fromThumbnail */);
854bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan            } else {
864bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan                // Fall through below to the non-thumbnail transition
874bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan                useThumbnailTransition = false;
884bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan            }
894bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        }
904bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan
914bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        if (!useThumbnailTransition) {
92d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson            startRecentsActivity(runningTask, null, true /* fromHome */, false /* fromThumbnail */);
934bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        }
944bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        mLastToggleTime = SystemClock.elapsedRealtime();
954bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan    }
964bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan
97d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson    protected void startRecentsActivity(ActivityManager.RunningTaskInfo runningTask,
984bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan            ActivityOptions opts, boolean fromHome, boolean fromThumbnail) {
994bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        // Update the configuration based on the launch options
1004bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        RecentsConfiguration config = Recents.getConfiguration();
1014bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        RecentsActivityLaunchState launchState = config.getLaunchState();
1024bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        launchState.launchedFromHome = fromHome;
1034bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        launchState.launchedFromApp = fromThumbnail;
104d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson        launchState.launchedToTaskId = (runningTask != null) ? runningTask.id : -1;
1054bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        launchState.launchedWithAltTab = mTriggeredFromAltTab;
1064bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan
1074bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        Intent intent = new Intent();
1084bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        intent.setClassName(RECENTS_PACKAGE, RECENTS_TV_ACTIVITY);
1094bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1104bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan                | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
1114bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan                | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
1124bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan
1134bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        if (opts != null) {
1144bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan            mContext.startActivityAsUser(intent, opts.toBundle(), UserHandle.CURRENT);
1154bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        } else {
1164bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan            mContext.startActivityAsUser(intent, UserHandle.CURRENT);
1174bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        }
1184bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        EventBus.getDefault().send(new RecentsActivityStartingEvent());
1194bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan    }
1204bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan
1214bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan    /**
1224bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan     * Creates the activity options for an app->recents transition on TV.
1234bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan     */
1244bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan    private ActivityOptions getThumbnailTransitionActivityOptionsForTV(
125d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson            ActivityManager.RunningTaskInfo runningTask, int numTasks) {
126ea347d3cafa7ab03dedeb5fe9c330adf6ff34b6aJaewan Kim        Rect rect = TaskCardView.getStartingCardThumbnailRect(
127ea347d3cafa7ab03dedeb5fe9c330adf6ff34b6aJaewan Kim            mContext, !mPipManager.isPipShown(), numTasks);
128c81082b7ee925aeeb7edddbb181dc365a4600be1Sid Soundararajan        SystemServicesProxy ssp = Recents.getSystemServices();
129d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson        ThumbnailData thumbnailData = ssp.getTaskThumbnail(runningTask.id);
130c81082b7ee925aeeb7edddbb181dc365a4600be1Sid Soundararajan        if (thumbnailData.thumbnail != null) {
131c81082b7ee925aeeb7edddbb181dc365a4600be1Sid Soundararajan            Bitmap thumbnail = Bitmap.createScaledBitmap(thumbnailData.thumbnail, rect.width(),
132c81082b7ee925aeeb7edddbb181dc365a4600be1Sid Soundararajan                    rect.height(), false);
1334bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan            return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
134c81082b7ee925aeeb7edddbb181dc365a4600be1Sid Soundararajan                    thumbnail, (int) rect.left, (int) rect.top, (int) rect.width(),
135c81082b7ee925aeeb7edddbb181dc365a4600be1Sid Soundararajan                    (int) rect.height(), mHandler, null);
1364bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        }
1374bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        // If both the screenshot and thumbnail fails, then just fall back to the default transition
1384bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan        return getUnknownTransitionActivityOptions();
1394bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan    }
14067ed54a724df258738062e60d7f702f396502b49Sid Soundararajan
14167ed54a724df258738062e60d7f702f396502b49Sid Soundararajan    @Override
14267ed54a724df258738062e60d7f702f396502b49Sid Soundararajan    public void onVisibilityChanged(Context context, boolean visible) {
143ab216609f1608e61827d955fcc9fd0560bc52e4dWinson        Recents.getSystemServices().setRecentsVisibility(visible);
14467ed54a724df258738062e60d7f702f396502b49Sid Soundararajan    }
1454bdb6879bd5f1b7e93e7e9ac236a073921862075Sid Soundararajan}
146