From bcbcaa7edd32ba67c6290d79f7e7821c4b5b39ac Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Thu, 10 Sep 2009 10:54:46 -0700 Subject: [PATCH] Wallpapers, animations, pending intent. Some more tweaks and fixes to wallpapers. Make sure wallpapers are told they are not visible when the screen is off. Add some new animations for transitions across tasks, and fiddle with many of the existing animations. Clean up the relationship between translucent activities and animations. Add new API to start a PendingIntent from an activity. Change-Id: Ie0bf45fe44081bb6982c75361257a55d9cd9d863 --- api/current.xml | 69 ++++++++ core/java/android/app/Activity.java | 100 +++++++++++- .../android/app/ActivityManagerNative.java | 52 ++++++ core/java/android/app/IActivityManager.java | 7 + core/java/android/app/Instrumentation.java | 9 +- core/java/android/app/PendingIntent.java | 3 +- .../service/wallpaper/WallpaperService.java | 43 ++++- core/res/res/anim/activity_close_enter.xml | 25 +++ core/res/res/anim/activity_close_exit.xml | 24 +++ core/res/res/anim/activity_open_enter.xml | 24 +++ core/res/res/anim/activity_open_exit.xml | 25 +++ core/res/res/anim/task_close_enter.xml | 14 +- core/res/res/anim/task_close_exit.xml | 16 +- core/res/res/anim/task_open_enter.xml | 16 +- core/res/res/anim/task_open_exit.xml | 11 +- core/res/res/anim/translucent_enter.xml | 26 +++ core/res/res/anim/translucent_exit.xml | 26 +++ core/res/res/anim/wallpaper_close_enter.xml | 5 +- core/res/res/anim/wallpaper_close_exit.xml | 11 +- core/res/res/anim/wallpaper_enter.xml | 5 +- core/res/res/anim/wallpaper_exit.xml | 5 +- .../res/anim/wallpaper_intra_close_enter.xml | 9 +- .../res/anim/wallpaper_intra_close_exit.xml | 9 +- .../res/anim/wallpaper_intra_open_enter.xml | 9 +- .../res/anim/wallpaper_intra_open_exit.xml | 9 +- core/res/res/anim/wallpaper_open_enter.xml | 11 +- core/res/res/anim/wallpaper_open_exit.xml | 5 +- core/res/res/values/styles.xml | 19 ++- core/res/res/values/themes.xml | 7 +- .../android/server/WindowManagerService.java | 151 +++++++----------- .../server/am/ActivityManagerService.java | 60 +++++-- .../server/am/PendingIntentRecord.java | 15 +- 32 files changed, 619 insertions(+), 201 deletions(-) create mode 100644 core/res/res/anim/activity_close_enter.xml create mode 100644 core/res/res/anim/activity_close_exit.xml create mode 100644 core/res/res/anim/activity_open_enter.xml create mode 100644 core/res/res/anim/activity_open_exit.xml create mode 100644 core/res/res/anim/translucent_enter.xml create mode 100644 core/res/res/anim/translucent_exit.xml diff --git a/api/current.xml b/api/current.xml index fa9ab9362db19..d6b272f638f51 100644 --- a/api/current.xml +++ b/api/current.xml @@ -17060,6 +17060,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + must have been created with + * {@link PendingIntent#getActivity PendingIntent.getActivity}; all other + * types will result in an IllegalArgumentException being thrown. + * + * @param intent The PendingIntent to launch. + * @param requestCode If >= 0, this code will be returned in + * onActivityResult() when the activity exits. + * @param fillInIntent If non-null, this will be provided as the + * intent parameter to {@link PendingIntent#send(Context, int, Intent) + * PendingIntent.send(Context, int, Intent)}. + * @param flagsMask Intent flags in the original PendingIntent that you + * would like to change. + * @param flagsValues Desired values for any bits set in + * flagsMask + */ + public void startActivityForResult(PendingIntent intent, int requestCode, + Intent fillInIntent, int flagsMask, int flagsValues) + throws PendingIntent.CanceledException { + if (mParent == null) { + startActivityForResultInner(intent, requestCode, fillInIntent, + flagsMask, flagsValues, this); + } else { + mParent.startActivityFromChild(this, intent, requestCode, + fillInIntent, flagsMask, flagsValues); + } + } + + private void startActivityForResultInner(PendingIntent intent, int requestCode, + Intent fillInIntent, int flagsMask, int flagsValues, Activity activity) + throws PendingIntent.CanceledException { + try { + String resolvedType = null; + if (fillInIntent != null) { + resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver()); + } + int result = ActivityManagerNative.getDefault() + .startActivityPendingIntent(mMainThread.getApplicationThread(), intent, + fillInIntent, resolvedType, mToken, activity.mEmbeddedID, + requestCode, flagsMask, flagsValues); + if (result == IActivityManager.START_CANCELED) { + throw new PendingIntent.CanceledException(); + } + Instrumentation.checkStartActivityResult(result, null); + } catch (RemoteException e) { + } + if (requestCode >= 0) { + // If this start is requesting a result, we can avoid making + // the activity visible until the result is received. Setting + // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the + // activity hidden during this time, to avoid flickering. + // This can only be done when a result is requested because + // that guarantees we will get information back when the + // activity is finished, no matter what happens to it. + mStartedActivity = true; + } + } + /** * Launch a new activity. You will not receive any information about when * the activity exits. This implementation overrides the base version, @@ -2745,6 +2803,27 @@ public class Activity extends ContextThemeWrapper startActivityForResult(intent, -1); } + /** + * Like {@link #startActivity(Intent)}, but taking a PendingIntent + * to start; see + * {@link #startActivityForResult(PendingIntent, int, Intent, int, int)} + * for more information. + * + * @param intent The PendingIntent to launch. + * @param fillInIntent If non-null, this will be provided as the + * intent parameter to {@link PendingIntent#send(Context, int, Intent) + * PendingIntent.send(Context, int, Intent)}. + * @param flagsMask Intent flags in the original PendingIntent that you + * would like to change. + * @param flagsValues Desired values for any bits set in + * flagsMask + */ + public void startActivity(PendingIntent intent, + Intent fillInIntent, int flagsMask, int flagsValues) + throws PendingIntent.CanceledException { + startActivityForResult(intent, -1, fillInIntent, flagsMask, flagsValues); + } + /** * A special variation to launch an activity only if a new activity * instance is needed to handle the given Intent. In other words, this is @@ -2865,6 +2944,19 @@ public class Activity extends ContextThemeWrapper } } + /** + * Like {@link #startActivityFromChild(Activity, Intent, int)}, but + * taking a PendingIntent; see + * {@link #startActivityForResult(PendingIntent, int, Intent, int, int)} + * for more information. + */ + public void startActivityFromChild(Activity child, PendingIntent intent, + int requestCode, Intent fillInIntent, int flagsMask, int flagsValues) + throws PendingIntent.CanceledException { + startActivityForResultInner(intent, requestCode, fillInIntent, + flagsMask, flagsValues, child); + } + /** * Call this to set the result that your activity will return to its * caller. diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 4ed152e34631e..4796e49375e8b 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -144,6 +144,30 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM reply.writeInt(result); return true; } + + case START_ACTIVITY_PENDING_INTENT_TRANSACTION: + { + data.enforceInterface(IActivityManager.descriptor); + IBinder b = data.readStrongBinder(); + IApplicationThread app = ApplicationThreadNative.asInterface(b); + PendingIntent intent = PendingIntent.CREATOR.createFromParcel(data); + Intent fillInIntent = null; + if (data.readInt() != 0) { + fillInIntent = Intent.CREATOR.createFromParcel(data); + } + String resolvedType = data.readString(); + IBinder resultTo = data.readStrongBinder(); + String resultWho = data.readString(); + int requestCode = data.readInt(); + int flagsMask = data.readInt(); + int flagsValues = data.readInt(); + int result = startActivityPendingIntent(app, intent, + fillInIntent, resolvedType, resultTo, resultWho, + requestCode, flagsMask, flagsValues); + reply.writeNoException(); + reply.writeInt(result); + return true; + } case START_NEXT_MATCHING_ACTIVITY_TRANSACTION: { @@ -1179,6 +1203,34 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); return result; } + public int startActivityPendingIntent(IApplicationThread caller, + PendingIntent intent, Intent fillInIntent, String resolvedType, + IBinder resultTo, String resultWho, int requestCode, + int flagsMask, int flagsValues) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(caller != null ? caller.asBinder() : null); + intent.writeToParcel(data, 0); + if (fillInIntent != null) { + data.writeInt(1); + fillInIntent.writeToParcel(data, 0); + } else { + data.writeInt(0); + } + data.writeString(resolvedType); + data.writeStrongBinder(resultTo); + data.writeString(resultWho); + data.writeInt(requestCode); + data.writeInt(flagsMask); + data.writeInt(flagsValues); + mRemote.transact(START_ACTIVITY_PENDING_INTENT_TRANSACTION, data, reply, 0); + reply.readException(); + int result = reply.readInt(); + reply.recycle(); + data.recycle(); + return result; + } public boolean startNextMatchingActivity(IBinder callingActivity, Intent intent) throws RemoteException { Parcel data = Parcel.obtain(); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index a937c11f789cd..82446455cddc1 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -77,10 +77,16 @@ public interface IActivityManager extends IInterface { public static final int START_CLASS_NOT_FOUND = -2; public static final int START_FORWARD_AND_REQUEST_CONFLICT = -3; public static final int START_PERMISSION_DENIED = -4; + public static final int START_NOT_ACTIVITY = -5; + public static final int START_CANCELED = -6; public int startActivity(IApplicationThread caller, Intent intent, String resolvedType, Uri[] grantedUriPermissions, int grantedMode, IBinder resultTo, String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug) throws RemoteException; + public int startActivityPendingIntent(IApplicationThread caller, + PendingIntent intent, Intent fillInIntent, String resolvedType, + IBinder resultTo, String resultWho, int requestCode, + int flagsMask, int flagsValues) throws RemoteException; public boolean startNextMatchingActivity(IBinder callingActivity, Intent intent) throws RemoteException; public boolean finishActivity(IBinder token, int code, Intent data) @@ -436,4 +442,5 @@ public interface IActivityManager extends IInterface { int CLOSE_SYSTEM_DIALOGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+96; int GET_PROCESS_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+97; int KILL_APPLICATION_PROCESS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+98; + int START_ACTIVITY_PENDING_INTENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+99; } diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index e31f4f834404d..6d79aee973f96 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -1468,7 +1468,7 @@ public class Instrumentation { mWatcher = watcher; } - /*package*/ static void checkStartActivityResult(int res, Intent intent) { + /*package*/ static void checkStartActivityResult(int res, Object intent) { if (res >= IActivityManager.START_SUCCESS) { return; } @@ -1476,10 +1476,10 @@ public class Instrumentation { switch (res) { case IActivityManager.START_INTENT_NOT_RESOLVED: case IActivityManager.START_CLASS_NOT_FOUND: - if (intent.getComponent() != null) + if (intent instanceof Intent && ((Intent)intent).getComponent() != null) throw new ActivityNotFoundException( "Unable to find explicit activity class " - + intent.getComponent().toShortString() + + ((Intent)intent).getComponent().toShortString() + "; have you declared this activity in your AndroidManifest.xml?"); throw new ActivityNotFoundException( "No Activity found to handle " + intent); @@ -1489,6 +1489,9 @@ public class Instrumentation { case IActivityManager.START_FORWARD_AND_REQUEST_CONFLICT: throw new AndroidRuntimeException( "FORWARD_RESULT_FLAG used while also requesting a result"); + case IActivityManager.START_NOT_ACTIVITY: + throw new IllegalArgumentException( + "PendingIntent is not an activity"); default: throw new AndroidRuntimeException("Unknown error code " + res + " when starting " + intent); diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java index f7479bcdb8bf0..18d9b92fbc5cd 100644 --- a/core/java/android/app/PendingIntent.java +++ b/core/java/android/app/PendingIntent.java @@ -519,7 +519,8 @@ public final class PendingIntent implements Parcelable { mTarget = IIntentSender.Stub.asInterface(target); } - /*package*/ IIntentSender getTarget() { + /** @hide */ + public IIntentSender getTarget() { return mTarget; } } diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 95b5730c0fecd..e5659d57a0cb1 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -22,7 +22,10 @@ import com.android.internal.view.BaseSurfaceHolder; import android.app.Service; import android.app.WallpaperManager; +import android.content.BroadcastReceiver; +import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.graphics.Rect; import android.os.IBinder; import android.os.Message; @@ -88,6 +91,8 @@ public abstract class WallpaperService extends Service { boolean mInitializing = true; boolean mVisible; + boolean mScreenOn = true; + boolean mReportedVisible; boolean mDestroyed; // Current window state. @@ -117,6 +122,19 @@ public abstract class WallpaperService extends Service { float mPendingYOffset; MotionEvent mPendingMove; + final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) { + mScreenOn = true; + reportVisibility(); + } else if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) { + mScreenOn = false; + reportVisibility(); + } + } + }; + final BaseSurfaceHolder mSurfaceHolder = new BaseSurfaceHolder() { @Override @@ -239,7 +257,7 @@ public abstract class WallpaperService extends Service { * {@link #onVisibilityChanged(boolean)}. */ public boolean isVisible() { - return mVisible; + return mReportedVisible; } /** @@ -489,6 +507,11 @@ public abstract class WallpaperService extends Service { mSession = ViewRoot.getWindowSession(getMainLooper()); mWindow.setSession(mSession); + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_SCREEN_ON); + filter.addAction(Intent.ACTION_SCREEN_OFF); + registerReceiver(mReceiver, filter); + if (DEBUG) Log.v(TAG, "onCreate(): " + this); onCreate(mSurfaceHolder); @@ -505,11 +528,19 @@ public abstract class WallpaperService extends Service { } void doVisibilityChanged(boolean visible) { + mVisible = visible; + reportVisibility(); + } + + void reportVisibility() { if (!mDestroyed) { - mVisible = visible; - if (DEBUG) Log.v(TAG, "onVisibilityChanged(" + visible - + "): " + this); - onVisibilityChanged(visible); + boolean visible = mVisible && mScreenOn; + if (mReportedVisible != visible) { + mReportedVisible = visible; + if (DEBUG) Log.v(TAG, "onVisibilityChanged(" + visible + + "): " + this); + onVisibilityChanged(visible); + } } } @@ -562,6 +593,8 @@ public abstract class WallpaperService extends Service { if (DEBUG) Log.v(TAG, "onDestroy(): " + this); onDestroy(); + unregisterReceiver(mReceiver); + if (mCreated) { try { mSession.remove(mWindow); diff --git a/core/res/res/anim/activity_close_enter.xml b/core/res/res/anim/activity_close_enter.xml new file mode 100644 index 0000000000000..9d1ef53743a24 --- /dev/null +++ b/core/res/res/anim/activity_close_enter.xml @@ -0,0 +1,25 @@ + + + + + + diff --git a/core/res/res/anim/activity_close_exit.xml b/core/res/res/anim/activity_close_exit.xml new file mode 100644 index 0000000000000..47cb6d69423b8 --- /dev/null +++ b/core/res/res/anim/activity_close_exit.xml @@ -0,0 +1,24 @@ + + + + + + diff --git a/core/res/res/anim/activity_open_enter.xml b/core/res/res/anim/activity_open_enter.xml new file mode 100644 index 0000000000000..e4c7e9bcc9d5b --- /dev/null +++ b/core/res/res/anim/activity_open_enter.xml @@ -0,0 +1,24 @@ + + + + + + diff --git a/core/res/res/anim/activity_open_exit.xml b/core/res/res/anim/activity_open_exit.xml new file mode 100644 index 0000000000000..9d47b7f59c332 --- /dev/null +++ b/core/res/res/anim/activity_open_exit.xml @@ -0,0 +1,25 @@ + + + + + + diff --git a/core/res/res/anim/task_close_enter.xml b/core/res/res/anim/task_close_enter.xml index c289869cafcb7..303cfd6827381 100644 --- a/core/res/res/anim/task_close_enter.xml +++ b/core/res/res/anim/task_close_enter.xml @@ -1,8 +1,7 @@ - + android:interpolator="@anim/decelerate_interpolator"> + diff --git a/core/res/res/anim/task_close_exit.xml b/core/res/res/anim/task_close_exit.xml index 96fff94a27b10..a28ac3ba902a6 100644 --- a/core/res/res/anim/task_close_exit.xml +++ b/core/res/res/anim/task_close_exit.xml @@ -1,8 +1,7 @@ - + android:interpolator="@anim/decelerate_interpolator" + android:zAdjustment="top"> + + diff --git a/core/res/res/anim/task_open_enter.xml b/core/res/res/anim/task_open_enter.xml index 8e7d049ce8537..234abb23cbcda 100644 --- a/core/res/res/anim/task_open_enter.xml +++ b/core/res/res/anim/task_open_enter.xml @@ -1,8 +1,7 @@ - + android:interpolator="@anim/decelerate_interpolator" + android:zAdjustment="top"> + + diff --git a/core/res/res/anim/task_open_exit.xml b/core/res/res/anim/task_open_exit.xml index 5e5c66d0edf50..98975fb92fcc6 100644 --- a/core/res/res/anim/task_open_exit.xml +++ b/core/res/res/anim/task_open_exit.xml @@ -1,8 +1,7 @@ + + + + + diff --git a/core/res/res/anim/translucent_exit.xml b/core/res/res/anim/translucent_exit.xml new file mode 100644 index 0000000000000..1d424e18d3be8 --- /dev/null +++ b/core/res/res/anim/translucent_exit.xml @@ -0,0 +1,26 @@ + + + + + + + diff --git a/core/res/res/anim/wallpaper_close_enter.xml b/core/res/res/anim/wallpaper_close_enter.xml index 8e7d049ce8537..e4c7e9bcc9d5b 100644 --- a/core/res/res/anim/wallpaper_close_enter.xml +++ b/core/res/res/anim/wallpaper_close_enter.xml @@ -1,8 +1,7 @@ + - + diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index bfdce1e25328a..3b9590d246526 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -306,19 +306,22 @@