From 044d52934e57a337665f707aa4be1d423ee3fb29 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Thu, 6 Nov 2014 11:05:19 -0800 Subject: [PATCH] Adding bounce animation for affiliated tasks. (Bug 16656169) Change-Id: I39e4a57c4e6b707d15513dacde2d40c23bb05058 --- .../android/app/ActivityManagerNative.java | 32 +++++++++++++ core/java/android/app/ActivityOptions.java | 48 +++++++++++++++++++ core/java/android/app/IActivityManager.java | 4 ++ core/java/android/view/IWindowManager.aidl | 1 + .../res/anim/launch_task_behind_source.xml | 39 ++++++--------- .../res/anim/launch_task_behind_target.xml | 16 +++---- .../launch_task_behind_source_scale_1.xml | 21 ++++++++ .../launch_task_behind_source_scale_2.xml | 21 ++++++++ .../launch_task_behind_target_ydelta.xml | 21 ++++++++ core/res/res/values/symbols.xml | 1 + ...nts_launch_next_affiliated_task_bounce.xml | 42 +++++++--------- ...nts_launch_prev_affiliated_task_bounce.xml | 12 ++--- ...unch_next_affiliated_task_bounce_scale.xml | 20 ++++++++ ...nch_prev_affiliated_task_bounce_ydelta.xml | 20 ++++++++ .../recents/AlternateRecentsComponent.java | 19 +++++--- .../recents/misc/SystemServicesProxy.java | 14 ++++++ .../server/am/ActivityManagerService.java | 14 ++++++ .../com/android/server/wm/AppTransition.java | 28 +++++++++++ .../server/wm/WindowManagerService.java | 39 +++++++++++++++ .../src/android/view/IWindowManagerImpl.java | 5 ++ 20 files changed, 345 insertions(+), 72 deletions(-) create mode 100644 core/res/res/interpolator/launch_task_behind_source_scale_1.xml create mode 100644 core/res/res/interpolator/launch_task_behind_source_scale_2.xml create mode 100644 core/res/res/interpolator/launch_task_behind_target_ydelta.xml create mode 100644 packages/SystemUI/res/interpolator/recents_launch_next_affiliated_task_bounce_scale.xml create mode 100644 packages/SystemUI/res/interpolator/recents_launch_prev_affiliated_task_bounce_ydelta.xml diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index bc7114b2ee9d4..c3028b7f63ea0 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -2279,6 +2279,20 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case START_IN_PLACE_ANIMATION_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + final Bundle bundle; + if (data.readInt() == 0) { + bundle = null; + } else { + bundle = data.readBundle(); + } + final ActivityOptions options = bundle == null ? null : new ActivityOptions(bundle); + startInPlaceAnimationOnFrontMostApplication(options); + reply.writeNoException(); + return true; + } + case REQUEST_VISIBLE_BEHIND_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); @@ -5297,6 +5311,24 @@ class ActivityManagerProxy implements IActivityManager return icon; } + @Override + public void startInPlaceAnimationOnFrontMostApplication(ActivityOptions options) + throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + if (options == null) { + data.writeInt(0); + } else { + data.writeInt(1); + data.writeBundle(options.toBundle()); + } + mRemote.transact(START_IN_PLACE_ANIMATION_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY); + reply.readException(); + data.recycle(); + reply.recycle(); + } + @Override public boolean requestVisibleBehind(IBinder token, boolean visible) throws RemoteException { Parcel data = Parcel.obtain(); diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index cd6a4f51bf906..3d390bfe916b3 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -62,6 +62,12 @@ public class ActivityOptions { */ public static final String KEY_ANIM_EXIT_RES_ID = "android:animExitRes"; + /** + * Custom in-place animation resource ID. + * @hide + */ + public static final String KEY_ANIM_IN_PLACE_RES_ID = "android:animInPlaceRes"; + /** * Bitmap for thumbnail animation. * @hide @@ -132,11 +138,14 @@ public class ActivityOptions { public static final int ANIM_THUMBNAIL_ASPECT_SCALE_UP = 8; /** @hide */ public static final int ANIM_THUMBNAIL_ASPECT_SCALE_DOWN = 9; + /** @hide */ + public static final int ANIM_CUSTOM_IN_PLACE = 10; private String mPackageName; private int mAnimationType = ANIM_NONE; private int mCustomEnterResId; private int mCustomExitResId; + private int mCustomInPlaceResId; private Bitmap mThumbnail; private int mStartX; private int mStartY; @@ -198,6 +207,30 @@ public class ActivityOptions { return opts; } + /** + * Creates an ActivityOptions specifying a custom animation to run in place on an existing + * activity. + * + * @param context Who is defining this. This is the application that the + * animation resources will be loaded from. + * @param animId A resource ID of the animation resource to use for + * the incoming activity. + * @return Returns a new ActivityOptions object that you can use to + * supply these options as the options Bundle when running an in-place animation. + * @hide + */ + public static ActivityOptions makeCustomInPlaceAnimation(Context context, int animId) { + if (animId == 0) { + throw new RuntimeException("You must specify a valid animation."); + } + + ActivityOptions opts = new ActivityOptions(); + opts.mPackageName = context.getPackageName(); + opts.mAnimationType = ANIM_CUSTOM_IN_PLACE; + opts.mCustomInPlaceResId = animId; + return opts; + } + private void setOnAnimationStartedListener(Handler handler, OnAnimationStartedListener listener) { if (listener != null) { @@ -540,6 +573,10 @@ public class ActivityOptions { opts.getBinder(KEY_ANIM_START_LISTENER)); break; + case ANIM_CUSTOM_IN_PLACE: + mCustomInPlaceResId = opts.getInt(KEY_ANIM_IN_PLACE_RES_ID, 0); + break; + case ANIM_SCALE_UP: mStartX = opts.getInt(KEY_ANIM_START_X, 0); mStartY = opts.getInt(KEY_ANIM_START_Y, 0); @@ -591,6 +628,11 @@ public class ActivityOptions { return mCustomExitResId; } + /** @hide */ + public int getCustomInPlaceResId() { + return mCustomInPlaceResId; + } + /** @hide */ public Bitmap getThumbnail() { return mThumbnail; @@ -689,6 +731,9 @@ public class ActivityOptions { } mAnimationStartedListener = otherOptions.mAnimationStartedListener; break; + case ANIM_CUSTOM_IN_PLACE: + mCustomInPlaceResId = otherOptions.mCustomInPlaceResId; + break; case ANIM_SCALE_UP: mStartX = otherOptions.mStartX; mStartY = otherOptions.mStartY; @@ -756,6 +801,9 @@ public class ActivityOptions { b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener != null ? mAnimationStartedListener.asBinder() : null); break; + case ANIM_CUSTOM_IN_PLACE: + b.putInt(KEY_ANIM_IN_PLACE_RES_ID, mCustomInPlaceResId); + break; case ANIM_SCALE_UP: b.putInt(KEY_ANIM_START_X, mStartX); b.putInt(KEY_ANIM_START_Y, mStartY); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index efcb197e4a284..6433f3faa3518 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -456,6 +456,9 @@ public interface IActivityManager extends IInterface { throws RemoteException; public Bitmap getTaskDescriptionIcon(String filename) throws RemoteException; + public void startInPlaceAnimationOnFrontMostApplication(ActivityOptions opts) + throws RemoteException; + public boolean requestVisibleBehind(IBinder token, boolean visible) throws RemoteException; public boolean isBackgroundVisibleBehind(IBinder token) throws RemoteException; public void backgroundResourcesReleased(IBinder token) throws RemoteException; @@ -781,4 +784,5 @@ public interface IActivityManager extends IInterface { int BOOT_ANIMATION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+237; int GET_TASK_DESCRIPTION_ICON_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+238; int LAUNCH_ASSIST_INTENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+239; + int START_IN_PLACE_ANIMATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+240; } diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 6aa86c7a0bef0..7b20e721832ca 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -96,6 +96,7 @@ interface IWindowManager void overridePendingAppTransitionAspectScaledThumb(in Bitmap srcThumb, int startX, int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback, boolean scaleUp); + void overridePendingAppTransitionInPlace(String packageName, int anim); void executeAppTransition(); void setAppStartingWindow(IBinder token, String pkg, int theme, in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, diff --git a/core/res/res/anim/launch_task_behind_source.xml b/core/res/res/anim/launch_task_behind_source.xml index cd3e30a876940..a7157056f4a56 100644 --- a/core/res/res/anim/launch_task_behind_source.xml +++ b/core/res/res/anim/launch_task_behind_source.xml @@ -22,38 +22,27 @@ + android:interpolator="@interpolator/linear_out_slow_in" + android:duration="417"/> - - - + android:interpolator="@interpolator/launch_task_behind_source_scale_1" + android:duration="417" /> + android:interpolator="@interpolator/linear" + android:startOffset="500" + android:duration="167"/> - - - + android:interpolator="@interpolator/launch_task_behind_source_scale_2" + android:startOffset="500" + android:duration="317" /> \ No newline at end of file diff --git a/core/res/res/anim/launch_task_behind_target.xml b/core/res/res/anim/launch_task_behind_target.xml index 358511f72e26f..805918bf4b072 100644 --- a/core/res/res/anim/launch_task_behind_target.xml +++ b/core/res/res/anim/launch_task_behind_target.xml @@ -20,15 +20,15 @@ - + android:duration="333" /> - - \ No newline at end of file + android:interpolator="@interpolator/fast_out_linear_in" + android:startOffset="467" + android:duration="317" /> + diff --git a/core/res/res/interpolator/launch_task_behind_source_scale_1.xml b/core/res/res/interpolator/launch_task_behind_source_scale_1.xml new file mode 100644 index 0000000000000..7e295d8a65ed7 --- /dev/null +++ b/core/res/res/interpolator/launch_task_behind_source_scale_1.xml @@ -0,0 +1,21 @@ + + + + diff --git a/core/res/res/interpolator/launch_task_behind_source_scale_2.xml b/core/res/res/interpolator/launch_task_behind_source_scale_2.xml new file mode 100644 index 0000000000000..1601fd026482e --- /dev/null +++ b/core/res/res/interpolator/launch_task_behind_source_scale_2.xml @@ -0,0 +1,21 @@ + + + + diff --git a/core/res/res/interpolator/launch_task_behind_target_ydelta.xml b/core/res/res/interpolator/launch_task_behind_target_ydelta.xml new file mode 100644 index 0000000000000..96b539f24d2cf --- /dev/null +++ b/core/res/res/interpolator/launch_task_behind_target_ydelta.xml @@ -0,0 +1,21 @@ + + + + diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 6e881a7104699..df1550a74cc17 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1810,6 +1810,7 @@ + diff --git a/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_bounce.xml b/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_bounce.xml index a571cbc8c1f3a..74f2814b2ce86 100644 --- a/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_bounce.xml +++ b/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_bounce.xml @@ -20,40 +20,30 @@ - - - - + android:duration="133" /> - + - - - + android:interpolator="@interpolator/recents_launch_next_affiliated_task_bounce_scale" + android:startOffset="133" + android:duration="217" /> \ No newline at end of file diff --git a/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_bounce.xml b/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_bounce.xml index 46045acd9ac43..b19167da3ddee 100644 --- a/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_bounce.xml +++ b/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_bounce.xml @@ -22,12 +22,12 @@ + android:interpolator="@android:interpolator/fast_out_slow_in" + android:duration="133" /> - + android:interpolator="@interpolator/recents_launch_prev_affiliated_task_bounce_ydelta" + android:startOffset="133" + android:duration="217" /> \ No newline at end of file diff --git a/packages/SystemUI/res/interpolator/recents_launch_next_affiliated_task_bounce_scale.xml b/packages/SystemUI/res/interpolator/recents_launch_next_affiliated_task_bounce_scale.xml new file mode 100644 index 0000000000000..c4e5d972222c5 --- /dev/null +++ b/packages/SystemUI/res/interpolator/recents_launch_next_affiliated_task_bounce_scale.xml @@ -0,0 +1,20 @@ + + + diff --git a/packages/SystemUI/res/interpolator/recents_launch_prev_affiliated_task_bounce_ydelta.xml b/packages/SystemUI/res/interpolator/recents_launch_prev_affiliated_task_bounce_ydelta.xml new file mode 100644 index 0000000000000..40a08b97160d5 --- /dev/null +++ b/packages/SystemUI/res/interpolator/recents_launch_prev_affiliated_task_bounce_ydelta.xml @@ -0,0 +1,20 @@ + + + diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java index 76e8181407409..4f4c06f91e4f9 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java +++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java @@ -16,13 +16,11 @@ package com.android.systemui.recents; -import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityOptions; import android.appwidget.AppWidgetHost; import android.appwidget.AppWidgetProviderInfo; import android.content.ActivityNotFoundException; -import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -31,7 +29,6 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Rect; -import android.os.Handler; import android.os.UserHandle; import android.util.Pair; import android.view.LayoutInflater; @@ -199,6 +196,7 @@ public class AlternateRecentsComponent { Task toTask = null; ActivityOptions launchOpts = null; int taskCount = tasks.size(); + int numAffiliatedTasks = 0; for (int i = 0; i < taskCount; i++) { Task task = tasks.get(i); if (task.key.id == runningTask.id) { @@ -218,16 +216,23 @@ public class AlternateRecentsComponent { if (toTaskKey != null) { toTask = stack.findTaskWithId(toTaskKey.id); } + numAffiliatedTasks = group.getTaskCount(); break; } } // Return early if there is no next task if (toTask == null) { - if (showNextTask) { - // XXX: Show the next-task bounce animation - } else { - // XXX: Show the prev-task bounce animation + if (numAffiliatedTasks > 1) { + if (showNextTask) { + mSystemServicesProxy.startInPlaceAnimationOnFrontMostApplication( + ActivityOptions.makeCustomInPlaceAnimation(mContext, + R.anim.recents_launch_next_affiliated_task_bounce)); + } else { + mSystemServicesProxy.startInPlaceAnimationOnFrontMostApplication( + ActivityOptions.makeCustomInPlaceAnimation(mContext, + R.anim.recents_launch_prev_affiliated_task_bounce)); + } } return; } diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java index b661385184660..646d7018c3d36 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -48,12 +48,14 @@ import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.UserHandle; import android.provider.Settings; import android.util.Log; import android.util.Pair; import android.view.Display; import android.view.DisplayInfo; +import android.view.IWindowManager; import android.view.SurfaceControl; import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; @@ -429,6 +431,7 @@ public class SystemServicesProxy { opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX); if (!mAwm.bindAppWidgetIdIfAllowed(searchWidgetId, searchWidgetInfo.provider, opts)) { + host.deleteAppWidgetId(searchWidgetId); return null; } return new Pair(searchWidgetId, searchWidgetInfo); @@ -532,4 +535,15 @@ public class SystemServicesProxy { } return false; } + + /** Starts an in-place animation on the front most application windows. */ + public void startInPlaceAnimationOnFrontMostApplication(ActivityOptions opts) { + if (mIam == null) return; + + try { + mIam.startInPlaceAnimationOnFrontMostApplication(opts); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 91e2df012e536..5897924c1c176 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -8285,6 +8285,20 @@ public final class ActivityManagerService extends ActivityManagerNative return mTaskPersister.getTaskDescriptionIcon(filename); } + @Override + public void startInPlaceAnimationOnFrontMostApplication(ActivityOptions opts) + throws RemoteException { + if (opts.getAnimationType() != ActivityOptions.ANIM_CUSTOM_IN_PLACE || + opts.getCustomInPlaceResId() == 0) { + throw new IllegalArgumentException("Expected in-place ActivityOption " + + "with valid animation"); + } + mWindowManager.prepareAppTransition(AppTransition.TRANSIT_TASK_IN_PLACE, false); + mWindowManager.overridePendingAppTransitionInPlace(opts.getPackageName(), + opts.getCustomInPlaceResId()); + mWindowManager.executeAppTransition(); + } + private void cleanUpRemovedTaskLocked(TaskRecord tr, boolean killProcess) { mRecentTasks.remove(tr); tr.removedFromRecents(mTaskPersister); diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index eeb007c33f6e3..f6e8bcf0c3d8b 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -109,6 +109,8 @@ public class AppTransition implements Dump { /** A window in a new task is being opened behind an existing one in another activity's task. * The new window will show briefly and then be gone. */ public static final int TRANSIT_TASK_OPEN_BEHIND = 16; + /** A window in a task is being animated in-place. */ + public static final int TRANSIT_TASK_IN_PLACE = 17; /** Fraction of animation at which the recents thumbnail stays completely transparent */ private static final float RECENTS_THUMBNAIL_FADEIN_FRACTION = 0.7f; @@ -131,6 +133,7 @@ public class AppTransition implements Dump { private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN = 4; private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP = 5; private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN = 6; + private static final int NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE = 7; private int mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE; // These are the possible states for the enter/exit activities during a thumbnail transition @@ -146,6 +149,7 @@ public class AppTransition implements Dump { private IRemoteCallback mNextAppTransitionCallback; private int mNextAppTransitionEnter; private int mNextAppTransitionExit; + private int mNextAppTransitionInPlace; private int mNextAppTransitionStartX; private int mNextAppTransitionStartY; private int mNextAppTransitionStartWidth; @@ -835,6 +839,12 @@ public class AppTransition implements Dump { + " anim=" + a + " nextAppTransition=ANIM_CUSTOM" + " transit=" + transit + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3)); + } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE) { + a = loadAnimationRes(mNextAppTransitionPackage, mNextAppTransitionInPlace); + if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, + "applyAnimation:" + + " anim=" + a + " nextAppTransition=ANIM_CUSTOM_IN_PLACE" + + " transit=" + transit + " Callers=" + Debug.getCallers(3)); } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_SCALE_UP) { a = createScaleUpAnimationLocked(transit, enter, appWidth, appHeight); if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, @@ -1013,6 +1023,16 @@ public class AppTransition implements Dump { } } + void overrideInPlaceAppTransition(String packageName, int anim) { + if (isTransitionSet()) { + mNextAppTransitionType = NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE; + mNextAppTransitionPackage = packageName; + mNextAppTransitionInPlace = anim; + } else { + postAnimationCallback(); + } + } + @Override public String toString() { return "mNextAppTransition=0x" + Integer.toHexString(mNextAppTransition); @@ -1092,6 +1112,8 @@ public class AppTransition implements Dump { return "NEXT_TRANSIT_TYPE_NONE"; case NEXT_TRANSIT_TYPE_CUSTOM: return "NEXT_TRANSIT_TYPE_CUSTOM"; + case NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE: + return "NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE"; case NEXT_TRANSIT_TYPE_SCALE_UP: return "NEXT_TRANSIT_TYPE_SCALE_UP"; case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP: @@ -1123,6 +1145,12 @@ public class AppTransition implements Dump { pw.print(" mNextAppTransitionExit=0x"); pw.println(Integer.toHexString(mNextAppTransitionExit)); break; + case NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE: + pw.print(" mNextAppTransitionPackage="); + pw.println(mNextAppTransitionPackage); + pw.print(" mNextAppTransitionInPlace=0x"); + pw.print(Integer.toHexString(mNextAppTransitionInPlace)); + break; case NEXT_TRANSIT_TYPE_SCALE_UP: pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX); pw.print(" mNextAppTransitionStartY="); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 968b35c3c3d01..6ee45378c2739 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -4123,6 +4123,13 @@ public class WindowManagerService extends IWindowManager.Stub } } + @Override + public void overridePendingAppTransitionInPlace(String packageName, int anim) { + synchronized(mWindowMap) { + mAppTransition.overrideInPlaceAppTransition(packageName, anim); + } + } + @Override public void executeAppTransition() { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, @@ -4535,6 +4542,15 @@ public class WindowManagerService extends IWindowManager.Stub return delayed; } + void updateTokenInPlaceLocked(AppWindowToken wtoken, int transit) { + if (transit != AppTransition.TRANSIT_UNSET) { + if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { + wtoken.mAppAnimator.animation = null; + } + applyAnimationLocked(wtoken, null, transit, false, false); + } + } + @Override public void setAppVisibility(IBinder token, boolean visible) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, @@ -9125,6 +9141,29 @@ public class WindowManagerService extends IWindowManager.Stub int topOpeningLayer = 0; int topClosingLayer = 0; + // Process all applications animating in place + if (transit == AppTransition.TRANSIT_TASK_IN_PLACE) { + // Find the focused window + final WindowState win = + findFocusedWindowLocked(getDefaultDisplayContentLocked()); + if (win != null) { + final AppWindowToken wtoken = win.mAppToken; + final AppWindowAnimator appAnimator = wtoken.mAppAnimator; + if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now animating app in place " + wtoken); + appAnimator.clearThumbnail(); + appAnimator.animation = null; + updateTokenInPlaceLocked(wtoken, transit); + wtoken.updateReportedVisibilityLocked(); + + appAnimator.mAllAppWinAnimators.clear(); + final int N = wtoken.allAppWindows.size(); + for (int j = 0; j < N; j++) { + appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); + } + mAnimator.mAnimating |= appAnimator.showAllWindowsLocked(); + } + } + NN = mOpeningApps.size(); for (i=0; i