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 */
16package com.android.systemui.recents.tv;
17
18import android.app.Activity;
19import android.app.ActivityOptions;
20import android.content.Intent;
21import android.graphics.Rect;
22import android.os.Bundle;
23import android.os.UserHandle;
24import android.util.Log;
25import android.view.KeyEvent;
26import android.view.View;
27import android.view.ViewTreeObserver.OnPreDrawListener;
28import android.view.WindowManager;
29import android.view.accessibility.AccessibilityEvent;
30import android.widget.FrameLayout.LayoutParams;
31
32import com.android.systemui.R;
33import com.android.systemui.recents.Recents;
34import com.android.systemui.recents.RecentsActivityLaunchState;
35import com.android.systemui.recents.RecentsConfiguration;
36import com.android.systemui.recents.RecentsImpl;
37import com.android.systemui.recents.events.EventBus;
38import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
39import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
40import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
41import com.android.systemui.recents.events.activity.HideRecentsEvent;
42import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
43import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
44import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
45import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
46import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
47import com.android.systemui.recents.events.ui.UserInteractionEvent;
48import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
49import com.android.systemui.recents.misc.SystemServicesProxy;
50import com.android.systemui.recents.model.RecentsPackageMonitor;
51import com.android.systemui.recents.model.RecentsTaskLoadPlan;
52import com.android.systemui.recents.model.RecentsTaskLoader;
53import com.android.systemui.recents.model.Task;
54import com.android.systemui.recents.model.TaskStack;
55import com.android.systemui.recents.tv.animations.HomeRecentsEnterExitAnimationHolder;
56import com.android.systemui.recents.tv.views.RecentsTvView;
57import com.android.systemui.recents.tv.views.TaskCardView;
58import com.android.systemui.recents.tv.views.TaskStackHorizontalGridView;
59import com.android.systemui.recents.tv.views.TaskStackHorizontalViewAdapter;
60import com.android.systemui.statusbar.BaseStatusBar;
61import com.android.systemui.tv.pip.PipManager;
62import com.android.systemui.tv.pip.PipRecentsOverlayManager;
63
64import java.util.ArrayList;
65import java.util.Collections;
66import java.util.List;
67
68/**
69 * The main TV recents activity started by the RecentsImpl.
70 */
71public class RecentsTvActivity extends Activity implements OnPreDrawListener {
72    private final static String TAG = "RecentsTvActivity";
73    private final static boolean DEBUG = false;
74
75    public final static int EVENT_BUS_PRIORITY = Recents.EVENT_BUS_PRIORITY + 1;
76    private final static String RECENTS_HOME_INTENT_EXTRA =
77            "com.android.systemui.recents.tv.RecentsTvActivity.RECENTS_HOME_INTENT_EXTRA";
78
79    private boolean mFinishedOnStartup;
80    private RecentsPackageMonitor mPackageMonitor;
81    private long mLastTabKeyEventTime;
82    private boolean mIgnoreAltTabRelease;
83    private boolean mLaunchedFromHome;
84    private boolean mTalkBackEnabled;
85
86    private RecentsTvView mRecentsView;
87    private View mPipView;
88    private TaskStackHorizontalViewAdapter mTaskStackViewAdapter;
89    private TaskStackHorizontalGridView mTaskStackHorizontalGridView;
90    private FinishRecentsRunnable mFinishLaunchHomeRunnable;
91    private HomeRecentsEnterExitAnimationHolder mHomeRecentsEnterExitAnimationHolder;
92
93    private final PipManager mPipManager = PipManager.getInstance();
94    private final PipManager.Listener mPipListener = new PipManager.Listener() {
95        @Override
96        public void onPipEntered() {
97            updatePipUI();
98        }
99
100        @Override
101        public void onPipActivityClosed() {
102            updatePipUI();
103        }
104
105        @Override
106        public void onShowPipMenu() {
107            updatePipUI();
108        }
109
110        @Override
111        public void onMoveToFullscreen() {
112            // Recents should be dismissed when PIP moves to fullscreen. If not, Recents will
113            // be unnecessarily shown in the scenario: PIP->Fullscreen->PIP.
114            // Do not show Recents close animation because PIP->Fullscreen animation will be shown
115            // instead.
116            dismissRecentsToLaunchTargetTaskOrHome(false);
117        }
118
119        @Override
120        public void onPipResizeAboutToStart() { }
121    };
122    private PipRecentsOverlayManager mPipRecentsOverlayManager;
123    private final PipRecentsOverlayManager.Callback mPipRecentsOverlayManagerCallback =
124            new PipRecentsOverlayManager.Callback() {
125                @Override
126                public void onClosed() {
127                    dismissRecentsToLaunchTargetTaskOrHome(true);
128                }
129
130                @Override
131                public void onBackPressed() {
132                    RecentsTvActivity.this.onBackPressed();
133                }
134
135                @Override
136                public void onRecentsFocused() {
137                    if (mTalkBackEnabled) {
138                        mTaskStackHorizontalGridView.requestFocus();
139                        mTaskStackHorizontalGridView.sendAccessibilityEvent(
140                                AccessibilityEvent.TYPE_VIEW_FOCUSED);
141                    }
142                    mTaskStackHorizontalGridView.startFocusGainAnimation();
143                }
144            };
145
146    private final View.OnFocusChangeListener mPipViewFocusChangeListener =
147            new View.OnFocusChangeListener() {
148                @Override
149                public void onFocusChange(View v, boolean hasFocus) {
150                    if (hasFocus) {
151                        requestPipControlsFocus();
152                    }
153                }
154            };
155
156    /**
157     * A common Runnable to finish Recents by launching Home with an animation depending on the
158     * last activity launch state.  Generally we always launch home when we exit Recents rather than
159     * just finishing the activity since we don't know what is behind Recents in the task stack.
160     */
161    class FinishRecentsRunnable implements Runnable {
162        Intent mLaunchIntent;
163
164        /**
165         * Creates a finish runnable that starts the specified intent.
166         */
167        public FinishRecentsRunnable(Intent launchIntent) {
168            mLaunchIntent = launchIntent;
169        }
170
171        @Override
172        public void run() {
173            try {
174                ActivityOptions opts = ActivityOptions.makeCustomAnimation(RecentsTvActivity.this,
175                        R.anim.recents_to_launcher_enter, R.anim.recents_to_launcher_exit);
176                startActivityAsUser(mLaunchIntent, opts.toBundle(), UserHandle.CURRENT);
177            } catch (Exception e) {
178                Log.e(TAG, getString(R.string.recents_launch_error_message, "Home"), e);
179            }
180        }
181    }
182
183    private void updateRecentsTasks() {
184        RecentsTaskLoader loader = Recents.getTaskLoader();
185        RecentsTaskLoadPlan plan = RecentsImpl.consumeInstanceLoadPlan();
186        if (plan == null) {
187            plan = loader.createLoadPlan(this);
188        }
189
190        RecentsConfiguration config = Recents.getConfiguration();
191        RecentsActivityLaunchState launchState = config.getLaunchState();
192        if (!plan.hasTasks()) {
193            loader.preloadTasks(plan, -1, !launchState.launchedFromHome);
194        }
195
196        int numVisibleTasks = TaskCardView.getNumberOfVisibleTasks(getApplicationContext());
197        mLaunchedFromHome = launchState.launchedFromHome;
198        TaskStack stack = plan.getTaskStack();
199        RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
200        loadOpts.runningTaskId = launchState.launchedToTaskId;
201        loadOpts.numVisibleTasks = numVisibleTasks;
202        loadOpts.numVisibleTaskThumbnails = numVisibleTasks;
203        loader.loadTasks(this, plan, loadOpts);
204
205        List stackTasks = stack.getStackTasks();
206        Collections.reverse(stackTasks);
207        if (mTaskStackViewAdapter == null) {
208            mTaskStackViewAdapter = new TaskStackHorizontalViewAdapter(stackTasks);
209            mTaskStackHorizontalGridView = mRecentsView
210                    .setTaskStackViewAdapter(mTaskStackViewAdapter);
211            mHomeRecentsEnterExitAnimationHolder = new HomeRecentsEnterExitAnimationHolder(
212                    getApplicationContext(), mTaskStackHorizontalGridView);
213        } else {
214            mTaskStackViewAdapter.setNewStackTasks(stackTasks);
215        }
216        mRecentsView.init(stack);
217
218        if (launchState.launchedToTaskId != -1) {
219            ArrayList<Task> tasks = stack.getStackTasks();
220            int taskCount = tasks.size();
221            for (int i = 0; i < taskCount; i++) {
222                Task t = tasks.get(i);
223                if (t.key.id == launchState.launchedToTaskId) {
224                    t.isLaunchTarget = true;
225                    break;
226                }
227            }
228        }
229    }
230
231    boolean dismissRecentsToLaunchTargetTaskOrHome(boolean animate) {
232        SystemServicesProxy ssp = Recents.getSystemServices();
233        if (ssp.isRecentsActivityVisible()) {
234            // If we have a focused Task, launch that Task now
235            if (mRecentsView.launchPreviousTask(animate)) {
236              return true;
237            }
238            // If none of the other cases apply, then just go Home
239            dismissRecentsToHome(animate /* animateTaskViews */);
240        }
241        return false;
242    }
243
244    boolean dismissRecentsToFocusedTaskOrHome() {
245        SystemServicesProxy ssp = Recents.getSystemServices();
246        if (ssp.isRecentsActivityVisible()) {
247            // If we have a focused Task, launch that Task now
248            if (mRecentsView.launchFocusedTask()) return true;
249            // If none of the other cases apply, then just go Home
250            dismissRecentsToHome(true /* animateTaskViews */);
251            return true;
252        }
253        return false;
254    }
255
256    void dismissRecentsToHome(boolean animateTaskViews) {
257        Runnable closeSystemWindows = new Runnable() {
258            @Override
259            public void run() {
260                Recents.getSystemServices().sendCloseSystemWindows(
261                        BaseStatusBar.SYSTEM_DIALOG_REASON_HOME_KEY);
262            }
263        };
264        DismissRecentsToHomeAnimationStarted dismissEvent =
265                new DismissRecentsToHomeAnimationStarted(animateTaskViews);
266        dismissEvent.addPostAnimationCallback(mFinishLaunchHomeRunnable);
267        dismissEvent.addPostAnimationCallback(closeSystemWindows);
268
269        if (mTaskStackHorizontalGridView.getChildCount() > 0 && animateTaskViews) {
270            mHomeRecentsEnterExitAnimationHolder.startExitAnimation(dismissEvent);
271        } else {
272            closeSystemWindows.run();
273            mFinishLaunchHomeRunnable.run();
274        }
275    }
276
277    boolean dismissRecentsToHomeIfVisible(boolean animated) {
278        SystemServicesProxy ssp = Recents.getSystemServices();
279        if (ssp.isRecentsActivityVisible()) {
280            // Return to Home
281            dismissRecentsToHome(animated);
282            return true;
283        }
284        return false;
285    }
286
287    @Override
288    public void onCreate(Bundle savedInstanceState) {
289        super.onCreate(savedInstanceState);
290        mFinishedOnStartup = false;
291
292        // In the case that the activity starts up before the Recents component has initialized
293        // (usually when debugging/pushing the SysUI apk), just finish this activity.
294        SystemServicesProxy ssp = Recents.getSystemServices();
295        if (ssp == null) {
296            mFinishedOnStartup = true;
297            finish();
298            return;
299        }
300        mPipRecentsOverlayManager = PipManager.getInstance().getPipRecentsOverlayManager();
301
302        // Register this activity with the event bus
303        EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);
304
305        mPackageMonitor = new RecentsPackageMonitor();
306        mPackageMonitor.register(this);
307
308        // Set the Recents layout
309        setContentView(R.layout.recents_on_tv);
310
311        mRecentsView = (RecentsTvView) findViewById(R.id.recents_view);
312        mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
313                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
314                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
315
316        mPipView = findViewById(R.id.pip);
317        mPipView.setOnFocusChangeListener(mPipViewFocusChangeListener);
318        // Place mPipView at the PIP bounds for fine tuned focus handling.
319        Rect pipBounds = mPipManager.getRecentsFocusedPipBounds();
320        LayoutParams lp = (LayoutParams) mPipView.getLayoutParams();
321        lp.width = pipBounds.width();
322        lp.height = pipBounds.height();
323        lp.leftMargin = pipBounds.left;
324        lp.topMargin = pipBounds.top;
325        mPipView.setLayoutParams(lp);
326
327        mPipRecentsOverlayManager.setCallback(mPipRecentsOverlayManagerCallback);
328
329        getWindow().getAttributes().privateFlags |=
330                WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
331
332        // Create the home intent runnable
333        Intent homeIntent = new Intent(Intent.ACTION_MAIN, null);
334        homeIntent.addCategory(Intent.CATEGORY_HOME);
335        homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
336                Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
337        homeIntent.putExtra(RECENTS_HOME_INTENT_EXTRA, true);
338        mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent);
339
340        mPipManager.addListener(mPipListener);
341    }
342
343    @Override
344    protected void onNewIntent(Intent intent) {
345        super.onNewIntent(intent);
346        setIntent(intent);
347    }
348
349    @Override
350    public void onEnterAnimationComplete() {
351        super.onEnterAnimationComplete();
352        if(mLaunchedFromHome) {
353            mHomeRecentsEnterExitAnimationHolder.startEnterAnimation(mPipManager.isPipShown());
354        }
355        EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
356    }
357
358    @Override
359    public void onResume() {
360        super.onResume();
361        mPipRecentsOverlayManager.onRecentsResumed();
362        // Update the recent tasks
363        updateRecentsTasks();
364
365        // If this is a new instance from a configuration change, then we have to manually trigger
366        // the enter animation state, or if recents was relaunched by AM, without going through
367        // the normal mechanisms
368        RecentsConfiguration config = Recents.getConfiguration();
369        RecentsActivityLaunchState launchState = config.getLaunchState();
370        boolean wasLaunchedByAm = !launchState.launchedFromHome &&
371                !launchState.launchedFromApp;
372        if (wasLaunchedByAm) {
373            EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
374        }
375
376        // Notify that recents is now visible
377        SystemServicesProxy ssp = Recents.getSystemServices();
378        EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, true));
379        if(mTaskStackHorizontalGridView.getStack().getTaskCount() > 1 && !mLaunchedFromHome) {
380            // If there are 2 or more tasks, and we are not launching from home
381            // set the selected position to the 2nd task to allow for faster app switching
382            mTaskStackHorizontalGridView.setSelectedPosition(1);
383        } else {
384            mTaskStackHorizontalGridView.setSelectedPosition(0);
385        }
386        mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
387
388        View dismissPlaceholder = findViewById(R.id.dismiss_placeholder);
389        mTalkBackEnabled = ssp.isTouchExplorationEnabled();
390        if (mTalkBackEnabled) {
391            dismissPlaceholder.setAccessibilityTraversalBefore(R.id.task_list);
392            dismissPlaceholder.setAccessibilityTraversalAfter(R.id.dismiss_placeholder);
393            mTaskStackHorizontalGridView.setAccessibilityTraversalAfter(R.id.dismiss_placeholder);
394            mTaskStackHorizontalGridView.setAccessibilityTraversalBefore(R.id.pip);
395            dismissPlaceholder.setOnClickListener(new View.OnClickListener() {
396                @Override
397                public void onClick(View v) {
398                    mTaskStackHorizontalGridView.requestFocus();
399                    mTaskStackHorizontalGridView.
400                            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
401                    Task focusedTask = mTaskStackHorizontalGridView.getFocusedTask();
402                    if (focusedTask != null) {
403                        mTaskStackViewAdapter.removeTask(focusedTask);
404                        EventBus.getDefault().send(new DeleteTaskDataEvent(focusedTask));
405                    }
406                }
407            });
408        }
409
410        // Initialize PIP UI
411        if (mPipManager.isPipShown()) {
412            if (mTalkBackEnabled) {
413                // If talkback is on, use the mPipView to handle focus changes
414                // between recents row and PIP controls.
415                mPipView.setVisibility(View.VISIBLE);
416            } else {
417                mPipView.setVisibility(View.GONE);
418            }
419            // When PIP view has focus, recents overlay view will takes the focus
420            // as if it's the part of the Recents UI.
421            mPipRecentsOverlayManager.requestFocus(mTaskStackViewAdapter.getItemCount() > 0);
422        } else {
423            mPipView.setVisibility(View.GONE);
424            mPipRecentsOverlayManager.removePipRecentsOverlayView();
425        }
426    }
427
428    @Override
429    public void onPause() {
430        super.onPause();
431        mPipRecentsOverlayManager.onRecentsPaused();
432    }
433
434    @Override
435    protected void onStop() {
436        super.onStop();
437
438        mIgnoreAltTabRelease = false;
439        // Notify that recents is now hidden
440        EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, false));
441
442        // Workaround for b/22542869, if the RecentsActivity is started again, but without going
443        // through SystemUI, we need to reset the config launch flags to ensure that we do not
444        // wait on the system to send a signal that was never queued.
445        RecentsConfiguration config = Recents.getConfiguration();
446        RecentsActivityLaunchState launchState = config.getLaunchState();
447        launchState.reset();
448
449        // Workaround for b/28333917.
450        finish();
451    }
452
453    @Override
454    protected void onDestroy() {
455        super.onDestroy();
456
457        mPipManager.removeListener(mPipListener);
458        // In the case that the activity finished on startup, just skip the unregistration below
459        if (mFinishedOnStartup) {
460            return;
461        }
462
463        // Unregister any broadcast receivers for the task loader
464        mPackageMonitor.unregister();
465
466        EventBus.getDefault().unregister(this);
467    }
468
469    @Override
470    public void onTrimMemory(int level) {
471        RecentsTaskLoader loader = Recents.getTaskLoader();
472        if (loader != null) {
473            loader.onTrimMemory(level);
474        }
475    }
476
477    @Override
478    public boolean onKeyDown(int keyCode, KeyEvent event) {
479        switch (keyCode) {
480            case KeyEvent.KEYCODE_DEL:
481            case KeyEvent.KEYCODE_FORWARD_DEL: {
482                EventBus.getDefault().send(new DismissFocusedTaskViewEvent());
483                return true;
484            }
485            default:
486                break;
487        }
488        return super.onKeyDown(keyCode, event);
489    }
490
491    @Override
492    public void onUserInteraction() {
493        EventBus.getDefault().send(new UserInteractionEvent());
494    }
495
496    @Override
497    public void onBackPressed() {
498        // Back behaves like the recents button so just trigger a toggle event
499        EventBus.getDefault().send(new ToggleRecentsEvent());
500    }
501
502    /**** EventBus events ****/
503
504    public final void onBusEvent(ToggleRecentsEvent event) {
505        RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
506        if (launchState.launchedFromHome) {
507            dismissRecentsToHome(true /* animateTaskViews */);
508        } else {
509            dismissRecentsToLaunchTargetTaskOrHome(true);
510        }
511    }
512
513    public final void onBusEvent(HideRecentsEvent event) {
514        if (event.triggeredFromAltTab) {
515            // If we are hiding from releasing Alt-Tab, dismiss Recents to the focused app
516            if (!mIgnoreAltTabRelease) {
517                dismissRecentsToFocusedTaskOrHome();
518            }
519        } else if (event.triggeredFromHomeKey) {
520                dismissRecentsToHome(true /* animateTaskViews */);
521        } else {
522            // Do nothing
523        }
524    }
525
526    public final void onBusEvent(CancelEnterRecentsWindowAnimationEvent event) {
527        RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
528        int launchToTaskId = launchState.launchedToTaskId;
529        if (launchToTaskId != -1 &&
530                (event.launchTask == null || launchToTaskId != event.launchTask.key.id)) {
531            SystemServicesProxy ssp = Recents.getSystemServices();
532            ssp.cancelWindowTransition(launchState.launchedToTaskId);
533            ssp.cancelThumbnailTransition(getTaskId());
534        }
535    }
536
537    public final void onBusEvent(DeleteTaskDataEvent event) {
538        // Remove any stored data from the loader
539        RecentsTaskLoader loader = Recents.getTaskLoader();
540        loader.deleteTaskData(event.task, false);
541
542        // Remove the task from activity manager
543        SystemServicesProxy ssp = Recents.getSystemServices();
544        ssp.removeTask(event.task.key.id);
545    }
546
547    public final void onBusEvent(AllTaskViewsDismissedEvent event) {
548        if (mPipManager.isPipShown()) {
549            mRecentsView.showEmptyView();
550            mPipRecentsOverlayManager.requestFocus(false);
551        } else {
552            dismissRecentsToHome(false);
553        }
554    }
555
556    public final void onBusEvent(LaunchTaskFailedEvent event) {
557        // Return to Home
558        dismissRecentsToHome(true /* animateTaskViews */);
559    }
560
561    @Override
562    public boolean onPreDraw() {
563        mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
564        // Sets the initial values for enter animation.
565        // Animation will be started in {@link #onEnterAnimationComplete()}
566        if (mLaunchedFromHome) {
567            mHomeRecentsEnterExitAnimationHolder
568                    .setEnterFromHomeStartingAnimationValues(mPipManager.isPipShown());
569        } else {
570            mHomeRecentsEnterExitAnimationHolder
571                    .setEnterFromAppStartingAnimationValues(mPipManager.isPipShown());
572        }
573        // We post to make sure that this information is delivered after this traversals is
574        // finished.
575        mRecentsView.post(new Runnable() {
576            @Override
577            public void run() {
578                Recents.getSystemServices().endProlongedAnimations();
579            }
580        });
581        return true;
582    }
583
584    private void updatePipUI() {
585        if (!mPipManager.isPipShown()) {
586            mPipRecentsOverlayManager.removePipRecentsOverlayView();
587            mTaskStackHorizontalGridView.startFocusLossAnimation();
588        } else {
589            Log.w(TAG, "An activity entered PIP mode while Recents is shown");
590        }
591    }
592
593    /**
594     * Requests the focus to the PIP controls.
595     * This starts the relevant recents row animation
596     * and give focus to the recents overlay if needed.
597     */
598    public void requestPipControlsFocus() {
599        if (!mPipManager.isPipShown()) {
600            return;
601        }
602
603        mTaskStackHorizontalGridView.startFocusLossAnimation();
604        mPipRecentsOverlayManager.requestFocus(mTaskStackViewAdapter.getItemCount() > 0);
605    }
606}
607