• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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;
17 
18 import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
19 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
20 
21 import static com.android.launcher3.LauncherAppTransitionManagerImpl.RECENTS_LAUNCH_DURATION;
22 import static com.android.launcher3.LauncherAppTransitionManagerImpl.STATUS_BAR_TRANSITION_DURATION;
23 import static com.android.quickstep.TaskUtils.getRecentsWindowAnimator;
24 import static com.android.quickstep.TaskUtils.taskIsATargetWithMode;
25 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
26 
27 import android.animation.Animator;
28 import android.animation.AnimatorListenerAdapter;
29 import android.animation.AnimatorSet;
30 import android.app.ActivityOptions;
31 import android.content.Intent;
32 import android.content.res.Configuration;
33 import android.os.Bundle;
34 import android.os.Handler;
35 import android.os.Looper;
36 import android.view.View;
37 
38 import com.android.launcher3.AbstractFloatingView;
39 import com.android.launcher3.BaseDraggingActivity;
40 import com.android.launcher3.DeviceProfile;
41 import com.android.launcher3.InvariantDeviceProfile;
42 import com.android.launcher3.ItemInfo;
43 import com.android.launcher3.LauncherAnimationRunner;
44 import com.android.launcher3.LauncherAppState;
45 import com.android.launcher3.R;
46 import com.android.launcher3.anim.Interpolators;
47 import com.android.launcher3.badge.BadgeInfo;
48 import com.android.launcher3.uioverrides.UiFactory;
49 import com.android.launcher3.util.SystemUiController;
50 import com.android.launcher3.util.Themes;
51 import com.android.launcher3.views.BaseDragLayer;
52 import com.android.quickstep.fallback.FallbackRecentsView;
53 import com.android.quickstep.fallback.RecentsRootView;
54 import com.android.quickstep.util.ClipAnimationHelper;
55 import com.android.quickstep.views.RecentsViewContainer;
56 import com.android.quickstep.views.TaskView;
57 import com.android.systemui.shared.system.ActivityOptionsCompat;
58 import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
59 import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
60 import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
61 
62 import java.io.FileDescriptor;
63 import java.io.PrintWriter;
64 
65 /**
66  * A simple activity to show the recently launched tasks
67  */
68 public class RecentsActivity extends BaseDraggingActivity {
69 
70     private Handler mUiHandler = new Handler(Looper.getMainLooper());
71     private RecentsRootView mRecentsRootView;
72     private FallbackRecentsView mFallbackRecentsView;
73     private RecentsViewContainer mOverviewPanelContainer;
74 
75     private Configuration mOldConfig;
76 
77     @Override
onCreate(Bundle savedInstanceState)78     protected void onCreate(Bundle savedInstanceState) {
79         super.onCreate(savedInstanceState);
80 
81         mOldConfig = new Configuration(getResources().getConfiguration());
82         initDeviceProfile();
83 
84         setContentView(R.layout.fallback_recents_activity);
85         mRecentsRootView = findViewById(R.id.drag_layer);
86         mFallbackRecentsView = findViewById(R.id.overview_panel);
87         mOverviewPanelContainer = findViewById(R.id.overview_panel_container);
88 
89         mRecentsRootView.setup();
90 
91         getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW,
92                 Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText));
93         RecentsActivityTracker.onRecentsActivityCreate(this);
94     }
95 
96     @Override
onConfigurationChanged(Configuration newConfig)97     public void onConfigurationChanged(Configuration newConfig) {
98         int diff = newConfig.diff(mOldConfig);
99         if ((diff & (CONFIG_ORIENTATION | CONFIG_SCREEN_SIZE)) != 0) {
100             onHandleConfigChanged();
101         }
102         mOldConfig.setTo(newConfig);
103         super.onConfigurationChanged(newConfig);
104     }
105 
106     @Override
onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig)107     public void onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig) {
108         onHandleConfigChanged();
109         super.onMultiWindowModeChanged(isInMultiWindowMode, newConfig);
110     }
111 
onRootViewSizeChanged()112     public void onRootViewSizeChanged() {
113         if (isInMultiWindowModeCompat()) {
114             onHandleConfigChanged();
115         }
116     }
117 
onHandleConfigChanged()118     private void onHandleConfigChanged() {
119         mUserEventDispatcher = null;
120         initDeviceProfile();
121 
122         AbstractFloatingView.closeOpenViews(this, true,
123                 AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
124         dispatchDeviceProfileChanged();
125 
126         mRecentsRootView.setup();
127         reapplyUi();
128     }
129 
130     @Override
reapplyUi()131     protected void reapplyUi() {
132         mRecentsRootView.dispatchInsets();
133     }
134 
initDeviceProfile()135     private void initDeviceProfile() {
136         // In case we are reusing IDP, create a copy so that we dont conflict with Launcher
137         // activity.
138         LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
139         if (isInMultiWindowModeCompat()) {
140             InvariantDeviceProfile idp = appState == null
141                     ? new InvariantDeviceProfile(this) : appState.getInvariantDeviceProfile();
142             DeviceProfile dp = idp.getDeviceProfile(this);
143             mDeviceProfile = mRecentsRootView == null ? dp.copy(this)
144                     : dp.getMultiWindowProfile(this, mRecentsRootView.getLastKnownSize());
145         } else {
146             // If we are reusing the Invariant device profile, make a copy.
147             mDeviceProfile = appState == null
148                     ? new InvariantDeviceProfile(this).getDeviceProfile(this)
149                     : appState.getInvariantDeviceProfile().getDeviceProfile(this).copy(this);
150         }
151         onDeviceProfileInitiated();
152     }
153 
154     @Override
getDragLayer()155     public BaseDragLayer getDragLayer() {
156         return mRecentsRootView;
157     }
158 
159     @Override
getRootView()160     public View getRootView() {
161         return mRecentsRootView;
162     }
163 
164     @Override
getOverviewPanel()165     public <T extends View> T getOverviewPanel() {
166         return (T) mFallbackRecentsView;
167     }
168 
getOverviewPanelContainer()169     public RecentsViewContainer getOverviewPanelContainer() {
170         return mOverviewPanelContainer;
171     }
172 
173     @Override
getBadgeInfoForItem(ItemInfo info)174     public BadgeInfo getBadgeInfoForItem(ItemInfo info) {
175         return null;
176     }
177 
178     @Override
getActivityLaunchOptions(final View v)179     public ActivityOptions getActivityLaunchOptions(final View v) {
180         if (!(v instanceof TaskView)) {
181             return null;
182         }
183 
184         final TaskView taskView = (TaskView) v;
185         RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mUiHandler,
186                 true /* startAtFrontOfQueue */) {
187 
188             @Override
189             public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats,
190                     AnimationResult result) {
191                 result.setAnimation(composeRecentsLaunchAnimator(taskView, targetCompats));
192             }
193         };
194         return ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat(
195                 runner, RECENTS_LAUNCH_DURATION,
196                 RECENTS_LAUNCH_DURATION - STATUS_BAR_TRANSITION_DURATION));
197     }
198 
199     /**
200      * Composes the animations for a launch from the recents list if possible.
201      */
composeRecentsLaunchAnimator(TaskView taskView, RemoteAnimationTargetCompat[] targets)202     private AnimatorSet composeRecentsLaunchAnimator(TaskView taskView,
203             RemoteAnimationTargetCompat[] targets) {
204         AnimatorSet target = new AnimatorSet();
205         boolean activityClosing = taskIsATargetWithMode(targets, getTaskId(), MODE_CLOSING);
206         ClipAnimationHelper helper = new ClipAnimationHelper();
207         target.play(getRecentsWindowAnimator(taskView, !activityClosing, targets, helper)
208                 .setDuration(RECENTS_LAUNCH_DURATION));
209 
210         // Found a visible recents task that matches the opening app, lets launch the app from there
211         if (activityClosing) {
212             Animator adjacentAnimation = mFallbackRecentsView
213                     .createAdjacentPageAnimForTaskLaunch(taskView, helper);
214             adjacentAnimation.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR);
215             adjacentAnimation.setDuration(RECENTS_LAUNCH_DURATION);
216             adjacentAnimation.addListener(new AnimatorListenerAdapter() {
217                 @Override
218                 public void onAnimationEnd(Animator animation) {
219                     mFallbackRecentsView.resetTaskVisuals();
220                 }
221             });
222             target.play(adjacentAnimation);
223         }
224         return target;
225     }
226 
227     @Override
invalidateParent(ItemInfo info)228     public void invalidateParent(ItemInfo info) { }
229 
230     @Override
onStart()231     protected void onStart() {
232         // Set the alpha to 1 before calling super, as it may get set back to 0 due to
233         // onActivityStart callback.
234         mFallbackRecentsView.setContentAlpha(1);
235         super.onStart();
236         UiFactory.onStart(this);
237         mFallbackRecentsView.resetTaskVisuals();
238     }
239 
240     @Override
onStop()241     protected void onStop() {
242         super.onStop();
243 
244         // Workaround for b/78520668, explicitly trim memory once UI is hidden
245         onTrimMemory(TRIM_MEMORY_UI_HIDDEN);
246     }
247 
248     @Override
onTrimMemory(int level)249     public void onTrimMemory(int level) {
250         super.onTrimMemory(level);
251         UiFactory.onTrimMemory(this, level);
252     }
253 
254     @Override
onNewIntent(Intent intent)255     protected void onNewIntent(Intent intent) {
256         super.onNewIntent(intent);
257         RecentsActivityTracker.onRecentsActivityNewIntent(this);
258     }
259 
260     @Override
onDestroy()261     protected void onDestroy() {
262         super.onDestroy();
263         RecentsActivityTracker.onRecentsActivityDestroy(this);
264     }
265 
266     @Override
onBackPressed()267     public void onBackPressed() {
268         // TODO: Launch the task we came from
269         startHome();
270     }
271 
startHome()272     public void startHome() {
273         startActivity(new Intent(Intent.ACTION_MAIN)
274                 .addCategory(Intent.CATEGORY_HOME)
275                 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
276     }
277 
278     @Override
dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args)279     public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
280         super.dump(prefix, fd, writer, args);
281         writer.println(prefix + "Misc:");
282         dumpMisc(writer);
283     }
284 }
285