Launch activity behind launching task.
Use ActivityOptions.makeLaunchTaskBehindAnimation() to launch tasks
behind the current task. Includes animations for launching and
launched tasks.
Fixes bug 16157517.
Change-Id: I0a94af70b4748592e94673b958ee824cfb3d7ec0
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 4a70e15..e2b5a84 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -30,7 +30,6 @@
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
-import android.graphics.Bitmap;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Binder;
@@ -2196,13 +2195,21 @@
return true;
}
- case MEDIA_RESOURCES_RELEASED: {
+ case MEDIA_RESOURCES_RELEASED_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
mediaResourcesReleased(token);
reply.writeNoException();
return true;
}
+
+ case NOTIFY_LAUNCH_TASK_BEHIND_COMPLETE_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder token = data.readStrongBinder();
+ notifyLaunchTaskBehindComplete(token);
+ reply.writeNoException();
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -5069,7 +5076,20 @@
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(token);
- mRemote.transact(MEDIA_RESOURCES_RELEASED, data, reply, IBinder.FLAG_ONEWAY);
+ mRemote.transact(MEDIA_RESOURCES_RELEASED_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
+ @Override
+ public void notifyLaunchTaskBehindComplete(IBinder token) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(token);
+ mRemote.transact(NOTIFY_LAUNCH_TASK_BEHIND_COMPLETE_TRANSACTION, data, reply,
+ IBinder.FLAG_ONEWAY);
reply.readException();
data.recycle();
reply.recycle();
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index fafa948..4c02314 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -126,6 +126,8 @@
public static final int ANIM_SCENE_TRANSITION = 5;
/** @hide */
public static final int ANIM_DEFAULT = 6;
+ /** @hide */
+ public static final int ANIM_LAUNCH_TASK_BEHIND = 7;
private String mPackageName;
private int mAnimationType = ANIM_NONE;
@@ -432,6 +434,27 @@
return opts;
}
+ /**
+ * If set along with Intent.FLAG_ACTIVITY_NEW_DOCUMENT then the task being launched will not be
+ * presented to the user but will instead be only available through the recents task list.
+ * In addition, the new task wil be affiliated with the launching activity's task.
+ * Affiliated tasks are grouped together in the recents task list.
+ *
+ * <p>This behavior is not supported for activities with {@link
+ * android.R.styleable#AndroidManifestActivity_launchMode launchMode} values of
+ * <code>singleInstance</code> or <code>singleTask</code>.
+ */
+ public static ActivityOptions makeLaunchTaskBehindAnimation() {
+ final ActivityOptions opts = new ActivityOptions();
+ opts.mAnimationType = ANIM_LAUNCH_TASK_BEHIND;
+ return opts;
+ }
+
+ /** @hide */
+ public boolean getLaunchTaskBehind() {
+ return mAnimationType == ANIM_LAUNCH_TASK_BEHIND;
+ }
+
private ActivityOptions() {
}
@@ -647,16 +670,15 @@
if (mPackageName != null) {
b.putString(KEY_PACKAGE_NAME, mPackageName);
}
+ b.putInt(KEY_ANIM_TYPE, mAnimationType);
switch (mAnimationType) {
case ANIM_CUSTOM:
- b.putInt(KEY_ANIM_TYPE, mAnimationType);
b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);
b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId);
b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
!= null ? mAnimationStartedListener.asBinder() : null);
break;
case ANIM_SCALE_UP:
- b.putInt(KEY_ANIM_TYPE, mAnimationType);
b.putInt(KEY_ANIM_START_X, mStartX);
b.putInt(KEY_ANIM_START_Y, mStartY);
b.putInt(KEY_ANIM_START_WIDTH, mStartWidth);
@@ -664,7 +686,6 @@
break;
case ANIM_THUMBNAIL_SCALE_UP:
case ANIM_THUMBNAIL_SCALE_DOWN:
- b.putInt(KEY_ANIM_TYPE, mAnimationType);
b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
b.putInt(KEY_ANIM_START_X, mStartX);
b.putInt(KEY_ANIM_START_Y, mStartY);
@@ -672,7 +693,6 @@
!= null ? mAnimationStartedListener.asBinder() : null);
break;
case ANIM_SCENE_TRANSITION:
- b.putInt(KEY_ANIM_TYPE, mAnimationType);
if (mTransitionReceiver != null) {
b.putParcelable(KEY_TRANSITION_COMPLETE_LISTENER, mTransitionReceiver);
}
@@ -683,6 +703,7 @@
b.putInt(KEY_EXIT_COORDINATOR_INDEX, mExitCoordinatorIndex);
break;
}
+
return b;
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index b3a8a8a..c6921a2 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -444,6 +444,8 @@
public boolean isBackgroundMediaPlaying(IBinder token) throws RemoteException;
public void mediaResourcesReleased(IBinder token) throws RemoteException;
+ public void notifyLaunchTaskBehindComplete(IBinder token) throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -750,5 +752,6 @@
int IS_TOP_OF_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+224;
int SET_MEDIA_PLAYING_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+225;
int IS_BG_MEDIA_PLAYING_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+226;
- int MEDIA_RESOURCES_RELEASED = IBinder.FIRST_CALL_TRANSACTION+227;
+ int MEDIA_RESOURCES_RELEASED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+227;
+ int NOTIFY_LAUNCH_TASK_BEHIND_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+228;
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 4153a02..5bf8a97 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3809,17 +3809,6 @@
* {@link android.R.styleable#AndroidManifestActivity_autoRemoveFromRecents}.
*/
public static final int FLAG_ACTIVITY_AUTO_REMOVE_FROM_RECENTS = 0x00002000;
- /**
- * If set along with FLAG_ACTIVITY_NEW_DOCUMENT then the task being launched will not be
- * presented to the user but will instead be only available through the recents task list.
- * In addition, the new task wil be affiliated with the launching activity's task.
- * Affiliated tasks are grouped together in the recents task list.
- *
- * <p>This behavior is not supported for activities with {@link
- * android.R.styleable#AndroidManifestActivity_launchMode launchMode} values of
- * <code>singleInstance</code> or <code>singleTask</code>.
- */
- public static final int FLAG_ACTIVITY_LAUNCH_BEHIND = 0x00001000;
/**
* If set, when sending a broadcast only registered receivers will be
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index ae59bbc..a61d771 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -80,7 +80,7 @@
void removeWindowToken(IBinder token);
void addAppToken(int addPos, IApplicationToken token, int groupId, int stackId,
int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId,
- int configChanges, boolean voiceInteraction);
+ int configChanges, boolean voiceInteraction, boolean launchTaskBehind);
void setAppGroupId(IBinder token, int groupId);
void setAppOrientation(IApplicationToken token, int requestedOrientation);
int getAppOrientation(IApplicationToken token);
diff --git a/core/res/res/anim/launch_task_behind_background.xml b/core/res/res/anim/launch_task_behind_background.xml
new file mode 100644
index 0000000..358511f
--- /dev/null
+++ b/core/res/res/anim/launch_task_behind_background.xml
@@ -0,0 +1,34 @@
+<?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.
+*/
+-->
+
+<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%"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@interpolator/decelerate_quint"
+ android:startOffset="50"
+ android:duration="300" />
+
+ <translate android:fromYDelta="0%" android:toYDelta="167%"
+ 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
diff --git a/core/res/res/anim/launch_task_behind_source.xml b/core/res/res/anim/launch_task_behind_source.xml
new file mode 100644
index 0000000..426ee5d
--- /dev/null
+++ b/core/res/res/anim/launch_task_behind_source.xml
@@ -0,0 +1,59 @@
+<?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.
+*/
+-->
+
+<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="@interpolator/accelerate_cubic"
+ android:duration="133"/>
+
+ <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"
+ 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" />
+
+ <alpha android:fromAlpha="1.0" android:toAlpha="1.6"
+ 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="-10%"
+ 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.1"
+ android:fromYScale="1.0" android:toYScale="1.1"
+ 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" />
+</set>
\ No newline at end of file
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index ed228e4..1b18997 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1892,6 +1892,14 @@
<!-- When opening an activity in a new task, this is the animation that is
run on the activity of the old task (which is exiting the screen). -->
<attr name="taskOpenExitAnimation" format="reference" />
+ <!-- When opening an activity in a new task using Intent/FLAG_ACTIVITY_LAUNCH_BEHIND,
+ this is the animation that is run on the activity of the new task (which is
+ entering the screen and then leaving). -->
+ <attr name="launchTaskBehindBackgroundAnimation" format="reference" />
+ <!-- When opening an activity in a new task using Intent.FLAG_ACTIVITY_LAUNCH_BEHIND,
+ this is the animation that is run on the activity of the old task (which is
+ already on the screen and then stays on). -->
+ <attr name="launchTaskBehindSourceAnimation" format="reference" />
<!-- When closing the last activity of a task, this is the animation that is
run on the activity of the next task (which is entering the screen). -->
<attr name="taskCloseEnterAnimation" format="reference" />
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index fee5c43..cb16b5f 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2236,6 +2236,8 @@
<public type="attr" name="multiArch" />
<public type="attr" name="touchscreenBlocksFocus" />
<public type="attr" name="windowElevation" />
+ <public type="attr" name="launchTaskBehindBackgroundAnimation" />
+ <public type="attr" name="launchTaskBehindSourceAnimation" />
<public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 32065a18..a8b634c 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -82,6 +82,8 @@
<item name="activityCloseExitAnimation">@anim/activity_close_exit</item>
<item name="taskOpenEnterAnimation">@anim/task_open_enter</item>
<item name="taskOpenExitAnimation">@anim/task_open_exit</item>
+ <item name="launchTaskBehindBackgroundAnimation">@anim/launch_task_behind_background</item>
+ <item name="launchTaskBehindSourceAnimation">@anim/launch_task_behind_source</item>
<item name="taskCloseEnterAnimation">@anim/task_close_enter</item>
<item name="taskCloseExitAnimation">@anim/task_close_exit</item>
<item name="taskToFrontEnterAnimation">@anim/task_open_enter</item>