1 /* 2 * Copyright (C) 2019 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 package com.android.quickstep.util; 17 18 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; 19 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; 20 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; 21 22 import android.graphics.Rect; 23 24 import com.android.systemui.shared.recents.model.ThumbnailData; 25 import com.android.systemui.shared.system.RecentsAnimationControllerCompat; 26 import com.android.systemui.shared.system.RemoteAnimationTargetCompat; 27 28 import java.util.function.Consumer; 29 30 /** 31 * Extension of {@link RemoteAnimationTargetSet} with additional information about swipe 32 * up animation 33 */ 34 public class SwipeAnimationTargetSet extends RemoteAnimationTargetSet { 35 36 private final boolean mShouldMinimizeSplitScreen; 37 private final Consumer<SwipeAnimationTargetSet> mOnFinishListener; 38 39 public final RecentsAnimationControllerCompat controller; 40 public final Rect homeContentInsets; 41 public final Rect minimizedHomeBounds; 42 SwipeAnimationTargetSet(RecentsAnimationControllerCompat controller, RemoteAnimationTargetCompat[] targets, Rect homeContentInsets, Rect minimizedHomeBounds, boolean shouldMinimizeSplitScreen, Consumer<SwipeAnimationTargetSet> onFinishListener)43 public SwipeAnimationTargetSet(RecentsAnimationControllerCompat controller, 44 RemoteAnimationTargetCompat[] targets, Rect homeContentInsets, 45 Rect minimizedHomeBounds, boolean shouldMinimizeSplitScreen, 46 Consumer<SwipeAnimationTargetSet> onFinishListener) { 47 super(targets, MODE_CLOSING); 48 this.controller = controller; 49 this.homeContentInsets = homeContentInsets; 50 this.minimizedHomeBounds = minimizedHomeBounds; 51 this.mShouldMinimizeSplitScreen = shouldMinimizeSplitScreen; 52 this.mOnFinishListener = onFinishListener; 53 } 54 hasTargets()55 public boolean hasTargets() { 56 return unfilteredApps.length != 0; 57 } 58 59 /** 60 * Clones the target set without any actual targets. Used only when continuing a gesture after 61 * the actual recents animation has finished. 62 */ cloneWithoutTargets()63 public SwipeAnimationTargetSet cloneWithoutTargets() { 64 return new SwipeAnimationTargetSet(controller, new RemoteAnimationTargetCompat[0], 65 homeContentInsets, minimizedHomeBounds, mShouldMinimizeSplitScreen, 66 mOnFinishListener); 67 } 68 finishController(boolean toRecents, Runnable callback, boolean sendUserLeaveHint)69 public void finishController(boolean toRecents, Runnable callback, boolean sendUserLeaveHint) { 70 mOnFinishListener.accept(this); 71 UI_HELPER_EXECUTOR.execute(() -> { 72 controller.setInputConsumerEnabled(false); 73 controller.finish(toRecents, sendUserLeaveHint); 74 75 if (callback != null) { 76 MAIN_EXECUTOR.execute(callback); 77 } 78 }); 79 } 80 enableInputConsumer()81 public void enableInputConsumer() { 82 UI_HELPER_EXECUTOR.submit(() -> { 83 controller.hideCurrentInputMethod(); 84 controller.setInputConsumerEnabled(true); 85 }); 86 } 87 setWindowThresholdCrossed(boolean thresholdCrossed)88 public void setWindowThresholdCrossed(boolean thresholdCrossed) { 89 UI_HELPER_EXECUTOR.execute(() -> { 90 controller.setAnimationTargetsBehindSystemBars(!thresholdCrossed); 91 if (mShouldMinimizeSplitScreen && thresholdCrossed) { 92 // NOTE: As a workaround for conflicting animations (Launcher animating the task 93 // leash, and SystemUI resizing the docked stack, which resizes the task), we 94 // currently only set the minimized mode, and not the inverse. 95 // TODO: Synchronize the minimize animation with the launcher animation 96 controller.setSplitScreenMinimized(thresholdCrossed); 97 } 98 }); 99 } 100 screenshotTask(int taskId)101 public ThumbnailData screenshotTask(int taskId) { 102 return controller != null ? controller.screenshotTask(taskId) : null; 103 } 104 cancelAnimation()105 public void cancelAnimation() { 106 finishController(false /* toRecents */, null, false /* sendUserLeaveHint */); 107 } 108 finishAnimation()109 public void finishAnimation() { 110 finishController(true /* toRecents */, null, false /* sendUserLeaveHint */); 111 } 112 113 public interface SwipeAnimationListener { 114 onRecentsAnimationStart(SwipeAnimationTargetSet targetSet)115 void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet); 116 onRecentsAnimationCanceled()117 void onRecentsAnimationCanceled(); 118 } 119 } 120