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