am 3ed9f2f9: Merge "Adding bounce animation for affiliated tasks. (Bug 16656169)" into lmp-mr1-dev

* commit '3ed9f2f903a8e6c38ca9f2ce3819ac063281a020':
  Adding bounce animation for affiliated tasks. (Bug 16656169)
This commit is contained in:
Winson Chung
2014-11-07 01:33:28 +00:00
committed by Android Git Automerger
20 changed files with 345 additions and 72 deletions

View File

@ -2279,6 +2279,20 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true; 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: { case REQUEST_VISIBLE_BEHIND_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor); data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder(); IBinder token = data.readStrongBinder();
@ -5297,6 +5311,24 @@ class ActivityManagerProxy implements IActivityManager
return icon; 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 @Override
public boolean requestVisibleBehind(IBinder token, boolean visible) throws RemoteException { public boolean requestVisibleBehind(IBinder token, boolean visible) throws RemoteException {
Parcel data = Parcel.obtain(); Parcel data = Parcel.obtain();

View File

@ -62,6 +62,12 @@ public class ActivityOptions {
*/ */
public static final String KEY_ANIM_EXIT_RES_ID = "android:animExitRes"; 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. * Bitmap for thumbnail animation.
* @hide * @hide
@ -132,11 +138,14 @@ public class ActivityOptions {
public static final int ANIM_THUMBNAIL_ASPECT_SCALE_UP = 8; public static final int ANIM_THUMBNAIL_ASPECT_SCALE_UP = 8;
/** @hide */ /** @hide */
public static final int ANIM_THUMBNAIL_ASPECT_SCALE_DOWN = 9; public static final int ANIM_THUMBNAIL_ASPECT_SCALE_DOWN = 9;
/** @hide */
public static final int ANIM_CUSTOM_IN_PLACE = 10;
private String mPackageName; private String mPackageName;
private int mAnimationType = ANIM_NONE; private int mAnimationType = ANIM_NONE;
private int mCustomEnterResId; private int mCustomEnterResId;
private int mCustomExitResId; private int mCustomExitResId;
private int mCustomInPlaceResId;
private Bitmap mThumbnail; private Bitmap mThumbnail;
private int mStartX; private int mStartX;
private int mStartY; private int mStartY;
@ -198,6 +207,30 @@ public class ActivityOptions {
return opts; 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, private void setOnAnimationStartedListener(Handler handler,
OnAnimationStartedListener listener) { OnAnimationStartedListener listener) {
if (listener != null) { if (listener != null) {
@ -540,6 +573,10 @@ public class ActivityOptions {
opts.getBinder(KEY_ANIM_START_LISTENER)); opts.getBinder(KEY_ANIM_START_LISTENER));
break; break;
case ANIM_CUSTOM_IN_PLACE:
mCustomInPlaceResId = opts.getInt(KEY_ANIM_IN_PLACE_RES_ID, 0);
break;
case ANIM_SCALE_UP: case ANIM_SCALE_UP:
mStartX = opts.getInt(KEY_ANIM_START_X, 0); mStartX = opts.getInt(KEY_ANIM_START_X, 0);
mStartY = opts.getInt(KEY_ANIM_START_Y, 0); mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
@ -591,6 +628,11 @@ public class ActivityOptions {
return mCustomExitResId; return mCustomExitResId;
} }
/** @hide */
public int getCustomInPlaceResId() {
return mCustomInPlaceResId;
}
/** @hide */ /** @hide */
public Bitmap getThumbnail() { public Bitmap getThumbnail() {
return mThumbnail; return mThumbnail;
@ -689,6 +731,9 @@ public class ActivityOptions {
} }
mAnimationStartedListener = otherOptions.mAnimationStartedListener; mAnimationStartedListener = otherOptions.mAnimationStartedListener;
break; break;
case ANIM_CUSTOM_IN_PLACE:
mCustomInPlaceResId = otherOptions.mCustomInPlaceResId;
break;
case ANIM_SCALE_UP: case ANIM_SCALE_UP:
mStartX = otherOptions.mStartX; mStartX = otherOptions.mStartX;
mStartY = otherOptions.mStartY; mStartY = otherOptions.mStartY;
@ -756,6 +801,9 @@ public class ActivityOptions {
b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
!= null ? mAnimationStartedListener.asBinder() : null); != null ? mAnimationStartedListener.asBinder() : null);
break; break;
case ANIM_CUSTOM_IN_PLACE:
b.putInt(KEY_ANIM_IN_PLACE_RES_ID, mCustomInPlaceResId);
break;
case ANIM_SCALE_UP: case ANIM_SCALE_UP:
b.putInt(KEY_ANIM_START_X, mStartX); b.putInt(KEY_ANIM_START_X, mStartX);
b.putInt(KEY_ANIM_START_Y, mStartY); b.putInt(KEY_ANIM_START_Y, mStartY);

View File

@ -456,6 +456,9 @@ public interface IActivityManager extends IInterface {
throws RemoteException; throws RemoteException;
public Bitmap getTaskDescriptionIcon(String filename) 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 requestVisibleBehind(IBinder token, boolean visible) throws RemoteException;
public boolean isBackgroundVisibleBehind(IBinder token) throws RemoteException; public boolean isBackgroundVisibleBehind(IBinder token) throws RemoteException;
public void backgroundResourcesReleased(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 BOOT_ANIMATION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+237;
int GET_TASK_DESCRIPTION_ICON_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+238; int GET_TASK_DESCRIPTION_ICON_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+238;
int LAUNCH_ASSIST_INTENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+239; int LAUNCH_ASSIST_INTENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+239;
int START_IN_PLACE_ANIMATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+240;
} }

View File

@ -96,6 +96,7 @@ interface IWindowManager
void overridePendingAppTransitionAspectScaledThumb(in Bitmap srcThumb, int startX, void overridePendingAppTransitionAspectScaledThumb(in Bitmap srcThumb, int startX,
int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback, int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
boolean scaleUp); boolean scaleUp);
void overridePendingAppTransitionInPlace(String packageName, int anim);
void executeAppTransition(); void executeAppTransition();
void setAppStartingWindow(IBinder token, String pkg, int theme, void setAppStartingWindow(IBinder token, String pkg, int theme,
in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,

View File

@ -22,38 +22,27 @@
<alpha android:fromAlpha="1.0" android:toAlpha="0.6" <alpha android:fromAlpha="1.0" android:toAlpha="0.6"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
android:interpolator="@interpolator/accelerate_cubic" android:interpolator="@interpolator/linear_out_slow_in"
android:duration="133"/> android:duration="417"/>
<translate android:fromYDelta="0" android:toYDelta="10%" <scale android:fromXScale="1.0" android:toXScale="0.918"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" android:fromYScale="1.0" android:toYScale="0.918"
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:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
android:pivotX="50%p" android:pivotY="50%p" android:pivotX="50%p" android:pivotY="50%p"
android:interpolator="@interpolator/fast_out_slow_in" android:interpolator="@interpolator/launch_task_behind_source_scale_1"
android:duration="350" /> android:duration="417" />
<alpha android:fromAlpha="1.0" android:toAlpha="1.6666666666" <alpha android:fromAlpha="1.0" android:toAlpha="1.6666666666"
android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true" android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true"
android:interpolator="@interpolator/decelerate_cubic" android:interpolator="@interpolator/linear"
android:startOffset="433" android:startOffset="500"
android:duration="133"/> android:duration="167"/>
<translate android:fromYDelta="0%" android:toYDelta="-8.8888888888%" <scale android:fromXScale="1.0" android:toXScale="1.08932461873638"
android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true" android:fromYScale="1.0" android:toYScale="1.08932461873638"
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"
android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true" android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true"
android:pivotX="50%p" android:pivotY="50%p" android:pivotX="50%p" android:pivotY="50%p"
android:interpolator="@interpolator/decelerate_cubic" android:interpolator="@interpolator/launch_task_behind_source_scale_2"
android:startOffset="433" android:startOffset="500"
android:duration="350" /> android:duration="317" />
</set> </set>

View File

@ -20,15 +20,15 @@
<set xmlns:android="http://schemas.android.com/apk/res/android" <set xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="top"> 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: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: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:fillEnabled="true" android:fillBefore="false" android:fillAfter="true"
android:interpolator="@interpolator/accelerate_quint" android:interpolator="@interpolator/fast_out_linear_in"
android:startOffset="433" android:startOffset="467"
android:duration="300" /> android:duration="317" />
</set> </set>

View File

@ -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" />

View File

@ -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" />

View File

@ -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" />

View File

@ -1811,6 +1811,7 @@
<java-symbol type="anim" name="lock_screen_behind_enter_wallpaper" /> <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_behind_enter_fade_in" />
<java-symbol type="anim" name="lock_screen_wallpaper_exit" /> <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="bool" name="config_alwaysUseCdmaRssi" />
<java-symbol type="dimen" name="status_bar_icon_size" /> <java-symbol type="dimen" name="status_bar_icon_size" />

View File

@ -20,40 +20,30 @@
<set xmlns:android="http://schemas.android.com/apk/res/android" <set xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="normal"> 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: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"/> android:duration="133"/>
<translate android:fromYDelta="0" android:toYDelta="10%" <scale android:fromXScale="1.0" android:toXScale="0.98"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" android:fromYScale="1.0" android:toYScale="0.98"
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"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
android:pivotX="50%p" android:pivotY="50%p" android:pivotX="50%p" android:pivotY="50%p"
android:interpolator="@android:interpolator/fast_out_slow_in" android:interpolator="@android:interpolator/fast_out_slow_in"
android:duration="350" /> android:duration="133" />
<alpha android:fromAlpha="1.0" android:toAlpha="1.6666666666" <translate android:fromYDelta="0" android:toYDelta="-2%"
android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true" android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
android:interpolator="@android:interpolator/decelerate_cubic" android:interpolator="@interpolator/recents_launch_prev_affiliated_task_bounce_ydelta"
android:startOffset="350" android:startOffset="133"
android:duration="133"/> android:duration="217"/>
<translate android:fromYDelta="0%" android:toYDelta="-8.8888888888%" <scale android:fromXScale="1.0" android:toXScale="1.02040816326531"
android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true" android:fromYScale="1.0" android:toYScale="1.02040816326531"
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"
android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true" android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true"
android:pivotX="50%p" android:pivotY="50%p" android:pivotX="50%p" android:pivotY="50%p"
android:interpolator="@android:interpolator/decelerate_cubic" android:interpolator="@interpolator/recents_launch_next_affiliated_task_bounce_scale"
android:startOffset="350" android:startOffset="133"
android:duration="350" /> android:duration="217" />
</set> </set>

View File

@ -22,12 +22,12 @@
<translate android:fromYDelta="0%" android:toYDelta="10%" <translate android:fromYDelta="0%" android:toYDelta="10%"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
android:interpolator="@android:interpolator/decelerate_quint" android:interpolator="@android:interpolator/fast_out_slow_in"
android:duration="300" /> 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:fillEnabled="true" android:fillBefore="false" android:fillAfter="true"
android:interpolator="@android:interpolator/accelerate_quint" android:interpolator="@interpolator/recents_launch_prev_affiliated_task_bounce_ydelta"
android:startOffset="300" android:startOffset="133"
android:duration="300" /> android:duration="217" />
</set> </set>

View File

@ -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" />

View File

@ -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" />

View File

@ -16,13 +16,11 @@
package com.android.systemui.recents; package com.android.systemui.recents;
import android.app.Activity;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.ActivityOptions; import android.app.ActivityOptions;
import android.appwidget.AppWidgetHost; import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetProviderInfo; import android.appwidget.AppWidgetProviderInfo;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -31,7 +29,6 @@ import android.content.res.Resources;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Handler;
import android.os.UserHandle; import android.os.UserHandle;
import android.util.Pair; import android.util.Pair;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -207,6 +204,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
Task toTask = null; Task toTask = null;
ActivityOptions launchOpts = null; ActivityOptions launchOpts = null;
int taskCount = tasks.size(); int taskCount = tasks.size();
int numAffiliatedTasks = 0;
for (int i = 0; i < taskCount; i++) { for (int i = 0; i < taskCount; i++) {
Task task = tasks.get(i); Task task = tasks.get(i);
if (task.key.id == runningTask.id) { if (task.key.id == runningTask.id) {
@ -226,16 +224,23 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
if (toTaskKey != null) { if (toTaskKey != null) {
toTask = stack.findTaskWithId(toTaskKey.id); toTask = stack.findTaskWithId(toTaskKey.id);
} }
numAffiliatedTasks = group.getTaskCount();
break; break;
} }
} }
// Return early if there is no next task // Return early if there is no next task
if (toTask == null) { if (toTask == null) {
if (showNextTask) { if (numAffiliatedTasks > 1) {
// XXX: Show the next-task bounce animation if (showNextTask) {
} else { mSystemServicesProxy.startInPlaceAnimationOnFrontMostApplication(
// XXX: Show the prev-task bounce animation 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; return;
} }

View File

@ -48,12 +48,14 @@ import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle; import android.os.UserHandle;
import android.provider.Settings; import android.provider.Settings;
import android.util.Log; import android.util.Log;
import android.util.Pair; import android.util.Pair;
import android.view.Display; import android.view.Display;
import android.view.DisplayInfo; import android.view.DisplayInfo;
import android.view.IWindowManager;
import android.view.SurfaceControl; import android.view.SurfaceControl;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityManager;
@ -429,6 +431,7 @@ public class SystemServicesProxy {
opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX); AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX);
if (!mAwm.bindAppWidgetIdIfAllowed(searchWidgetId, searchWidgetInfo.provider, opts)) { if (!mAwm.bindAppWidgetIdIfAllowed(searchWidgetId, searchWidgetInfo.provider, opts)) {
host.deleteAppWidgetId(searchWidgetId);
return null; return null;
} }
return new Pair<Integer, AppWidgetProviderInfo>(searchWidgetId, searchWidgetInfo); return new Pair<Integer, AppWidgetProviderInfo>(searchWidgetId, searchWidgetInfo);
@ -532,4 +535,15 @@ public class SystemServicesProxy {
} }
return false; 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();
}
}
} }

View File

@ -8298,6 +8298,20 @@ public final class ActivityManagerService extends ActivityManagerNative
return mTaskPersister.getTaskDescriptionIcon(filename); 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) { private void cleanUpRemovedTaskLocked(TaskRecord tr, boolean killProcess) {
mRecentTasks.remove(tr); mRecentTasks.remove(tr);
tr.removedFromRecents(mTaskPersister); tr.removedFromRecents(mTaskPersister);

View File

@ -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. /** 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. */ * The new window will show briefly and then be gone. */
public static final int TRANSIT_TASK_OPEN_BEHIND = 16; 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 */ /** Fraction of animation at which the recents thumbnail stays completely transparent */
private static final float RECENTS_THUMBNAIL_FADEIN_FRACTION = 0.7f; 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_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_UP = 5;
private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN = 6; 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; private int mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
// These are the possible states for the enter/exit activities during a thumbnail transition // 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 IRemoteCallback mNextAppTransitionCallback;
private int mNextAppTransitionEnter; private int mNextAppTransitionEnter;
private int mNextAppTransitionExit; private int mNextAppTransitionExit;
private int mNextAppTransitionInPlace;
private int mNextAppTransitionStartX; private int mNextAppTransitionStartX;
private int mNextAppTransitionStartY; private int mNextAppTransitionStartY;
private int mNextAppTransitionStartWidth; private int mNextAppTransitionStartWidth;
@ -835,6 +839,12 @@ public class AppTransition implements Dump {
+ " anim=" + a + " nextAppTransition=ANIM_CUSTOM" + " anim=" + a + " nextAppTransition=ANIM_CUSTOM"
+ " transit=" + transit + " isEntrance=" + enter + " transit=" + transit + " isEntrance=" + enter
+ " Callers=" + Debug.getCallers(3)); + " 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) { } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_SCALE_UP) {
a = createScaleUpAnimationLocked(transit, enter, appWidth, appHeight); a = createScaleUpAnimationLocked(transit, enter, appWidth, appHeight);
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, 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 @Override
public String toString() { public String toString() {
return "mNextAppTransition=0x" + Integer.toHexString(mNextAppTransition); return "mNextAppTransition=0x" + Integer.toHexString(mNextAppTransition);
@ -1092,6 +1112,8 @@ public class AppTransition implements Dump {
return "NEXT_TRANSIT_TYPE_NONE"; return "NEXT_TRANSIT_TYPE_NONE";
case NEXT_TRANSIT_TYPE_CUSTOM: case NEXT_TRANSIT_TYPE_CUSTOM:
return "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: case NEXT_TRANSIT_TYPE_SCALE_UP:
return "NEXT_TRANSIT_TYPE_SCALE_UP"; return "NEXT_TRANSIT_TYPE_SCALE_UP";
case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP: case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP:
@ -1123,6 +1145,12 @@ public class AppTransition implements Dump {
pw.print(" mNextAppTransitionExit=0x"); pw.print(" mNextAppTransitionExit=0x");
pw.println(Integer.toHexString(mNextAppTransitionExit)); pw.println(Integer.toHexString(mNextAppTransitionExit));
break; 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: case NEXT_TRANSIT_TYPE_SCALE_UP:
pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX); pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX);
pw.print(" mNextAppTransitionStartY="); pw.print(" mNextAppTransitionStartY=");

View File

@ -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 @Override
public void executeAppTransition() { public void executeAppTransition() {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
@ -4535,6 +4542,15 @@ public class WindowManagerService extends IWindowManager.Stub
return delayed; 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 @Override
public void setAppVisibility(IBinder token, boolean visible) { public void setAppVisibility(IBinder token, boolean visible) {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
@ -9125,6 +9141,29 @@ public class WindowManagerService extends IWindowManager.Stub
int topOpeningLayer = 0; int topOpeningLayer = 0;
int topClosingLayer = 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(); NN = mOpeningApps.size();
for (i=0; i<NN; i++) { for (i=0; i<NN; i++) {
AppWindowToken wtoken = mOpeningApps.valueAt(i); AppWindowToken wtoken = mOpeningApps.valueAt(i);

View File

@ -227,6 +227,11 @@ public class IWindowManagerImpl implements IWindowManager {
// TODO Auto-generated method stub // TODO Auto-generated method stub
} }
@Override
public void overridePendingAppTransitionInPlace(String packageName, int anim) {
// TODO Auto-generated method stub
}
@Override @Override
public void pauseKeyDispatching(IBinder arg0) throws RemoteException { public void pauseKeyDispatching(IBinder arg0) throws RemoteException {
// TODO Auto-generated method stub // TODO Auto-generated method stub