Skip to content

Commit 7cf4640

Browse files
Dianne HackbornAndroid (Google) Code Review
authored andcommitted
Merge "Add new thumbnail animation."
2 parents 3e93e43 + 8078d8c commit 7cf4640

File tree

19 files changed

+598
-49
lines changed

19 files changed

+598
-49
lines changed

api/current.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2744,6 +2744,7 @@ package android.app {
27442744
method public static boolean isUserAMonkey();
27452745
method public void killBackgroundProcesses(java.lang.String);
27462746
method public void moveTaskToFront(int, int);
2747+
method public void moveTaskToFront(int, int, android.os.Bundle);
27472748
method public deprecated void restartPackage(java.lang.String);
27482749
field public static final int MOVE_TASK_NO_USER_ACTION = 2; // 0x2
27492750
field public static final int MOVE_TASK_WITH_HOME = 1; // 0x1
@@ -2867,9 +2868,14 @@ package android.app {
28672868
public class ActivityOptions {
28682869
method public void join(android.app.ActivityOptions);
28692870
method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
2871+
method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int, android.app.ActivityOptions.OnAnimationStartedListener);
28702872
method public android.os.Bundle toBundle();
28712873
}
28722874

2875+
public static abstract interface ActivityOptions.OnAnimationStartedListener {
2876+
method public abstract void onAnimationStarted();
2877+
}
2878+
28732879
public class AlarmManager {
28742880
method public void cancel(android.app.PendingIntent);
28752881
method public void set(int, long, android.app.PendingIntent);

core/java/android/app/Activity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3639,7 +3639,7 @@ public boolean startNextMatchingActivity(Intent intent, Bundle options) {
36393639
*/
36403640
public void startActivityFromChild(Activity child, Intent intent,
36413641
int requestCode) {
3642-
startActivityFromChild(child, intent, requestCode);
3642+
startActivityFromChild(child, intent, requestCode, null);
36433643
}
36443644

36453645
/**

core/java/android/app/ActivityManager.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import android.graphics.Bitmap;
3232
import android.graphics.Point;
3333
import android.os.Binder;
34+
import android.os.Bundle;
3435
import android.os.Debug;
3536
import android.os.Handler;
3637
import android.os.Parcel;
@@ -815,6 +816,19 @@ public TaskThumbnails getTaskThumbnails(int id) throws SecurityException {
815816
*/
816817
public static final int MOVE_TASK_NO_USER_ACTION = 0x00000002;
817818

819+
/**
820+
* Equivalent to calling {@link #moveTaskToFront(int, int, Bundle)}
821+
* with a null options argument.
822+
*
823+
* @param taskId The identifier of the task to be moved, as found in
824+
* {@link RunningTaskInfo} or {@link RecentTaskInfo}.
825+
* @param flags Additional operational flags, 0 or more of
826+
* {@link #MOVE_TASK_WITH_HOME}.
827+
*/
828+
public void moveTaskToFront(int taskId, int flags) {
829+
moveTaskToFront(taskId, flags, null);
830+
}
831+
818832
/**
819833
* Ask that the task associated with a given task ID be moved to the
820834
* front of the stack, so it is now visible to the user. Requires that
@@ -825,10 +839,13 @@ public TaskThumbnails getTaskThumbnails(int id) throws SecurityException {
825839
* {@link RunningTaskInfo} or {@link RecentTaskInfo}.
826840
* @param flags Additional operational flags, 0 or more of
827841
* {@link #MOVE_TASK_WITH_HOME}.
842+
* @param options Additional options for the operation, either null or
843+
* as per {@link Context#startActivity(Intent, android.os.Bundle)
844+
* Context.startActivity(Intent, Bundle)}.
828845
*/
829-
public void moveTaskToFront(int taskId, int flags) {
846+
public void moveTaskToFront(int taskId, int flags, Bundle options) {
830847
try {
831-
ActivityManagerNative.getDefault().moveTaskToFront(taskId, flags);
848+
ActivityManagerNative.getDefault().moveTaskToFront(taskId, flags, options);
832849
} catch (RemoteException e) {
833850
// System dead, we will be dead too soon!
834851
}

core/java/android/app/ActivityManagerNative.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,9 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
510510
data.enforceInterface(IActivityManager.descriptor);
511511
int task = data.readInt();
512512
int fl = data.readInt();
513-
moveTaskToFront(task, fl);
513+
Bundle options = data.readInt() != 0
514+
? Bundle.CREATOR.createFromParcel(data) : null;
515+
moveTaskToFront(task, fl, options);
514516
reply.writeNoException();
515517
return true;
516518
}
@@ -2134,13 +2136,19 @@ public List<ApplicationInfo> getRunningExternalApplications()
21342136
reply.recycle();
21352137
return list;
21362138
}
2137-
public void moveTaskToFront(int task, int flags) throws RemoteException
2139+
public void moveTaskToFront(int task, int flags, Bundle options) throws RemoteException
21382140
{
21392141
Parcel data = Parcel.obtain();
21402142
Parcel reply = Parcel.obtain();
21412143
data.writeInterfaceToken(IActivityManager.descriptor);
21422144
data.writeInt(task);
21432145
data.writeInt(flags);
2146+
if (options != null) {
2147+
data.writeInt(1);
2148+
options.writeToParcel(data, 0);
2149+
} else {
2150+
data.writeInt(0);
2151+
}
21442152
mRemote.transact(MOVE_TASK_TO_FRONT_TRANSACTION, data, reply, 0);
21452153
reply.readException();
21462154
data.recycle();

core/java/android/app/ActivityOptions.java

Lines changed: 181 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,13 @@
1717
package android.app;
1818

1919
import android.content.Context;
20+
import android.graphics.Bitmap;
2021
import android.os.Bundle;
22+
import android.os.Handler;
23+
import android.os.IRemoteCallback;
24+
import android.os.Message;
25+
import android.os.RemoteException;
26+
import android.view.View;
2127

2228
/**
2329
* Helper class for building an options Bundle that can be used with
@@ -31,6 +37,12 @@ public class ActivityOptions {
3137
*/
3238
public static final String KEY_PACKAGE_NAME = "android:packageName";
3339

40+
/**
41+
* Type of animation that arguments specify.
42+
* @hide
43+
*/
44+
public static final String KEY_ANIM_TYPE = "android:animType";
45+
3446
/**
3547
* Custom enter animation resource ID.
3648
* @hide
@@ -43,10 +55,45 @@ public class ActivityOptions {
4355
*/
4456
public static final String KEY_ANIM_EXIT_RES_ID = "android:animExitRes";
4557

58+
/**
59+
* Bitmap for thumbnail animation.
60+
* @hide
61+
*/
62+
public static final String KEY_ANIM_THUMBNAIL = "android:animThumbnail";
63+
64+
/**
65+
* Start X position of thumbnail animation.
66+
* @hide
67+
*/
68+
public static final String KEY_ANIM_START_X = "android:animStartX";
69+
70+
/**
71+
* Start Y position of thumbnail animation.
72+
* @hide
73+
*/
74+
public static final String KEY_ANIM_START_Y = "android:animStartY";
75+
76+
/**
77+
* Callback for when animation is started.
78+
* @hide
79+
*/
80+
public static final String KEY_ANIM_START_LISTENER = "android:animStartListener";
81+
82+
/** @hide */
83+
public static final int ANIM_NONE = 0;
84+
/** @hide */
85+
public static final int ANIM_CUSTOM = 1;
86+
/** @hide */
87+
public static final int ANIM_THUMBNAIL = 2;
88+
4689
private String mPackageName;
47-
private boolean mIsCustomAnimation;
90+
private int mAnimationType = ANIM_NONE;
4891
private int mCustomEnterResId;
4992
private int mCustomExitResId;
93+
private Bitmap mThumbnail;
94+
private int mStartX;
95+
private int mStartY;
96+
private IRemoteCallback mAnimationStartedListener;
5097

5198
/**
5299
* Create an ActivityOptions specifying a custom animation to run when
@@ -65,22 +112,79 @@ public static ActivityOptions makeCustomAnimation(Context context,
65112
int enterResId, int exitResId) {
66113
ActivityOptions opts = new ActivityOptions();
67114
opts.mPackageName = context.getPackageName();
68-
opts.mIsCustomAnimation = true;
115+
opts.mAnimationType = ANIM_CUSTOM;
69116
opts.mCustomEnterResId = enterResId;
70117
opts.mCustomExitResId = exitResId;
71118
return opts;
72119
}
73120

121+
/**
122+
* Callback for use with {@link ActivityOptions#makeThumbnailScaleUpAnimation}
123+
* to find out when the given animation has started running.
124+
*/
125+
public interface OnAnimationStartedListener {
126+
void onAnimationStarted();
127+
}
128+
129+
/**
130+
* Create an ActivityOptions specifying an animation where a thumbnail
131+
* is scaled from a given position to the new activity window that is
132+
* being started.
133+
*
134+
* @param source The View that this thumbnail is animating from. This
135+
* defines the coordinate space for <var>startX</var> and <var>startY</var>.
136+
* @param thumbnail The bitmap that will be shown as the initial thumbnail
137+
* of the animation.
138+
* @param startX The x starting location of the bitmap, in screen coordiantes.
139+
* @param startY The y starting location of the bitmap, in screen coordinates.
140+
* @param listener Optional OnAnimationStartedListener to find out when the
141+
* requested animation has started running. If for some reason the animation
142+
* is not executed, the callback will happen immediately.
143+
* @return Returns a new ActivityOptions object that you can use to
144+
* supply these options as the options Bundle when starting an activity.
145+
*/
146+
public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
147+
Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
148+
ActivityOptions opts = new ActivityOptions();
149+
opts.mPackageName = source.getContext().getPackageName();
150+
opts.mAnimationType = ANIM_THUMBNAIL;
151+
opts.mThumbnail = thumbnail;
152+
int[] pts = new int[2];
153+
source.getLocationOnScreen(pts);
154+
opts.mStartX = pts[0] + startX;
155+
opts.mStartY = pts[1] + startY;
156+
if (listener != null) {
157+
final Handler h = source.getHandler();
158+
final OnAnimationStartedListener finalListener = listener;
159+
opts.mAnimationStartedListener = new IRemoteCallback.Stub() {
160+
@Override public void sendResult(Bundle data) throws RemoteException {
161+
h.post(new Runnable() {
162+
@Override public void run() {
163+
finalListener.onAnimationStarted();
164+
}
165+
});
166+
}
167+
};
168+
}
169+
return opts;
170+
}
171+
74172
private ActivityOptions() {
75173
}
76174

77175
/** @hide */
78176
public ActivityOptions(Bundle opts) {
79177
mPackageName = opts.getString(KEY_PACKAGE_NAME);
80-
if (opts.containsKey(KEY_ANIM_ENTER_RES_ID)) {
81-
mIsCustomAnimation = true;
178+
mAnimationType = opts.getInt(KEY_ANIM_TYPE);
179+
if (mAnimationType == ANIM_CUSTOM) {
82180
mCustomEnterResId = opts.getInt(KEY_ANIM_ENTER_RES_ID, 0);
83181
mCustomExitResId = opts.getInt(KEY_ANIM_EXIT_RES_ID, 0);
182+
} else if (mAnimationType == ANIM_THUMBNAIL) {
183+
mThumbnail = (Bitmap)opts.getParcelable(KEY_ANIM_THUMBNAIL);
184+
mStartX = opts.getInt(KEY_ANIM_START_X, 0);
185+
mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
186+
mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
187+
opts.getIBinder(KEY_ANIM_START_LISTENER));
84188
}
85189
}
86190

@@ -90,8 +194,8 @@ public String getPackageName() {
90194
}
91195

92196
/** @hide */
93-
public boolean isCustomAnimation() {
94-
return mIsCustomAnimation;
197+
public int getAnimationType() {
198+
return mAnimationType;
95199
}
96200

97201
/** @hide */
@@ -104,6 +208,43 @@ public int getCustomExitResId() {
104208
return mCustomExitResId;
105209
}
106210

211+
/** @hide */
212+
public Bitmap getThumbnail() {
213+
return mThumbnail;
214+
}
215+
216+
/** @hide */
217+
public int getStartX() {
218+
return mStartX;
219+
}
220+
221+
/** @hide */
222+
public int getStartY() {
223+
return mStartY;
224+
}
225+
226+
/** @hide */
227+
public IRemoteCallback getOnAnimationStartListener() {
228+
return mAnimationStartedListener;
229+
}
230+
231+
/** @hide */
232+
public void abort() {
233+
if (mAnimationStartedListener != null) {
234+
try {
235+
mAnimationStartedListener.sendResult(null);
236+
} catch (RemoteException e) {
237+
}
238+
}
239+
}
240+
241+
/** @hide */
242+
public static void abort(Bundle options) {
243+
if (options != null) {
244+
(new ActivityOptions(options)).abort();
245+
}
246+
}
247+
107248
/**
108249
* Join the values in <var>otherOptions</var> in to this one. Any values
109250
* defined in <var>otherOptions</var> replace those in the base options.
@@ -112,10 +253,27 @@ public void join(ActivityOptions otherOptions) {
112253
if (otherOptions.mPackageName != null) {
113254
mPackageName = otherOptions.mPackageName;
114255
}
115-
if (otherOptions.mIsCustomAnimation) {
116-
mIsCustomAnimation = true;
117-
mCustomEnterResId = otherOptions.mCustomEnterResId;
118-
mCustomExitResId = otherOptions.mCustomExitResId;
256+
switch (otherOptions.mAnimationType) {
257+
case ANIM_CUSTOM:
258+
mAnimationType = otherOptions.mAnimationType;
259+
mCustomEnterResId = otherOptions.mCustomEnterResId;
260+
mCustomExitResId = otherOptions.mCustomExitResId;
261+
mThumbnail = null;
262+
mAnimationStartedListener = null;
263+
break;
264+
case ANIM_THUMBNAIL:
265+
mAnimationType = otherOptions.mAnimationType;
266+
mThumbnail = otherOptions.mThumbnail;
267+
mStartX = otherOptions.mStartX;
268+
mStartY = otherOptions.mStartY;
269+
if (otherOptions.mAnimationStartedListener != null) {
270+
try {
271+
otherOptions.mAnimationStartedListener.sendResult(null);
272+
} catch (RemoteException e) {
273+
}
274+
}
275+
mAnimationStartedListener = otherOptions.mAnimationStartedListener;
276+
break;
119277
}
120278
}
121279

@@ -132,9 +290,19 @@ public Bundle toBundle() {
132290
if (mPackageName != null) {
133291
b.putString(KEY_PACKAGE_NAME, mPackageName);
134292
}
135-
if (mIsCustomAnimation) {
136-
b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);
137-
b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId);
293+
switch (mAnimationType) {
294+
case ANIM_CUSTOM:
295+
b.putInt(KEY_ANIM_TYPE, mAnimationType);
296+
b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);
297+
b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId);
298+
break;
299+
case ANIM_THUMBNAIL:
300+
b.putInt(KEY_ANIM_TYPE, mAnimationType);
301+
b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
302+
b.putInt(KEY_ANIM_START_X, mStartX);
303+
b.putInt(KEY_ANIM_START_Y, mStartY);
304+
b.putIBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
305+
!= null ? mAnimationStartedListener.asBinder() : null);
138306
}
139307
return b;
140308
}

core/java/android/app/IActivityManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
105105
public List getServices(int maxNum, int flags) throws RemoteException;
106106
public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState()
107107
throws RemoteException;
108-
public void moveTaskToFront(int task, int flags) throws RemoteException;
108+
public void moveTaskToFront(int task, int flags, Bundle options) throws RemoteException;
109109
public void moveTaskToBack(int task) throws RemoteException;
110110
public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) throws RemoteException;
111111
public void moveTaskBackwards(int task) throws RemoteException;

core/java/android/view/IWindowManager.aidl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ interface IWindowManager
8989
void prepareAppTransition(int transit, boolean alwaysKeepCurrent);
9090
int getPendingAppTransition();
9191
void overridePendingAppTransition(String packageName, int enterAnim, int exitAnim);
92+
void overridePendingAppTransitionThumb(in Bitmap srcThumb, int startX, int startY,
93+
IRemoteCallback startedCallback);
9294
void executeAppTransition();
9395
void setAppStartingWindow(IBinder token, String pkg, int theme,
9496
in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,

0 commit comments

Comments
 (0)