1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.systemui.recents.tv; 18 19import android.app.ActivityManager; 20import android.app.ActivityOptions; 21import android.content.Context; 22import android.content.Intent; 23import android.graphics.Bitmap; 24import android.graphics.Rect; 25import android.os.SystemClock; 26import android.os.UserHandle; 27 28import com.android.systemui.SystemUIApplication; 29import com.android.systemui.recents.Recents; 30import com.android.systemui.recents.RecentsActivityLaunchState; 31import com.android.systemui.recents.RecentsConfiguration; 32import com.android.systemui.recents.RecentsImpl; 33import com.android.systemui.recents.events.EventBus; 34import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent; 35import com.android.systemui.recents.misc.SystemServicesProxy; 36import com.android.systemui.recents.model.RecentsTaskLoader; 37import com.android.systemui.recents.model.TaskStack; 38import com.android.systemui.recents.model.ThumbnailData; 39import com.android.systemui.recents.tv.views.TaskCardView; 40import com.android.systemui.statusbar.tv.TvStatusBar; 41import com.android.systemui.tv.pip.PipManager; 42 43public class RecentsTvImpl extends RecentsImpl{ 44 public final static String RECENTS_TV_ACTIVITY = 45 "com.android.systemui.recents.tv.RecentsTvActivity"; 46 47 private static final PipManager mPipManager = PipManager.getInstance(); 48 49 public RecentsTvImpl(Context context) { 50 super(context); 51 } 52 53 @Override 54 protected void startRecentsActivity(ActivityManager.RunningTaskInfo runningTask, 55 boolean isHomeStackVisible, boolean animate, int growTarget) { 56 RecentsTaskLoader loader = Recents.getTaskLoader(); 57 58 // In the case where alt-tab is triggered, we never get a preloadRecents() call, so we 59 // should always preload the tasks now. If we are dragging in recents, reload them as 60 // the stacks might have changed. 61 if (mTriggeredFromAltTab || sInstanceLoadPlan == null) { 62 // Create a new load plan if preloadRecents() was never triggered 63 sInstanceLoadPlan = loader.createLoadPlan(mContext); 64 } 65 if (mTriggeredFromAltTab || !sInstanceLoadPlan.hasTasks()) { 66 loader.preloadTasks(sInstanceLoadPlan, runningTask.id, !isHomeStackVisible); 67 } 68 TaskStack stack = sInstanceLoadPlan.getTaskStack(); 69 70 if (!animate) { 71 ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, -1, -1); 72 startRecentsActivity(runningTask, opts, false /* fromHome */, false /* fromThumbnail*/); 73 return; 74 } 75 76 boolean hasRecentTasks = stack.getTaskCount() > 0; 77 boolean useThumbnailTransition = (runningTask != null) && !isHomeStackVisible && hasRecentTasks; 78 79 if (useThumbnailTransition) { 80 // Try starting with a thumbnail transition 81 ActivityOptions opts = getThumbnailTransitionActivityOptionsForTV(runningTask, 82 stack.getTaskCount()); 83 if (opts != null) { 84 startRecentsActivity(runningTask, opts, false /* fromHome */, true /* fromThumbnail */); 85 } else { 86 // Fall through below to the non-thumbnail transition 87 useThumbnailTransition = false; 88 } 89 } 90 91 if (!useThumbnailTransition) { 92 startRecentsActivity(runningTask, null, true /* fromHome */, false /* fromThumbnail */); 93 } 94 mLastToggleTime = SystemClock.elapsedRealtime(); 95 } 96 97 protected void startRecentsActivity(ActivityManager.RunningTaskInfo runningTask, 98 ActivityOptions opts, boolean fromHome, boolean fromThumbnail) { 99 // Update the configuration based on the launch options 100 RecentsConfiguration config = Recents.getConfiguration(); 101 RecentsActivityLaunchState launchState = config.getLaunchState(); 102 launchState.launchedFromHome = fromHome; 103 launchState.launchedFromApp = fromThumbnail; 104 launchState.launchedToTaskId = (runningTask != null) ? runningTask.id : -1; 105 launchState.launchedWithAltTab = mTriggeredFromAltTab; 106 107 Intent intent = new Intent(); 108 intent.setClassName(RECENTS_PACKAGE, RECENTS_TV_ACTIVITY); 109 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 110 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 111 | Intent.FLAG_ACTIVITY_TASK_ON_HOME); 112 113 if (opts != null) { 114 mContext.startActivityAsUser(intent, opts.toBundle(), UserHandle.CURRENT); 115 } else { 116 mContext.startActivityAsUser(intent, UserHandle.CURRENT); 117 } 118 EventBus.getDefault().send(new RecentsActivityStartingEvent()); 119 } 120 121 /** 122 * Creates the activity options for an app->recents transition on TV. 123 */ 124 private ActivityOptions getThumbnailTransitionActivityOptionsForTV( 125 ActivityManager.RunningTaskInfo runningTask, int numTasks) { 126 Rect rect = TaskCardView.getStartingCardThumbnailRect( 127 mContext, !mPipManager.isPipShown(), numTasks); 128 SystemServicesProxy ssp = Recents.getSystemServices(); 129 ThumbnailData thumbnailData = ssp.getTaskThumbnail(runningTask.id); 130 if (thumbnailData.thumbnail != null) { 131 Bitmap thumbnail = Bitmap.createScaledBitmap(thumbnailData.thumbnail, rect.width(), 132 rect.height(), false); 133 return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView, 134 thumbnail, (int) rect.left, (int) rect.top, (int) rect.width(), 135 (int) rect.height(), mHandler, null); 136 } 137 // If both the screenshot and thumbnail fails, then just fall back to the default transition 138 return getUnknownTransitionActivityOptions(); 139 } 140 141 @Override 142 public void onVisibilityChanged(Context context, boolean visible) { 143 SystemUIApplication app = (SystemUIApplication) context; 144 TvStatusBar statusBar = app.getComponent(TvStatusBar.class); 145 if (statusBar != null) { 146 statusBar.updateRecentsVisibility(visible); 147 } 148 } 149} 150