Adding bounce animation for affiliated tasks. (Bug 16656169)
Change-Id: I39e4a57c4e6b707d15513dacde2d40c23bb05058
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 @@
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 @@
}
@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 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 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 @@
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 @@
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 @@
}
/** @hide */
+ public int getCustomInPlaceResId() {
+ return mCustomInPlaceResId;
+ }
+
+ /** @hide */
public Bitmap getThumbnail() {
return mThumbnail;
}
@@ -689,6 +731,9 @@
}
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 @@
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 @@
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 @@
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 @@
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"/>
+ android:interpolator="@interpolator/linear"
+ android:startOffset="500"
+ android:duration="167"/>
- <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"/>
-
- <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"
+
+ <translate android:fromYDelta="0" android:toYDelta="2%"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@android:interpolator/accelerate_cubic"
+ android:interpolator="@android:interpolator/fast_out_slow_in"
android:duration="133"/>
- <translate android:fromYDelta="0" android:toYDelta="10%"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@android: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.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="-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"/>
- <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"/>
-
- <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.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 @@
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 @@
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.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 @@
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 @@
}
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 @@
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 @@
/** 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 @@
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 @@
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 @@
+ " 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 @@
}
}
+ 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 @@
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 @@
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 @@
}
@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 @@
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 @@
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 @@
}
@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