A variety of work on animations.

- The lock screen now fades in and out.
- Fixed a bug where we would accidentally freeze the screen when switching
  to an activity with a different orientation than the current (but
  the screen itself is in the current orientation).  This would mess up
  the animations on the car dock.
- New API to force a particular animation for an activity transition
  (untested).
- New wallpaper animations.
- Resources now uses the next API version when in a development build,
  to help applications being developed against such builds.

Change-Id: I2d9998f8400967ff09a04d693dc4ce55f0dbef5b
diff --git a/api/current.xml b/api/current.xml
index 35bfab3..d5f3f46 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -16877,6 +16877,21 @@
  visibility="public"
 >
 </method>
+<method name="overridePendingTransition"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enterAnim" type="int">
+</parameter>
+<parameter name="exitAnim" type="int">
+</parameter>
+</method>
 <method name="registerForContextMenu"
  return="void"
  abstract="false"
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 4561899..8755477 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -3015,6 +3015,23 @@
     }
 
     /**
+     * Call immediately after one of the flavors of {@link #startActivity(Intent)}
+     * or {@link #finish} to specify an explicit transition animation to
+     * perform next.
+     * @param enterAnim A resource ID of the animation resource to use for
+     * the incoming activity.
+     * @param exitAnim A resource ID of the animation resource to use for
+     * the outgoing activity.
+     */
+    public void overridePendingTransition(int enterAnim, int exitAnim) {
+        try {
+            ActivityManagerNative.getDefault().overridePendingTransition(
+                    mToken, getPackageName(), enterAnim, exitAnim);
+        } catch (RemoteException e) {
+        }
+    }
+    
+    /**
      * 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 82d49e3..2d7658a 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1153,6 +1153,16 @@
             reply.writeNoException();
             return true;
         }
+        
+        case OVERRIDE_PENDING_TRANSITION_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IBinder token = data.readStrongBinder();
+            String packageName = data.readString();
+            int enterAnim = data.readInt();
+            int exitAnim = data.readInt();
+            overridePendingTransition(token, packageName, enterAnim, exitAnim);
+            return true;
+        }
         }
         
         return super.onTransact(code, data, reply, flags);
@@ -2530,5 +2540,20 @@
         reply.recycle();
     }
         
+    public void overridePendingTransition(IBinder token, String packageName,
+            int enterAnim, int exitAnim) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(token);
+        data.writeString(packageName);
+        data.writeInt(enterAnim);
+        data.writeInt(exitAnim);
+        mRemote.transact(OVERRIDE_PENDING_TRANSITION_TRANSACTION, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+    
     private IBinder mRemote;
 }
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 110b72d..7ad7561 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -285,6 +285,9 @@
     public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
             throws RemoteException;
     
+    public void overridePendingTransition(IBinder token, String packageName,
+            int enterAnim, int exitAnim) throws RemoteException;
+    
     /*
      * Private non-Binder interfaces
      */
@@ -444,4 +447,5 @@
     int GET_PROCESS_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+97;
     int KILL_APPLICATION_PROCESS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+98;
     int START_ACTIVITY_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+99;
+    int OVERRIDE_PENDING_TRANSITION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+100;
 }
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 8839f95..7a65af8 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -253,7 +253,7 @@
     public int uid;
     
     /**
-     * The minimum SDK version this application targets.  It may run on earilier
+     * The minimum SDK version this application targets.  It may run on earlier
      * versions, but it knows how to work with any new behavior added at this
      * version.  Will be {@link android.os.Build.VERSION_CODES#CUR_DEVELOPMENT}
      * if this is a development build and the app is targeting that.  You should
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 3796201..00ab7de 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -25,6 +25,7 @@
 import android.graphics.Movie;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.ColorDrawable;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.SystemProperties;
 import android.util.AttributeSet;
@@ -50,8 +51,10 @@
     private static final boolean DEBUG_CONFIG = false;
     private static final boolean TRACE_FOR_PRELOAD = false;
 
-    private static final int sSdkVersion = SystemProperties.getInt(
-            "ro.build.version.sdk", 0);
+    // Use the current SDK version code.  If we are a development build,
+    // also allow the previous SDK version + 1.
+    private static final int sSdkVersion = Build.VERSION.SDK_INT
+            + ("REL".equals(Build.VERSION.CODENAME) ? 1 : 0);
     private static final Object mSync = new Object();
     private static Resources mSystem = null;
     
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 7d1872a..23e7fb7 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -71,6 +71,7 @@
     void setFocusedApp(IBinder token, boolean moveFocusNow);
     void prepareAppTransition(int transit);
     int getPendingAppTransition();
+    void overridePendingAppTransition(String packageName, int enterAnim, int exitAnim);
     void executeAppTransition();
     void setAppStartingWindow(IBinder token, String pkg, int theme,
             CharSequence nonLocalizedLabel, int labelRes,
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 396e380..7a22301 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -522,6 +522,13 @@
          * also been set. */
         public static final int FLAG_DISMISS_KEYGUARD = 0x00400000;
         
+        /** Window flag: *sigh* The lock screen wants to continue running its
+         * animation while it is fading.  A kind-of hack to allow this.  Maybe
+         * in the future we just make this the default behavior.
+         *
+         * {@hide} */
+        public static final int FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000;
+        
         /** Window flag: special flag to limit the size of the window to be
          * original size ([320x480] x density). Used to create window for applications
          * running under compatibility mode.
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 1923743..b3125b2 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -314,50 +314,60 @@
         public boolean showLw(boolean doAnimation);
     }
 
+    /**
+     * Bit mask that is set for all enter transition.
+     */
+    public final int TRANSIT_ENTER_MASK = 0x1000;
+    
+    /**
+     * Bit mask that is set for all exit transitions.
+     */
+    public final int TRANSIT_EXIT_MASK = 0x2000;
+    
     /** Not set up for a transition. */
-    public final int TRANSIT_UNSET = 0;
+    public final int TRANSIT_UNSET = -1;
     /** No animation for transition. */
     public final int TRANSIT_NONE = 0;
     /** Window has been added to the screen. */
-    public final int TRANSIT_ENTER = 1;
+    public final int TRANSIT_ENTER = 1 | TRANSIT_ENTER_MASK;
     /** Window has been removed from the screen. */
-    public final int TRANSIT_EXIT = 2;
+    public final int TRANSIT_EXIT = 2 | TRANSIT_EXIT_MASK;
     /** Window has been made visible. */
-    public final int TRANSIT_SHOW = 3;
+    public final int TRANSIT_SHOW = 3 | TRANSIT_ENTER_MASK;
     /** Window has been made invisible. */
-    public final int TRANSIT_HIDE = 4;
+    public final int TRANSIT_HIDE = 4 | TRANSIT_EXIT_MASK;
     /** The "application starting" preview window is no longer needed, and will
      * animate away to show the real window. */
     public final int TRANSIT_PREVIEW_DONE = 5;
     /** A window in a new activity is being opened on top of an existing one
      * in the same task. */
-    public final int TRANSIT_ACTIVITY_OPEN = 6;
+    public final int TRANSIT_ACTIVITY_OPEN = 6 | TRANSIT_ENTER_MASK;
     /** The window in the top-most activity is being closed to reveal the
      * previous activity in the same task. */
-    public final int TRANSIT_ACTIVITY_CLOSE = 7;
+    public final int TRANSIT_ACTIVITY_CLOSE = 7 | TRANSIT_EXIT_MASK;
     /** A window in a new task is being opened on top of an existing one
      * in another activity's task. */
-    public final int TRANSIT_TASK_OPEN = 8;
+    public final int TRANSIT_TASK_OPEN = 8 | TRANSIT_ENTER_MASK;
     /** A window in the top-most activity is being closed to reveal the
      * previous activity in a different task. */
-    public final int TRANSIT_TASK_CLOSE = 9;
+    public final int TRANSIT_TASK_CLOSE = 9 | TRANSIT_EXIT_MASK;
     /** A window in an existing task is being displayed on top of an existing one
      * in another activity's task. */
-    public final int TRANSIT_TASK_TO_FRONT = 10;
+    public final int TRANSIT_TASK_TO_FRONT = 10 | TRANSIT_ENTER_MASK;
     /** A window in an existing task is being put below all other tasks. */
-    public final int TRANSIT_TASK_TO_BACK = 11;
+    public final int TRANSIT_TASK_TO_BACK = 11 | TRANSIT_EXIT_MASK;
     /** A window in a new activity that doesn't have a wallpaper is being
      * opened on top of one that does, effectively closing the wallpaper. */
-    public final int TRANSIT_WALLPAPER_CLOSE = 12;
+    public final int TRANSIT_WALLPAPER_CLOSE = 12 | TRANSIT_EXIT_MASK;
     /** A window in a new activity that does have a wallpaper is being
      * opened on one that didn't, effectively opening the wallpaper. */
-    public final int TRANSIT_WALLPAPER_OPEN = 13;
+    public final int TRANSIT_WALLPAPER_OPEN = 13 | TRANSIT_ENTER_MASK;
     /** A window in a new activity is being opened on top of an existing one,
      * and both are on top of the wallpaper. */
-    public final int TRANSIT_WALLPAPER_INTRA_OPEN = 14;
+    public final int TRANSIT_WALLPAPER_INTRA_OPEN = 14 | TRANSIT_ENTER_MASK;
     /** The window in the top-most activity is being closed to reveal the
      * previous activity, and both are on top of he wallpaper. */
-    public final int TRANSIT_WALLPAPER_INTRA_CLOSE = 15;
+    public final int TRANSIT_WALLPAPER_INTRA_CLOSE = 15 | TRANSIT_EXIT_MASK;
     
     /** Screen turned off because of power button */
     public final int OFF_BECAUSE_OF_USER = 1;
@@ -444,6 +454,21 @@
     public int getMaxWallpaperLayer();
     
     /**
+     * Return whether the given window should forcibly hide everything
+     * behind it.  Typically returns true for the keyguard.
+     */
+    public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs);
+    
+    /**
+     * Determine if a window that is behind one that is force hiding
+     * (as determined by {@link #doesForceHide}) should actually be hidden.
+     * For example, typically returns false for the status bar.  Be careful
+     * to return false for any window that you may hide yourself, since this
+     * will conflict with what you set.
+     */
+    public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs);
+    
+    /**
      * Called when the system would like to show a UI to indicate that an
      * application is starting.  You can use this to add a
      * APPLICATION_STARTING_TYPE window with the given appToken to the window
@@ -524,6 +549,11 @@
     public int selectAnimationLw(WindowState win, int transit);
 
     /**
+     * Create and return an animation to re-display a force hidden window.
+     */
+    public Animation createForceHideEnterAnimation();
+    
+    /**
      * Called from the key queue thread before a key is dispatched to the
      * input thread.
      *
diff --git a/core/res/res/anim/lock_screen_behind_enter.xml b/core/res/res/anim/lock_screen_behind_enter.xml
new file mode 100644
index 0000000..9e03e15
--- /dev/null
+++ b/core/res/res/anim/lock_screen_behind_enter.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2007, 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:interpolator="@anim/accelerate_interpolator">
+    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+            android:duration="@android:integer/config_mediumAnimTime" />
+</set>
diff --git a/core/res/res/anim/lock_screen_exit.xml b/core/res/res/anim/lock_screen_exit.xml
index 55c5ec9..0d32921 100644
--- a/core/res/res/anim/lock_screen_exit.xml
+++ b/core/res/res/anim/lock_screen_exit.xml
@@ -1,7 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-/* //device/apps/common/res/anim/options_panel_exit.xml
-**
+/*
 ** Copyright 2007, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License"); 
diff --git a/core/res/res/anim/wallpaper_close_enter.xml b/core/res/res/anim/wallpaper_close_enter.xml
index 5bc299e..2329abb 100644
--- a/core/res/res/anim/wallpaper_close_enter.xml
+++ b/core/res/res/anim/wallpaper_close_enter.xml
@@ -17,8 +17,22 @@
 */
 -->
 
+<!-- This version zooms the new non-wallpaper up out of the
+     wallpaper, without zooming the wallpaper itself. -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+        android:interpolator="@anim/decelerate_interpolator"
+        android:zAdjustment="top">
+    <scale android:fromXScale=".5" android:toXScale="1.0"
+           android:fromYScale=".5" android:toYScale="1.0"
+           android:pivotX="50%p" android:pivotY="50%p"
+           android:duration="@android:integer/config_mediumAnimTime" />
+    <alpha android:fromAlpha="0" android:toAlpha="1.0"
+            android:duration="@android:integer/config_mediumAnimTime"/>
+</set>
+
 <!-- This version zooms the new non-wallpaper down on top of the
      wallpaper, without zooming the wallpaper itself. -->
+<!--
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@anim/decelerate_interpolator"
         android:zAdjustment="top">
@@ -29,6 +43,7 @@
     <alpha android:fromAlpha="0" android:toAlpha="1.0"
             android:duration="@android:integer/config_mediumAnimTime"/>
 </set>
+-->
 
 <!-- This version zooms the new non-wallpaper down on top of the
      wallpaper. -->
diff --git a/core/res/res/anim/wallpaper_close_exit.xml b/core/res/res/anim/wallpaper_close_exit.xml
index c3ae620..eccce81 100644
--- a/core/res/res/anim/wallpaper_close_exit.xml
+++ b/core/res/res/anim/wallpaper_close_exit.xml
@@ -17,8 +17,20 @@
 */
 -->
 
+<!-- This version zooms the new non-wallpaper up out of the
+     wallpaper, without zooming the wallpaper itself. -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+        android:interpolator="@anim/decelerate_interpolator"
+        android:detachWallpaper="true">
+    <scale android:fromXScale="1.0" android:toXScale="2.0"
+           android:fromYScale="1.0" android:toYScale="2.0"
+           android:pivotX="50%p" android:pivotY="50%p"
+           android:duration="@android:integer/config_mediumAnimTime" />
+</set>
+
 <!-- This version zooms the new non-wallpaper down on top of the
      wallpaper, without zooming the wallpaper itself. -->
+<!--
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@anim/decelerate_interpolator"
         android:detachWallpaper="true">
@@ -27,6 +39,7 @@
            android:pivotX="50%p" android:pivotY="50%p"
            android:duration="@android:integer/config_mediumAnimTime" />
 </set>
+-->
 
 <!-- This version zooms the new non-wallpaper down on top of the
      wallpaper.  The wallpaper here just stays fixed behind. -->
diff --git a/core/res/res/anim/wallpaper_open_enter.xml b/core/res/res/anim/wallpaper_open_enter.xml
index 7fe7e1e..3a6fb05 100644
--- a/core/res/res/anim/wallpaper_open_enter.xml
+++ b/core/res/res/anim/wallpaper_open_enter.xml
@@ -17,8 +17,20 @@
 */
 -->
 
+<!-- This version zooms the new non-wallpaper up out of the
+     wallpaper, without zooming the wallpaper itself. -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+        android:interpolator="@anim/decelerate_interpolator"
+        android:detachWallpaper="true">
+    <scale android:fromXScale="2.0" android:toXScale="1.0"
+           android:fromYScale="2.0" android:toYScale="1.0"
+           android:pivotX="50%p" android:pivotY="50%p"
+           android:duration="@android:integer/config_mediumAnimTime" />
+</set>
+
 <!-- This version zooms the new non-wallpaper down on top of the
      wallpaper, without zooming the wallpaper itself. -->
+<!--
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@anim/decelerate_interpolator"
         android:detachWallpaper="true">
@@ -27,6 +39,7 @@
            android:pivotX="50%p" android:pivotY="50%p"
            android:duration="@android:integer/config_mediumAnimTime" />
 </set>
+-->
 
 <!-- This version zooms the new non-wallpaper up off the wallpaper the
      wallpaper.  The wallpaper here just stays fixed behind. -->
diff --git a/core/res/res/anim/wallpaper_open_exit.xml b/core/res/res/anim/wallpaper_open_exit.xml
index 9489c6d..e5b7007 100644
--- a/core/res/res/anim/wallpaper_open_exit.xml
+++ b/core/res/res/anim/wallpaper_open_exit.xml
@@ -16,9 +16,22 @@
 ** limitations under the License.
 */
 -->
+<!-- This version zooms the new non-wallpaper up out of the
+     wallpaper, without zooming the wallpaper itself. -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+        android:interpolator="@anim/decelerate_interpolator"
+        android:zAdjustment="top">
+    <scale android:fromXScale="1.0" android:toXScale=".5"
+           android:fromYScale="1.0" android:toYScale=".5"
+           android:pivotX="50%p" android:pivotY="50%p"
+           android:duration="@android:integer/config_mediumAnimTime" />
+    <alpha android:fromAlpha="1.0" android:toAlpha="0"
+            android:duration="@android:integer/config_mediumAnimTime"/>
+</set>
 
 <!-- This version zooms the new non-wallpaper down on top of the
      wallpaper, without zooming the wallpaper itself. -->
+<!--
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@anim/decelerate_interpolator"
         android:zAdjustment="top">
@@ -29,6 +42,7 @@
     <alpha android:fromAlpha="1.0" android:toAlpha="0"
             android:duration="@android:integer/config_mediumAnimTime"/>
 </set>
+-->
 
 <!-- This version zooms the new non-wallpaper down on top of the
      wallpaper. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b508372..cf0dfd7 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -33,7 +33,7 @@
     <integer name="config_mediumAnimTime">200</integer>
     
     <!-- The duration (in milliseconds) of a long animation. -->
-    <integer name="config_longAnimTime">400</integer>
+    <integer name="config_longAnimTime">350</integer>
 
     <!-- XXXXX NOTE THE FOLLOWING RESOURCES USE THE WRONG NAMING CONVENTION.
          Please don't copy them, copy anything else. -->
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 2c39c2a..78a82dd 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -302,6 +302,18 @@
     final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>();
 
     /**
+     * This was the app token that was used to retrieve the last enter
+     * animation.  It will be used for the next exit animation.
+     */
+    AppWindowToken mLastEnterAnimToken;
+    
+    /**
+     * These were the layout params used to retrieve the last enter animation.
+     * They will be used for the next exit animation.
+     */
+    LayoutParams mLastEnterAnimParams;
+    
+    /**
      * Z-ordered (bottom-most first) list of all Window objects.
      */
     final ArrayList mWindows = new ArrayList();
@@ -374,6 +386,9 @@
     // mOpeningApps and mClosingApps are the lists of tokens that will be
     // made visible or hidden at the next transition.
     int mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
+    String mNextAppTransitionPackage;
+    int mNextAppTransitionEnter;
+    int mNextAppTransitionExit;
     boolean mAppTransitionReady = false;
     boolean mAppTransitionRunning = false;
     boolean mAppTransitionTimeout = false;
@@ -1245,16 +1260,27 @@
         WindowState w = null;
         WindowState foundW = null;
         int foundI = 0;
+        WindowState topCurW = null;
+        int topCurI = 0;
         int i = N;
         while (i > 0) {
             i--;
             w = (WindowState)localmWindows.get(i);
+            if ((w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER)) {
+                if (topCurW == null) {
+                    topCurW = w;
+                    topCurI = i;
+                }
+                continue;
+            }
+            topCurW = null;
             if (w.mAppToken != null) {
                 // If this window's app token is hidden and not animating,
                 // it is of no interest to us.
                 if (w.mAppToken.hidden && w.mAppToken.animation == null) {
                     if (DEBUG_WALLPAPER) Log.v(TAG,
                             "Skipping hidden or animating token: " + w);
+                    topCurW = null;
                     continue;
                 }
             }
@@ -1268,8 +1294,9 @@
                         "Found wallpaper activity: #" + i + "=" + w);
                 foundW = w;
                 foundI = i;
-                if (w == mWallpaperTarget && w.mAppToken != null
-                        && w.mAppToken.animation != null) {
+                if (w == mWallpaperTarget && ((w.mAppToken != null
+                        && w.mAppToken.animation != null)
+                        || w.mAnimation != null)) {
                     // The current wallpaper target is animating, so we'll
                     // look behind it for another possible target and figure
                     // out what is going on below.
@@ -1316,14 +1343,16 @@
             
             // Now what is happening...  if the current and new targets are
             // animating, then we are in our super special mode!
-            if (foundW != null && foundW.mAppToken != null && oldW != null
-                    && oldW.mAppToken != null) {
+            if (foundW != null && oldW != null) {
+                boolean oldAnim = oldW.mAnimation != null
+                        || (oldW.mAppToken != null && oldW.mAppToken.animation != null);
+                boolean foundAnim = foundW.mAnimation != null
+                        || (foundW.mAppToken != null && foundW.mAppToken.animation != null);
                 if (DEBUG_WALLPAPER) {
-                    Log.v(TAG, "New animation: " + foundW.mAppToken.animation
-                            + " old animation: " + oldW.mAppToken.animation);
+                    Log.v(TAG, "New animation: " + foundAnim
+                            + " old animation: " + oldAnim);
                 }
-                if (foundW.mAppToken.animation != null
-                        && oldW.mAppToken.animation != null) {
+                if (foundAnim && oldAnim) {
                     int oldI = localmWindows.indexOf(oldW);
                     if (DEBUG_WALLPAPER) {
                         Log.v(TAG, "New i: " + foundI + " old i: " + oldI);
@@ -1336,7 +1365,7 @@
                         }
                         
                         // Set the new target correctly.
-                        if (foundW.mAppToken.hiddenRequested) {
+                        if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) {
                             if (DEBUG_WALLPAPER) {
                                 Log.v(TAG, "Old wallpaper still the target.");
                             }
@@ -1417,12 +1446,19 @@
                 foundI--;
             }
         } else {
-            if (DEBUG_WALLPAPER) Log.v(TAG, "Wallpaper not visible");
+            if (DEBUG_WALLPAPER) Log.v(TAG, "No wallpaper target");
         }
         
-        // Okay i is the position immediately above the wallpaper.  Look at
-        // what is below it for later.
-        foundW = foundI > 0 ? (WindowState)localmWindows.get(foundI-1) : null;
+        if (foundW == null && topCurW != null) {
+            // There is no wallpaper target, so it goes at the bottom.
+            // We will assume it is the same place as last time, if known.
+            foundW = topCurW;
+            foundI = topCurI+1;
+        } else {
+            // Okay i is the position immediately above the wallpaper.  Look at
+            // what is below it for later.
+            foundW = foundI > 0 ? (WindowState)localmWindows.get(foundI-1) : null;
+        }
         
         if (visible) {
             mLastWallpaperX = mWallpaperTarget.mWallpaperX;
@@ -2244,6 +2280,8 @@
                     Surface surface = win.createSurfaceLocked();
                     if (surface != null) {
                         outSurface.copyFrom(surface);
+                        win.mReportDestroySurface = false;
+                        win.mSurfacePendingDestroy = false;
                         if (SHOW_TRANSACTIONS) Log.i(TAG,
                                 "  OUT SURFACE " + outSurface + ": copied");
                     } else {
@@ -2269,17 +2307,21 @@
             } else {
                 win.mEnterAnimationPending = false;
                 if (win.mSurface != null) {
+                    if (DEBUG_VISIBILITY) Log.i(TAG, "Relayout invis " + win
+                            + ": mExiting=" + win.mExiting
+                            + " mSurfacePendingDestroy=" + win.mSurfacePendingDestroy);
                     // If we are not currently running the exit animation, we
                     // need to see about starting one.
-                    if (!win.mExiting) {
+                    if (!win.mExiting || win.mSurfacePendingDestroy) {
                         // Try starting an animation; if there isn't one, we
                         // can destroy the surface right away.
                         int transit = WindowManagerPolicy.TRANSIT_EXIT;
                         if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
                             transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
                         }
-                        if (win.isWinVisibleLw() &&
+                        if (!win.mSurfacePendingDestroy && win.isWinVisibleLw() &&
                               applyAnimationLocked(win, transit, false)) {
+                            focusMayChange = true;
                             win.mExiting = true;
                             mKeyWaiter.finishedKey(session, client, true,
                                     KeyWaiter.RETURN_NOTHING);
@@ -2301,11 +2343,23 @@
                         }
                     }
                 }
-                // We are being called from a local process, which
-                // means outSurface holds its current surface.  Ensure the
-                // surface object is cleared, but we don't want it actually
-                // destroyed at this point.
-                outSurface.release();
+                
+                if (win.mSurface == null || (win.getAttrs().flags
+                        & WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING) == 0
+                        || win.mSurfacePendingDestroy) {
+                    // We are being called from a local process, which
+                    // means outSurface holds its current surface.  Ensure the
+                    // surface object is cleared, but we don't want it actually
+                    // destroyed at this point.
+                    win.mSurfacePendingDestroy = false;
+                    outSurface.release();
+                    if (DEBUG_VISIBILITY) Log.i(TAG, "Releasing surface in: " + win);
+                } else if (win.mSurface != null) {
+                    if (DEBUG_VISIBILITY) Log.i(TAG,
+                            "Keeping surface, will report destroy: " + win);
+                    win.mReportDestroySurface = true;
+                    outSurface.copyFrom(win.mSurface);
+                }
             }
 
             if (focusMayChange) {
@@ -2408,6 +2462,21 @@
         return null;
     }
 
+    private AttributeCache.Entry getCachedAnimations(String packageName, int resId) {
+        if (DEBUG_ANIM) Log.v(TAG, "Loading animations: params package="
+                + packageName + " resId=0x" + Integer.toHexString(resId));
+        if (packageName != null) {
+            if ((resId&0xFF000000) == 0x01000000) {
+                packageName = "android";
+            }
+            if (DEBUG_ANIM) Log.v(TAG, "Loading animations: picked package="
+                    + packageName);
+            return AttributeCache.instance().get(packageName, resId,
+                    com.android.internal.R.styleable.WindowAnimation);
+        }
+        return null;
+    }
+
     private void applyEnterAnimationLocked(WindowState win) {
         int transit = WindowManagerPolicy.TRANSIT_SHOW;
         if (win.mEnterAnimationPending) {
@@ -2491,6 +2560,22 @@
         return null;
     }
 
+    private Animation loadAnimation(String packageName, int resId) {
+        int anim = 0;
+        Context context = mContext;
+        if (resId >= 0) {
+            AttributeCache.Entry ent = getCachedAnimations(packageName, resId);
+            if (ent != null) {
+                context = ent.context;
+                anim = resId;
+            }
+        }
+        if (anim != 0) {
+            return AnimationUtils.loadAnimation(context, anim);
+        }
+        return null;
+    }
+
     private boolean applyAnimationLocked(AppWindowToken wtoken,
             WindowManager.LayoutParams lp, int transit, boolean enter) {
         // Only apply an animation if the display isn't frozen.  If it is
@@ -2503,6 +2588,9 @@
                 a = new FadeInOutAnimation(enter);
                 if (DEBUG_ANIM) Log.v(TAG,
                         "applying FadeInOutAnimation for a window in compatibility mode");
+            } else if (mNextAppTransitionPackage != null) {
+                a = loadAnimation(mNextAppTransitionPackage, enter ?
+                        mNextAppTransitionEnter : mNextAppTransitionExit);
             } else {
                 int animAttr = 0;
                 switch (transit) {
@@ -3032,6 +3120,15 @@
         return mNextAppTransition;
     }
 
+    public void overridePendingAppTransition(String packageName,
+            int enterAnim, int exitAnim) {
+        if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET){
+            mNextAppTransitionPackage = packageName;
+            mNextAppTransitionEnter = enterAnim;
+            mNextAppTransitionExit = exitAnim;
+        }
+    }
+    
     public void executeAppTransition() {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "executeAppTransition()")) {
@@ -3039,8 +3136,12 @@
         }
 
         synchronized(mWindowMap) {
-            if (DEBUG_APP_TRANSITIONS) Log.v(
-                    TAG, "Execute app transition: mNextAppTransition=" + mNextAppTransition);
+            if (DEBUG_APP_TRANSITIONS) {
+                RuntimeException e = new RuntimeException("here");
+                e.fillInStackTrace();
+                Log.w(TAG, "Execute app transition: mNextAppTransition="
+                        + mNextAppTransition, e);
+            }
             if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
                 mAppTransitionReady = true;
                 final long origId = Binder.clearCallingIdentity();
@@ -3537,6 +3638,10 @@
                     wtoken.animating = false;
                 }
                 mAppTokens.remove(wtoken);
+                if (mLastEnterAnimToken == wtoken) {
+                    mLastEnterAnimToken = null;
+                    mLastEnterAnimParams = null;
+                }
                 wtoken.removed = true;
                 if (wtoken.startingData != null) {
                     startingToken = wtoken;
@@ -6527,6 +6632,8 @@
         boolean mPolicyVisibilityAfterAnim = true;
         boolean mAppFreezing;
         Surface mSurface;
+        boolean mReportDestroySurface;
+        boolean mSurfacePendingDestroy;
         boolean mAttachedHidden;    // is our parent window hidden?
         boolean mLastHidden;        // was this window last hidden?
         boolean mWallpaperVisible;  // for wallpaper, what was last vis report?
@@ -6929,6 +7036,8 @@
 
         Surface createSurfaceLocked() {
             if (mSurface == null) {
+                mReportDestroySurface = false;
+                mSurfacePendingDestroy = false;
                 mDrawPending = true;
                 mCommitDrawPending = false;
                 mReadyToShow = false;
@@ -7033,6 +7142,28 @@
             }
 
             if (mSurface != null) {
+                mDrawPending = false;
+                mCommitDrawPending = false;
+                mReadyToShow = false;
+
+                int i = mChildWindows.size();
+                while (i > 0) {
+                    i--;
+                    WindowState c = (WindowState)mChildWindows.get(i);
+                    c.mAttachedHidden = true;
+                }
+                
+                if (mReportDestroySurface) {
+                    mReportDestroySurface = false;
+                    mSurfacePendingDestroy = true;
+                    try {
+                        mClient.dispatchGetNewSurface();
+                        // We'll really destroy on the next time around.
+                        return;
+                    } catch (RemoteException e) {
+                    }
+                }
+                
                 try {
                     if (DEBUG_VISIBILITY) {
                         RuntimeException e = new RuntimeException();
@@ -7052,17 +7183,8 @@
                         + " surface " + mSurface + " session " + mSession
                         + ": " + e.toString());
                 }
+                
                 mSurface = null;
-                mDrawPending = false;
-                mCommitDrawPending = false;
-                mReadyToShow = false;
-
-                int i = mChildWindows.size();
-                while (i > 0) {
-                    i--;
-                    WindowState c = (WindowState)mChildWindows.get(i);
-                    c.mAttachedHidden = true;
-                }
             }
         }
 
@@ -7471,7 +7593,7 @@
          */
         boolean isVisibleOrAdding() {
             final AppWindowToken atoken = mAppToken;
-            return (mSurface != null
+            return ((mSurface != null && !mReportDestroySurface)
                             || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
                     && mPolicyVisibility && !mAttachedHidden
                     && (atoken == null || !atoken.hiddenRequested)
@@ -7642,38 +7764,50 @@
         }
 
         public boolean showLw(boolean doAnimation) {
-            if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim) {
-                mPolicyVisibility = true;
-                mPolicyVisibilityAfterAnim = true;
-                if (doAnimation) {
-                    applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true);
-                }
-                requestAnimationLocked(0);
-                return true;
+            return showLw(doAnimation, true);
+        }
+
+        boolean showLw(boolean doAnimation, boolean requestAnim) {
+            if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
+                return false;
             }
-            return false;
+            mPolicyVisibility = true;
+            mPolicyVisibilityAfterAnim = true;
+            if (doAnimation) {
+                applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true);
+            }
+            if (requestAnim) {
+                requestAnimationLocked(0);
+            }
+            return true;
         }
 
         public boolean hideLw(boolean doAnimation) {
+            return hideLw(doAnimation, true);
+        }
+
+        boolean hideLw(boolean doAnimation, boolean requestAnim) {
             boolean current = doAnimation ? mPolicyVisibilityAfterAnim
                     : mPolicyVisibility;
-            if (current) {
-                if (doAnimation) {
-                    applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false);
-                    if (mAnimation == null) {
-                        doAnimation = false;
-                    }
-                }
-                if (doAnimation) {
-                    mPolicyVisibilityAfterAnim = false;
-                } else {
-                    mPolicyVisibilityAfterAnim = false;
-                    mPolicyVisibility = false;
-                }
-                requestAnimationLocked(0);
-                return true;
+            if (!current) {
+                return false;
             }
-            return false;
+            if (doAnimation) {
+                applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false);
+                if (mAnimation == null) {
+                    doAnimation = false;
+                }
+            }
+            if (doAnimation) {
+                mPolicyVisibilityAfterAnim = false;
+            } else {
+                mPolicyVisibilityAfterAnim = false;
+                mPolicyVisibility = false;
+            }
+            if (requestAnim) {
+                requestAnimationLocked(0);
+            }
+            return true;
         }
 
         void dump(PrintWriter pw, String prefix) {
@@ -8703,28 +8837,37 @@
     final void rebuildAppWindowListLocked() {
         int NW = mWindows.size();
         int i;
+        int lastWallpaper = -1;
         int numRemoved = 0;
         
         // First remove all existing app windows.
         i=0;
         while (i < NW) {
-            if (((WindowState)mWindows.get(i)).mAppToken != null) {
+            WindowState w = (WindowState)mWindows.get(i);
+            if (w.mAppToken != null) {
                 WindowState win = (WindowState)mWindows.remove(i);
                 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG,
                         "Rebuild removing window: " + win);
                 NW--;
                 numRemoved++;
                 continue;
+            } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER
+                    && lastWallpaper == i-1) {
+                lastWallpaper = i;
             }
             i++;
         }
         
+        // The wallpaper window(s) typically live at the bottom of the stack,
+        // so skip them before adding app tokens.
+        lastWallpaper++;
+        i = lastWallpaper;
+        
         // First add all of the exiting app tokens...  these are no longer
         // in the main app list, but still have windows shown.  We put them
         // in the back because now that the animation is over we no longer
         // will care about them.
         int NT = mExitingAppTokens.size();
-        i = 0;
         for (int j=0; j<NT; j++) {
             i = reAddAppWindowsLocked(i, mExitingAppTokens.get(j));
         }
@@ -8735,6 +8878,7 @@
             i = reAddAppWindowsLocked(i, mAppTokens.get(j));
         }
         
+        i -= lastWallpaper;
         if (i != numRemoved) {
             Log.w(TAG, "Rebuild removed " + numRemoved
                     + " windows but added " + i);
@@ -8970,6 +9114,7 @@
         Surface.openTransaction();
         try {
             boolean restart;
+            boolean forceHiding = false;
 
             do {
                 final int transactionSequence = ++mTransactionSequence;
@@ -8995,6 +9140,8 @@
 
                 boolean tokenMayBeDrawn = false;
                 boolean wallpaperMayChange = false;
+                boolean focusMayChange = false;
+                boolean wallpaperForceHidingChanged = false;
 
                 mPolicy.beginAnimationLw(dw, dh);
 
@@ -9015,6 +9162,7 @@
                                 wallpaperMayChange = true;
                             }
                         }
+                        
                         boolean wasAnimating = w.mAnimating;
                         if (w.stepAnimationLocked(currentTime, dw, dh)) {
                             animating = true;
@@ -9023,6 +9171,38 @@
                         if (wasAnimating && !w.mAnimating && mWallpaperTarget == w) {
                             wallpaperMayChange = true;
                         }
+                        
+                        if (mPolicy.doesForceHide(w, attrs)) {
+                            if (!wasAnimating && animating) {
+                                wallpaperForceHidingChanged = true;
+                                focusMayChange = true;
+                            } else if (w.isReadyForDisplay() && w.mAnimation == null) {
+                                forceHiding = true;
+                            }
+                        } else if (mPolicy.canBeForceHidden(w, attrs)) {
+                            boolean changed;
+                            if (forceHiding) {
+                                changed = w.hideLw(false, false);
+                            } else {
+                                changed = w.showLw(false, false);
+                                if (changed && wallpaperForceHidingChanged
+                                        && w.isReadyForDisplay()) {
+                                    // Assume we will need to animate.  If
+                                    // we don't (because the wallpaper will
+                                    // stay with the lock screen), then we will
+                                    // clean up later.
+                                    Animation a = mPolicy.createForceHideEnterAnimation();
+                                    if (a != null) {
+                                        w.setAnimation(a);
+                                    }
+                                }
+                            }
+                            if (changed && (attrs.flags
+                                    & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
+                                wallpaperMayChange = true;
+                            }
+                        }
+                        
                         mPolicy.animatingWindowLw(w, attrs);
                     }
 
@@ -9147,6 +9327,7 @@
                             transit = WindowManagerPolicy.TRANSIT_UNSET;
                         }
                         mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
+                        mNextAppTransitionPackage = null;
                         mAppTransitionReady = false;
                         mAppTransitionRunning = true;
                         mAppTransitionTimeout = false;
@@ -9180,6 +9361,7 @@
                         // The top-most window will supply the layout params,
                         // and we will determine it below.
                         LayoutParams animLp = null;
+                        AppWindowToken animToken = null;
                         int bestAnimLayer = -1;
                         
                         if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
@@ -9222,9 +9404,11 @@
                                     // window, we will always use its anim.
                                     if ((ws.mAttrs.flags&FLAG_COMPATIBLE_WINDOW) != 0) {
                                         animLp = ws.mAttrs;
+                                        animToken = ws.mAppToken;
                                         bestAnimLayer = Integer.MAX_VALUE;
                                     } else if (ws.mLayer > bestAnimLayer) {
                                         animLp = ws.mAttrs;
+                                        animToken = ws.mAppToken;
                                         bestAnimLayer = ws.mLayer;
                                     }
                                 }
@@ -9262,6 +9446,15 @@
                                     "New transit into wallpaper: " + transit);
                         }
                         
+                        if ((transit&WindowManagerPolicy.TRANSIT_ENTER_MASK) != 0) {
+                            mLastEnterAnimToken = animToken;
+                            mLastEnterAnimParams = animLp;
+                        } else if (mLastEnterAnimParams != null) {
+                            animLp = mLastEnterAnimParams;
+                            mLastEnterAnimToken = null;
+                            mLastEnterAnimParams = null;
+                        }
+                        
                         NN = mOpeningApps.size();
                         for (i=0; i<NN; i++) {
                             AppWindowToken wtoken = mOpeningApps.get(i);
@@ -9302,6 +9495,7 @@
                         }
                         performLayoutLockedInner();
                         updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES);
+                        focusMayChange = false;
 
                         restart = true;
                     }
@@ -9325,26 +9519,71 @@
                     mLayoutNeeded = true;
                 }
                 
+                int adjResult = 0;
+                
+                if (wallpaperForceHidingChanged) {
+                    // At this point, there was a window with a wallpaper that
+                    // was force hiding other windows behind it, but now it
+                    // is going away.  This may be simple -- just animate
+                    // away the wallpaper and its window -- or it may be
+                    // hard -- the wallpaper now needs to be shown behind
+                    // something that was hidden.
+                    WindowState oldWallpaper = mWallpaperTarget;
+                    adjResult = adjustWallpaperWindowsLocked();
+                    wallpaperMayChange = false;
+                    if (false) Log.v(TAG, "****** OLD: " + oldWallpaper
+                            + " NEW: " + mWallpaperTarget);
+                    if (mLowerWallpaperTarget == null) {
+                        // Whoops, we don't need a special wallpaper animation.
+                        // Clear them out.
+                        forceHiding = false;
+                        for (i=N-1; i>=0; i--) {
+                            WindowState w = (WindowState)mWindows.get(i);
+                            if (w.mSurface != null) {
+                                final WindowManager.LayoutParams attrs = w.mAttrs;
+                                if (mPolicy.doesForceHide(w, attrs)) {
+                                    forceHiding = true;
+                                } else if (mPolicy.canBeForceHidden(w, attrs)) {
+                                    if (!w.mAnimating) {
+                                        // We set the animation above so it
+                                        // is not yet running.
+                                        w.clearAnimation();
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                
                 if (wallpaperMayChange) {
                     if (DEBUG_WALLPAPER) Log.v(TAG,
                             "Wallpaper may change!  Adjusting");
-                    int adjResult = adjustWallpaperWindowsLocked();
-                    if ((adjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
-                        if (DEBUG_WALLPAPER) Log.v(TAG,
-                                "Wallpaper layer changed: assigning layers + relayout");
+                    adjResult = adjustWallpaperWindowsLocked();
+                }
+                
+                if ((adjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
+                    if (DEBUG_WALLPAPER) Log.v(TAG,
+                            "Wallpaper layer changed: assigning layers + relayout");
+                    restart = true;
+                    mLayoutNeeded = true;
+                    assignLayersLocked();
+                } else if ((adjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) {
+                    if (DEBUG_WALLPAPER) Log.v(TAG,
+                            "Wallpaper visibility changed: relayout");
+                    restart = true;
+                    mLayoutNeeded = true;
+                }
+                
+                if (focusMayChange) {
+                    if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES)) {
                         restart = true;
-                        mLayoutNeeded = true;
-                        assignLayersLocked();
-                    } else if ((adjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) {
-                        if (DEBUG_WALLPAPER) Log.v(TAG,
-                                "Wallpaper visibility changed: relayout");
-                        restart = true;
-                        mLayoutNeeded = true;
+                        adjResult = 0;
                     }
-                    if (mLayoutNeeded) {
-                        restart = true;
-                        performLayoutLockedInner();
-                    }
+                }
+
+                if (mLayoutNeeded) {
+                    restart = true;
+                    performLayoutLockedInner();
                 }
                 
             } while (restart);
@@ -9359,7 +9598,6 @@
             boolean covered = false;
             boolean syswin = false;
             boolean backgroundFillerShown = false;
-            boolean forceHiding = false;
 
             final int N = mWindows.size();
             
@@ -9492,15 +9730,12 @@
                         }
                     }
 
-                    if ((forceHiding
-                            && attrs.type != WindowManager.LayoutParams.TYPE_STATUS_BAR
-                            && attrs.type != WindowManager.LayoutParams.TYPE_WALLPAPER)
-                            || w.mAttachedHidden) {
+                    if (w.mAttachedHidden || !w.isReadyForDisplay()) {
                         if (!w.mLastHidden) {
                             //dump();
                             w.mLastHidden = true;
                             if (SHOW_TRANSACTIONS) Log.i(
-                                    TAG, "  SURFACE " + w.mSurface + ": HIDE (performLayout-attached)");
+                                    TAG, "  SURFACE " + w.mSurface + ": HIDE (performLayout)");
                             if (w.mSurface != null) {
                                 try {
                                     w.mSurface.hide();
@@ -9521,32 +9756,6 @@
                             if (DEBUG_ORIENTATION) Log.v(TAG,
                                     "Orientation change skips hidden " + w);
                         }
-                    } else if (!w.isReadyForDisplay()) {
-                        if (!w.mLastHidden) {
-                            //dump();
-                            w.mLastHidden = true;
-                            if (SHOW_TRANSACTIONS) Log.i(
-                                    TAG, "  SURFACE " + w.mSurface + ": HIDE (performLayout-ready)");
-                            if (w.mSurface != null) {
-                                try {
-                                    w.mSurface.hide();
-                                } catch (RuntimeException e) {
-                                    Log.w(TAG, "Exception exception hiding surface in " + w);
-                                }
-                            }
-                            mKeyWaiter.releasePendingPointerLocked(w.mSession);
-                        }
-                        // If we are waiting for this window to handle an
-                        // orientation change, well, it is hidden, so
-                        // doesn't really matter.  Note that this does
-                        // introduce a potential glitch if the window
-                        // becomes unhidden before it has drawn for the
-                        // new orientation.
-                        if (w.mOrientationChanging) {
-                            w.mOrientationChanging = false;
-                            if (DEBUG_ORIENTATION) Log.v(TAG,
-                                    "Orientation change skips hidden " + w);
-                        }
                     } else if (w.mLastLayer != w.mAnimLayer
                             || w.mLastAlpha != w.mShownAlpha
                             || w.mLastDsDx != w.mDsDx
@@ -9609,9 +9818,6 @@
                     }
 
                     if (displayed) {
-                        if (attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD) {
-                            forceHiding = true;
-                        }
                         if (!covered) {
                             if (attrs.width == LayoutParams.FILL_PARENT
                                     && attrs.height == LayoutParams.FILL_PARENT) {
@@ -9694,7 +9900,7 @@
                         }
                         backgroundFillerShown = true;
                         mBackgroundFillerShown = true;
-                    } else if (canBeSeen && !obscured && !forceHiding &&
+                    } else if (canBeSeen && !obscured &&
                             (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) {
                         if (localLOGV) Log.v(TAG, "Win " + w
                                 + ": blurring=" + blurring
@@ -9860,6 +10066,10 @@
                 token.animating = false;
                 mAppTokens.remove(token);
                 mExitingAppTokens.remove(i);
+                if (mLastEnterAnimToken == token) {
+                    mLastEnterAnimToken = null;
+                    mLastEnterAnimParams = null;
+                }
             }
         }
 
@@ -10169,6 +10379,7 @@
         mDisplayFrozen = true;
         if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
             mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
+            mNextAppTransitionPackage = null;
             mAppTransitionReady = true;
         }
 
@@ -10403,8 +10614,20 @@
                     pw.print(", mAppTransitionReady="); pw.print(mAppTransitionReady);
                     pw.print(", mAppTransitionRunning="); pw.print(mAppTransitionRunning);
                     pw.print(", mAppTransitionTimeout="); pw.println( mAppTransitionTimeout);
+            if (mNextAppTransitionPackage != null) {
+                pw.print("  mNextAppTransitionPackage=");
+                    pw.print(mNextAppTransitionPackage);
+                    pw.print(", mNextAppTransitionEnter=0x");
+                    pw.print(Integer.toHexString(mNextAppTransitionEnter));
+                    pw.print(", mNextAppTransitionExit=0x");
+                    pw.print(Integer.toHexString(mNextAppTransitionExit));
+            }
             pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
                     pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
+            if (mLastEnterAnimToken != null || mLastEnterAnimToken != null) {
+                pw.print("  mLastEnterAnimToken="); pw.print(mLastEnterAnimToken);
+                        pw.print(", mLastEnterAnimParams="); pw.println(mLastEnterAnimParams);
+            }
             if (mOpeningApps.size() > 0) {
                 pw.print("  mOpeningApps="); pw.println(mOpeningApps);
             }
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index e953b81..d917d17 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2722,6 +2722,8 @@
                     // Do over!
                     mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
                 }
+                setFocusedActivityLocked(next);
+                ensureActivitiesVisibleLocked(null, 0);
                 mWindowManager.executeAppTransition();
                 mNoAnimActivities.clear();
                 return true;
@@ -4196,6 +4198,27 @@
         }
     }
 
+    public void overridePendingTransition(IBinder token, String packageName,
+            int enterAnim, int exitAnim) {
+        synchronized(this) {
+            int index = indexOfTokenLocked(token);
+            if (index < 0) {
+                return;
+            }
+            HistoryRecord self = (HistoryRecord)mHistory.get(index);
+
+            final long origId = Binder.clearCallingIdentity();
+            
+            if (self.state == ActivityState.RESUMED
+                    || self.state == ActivityState.PAUSING) {
+                mWindowManager.overridePendingAppTransition(packageName,
+                        enterAnim, exitAnim);
+            }
+            
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+    
     /**
      * Perform clean-up of service connections in an activity record.
      */