diff options
20 files changed, 345 insertions, 72 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index bc7114b..c3028b7 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(); @@ -5298,6 +5312,24 @@ class ActivityManagerProxy implements IActivityManager } @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(); Parcel reply = Parcel.obtain(); diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index cd6a4f5..3d390bf 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -63,6 +63,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); @@ -592,6 +629,11 @@ public class ActivityOptions { } /** @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 efcb197..6433f3f 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 6aa86c7..7b20e72 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 cd3e30a..a715705 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 @@ <alpha android:fromAlpha="1.0" android:toAlpha="0.6" android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/accelerate_cubic" - android:duration="133"/> + android:interpolator="@interpolator/linear_out_slow_in" + android:duration="417"/> - <translate android:fromYDelta="0" android:toYDelta="10%" - android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/accelerate_cubic" - android:duration="350"/> - - <scale android:fromXScale="1.0" android:toXScale="0.9" - android:fromYScale="1.0" android:toYScale="0.9" + <scale android:fromXScale="1.0" android:toXScale="0.918" + android:fromYScale="1.0" android:toYScale="0.918" android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" android:pivotX="50%p" android:pivotY="50%p" - android:interpolator="@interpolator/fast_out_slow_in" - android:duration="350" /> + android:interpolator="@interpolator/launch_task_behind_source_scale_1" + android:duration="417" /> <alpha android:fromAlpha="1.0" android:toAlpha="1.6666666666" android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true" - android:interpolator="@interpolator/decelerate_cubic" - android:startOffset="433" - android:duration="133"/> - - <translate android:fromYDelta="0%" android:toYDelta="-8.8888888888%" - android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true" - android:interpolator="@interpolator/decelerate_cubic" - android:startOffset="433" - android:duration="350"/> + android:interpolator="@interpolator/linear" + android:startOffset="500" + android:duration="167"/> - <scale android:fromXScale="1.0" android:toXScale="1.1111111111" - android:fromYScale="1.0" android:toYScale="1.1111111111" + <scale android:fromXScale="1.0" android:toXScale="1.08932461873638" + android:fromYScale="1.0" android:toYScale="1.08932461873638" android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true" android:pivotX="50%p" android:pivotY="50%p" - android:interpolator="@interpolator/decelerate_cubic" - android:startOffset="433" - android:duration="350" /> + android:interpolator="@interpolator/launch_task_behind_source_scale_2" + android:startOffset="500" + android:duration="317" /> </set>
\ 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 358511f..805918b 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 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="top"> - <translate android:fromYDelta="110%" android:toYDelta="66%" + <translate android:fromYDelta="110%" android:toYDelta="70%" android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@interpolator/decelerate_quint" + android:interpolator="@interpolator/launch_task_behind_target_ydelta" android:startOffset="50" - android:duration="300" /> + android:duration="333" /> - <translate android:fromYDelta="0%" android:toYDelta="167%" + <translate android:fromYDelta="0%" android:toYDelta="50%" android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true" - android:interpolator="@interpolator/accelerate_quint" - android:startOffset="433" - android:duration="300" /> -</set>
\ No newline at end of file + android:interpolator="@interpolator/fast_out_linear_in" + android:startOffset="467" + android:duration="317" /> +</set> 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 0000000..7e295d8 --- /dev/null +++ b/core/res/res/interpolator/launch_task_behind_source_scale_1.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2014, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0,0 c 0.541795,0 0.2,1 1,1" /> 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 0000000..1601fd0 --- /dev/null +++ b/core/res/res/interpolator/launch_task_behind_source_scale_2.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2014, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0,0 c 0.220434,0 0.833333,1 1,1" /> 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 0000000..96b539f --- /dev/null +++ b/core/res/res/interpolator/launch_task_behind_target_ydelta.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2014, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0,0 c 0.3,0 0,1 1,1" /> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 6e881a7..df1550a 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1810,6 +1810,7 @@ <java-symbol type="anim" name="lock_screen_behind_enter_wallpaper" /> <java-symbol type="anim" name="lock_screen_behind_enter_fade_in" /> <java-symbol type="anim" name="lock_screen_wallpaper_exit" /> + <java-symbol type="anim" name="launch_task_behind_source" /> <java-symbol type="bool" name="config_alwaysUseCdmaRssi" /> <java-symbol type="dimen" name="status_bar_icon_size" /> 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 a571cbc..74f2814 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 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="normal"> - <alpha android:fromAlpha="1.0" android:toAlpha="0.6" - android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@android:interpolator/accelerate_cubic" - android:duration="133"/> - <translate android:fromYDelta="0" android:toYDelta="10%" + <translate android:fromYDelta="0" android:toYDelta="2%" android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@android:interpolator/accelerate_cubic" - android:duration="350"/> + android:interpolator="@android:interpolator/fast_out_slow_in" + android:duration="133"/> - <scale android:fromXScale="1.0" android:toXScale="0.9" - android:fromYScale="1.0" android:toYScale="0.9" + <scale android:fromXScale="1.0" android:toXScale="0.98" + android:fromYScale="1.0" android:toYScale="0.98" android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" android:pivotX="50%p" android:pivotY="50%p" android:interpolator="@android:interpolator/fast_out_slow_in" - android:duration="350" /> + android:duration="133" /> - <alpha android:fromAlpha="1.0" android:toAlpha="1.6666666666" - android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true" - android:interpolator="@android:interpolator/decelerate_cubic" - android:startOffset="350" - android:duration="133"/> - - <translate android:fromYDelta="0%" android:toYDelta="-8.8888888888%" - android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true" - android:interpolator="@android:interpolator/decelerate_cubic" - android:startOffset="350" - android:duration="350"/> + <translate android:fromYDelta="0" android:toYDelta="-2%" + android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" + android:interpolator="@interpolator/recents_launch_prev_affiliated_task_bounce_ydelta" + android:startOffset="133" + android:duration="217"/> - <scale android:fromXScale="1.0" android:toXScale="1.1111111111" - android:fromYScale="1.0" android:toYScale="1.1111111111" + <scale android:fromXScale="1.0" android:toXScale="1.02040816326531" + android:fromYScale="1.0" android:toYScale="1.02040816326531" android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true" android:pivotX="50%p" android:pivotY="50%p" - android:interpolator="@android:interpolator/decelerate_cubic" - android:startOffset="350" - android:duration="350" /> + android:interpolator="@interpolator/recents_launch_next_affiliated_task_bounce_scale" + android:startOffset="133" + android:duration="217" /> </set>
\ 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 46045ac..b19167d 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 @@ <translate android:fromYDelta="0%" android:toYDelta="10%" android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:interpolator="@android:interpolator/decelerate_quint" - android:duration="300" /> + android:interpolator="@android:interpolator/fast_out_slow_in" + android:duration="133" /> - <translate android:fromYDelta="10%" android:toYDelta="0%" + <translate android:fromYDelta="0%" android:toYDelta="-10%" android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true" - android:interpolator="@android:interpolator/accelerate_quint" - android:startOffset="300" - android:duration="300" /> + android:interpolator="@interpolator/recents_launch_prev_affiliated_task_bounce_ydelta" + android:startOffset="133" + android:duration="217" /> </set>
\ 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 0000000..c4e5d97 --- /dev/null +++ b/packages/SystemUI/res/interpolator/recents_launch_next_affiliated_task_bounce_scale.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2014, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0,0 c 0.8,0 0.2,1 1,1" /> 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 0000000..40a08b9 --- /dev/null +++ b/packages/SystemUI/res/interpolator/recents_launch_prev_affiliated_task_bounce_ydelta.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2014, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0,0 c 0.6,0 0.2,1 1,1" /> diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java index 76e8181..4f4c06f 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 b661385..646d701 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<Integer, AppWidgetProviderInfo>(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 91e2df0..5897924 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 eeb007c..f6e8bcf 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 968b35c..6ee4537 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -4124,6 +4124,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, "executeAppTransition()")) { @@ -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<NN; i++) { AppWindowToken wtoken = mOpeningApps.valueAt(i); diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java index c403ce6..5176419 100644 --- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java +++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java @@ -228,6 +228,11 @@ public class IWindowManagerImpl implements IWindowManager { } @Override + public void overridePendingAppTransitionInPlace(String packageName, int anim) { + // TODO Auto-generated method stub + } + + @Override public void pauseKeyDispatching(IBinder arg0) throws RemoteException { // TODO Auto-generated method stub |