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; 17 18 import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR; 19 import static com.android.launcher3.anim.Interpolators.ACCEL_2; 20 import static com.android.launcher3.anim.Interpolators.INSTANT; 21 import static com.android.launcher3.anim.Interpolators.LINEAR; 22 import static com.android.quickstep.AbsSwipeUpHandler.RECENTS_ATTACH_DURATION; 23 import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS; 24 import static com.android.quickstep.SysUINavigationMode.getMode; 25 import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_RECENTS_FADE_ANIM; 26 import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_RECENTS_TRANSLATE_X_ANIM; 27 import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET; 28 import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS; 29 import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; 30 import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION; 31 32 import android.animation.Animator; 33 import android.animation.ObjectAnimator; 34 import android.annotation.TargetApi; 35 import android.content.Context; 36 import android.content.res.Resources; 37 import android.graphics.Color; 38 import android.graphics.PointF; 39 import android.graphics.Rect; 40 import android.os.Build; 41 import android.view.Gravity; 42 import android.view.MotionEvent; 43 44 import androidx.annotation.Nullable; 45 import androidx.annotation.UiThread; 46 47 import com.android.launcher3.DeviceProfile; 48 import com.android.launcher3.R; 49 import com.android.launcher3.anim.AnimatorPlaybackController; 50 import com.android.launcher3.anim.PendingAnimation; 51 import com.android.launcher3.config.FeatureFlags; 52 import com.android.launcher3.statehandlers.DepthController; 53 import com.android.launcher3.statemanager.BaseState; 54 import com.android.launcher3.statemanager.StatefulActivity; 55 import com.android.launcher3.touch.PagedOrientationHandler; 56 import com.android.launcher3.util.WindowBounds; 57 import com.android.launcher3.views.ScrimView; 58 import com.android.quickstep.SysUINavigationMode.Mode; 59 import com.android.quickstep.util.ActivityInitListener; 60 import com.android.quickstep.util.AnimatorControllerWithResistance; 61 import com.android.quickstep.util.SplitScreenBounds; 62 import com.android.quickstep.views.OverviewActionsView; 63 import com.android.quickstep.views.RecentsView; 64 import com.android.quickstep.views.TaskView; 65 import com.android.systemui.shared.recents.model.ThumbnailData; 66 import com.android.systemui.shared.system.RemoteAnimationTargetCompat; 67 68 import java.util.function.Consumer; 69 import java.util.function.Predicate; 70 71 /** 72 * Utility class which abstracts out the logical differences between Launcher and RecentsActivity. 73 */ 74 @TargetApi(Build.VERSION_CODES.P) 75 public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_TYPE>, 76 ACTIVITY_TYPE extends StatefulActivity<STATE_TYPE>> { 77 78 public final boolean rotationSupportedByActivity; 79 80 private final STATE_TYPE mBackgroundState; 81 82 private STATE_TYPE mTargetState; 83 BaseActivityInterface(boolean rotationSupportedByActivity, STATE_TYPE overviewState, STATE_TYPE backgroundState)84 protected BaseActivityInterface(boolean rotationSupportedByActivity, 85 STATE_TYPE overviewState, STATE_TYPE backgroundState) { 86 this.rotationSupportedByActivity = rotationSupportedByActivity; 87 mTargetState = overviewState; 88 mBackgroundState = backgroundState; 89 } 90 91 /** 92 * Called when the current gesture transition is cancelled. 93 * @param activityVisible Whether the user can see the changes we make here, so try to animate. 94 * @param endTarget If the gesture ended before we got cancelled, where we were headed. 95 */ onTransitionCancelled(boolean activityVisible, @Nullable GestureState.GestureEndTarget endTarget)96 public void onTransitionCancelled(boolean activityVisible, 97 @Nullable GestureState.GestureEndTarget endTarget) { 98 ACTIVITY_TYPE activity = getCreatedActivity(); 99 if (activity == null) { 100 return; 101 } 102 STATE_TYPE startState = activity.getStateManager().getRestState(); 103 if (endTarget != null) { 104 // We were on our way to this state when we got canceled, end there instead. 105 startState = stateFromGestureEndTarget(endTarget); 106 } 107 activity.getStateManager().goToState(startState, activityVisible); 108 } 109 getSwipeUpDestinationAndLength( DeviceProfile dp, Context context, Rect outRect, PagedOrientationHandler orientationHandler)110 public abstract int getSwipeUpDestinationAndLength( 111 DeviceProfile dp, Context context, Rect outRect, 112 PagedOrientationHandler orientationHandler); 113 114 /** Called when the animation to home has fully settled. */ onSwipeUpToHomeComplete(RecentsAnimationDeviceState deviceState)115 public void onSwipeUpToHomeComplete(RecentsAnimationDeviceState deviceState) {} 116 onAssistantVisibilityChanged(float visibility)117 public abstract void onAssistantVisibilityChanged(float visibility); 118 119 /** Called when one handed mode activated or deactivated. */ onOneHandedModeStateChanged(boolean activated)120 public abstract void onOneHandedModeStateChanged(boolean activated); 121 prepareRecentsUI(RecentsAnimationDeviceState deviceState, boolean activityVisible, Consumer<AnimatorControllerWithResistance> callback)122 public abstract AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState, 123 boolean activityVisible, Consumer<AnimatorControllerWithResistance> callback); 124 createActivityInitListener( Predicate<Boolean> onInitListener)125 public abstract ActivityInitListener createActivityInitListener( 126 Predicate<Boolean> onInitListener); 127 128 /** 129 * Sets a callback to be run when an activity launch happens while launcher is not yet resumed. 130 */ setOnDeferredActivityLaunchCallback(Runnable r)131 public void setOnDeferredActivityLaunchCallback(Runnable r) {} 132 133 @Nullable getCreatedActivity()134 public abstract ACTIVITY_TYPE getCreatedActivity(); 135 136 @Nullable getDepthController()137 public DepthController getDepthController() { 138 return null; 139 } 140 isResumed()141 public final boolean isResumed() { 142 ACTIVITY_TYPE activity = getCreatedActivity(); 143 return activity != null && activity.hasBeenResumed(); 144 } 145 isStarted()146 public final boolean isStarted() { 147 ACTIVITY_TYPE activity = getCreatedActivity(); 148 return activity != null && activity.isStarted(); 149 } 150 151 @UiThread 152 @Nullable getVisibleRecentsView()153 public abstract <T extends RecentsView> T getVisibleRecentsView(); 154 155 @UiThread switchToRecentsIfVisible(Runnable onCompleteCallback)156 public abstract boolean switchToRecentsIfVisible(Runnable onCompleteCallback); 157 getOverviewWindowBounds( Rect homeBounds, RemoteAnimationTargetCompat target)158 public abstract Rect getOverviewWindowBounds( 159 Rect homeBounds, RemoteAnimationTargetCompat target); 160 allowMinimizeSplitScreen()161 public abstract boolean allowMinimizeSplitScreen(); 162 deferStartingActivity(RecentsAnimationDeviceState deviceState, MotionEvent ev)163 public boolean deferStartingActivity(RecentsAnimationDeviceState deviceState, MotionEvent ev) { 164 return deviceState.isInDeferredGestureRegion(ev); 165 } 166 167 /** 168 * @return Whether the gesture in progress should be cancelled. 169 */ shouldCancelCurrentGesture()170 public boolean shouldCancelCurrentGesture() { 171 return false; 172 } 173 onExitOverview(RotationTouchHelper deviceState, Runnable exitRunnable)174 public abstract void onExitOverview(RotationTouchHelper deviceState, 175 Runnable exitRunnable); 176 isInLiveTileMode()177 public abstract boolean isInLiveTileMode(); 178 onLaunchTaskFailed()179 public abstract void onLaunchTaskFailed(); 180 onLaunchTaskSuccess()181 public void onLaunchTaskSuccess() { 182 ACTIVITY_TYPE activity = getCreatedActivity(); 183 if (activity == null) { 184 return; 185 } 186 activity.getStateManager().moveToRestState(); 187 } 188 closeOverlay()189 public void closeOverlay() { } 190 switchRunningTaskViewToScreenshot(ThumbnailData thumbnailData, Runnable runnable)191 public void switchRunningTaskViewToScreenshot(ThumbnailData thumbnailData, Runnable runnable) { 192 ACTIVITY_TYPE activity = getCreatedActivity(); 193 if (activity == null) { 194 return; 195 } 196 RecentsView recentsView = activity.getOverviewPanel(); 197 if (recentsView == null) { 198 if (runnable != null) { 199 runnable.run(); 200 } 201 return; 202 } 203 recentsView.switchToScreenshot(thumbnailData, runnable); 204 } 205 206 /** 207 * Calculates the taskView size for the provided device configuration. 208 */ calculateTaskSize(Context context, DeviceProfile dp, Rect outRect, PagedOrientationHandler orientedState)209 public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect, 210 PagedOrientationHandler orientedState) { 211 Resources res = context.getResources(); 212 if (dp.isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()) { 213 Rect gridRect = new Rect(); 214 calculateGridSize(context, dp, gridRect); 215 216 int verticalMargin = res.getDimensionPixelSize( 217 R.dimen.overview_grid_focus_vertical_margin); 218 float taskHeight = gridRect.height() - verticalMargin * 2; 219 220 PointF taskDimension = getTaskDimension(context, dp); 221 float scale = taskHeight / Math.max(taskDimension.x, taskDimension.y); 222 int outWidth = Math.round(scale * taskDimension.x); 223 int outHeight = Math.round(scale * taskDimension.y); 224 225 int gravity = Gravity.CENTER_VERTICAL; 226 gravity |= orientedState.getRecentsRtlSetting(res) ? Gravity.RIGHT : Gravity.LEFT; 227 Gravity.apply(gravity, outWidth, outHeight, gridRect, outRect); 228 } else { 229 int taskMargin = dp.overviewTaskMarginPx; 230 int proactiveRowAndMargin; 231 if (!TaskView.SHOW_PROACTIVE_ACTIONS || dp.isVerticalBarLayout()) { 232 // In Vertical Bar Layout the proactive row doesn't have its own space, it's inside 233 // the actions row. 234 proactiveRowAndMargin = 0; 235 } else { 236 proactiveRowAndMargin = res.getDimensionPixelSize( 237 R.dimen.overview_proactive_row_height) 238 + res.getDimensionPixelSize(R.dimen.overview_proactive_row_bottom_margin); 239 } 240 calculateTaskSizeInternal(context, dp, 241 dp.overviewTaskThumbnailTopMarginPx, 242 proactiveRowAndMargin + getOverviewActionsHeight(context, dp), 243 res.getDimensionPixelSize(R.dimen.overview_minimum_next_prev_size) + taskMargin, 244 outRect); 245 } 246 } 247 calculateTaskSizeInternal(Context context, DeviceProfile dp, int claimedSpaceAbove, int claimedSpaceBelow, int minimumHorizontalPadding, Rect outRect)248 private void calculateTaskSizeInternal(Context context, DeviceProfile dp, 249 int claimedSpaceAbove, int claimedSpaceBelow, int minimumHorizontalPadding, 250 Rect outRect) { 251 PointF taskDimension = getTaskDimension(context, dp); 252 Rect insets = dp.getInsets(); 253 254 Rect potentialTaskRect = new Rect(0, 0, dp.widthPx, dp.heightPx); 255 potentialTaskRect.inset(insets.left, insets.top, insets.right, insets.bottom); 256 potentialTaskRect.inset( 257 minimumHorizontalPadding, 258 claimedSpaceAbove, 259 minimumHorizontalPadding, 260 claimedSpaceBelow); 261 262 float scale = Math.min( 263 potentialTaskRect.width() / taskDimension.x, 264 potentialTaskRect.height() / taskDimension.y); 265 int outWidth = Math.round(scale * taskDimension.x); 266 int outHeight = Math.round(scale * taskDimension.y); 267 268 Gravity.apply(Gravity.CENTER, outWidth, outHeight, potentialTaskRect, outRect); 269 } 270 getTaskDimension(Context context, DeviceProfile dp)271 private static PointF getTaskDimension(Context context, DeviceProfile dp) { 272 PointF dimension = new PointF(); 273 getTaskDimension(context, dp, dimension); 274 return dimension; 275 } 276 277 /** 278 * Gets the dimension of the task in the current system state. 279 */ getTaskDimension(Context context, DeviceProfile dp, PointF out)280 public static void getTaskDimension(Context context, DeviceProfile dp, PointF out) { 281 if (dp.isMultiWindowMode) { 282 WindowBounds bounds = SplitScreenBounds.INSTANCE.getSecondaryWindowBounds(context); 283 if (TaskView.CLIP_STATUS_AND_NAV_BARS) { 284 out.x = bounds.availableSize.x; 285 out.y = bounds.availableSize.y; 286 } else { 287 out.x = bounds.availableSize.x + bounds.insets.left + bounds.insets.right; 288 out.y = bounds.availableSize.y + bounds.insets.top + bounds.insets.bottom; 289 } 290 } else if (TaskView.CLIP_STATUS_AND_NAV_BARS) { 291 out.x = dp.availableWidthPx; 292 out.y = dp.availableHeightPx; 293 } else { 294 out.x = dp.widthPx; 295 out.y = dp.heightPx; 296 } 297 } 298 299 /** 300 * Calculates the overview grid size for the provided device configuration. 301 */ calculateGridSize(Context context, DeviceProfile dp, Rect outRect)302 public final void calculateGridSize(Context context, DeviceProfile dp, Rect outRect) { 303 Resources res = context.getResources(); 304 int topMargin = res.getDimensionPixelSize(R.dimen.overview_grid_top_margin); 305 int bottomMargin = res.getDimensionPixelSize(R.dimen.overview_grid_bottom_margin); 306 int sideMargin = res.getDimensionPixelSize(R.dimen.overview_grid_side_margin); 307 308 Rect insets = dp.getInsets(); 309 outRect.set(0, 0, dp.widthPx, dp.heightPx); 310 outRect.inset(Math.max(insets.left, sideMargin), Math.max(insets.top, topMargin), 311 Math.max(insets.right, sideMargin), Math.max(insets.bottom, bottomMargin)); 312 } 313 314 /** 315 * Calculates the overview grid non-focused task size for the provided device configuration. 316 */ calculateGridTaskSize(Context context, DeviceProfile dp, Rect outRect, PagedOrientationHandler orientedState)317 public final void calculateGridTaskSize(Context context, DeviceProfile dp, Rect outRect, 318 PagedOrientationHandler orientedState) { 319 Resources res = context.getResources(); 320 Rect gridRect = new Rect(); 321 calculateGridSize(context, dp, gridRect); 322 323 int rowSpacing = res.getDimensionPixelSize(R.dimen.overview_grid_row_spacing); 324 float rowHeight = (gridRect.height() - rowSpacing) / 2f; 325 326 PointF taskDimension = getTaskDimension(context, dp); 327 float scale = (rowHeight - dp.overviewTaskThumbnailTopMarginPx) / Math.max( 328 taskDimension.x, taskDimension.y); 329 int outWidth = Math.round(scale * taskDimension.x); 330 int outHeight = Math.round(scale * taskDimension.y); 331 332 int gravity = Gravity.TOP; 333 gravity |= orientedState.getRecentsRtlSetting(res) ? Gravity.RIGHT : Gravity.LEFT; 334 gridRect.inset(0, dp.overviewTaskThumbnailTopMarginPx, 0, 0); 335 Gravity.apply(gravity, outWidth, outHeight, gridRect, outRect); 336 } 337 338 /** 339 * Calculates the modal taskView size for the provided device configuration 340 */ calculateModalTaskSize(Context context, DeviceProfile dp, Rect outRect)341 public final void calculateModalTaskSize(Context context, DeviceProfile dp, Rect outRect) { 342 calculateTaskSizeInternal( 343 context, dp, 344 dp.overviewTaskMarginPx, 345 getOverviewActionsHeight(context, dp), 346 dp.overviewTaskMarginPx, 347 outRect); 348 } 349 350 /** Gets the space that the overview actions will take, including bottom margin. */ getOverviewActionsHeight(Context context, DeviceProfile dp)351 private int getOverviewActionsHeight(Context context, DeviceProfile dp) { 352 Resources res = context.getResources(); 353 return OverviewActionsView.getOverviewActionsBottomMarginPx(getMode(context), dp) 354 + OverviewActionsView.getOverviewActionsTopMarginPx(getMode(context), dp) 355 + res.getDimensionPixelSize(R.dimen.overview_actions_height); 356 } 357 358 /** 359 * Called when the gesture ends and the animation starts towards the given target. Used to add 360 * an optional additional animation with the same duration. 361 */ getParallelAnimationToLauncher( GestureState.GestureEndTarget endTarget, long duration)362 public @Nullable Animator getParallelAnimationToLauncher( 363 GestureState.GestureEndTarget endTarget, long duration) { 364 if (endTarget == RECENTS) { 365 ACTIVITY_TYPE activity = getCreatedActivity(); 366 if (activity == null) { 367 return null; 368 } 369 STATE_TYPE state = stateFromGestureEndTarget(endTarget); 370 ScrimView scrimView = activity.getScrimView(); 371 ObjectAnimator anim = ObjectAnimator.ofArgb(scrimView, VIEW_BACKGROUND_COLOR, 372 getOverviewScrimColorForState(activity, state)); 373 anim.setDuration(duration); 374 return anim; 375 } 376 return null; 377 } 378 379 /** 380 * Returns the color of the scrim behind overview when at rest in this state. 381 * Return {@link Color#TRANSPARENT} for no scrim. 382 */ getOverviewScrimColorForState(ACTIVITY_TYPE activity, STATE_TYPE state)383 protected abstract int getOverviewScrimColorForState(ACTIVITY_TYPE activity, STATE_TYPE state); 384 385 /** 386 * Returns the expected STATE_TYPE from the provided GestureEndTarget. 387 */ stateFromGestureEndTarget(GestureState.GestureEndTarget endTarget)388 public abstract STATE_TYPE stateFromGestureEndTarget(GestureState.GestureEndTarget endTarget); 389 390 public interface AnimationFactory { 391 createActivityInterface(long transitionLength)392 void createActivityInterface(long transitionLength); 393 394 /** 395 * @param attached Whether to show RecentsView alongside the app window. If false, recents 396 * will be hidden by some property we can animate, e.g. alpha. 397 * @param animate Whether to animate recents to/from its new attached state. 398 */ setRecentsAttachedToAppWindow(boolean attached, boolean animate)399 default void setRecentsAttachedToAppWindow(boolean attached, boolean animate) { } 400 isRecentsAttachedToAppWindow()401 default boolean isRecentsAttachedToAppWindow() { 402 return false; 403 } 404 405 /** Called when the gesture ends and we know what state it is going towards */ setEndTarget(GestureState.GestureEndTarget endTarget)406 default void setEndTarget(GestureState.GestureEndTarget endTarget) { } 407 } 408 409 class DefaultAnimationFactory implements AnimationFactory { 410 411 protected final ACTIVITY_TYPE mActivity; 412 private final STATE_TYPE mStartState; 413 private final Consumer<AnimatorControllerWithResistance> mCallback; 414 415 private boolean mIsAttachedToWindow; 416 DefaultAnimationFactory(Consumer<AnimatorControllerWithResistance> callback)417 DefaultAnimationFactory(Consumer<AnimatorControllerWithResistance> callback) { 418 mCallback = callback; 419 420 mActivity = getCreatedActivity(); 421 mStartState = mActivity.getStateManager().getState(); 422 } 423 initUI()424 protected ACTIVITY_TYPE initUI() { 425 STATE_TYPE resetState = mStartState; 426 if (mStartState.shouldDisableRestore()) { 427 resetState = mActivity.getStateManager().getRestState(); 428 } 429 mActivity.getStateManager().setRestState(resetState); 430 mActivity.getStateManager().goToState(mBackgroundState, false); 431 return mActivity; 432 } 433 434 @Override createActivityInterface(long transitionLength)435 public void createActivityInterface(long transitionLength) { 436 PendingAnimation pa = new PendingAnimation(transitionLength * 2); 437 createBackgroundToOverviewAnim(mActivity, pa); 438 AnimatorPlaybackController controller = pa.createPlaybackController(); 439 mActivity.getStateManager().setCurrentUserControlledAnimation(controller); 440 441 // Since we are changing the start position of the UI, reapply the state, at the end 442 controller.setEndAction(() -> mActivity.getStateManager().goToState( 443 controller.getInterpolatedProgress() > 0.5 ? mTargetState : mBackgroundState, 444 false)); 445 446 RecentsView recentsView = mActivity.getOverviewPanel(); 447 AnimatorControllerWithResistance controllerWithResistance = 448 AnimatorControllerWithResistance.createForRecents(controller, mActivity, 449 recentsView.getPagedViewOrientedState(), mActivity.getDeviceProfile(), 450 recentsView, RECENTS_SCALE_PROPERTY, recentsView, 451 TASK_SECONDARY_TRANSLATION); 452 mCallback.accept(controllerWithResistance); 453 454 // Creating the activity controller animation sometimes reapplies the launcher state 455 // (because we set the animation as the current state animation), so we reapply the 456 // attached state here as well to ensure recents is shown/hidden appropriately. 457 if (SysUINavigationMode.getMode(mActivity) == Mode.NO_BUTTON) { 458 setRecentsAttachedToAppWindow(mIsAttachedToWindow, false); 459 } 460 } 461 462 @Override setRecentsAttachedToAppWindow(boolean attached, boolean animate)463 public void setRecentsAttachedToAppWindow(boolean attached, boolean animate) { 464 if (mIsAttachedToWindow == attached && animate) { 465 return; 466 } 467 mIsAttachedToWindow = attached; 468 RecentsView recentsView = mActivity.getOverviewPanel(); 469 Animator fadeAnim = mActivity.getStateManager() 470 .createStateElementAnimation(INDEX_RECENTS_FADE_ANIM, attached ? 1 : 0); 471 472 float fromTranslation = attached ? 1 : 0; 473 float toTranslation = attached ? 0 : 1; 474 mActivity.getStateManager() 475 .cancelStateElementAnimation(INDEX_RECENTS_TRANSLATE_X_ANIM); 476 if (!recentsView.isShown() && animate) { 477 ADJACENT_PAGE_HORIZONTAL_OFFSET.set(recentsView, fromTranslation); 478 } else { 479 fromTranslation = ADJACENT_PAGE_HORIZONTAL_OFFSET.get(recentsView); 480 } 481 if (!animate) { 482 ADJACENT_PAGE_HORIZONTAL_OFFSET.set(recentsView, toTranslation); 483 } else { 484 mActivity.getStateManager().createStateElementAnimation( 485 INDEX_RECENTS_TRANSLATE_X_ANIM, 486 fromTranslation, toTranslation).start(); 487 } 488 489 fadeAnim.setInterpolator(attached ? INSTANT : ACCEL_2); 490 fadeAnim.setDuration(animate ? RECENTS_ATTACH_DURATION : 0).start(); 491 } 492 493 @Override isRecentsAttachedToAppWindow()494 public boolean isRecentsAttachedToAppWindow() { 495 return mIsAttachedToWindow; 496 } 497 498 @Override setEndTarget(GestureState.GestureEndTarget endTarget)499 public void setEndTarget(GestureState.GestureEndTarget endTarget) { 500 mTargetState = stateFromGestureEndTarget(endTarget); 501 } 502 createBackgroundToOverviewAnim(ACTIVITY_TYPE activity, PendingAnimation pa)503 protected void createBackgroundToOverviewAnim(ACTIVITY_TYPE activity, PendingAnimation pa) { 504 // Scale down recents from being full screen to being in overview. 505 RecentsView recentsView = activity.getOverviewPanel(); 506 pa.addFloat(recentsView, RECENTS_SCALE_PROPERTY, 507 recentsView.getMaxScaleForFullScreen(), 1, LINEAR); 508 pa.addFloat(recentsView, FULLSCREEN_PROGRESS, 1, 0, LINEAR); 509 } 510 } 511 512 /** Called when OverviewService is bound to this process */ onOverviewServiceBound()513 void onOverviewServiceBound() { 514 // Do nothing 515 } 516 } 517