• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.views;
17 
18 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
19 
20 import static com.android.launcher3.LauncherState.CLEAR_ALL_BUTTON;
21 import static com.android.launcher3.LauncherState.NORMAL;
22 import static com.android.launcher3.LauncherState.OVERVIEW;
23 import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK;
24 import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
25 import static com.android.launcher3.LauncherState.SPRING_LOADED;
26 
27 import android.annotation.TargetApi;
28 import android.content.Context;
29 import android.os.Build;
30 import android.util.AttributeSet;
31 import android.view.MotionEvent;
32 import android.view.Surface;
33 
34 import androidx.annotation.Nullable;
35 
36 import com.android.launcher3.AbstractFloatingView;
37 import com.android.launcher3.LauncherState;
38 import com.android.launcher3.logging.StatsLogManager;
39 import com.android.launcher3.statehandlers.DepthController;
40 import com.android.launcher3.statehandlers.DesktopVisibilityController;
41 import com.android.launcher3.statemanager.StateManager.StateListener;
42 import com.android.launcher3.uioverrides.QuickstepLauncher;
43 import com.android.launcher3.util.PendingSplitSelectInfo;
44 import com.android.launcher3.util.SplitConfigurationOptions;
45 import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource;
46 import com.android.quickstep.GestureState;
47 import com.android.quickstep.LauncherActivityInterface;
48 import com.android.quickstep.RotationTouchHelper;
49 import com.android.quickstep.SystemUiProxy;
50 import com.android.quickstep.util.SplitSelectStateController;
51 import com.android.systemui.shared.recents.model.Task;
52 
53 /**
54  * {@link RecentsView} used in Launcher activity
55  */
56 @TargetApi(Build.VERSION_CODES.O)
57 public class LauncherRecentsView extends RecentsView<QuickstepLauncher, LauncherState>
58         implements StateListener<LauncherState> {
59 
LauncherRecentsView(Context context)60     public LauncherRecentsView(Context context) {
61         this(context, null);
62     }
63 
LauncherRecentsView(Context context, @Nullable AttributeSet attrs)64     public LauncherRecentsView(Context context, @Nullable AttributeSet attrs) {
65         this(context, attrs, 0);
66     }
67 
LauncherRecentsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr)68     public LauncherRecentsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
69         super(context, attrs, defStyleAttr, LauncherActivityInterface.INSTANCE);
70         mActivity.getStateManager().addStateListener(this);
71     }
72 
73     @Override
init(OverviewActionsView actionsView, SplitSelectStateController splitPlaceholderView)74     public void init(OverviewActionsView actionsView,
75             SplitSelectStateController splitPlaceholderView) {
76         super.init(actionsView, splitPlaceholderView);
77         setContentAlpha(0);
78     }
79 
80     @Override
startHome()81     public void startHome() {
82         mActivity.getStateManager().goToState(NORMAL);
83         AbstractFloatingView.closeAllOpenViews(mActivity, mActivity.isStarted());
84     }
85 
86     @Override
onTaskLaunchAnimationEnd(boolean success)87     protected void onTaskLaunchAnimationEnd(boolean success) {
88         if (success) {
89             mActivity.getStateManager().moveToRestState();
90         } else {
91             LauncherState state = mActivity.getStateManager().getState();
92             mActivity.getAllAppsController().setState(state);
93         }
94         super.onTaskLaunchAnimationEnd(success);
95     }
96 
97     @Override
onTaskIconChanged(int taskId)98     public void onTaskIconChanged(int taskId) {
99         super.onTaskIconChanged(taskId);
100         // If Launcher needs to return to split select state, do it now, after the icon has updated.
101         if (mActivity.hasPendingSplitSelectInfo()) {
102             PendingSplitSelectInfo recoveryData = mActivity.getPendingSplitSelectInfo();
103             if (recoveryData.getStagedTaskId() == taskId) {
104                 initiateSplitSelect(
105                         getTaskViewByTaskId(recoveryData.getStagedTaskId()),
106                         recoveryData.getStagePosition(), recoveryData.getSource()
107                 );
108                 mActivity.finishSplitSelectRecovery();
109             }
110         }
111     }
112 
113     @Override
reset()114     public void reset() {
115         super.reset();
116         setLayoutRotation(Surface.ROTATION_0, Surface.ROTATION_0);
117     }
118 
119     @Override
onStateTransitionStart(LauncherState toState)120     public void onStateTransitionStart(LauncherState toState) {
121         setOverviewStateEnabled(toState.overviewUi);
122         setOverviewGridEnabled(toState.displayOverviewTasksAsGrid(mActivity.getDeviceProfile()));
123         setOverviewFullscreenEnabled(toState.getOverviewFullscreenProgress() == 1);
124         if (toState == OVERVIEW_MODAL_TASK) {
125             setOverviewSelectEnabled(true);
126         }
127         setFreezeViewVisibility(true);
128     }
129 
130     @Override
onStateTransitionComplete(LauncherState finalState)131     public void onStateTransitionComplete(LauncherState finalState) {
132         if (finalState == NORMAL || finalState == SPRING_LOADED) {
133             // Clean-up logic that occurs when recents is no longer in use/visible.
134             reset();
135         }
136         boolean isOverlayEnabled = finalState == OVERVIEW || finalState == OVERVIEW_MODAL_TASK;
137         setOverlayEnabled(isOverlayEnabled);
138         setFreezeViewVisibility(false);
139         if (finalState != OVERVIEW_MODAL_TASK) {
140             setOverviewSelectEnabled(false);
141         }
142 
143         if (isOverlayEnabled) {
144             runActionOnRemoteHandles(remoteTargetHandle ->
145                     remoteTargetHandle.getTaskViewSimulator().setDrawsBelowRecents(true));
146         }
147     }
148 
149     @Override
setOverviewStateEnabled(boolean enabled)150     public void setOverviewStateEnabled(boolean enabled) {
151         super.setOverviewStateEnabled(enabled);
152         if (enabled) {
153             LauncherState state = mActivity.getStateManager().getState();
154             boolean hasClearAllButton = (state.getVisibleElements(mActivity)
155                     & CLEAR_ALL_BUTTON) != 0;
156             setDisallowScrollToClearAll(!hasClearAllButton);
157         }
158         if (mActivity.getDesktopVisibilityController() != null) {
159             mActivity.getDesktopVisibilityController().setOverviewStateEnabled(enabled);
160         }
161     }
162 
163     @Override
onTouchEvent(MotionEvent ev)164     public boolean onTouchEvent(MotionEvent ev) {
165         boolean result = super.onTouchEvent(ev);
166         // Do not let touch escape to siblings below this view.
167         return result || mActivity.getStateManager().getState().overviewUi;
168     }
169 
170     @Override
getDepthController()171     protected DepthController getDepthController() {
172         return mActivity.getDepthController();
173     }
174 
175     @Override
setModalStateEnabled(int taskId, boolean animate)176     public void setModalStateEnabled(int taskId, boolean animate) {
177         if (taskId != INVALID_TASK_ID) {
178             setSelectedTask(taskId);
179             mActivity.getStateManager().goToState(LauncherState.OVERVIEW_MODAL_TASK, animate);
180         } else {
181             if (mActivity.isInState(LauncherState.OVERVIEW_MODAL_TASK)) {
182                 mActivity.getStateManager().goToState(LauncherState.OVERVIEW, animate);
183                 resetModalVisuals();
184             }
185         }
186     }
187 
188     @Override
onDismissAnimationEnds()189     protected void onDismissAnimationEnds() {
190         super.onDismissAnimationEnds();
191         if (mActivity.isInState(OVERVIEW_SPLIT_SELECT)) {
192             // We want to keep the tasks translations in this temporary state
193             // after resetting the rest above
194             setTaskViewsPrimarySplitTranslation(mTaskViewsPrimarySplitTranslation);
195             setTaskViewsSecondarySplitTranslation(mTaskViewsSecondarySplitTranslation);
196         }
197     }
198 
199     @Override
initiateSplitSelect(TaskView taskView, @SplitConfigurationOptions.StagePosition int stagePosition, StatsLogManager.EventEnum splitEvent)200     public void initiateSplitSelect(TaskView taskView,
201             @SplitConfigurationOptions.StagePosition int stagePosition,
202             StatsLogManager.EventEnum splitEvent) {
203         super.initiateSplitSelect(taskView, stagePosition, splitEvent);
204         mActivity.getStateManager().goToState(LauncherState.OVERVIEW_SPLIT_SELECT);
205     }
206 
207     @Override
initiateSplitSelect(SplitSelectSource splitSelectSource)208     public void initiateSplitSelect(SplitSelectSource splitSelectSource) {
209         super.initiateSplitSelect(splitSelectSource);
210         mActivity.getStateManager().goToState(LauncherState.OVERVIEW_SPLIT_SELECT);
211     }
212 
213     @Override
canLaunchFullscreenTask()214     protected boolean canLaunchFullscreenTask() {
215         return !mActivity.isInState(OVERVIEW_SPLIT_SELECT);
216     }
217 
218     @Override
onGestureAnimationStart(Task[] runningTasks, RotationTouchHelper rotationTouchHelper)219     public void onGestureAnimationStart(Task[] runningTasks,
220             RotationTouchHelper rotationTouchHelper) {
221         super.onGestureAnimationStart(runningTasks, rotationTouchHelper);
222         DesktopVisibilityController desktopVisibilityController =
223                 mActivity.getDesktopVisibilityController();
224         if (desktopVisibilityController != null) {
225             desktopVisibilityController.setGestureInProgress(true);
226         }
227     }
228 
229     @Override
onGestureAnimationEnd()230     public void onGestureAnimationEnd() {
231         DesktopVisibilityController desktopVisibilityController = null;
232         boolean showDesktopApps = false;
233         if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
234             desktopVisibilityController = mActivity.getDesktopVisibilityController();
235             if (mCurrentGestureEndTarget == GestureState.GestureEndTarget.LAST_TASK
236                     && desktopVisibilityController.areFreeformTasksVisible()) {
237                 // Recents gesture was cancelled and we are returning to the previous task.
238                 // After super class has handled clean up, show desktop apps on top again
239                 showDesktopApps = true;
240             }
241         }
242         super.onGestureAnimationEnd();
243         if (desktopVisibilityController != null) {
244             desktopVisibilityController.setGestureInProgress(false);
245         }
246         if (showDesktopApps) {
247             SystemUiProxy.INSTANCE.get(mActivity).showDesktopApps();
248         }
249     }
250 }
251