Merge "Cannot pan in browser if magnification is enabled." into jb-mr1-dev
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index 201d7b2..86fd7b9 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -312,7 +312,8 @@
         }
         public Editor putStringSet(String key, Set<String> values) {
             synchronized (this) {
-                mModified.put(key, values);
+                mModified.put(key,
+                        (values == null) ? null : new HashSet<String>(values));
                 return this;
             }
         }
diff --git a/core/java/android/content/SharedPreferences.java b/core/java/android/content/SharedPreferences.java
index bdc38d6..da5480e 100644
--- a/core/java/android/content/SharedPreferences.java
+++ b/core/java/android/content/SharedPreferences.java
@@ -25,7 +25,8 @@
  * there is a single instance of this class that all clients share.
  * Modifications to the preferences must go through an {@link Editor} object
  * to ensure the preference values remain in a consistent state and control
- * when they are committed to storage.
+ * when they are committed to storage.  Objects that are returned from the
+ * various <code>get</code> methods must be treated as immutable by the application.
  *
  * <p><em>Note: currently this class does not support use across multiple
  * processes.  This will be added later.</em>
@@ -226,6 +227,10 @@
     /**
      * Retrieve all values from the preferences.
      *
+     * <p>Note that you <em>must not</em> modify the collection returned
+     * by this method, or alter any of its contents.  The consistency of your
+     * stored data is not guaranteed if you do.
+     *
      * @return Returns a map containing a list of pairs key/value representing
      * the preferences.
      *
@@ -250,6 +255,10 @@
     /**
      * Retrieve a set of String values from the preferences.
      * 
+     * <p>Note that you <em>must not</em> modify the set instance returned
+     * by this call.  The consistency of the stored data is not guaranteed
+     * if you do, nor is your ability to modify the instance at all.
+     *
      * @param key The name of the preference to retrieve.
      * @param defValues Values to return if this preference does not exist.
      * 
diff --git a/core/java/android/service/dreams/Sandman.java b/core/java/android/service/dreams/Sandman.java
index 70142ce..5f5b079 100644
--- a/core/java/android/service/dreams/Sandman.java
+++ b/core/java/android/service/dreams/Sandman.java
@@ -36,9 +36,6 @@
 public final class Sandman {
     private static final String TAG = "Sandman";
 
-    private static final int DEFAULT_SCREENSAVER_ENABLED = 1;
-    private static final int DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK = 1;
-
     // The component name of a special dock app that merely launches a dream.
     // We don't want to launch this app when docked because it causes an unnecessary
     // activity transition.  We just want to start the dream.
@@ -109,14 +106,18 @@
     }
 
     private static boolean isScreenSaverEnabled(Context context) {
+        int def = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_dreamsEnabledByDefault) ? 1 : 0;
         return Settings.Secure.getIntForUser(context.getContentResolver(),
-                Settings.Secure.SCREENSAVER_ENABLED, DEFAULT_SCREENSAVER_ENABLED,
+                Settings.Secure.SCREENSAVER_ENABLED, def,
                 UserHandle.USER_CURRENT) != 0;
     }
 
     private static boolean isScreenSaverActivatedOnDock(Context context) {
+        int def = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault) ? 1 : 0;
         return Settings.Secure.getIntForUser(context.getContentResolver(),
-                Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
-                DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK, UserHandle.USER_CURRENT) != 0;
+                Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, def,
+                UserHandle.USER_CURRENT) != 0;
     }
 }
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index ec1695e..59f941d 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -1200,7 +1200,12 @@
                             Trace.traceEnd(Trace.TRACE_TAG_VIEW);
                         }
 
-                        status = onPreDraw(dirty);
+                        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "prepareFrame");
+                        try {
+                            status = onPreDraw(dirty);
+                        } finally {
+                            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+                        }
                         saveCount = canvas.save();
                         callbacks.onHardwarePreDraw(canvas);
 
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 67452ec..8a82a54 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -317,6 +317,8 @@
     private final int mDensity;
     private final int mNoncompatDensity;
 
+    private int mViewLayoutDirectionInitial;
+
     /**
      * Consistency verifier for debugging purposes.
      */
@@ -465,6 +467,7 @@
         synchronized (this) {
             if (mView == null) {
                 mView = view;
+                mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
                 mFallbackEventHandler.setView(view);
                 mWindowAttributes.copyFrom(attrs);
                 attrs = mWindowAttributes;
@@ -1186,7 +1189,10 @@
             viewVisibilityChanged = false;
             mLastConfiguration.setTo(host.getResources().getConfiguration());
             mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
-            host.setLayoutDirection(mLastConfiguration.getLayoutDirection());
+            // Set the layout direction if it has not been set before (inherit is the default)
+            if (mViewLayoutDirectionInitial == View.LAYOUT_DIRECTION_INHERIT) {
+                host.setLayoutDirection(mLastConfiguration.getLayoutDirection());
+            }
             host.dispatchAttachedToWindow(attachInfo, 0);
             mFitSystemWindowsInsets.set(mAttachInfo.mContentInsets);
             host.fitSystemWindows(mFitSystemWindowsInsets);
@@ -2682,7 +2688,8 @@
                 final int lastLayoutDirection = mLastConfiguration.getLayoutDirection();
                 final int currentLayoutDirection = config.getLayoutDirection();
                 mLastConfiguration.setTo(config);
-                if (lastLayoutDirection != currentLayoutDirection) {
+                if (lastLayoutDirection != currentLayoutDirection &&
+                        mViewLayoutDirectionInitial == View.LAYOUT_DIRECTION_INHERIT) {
                     mView.setLayoutDirection(currentLayoutDirection);
                 }
                 mView.dispatchConfigurationChanged(config);
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 7855763c..5cdc1ed 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -99,6 +99,7 @@
     public static final int ADD_STARTING_NOT_NEEDED = -6;
     public static final int ADD_MULTIPLE_SINGLETON = -7;
     public static final int ADD_PERMISSION_DENIED = -8;
+    public static final int ADD_INVALID_DISPLAY = -9;
 
     private static WindowManagerGlobal sDefaultWindowManager;
     private static IWindowManager sWindowManagerService;
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index af3365e..b71649a 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -142,6 +142,8 @@
         };
     private int mAnchorXoff, mAnchorYoff;
 
+    private boolean mPopupViewInitialLayoutDirectionInherited;
+
     /**
      * <p>Create a new empty, non focusable popup window of dimension (0,0).</p>
      *
@@ -968,6 +970,8 @@
         } else {
             mPopupView = mContentView;
         }
+        mPopupViewInitialLayoutDirectionInherited =
+                (mPopupView.getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT);
         mPopupWidth = p.width;
         mPopupHeight = p.height;
     }
@@ -985,9 +989,19 @@
             p.packageName = mContext.getPackageName();
         }
         mPopupView.setFitsSystemWindows(mLayoutInsetDecor);
+        setLayoutDirectionFromAnchor();
         mWindowManager.addView(mPopupView, p);
     }
 
+    private void setLayoutDirectionFromAnchor() {
+        if (mAnchor != null) {
+            View anchor = mAnchor.get();
+            if (anchor != null && mPopupViewInitialLayoutDirectionInherited) {
+                mPopupView.setLayoutDirection(anchor.getLayoutDirection());
+            }
+        }
+    }
+
     /**
      * <p>Generate the layout parameters for the popup window.</p>
      *
@@ -1304,8 +1318,9 @@
             p.flags = newFlags;
             update = true;
         }
-        
+
         if (update) {
+            setLayoutDirectionFromAnchor();
             mWindowManager.updateViewLayout(mPopupView, p);
         }
     }
@@ -1406,6 +1421,7 @@
         }
 
         if (update) {
+            setLayoutDirectionFromAnchor();
             mWindowManager.updateViewLayout(mPopupView, p);
         }
     }
@@ -1482,7 +1498,7 @@
         } else {
             updateAboveAnchor(findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff));            
         }
-        
+
         update(p.x, p.y, width, height, x != p.x || y != p.y);
     }
 
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
index 7287327..c9b7cb3 100644
--- a/core/java/com/android/internal/net/VpnProfile.java
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -70,6 +70,47 @@
         this.key = key;
     }
 
+    public VpnProfile(Parcel in) {
+        key = in.readString();
+        name = in.readString();
+        type = in.readInt();
+        server = in.readString();
+        username = in.readString();
+        password = in.readString();
+        dnsServers = in.readString();
+        searchDomains = in.readString();
+        routes = in.readString();
+        mppe = in.readInt() != 0;
+        l2tpSecret = in.readString();
+        ipsecIdentifier = in.readString();
+        ipsecSecret = in.readString();
+        ipsecUserCert = in.readString();
+        ipsecCaCert = in.readString();
+        ipsecServerCert = in.readString();
+        saveLogin = in.readInt() != 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(key);
+        out.writeString(name);
+        out.writeInt(type);
+        out.writeString(server);
+        out.writeString(username);
+        out.writeString(password);
+        out.writeString(dnsServers);
+        out.writeString(searchDomains);
+        out.writeString(routes);
+        out.writeInt(mppe ? 1 : 0);
+        out.writeString(l2tpSecret);
+        out.writeString(ipsecIdentifier);
+        out.writeString(ipsecSecret);
+        out.writeString(ipsecUserCert);
+        out.writeString(ipsecCaCert);
+        out.writeString(ipsecServerCert);
+        out.writeInt(saveLogin ? 1 : 0);
+    }
+
     public static VpnProfile decode(String key, byte[] value) {
         try {
             if (key == null) {
@@ -155,17 +196,10 @@
         }
     }
 
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeString(key);
-        out.writeByteArray(encode());
-    }
-
     public static final Creator<VpnProfile> CREATOR = new Creator<VpnProfile>() {
         @Override
         public VpnProfile createFromParcel(Parcel in) {
-            final String key = in.readString();
-            return decode(key, in.createByteArray());
+            return new VpnProfile(in);
         }
 
         @Override
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index afd847f..0890a18 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -895,8 +895,16 @@
     <!-- Name of the wimax state tracker clas -->
     <string name="config_wimaxStateTrackerClassname" translatable="false"></string>
 
-    <!-- enable screen saver feature -->
-    <bool name="config_enableDreams">true</bool>
+    <!-- Is the dreams feature supported? -->
+    <bool name="config_dreamsSupported">true</bool>
+    <!-- If supported, are dreams enabled? (by default) -->
+    <bool name="config_dreamsEnabledByDefault">true</bool>
+    <!-- If supported and enabled, are dreams activated when docked? (by default) -->
+    <bool name="config_dreamsActivatedOnDockByDefault">true</bool>
+    <!-- If supported and enabled, are dreams activated when asleep and charging? (by default) -->
+    <bool name="config_dreamsActivatedOnSleepByDefault">false</bool>
+    <!-- ComponentName of the default dream (Settings.Secure.SCREENSAVER_COMPONENT) -->
+    <string name="config_dreamsDefaultComponent">com.google.android.deskclock/com.android.deskclock.Screensaver</string>
 
     <!-- Base "touch slop" value used by ViewConfiguration as a
          movement threshold where scrolling should begin. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7c0547e..8ef91df 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1627,7 +1627,11 @@
   <java-symbol type="style" name="Theme.Dialog.AppError" />
   <java-symbol type="style" name="Theme.Toast" />
   <java-symbol type="xml" name="storage_list" />
-  <java-symbol type="bool" name="config_enableDreams" />
+  <java-symbol type="bool" name="config_dreamsSupported" />
+  <java-symbol type="bool" name="config_dreamsEnabledByDefault" />
+  <java-symbol type="bool" name="config_dreamsActivatedOnDockByDefault" />
+  <java-symbol type="bool" name="config_dreamsActivatedOnSleepByDefault" />
+  <java-symbol type="string" name="config_dreamsDefaultComponent" />
   <java-symbol type="string" name="enable_explore_by_touch_warning_title" />
   <java-symbol type="string" name="enable_explore_by_touch_warning_message" />
 
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 589d5c2..81e68bd 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -1434,7 +1434,7 @@
     mHeight = height;
 }
 
-int DisplayListRenderer::prepareDirty(float left, float top,
+status_t DisplayListRenderer::prepareDirty(float left, float top,
         float right, float bottom, bool opaque) {
     mSnapshot = new Snapshot(mFirstSnapshot,
             SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 2610055..e42def5 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -550,7 +550,7 @@
     virtual bool isDeferred();
 
     virtual void setViewport(int width, int height);
-    virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque);
+    virtual status_t prepareDirty(float left, float top, float right, float bottom, bool opaque);
     virtual void finish();
 
     virtual status_t callDrawGLFunction(Functor *functor, Rect& dirty);
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 882e4bb..1cdc063 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -31,6 +31,7 @@
     meshIndices = NULL;
     meshElementCount = 0;
     cacheable = true;
+    dirty = false;
     textureLayer = false;
     renderTarget = GL_TEXTURE_2D;
     texture.width = layerWidth;
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 448e3da..e1f6a70 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -162,6 +162,14 @@
         this->cacheable = cacheable;
     }
 
+    inline bool isDirty() {
+        return dirty;
+    }
+
+    inline void setDirty(bool dirty) {
+        this->dirty = dirty;
+    }
+
     inline bool isTextureLayer() {
         return textureLayer;
     }
@@ -287,6 +295,12 @@
     bool textureLayer;
 
     /**
+     * When set to true, this layer is dirty and should be cleared
+     * before any rendering occurs.
+     */
+    bool dirty;
+
+    /**
      * Indicates the render target.
      */
     GLenum renderTarget;
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index f2e7f66..3484d41 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -18,6 +18,8 @@
 
 #include <ui/Rect.h>
 
+#include <private/hwui/DrawGlInfo.h>
+
 #include "LayerCache.h"
 #include "LayerRenderer.h"
 #include "Matrix.h"
@@ -41,7 +43,8 @@
     initViewport(width, height);
 }
 
-int LayerRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) {
+status_t LayerRenderer::prepareDirty(float left, float top, float right, float bottom,
+        bool opaque) {
     LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->getFbo());
 
     glBindFramebuffer(GL_FRAMEBUFFER, mLayer->getFbo());
@@ -63,6 +66,20 @@
     return OpenGLRenderer::prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, opaque);
 }
 
+status_t LayerRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
+    if (mLayer->isDirty()) {
+        getCaches().disableScissor();
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        getCaches().resetScissor();
+        mLayer->setDirty(false);
+
+        return DrawGlInfo::kStatusDone;
+    }
+
+    return OpenGLRenderer::clear(left, top, right, bottom, opaque);
+}
+
 void LayerRenderer::finish() {
     OpenGLRenderer::finish();
 
@@ -201,6 +218,7 @@
     layer->setAlpha(255, SkXfermode::kSrcOver_Mode);
     layer->setBlend(!isOpaque);
     layer->setColorFilter(NULL);
+    layer->setDirty(true);
     layer->region.clear();
 
     GLuint previousFbo;
@@ -229,9 +247,6 @@
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
             layer->getTexture(), 0);
 
-    caches.disableScissor();
-    glClear(GL_COLOR_BUFFER_BIT);
-
     glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
 
     return layer;
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index acedbcc..c44abce 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -48,7 +48,8 @@
     virtual ~LayerRenderer();
 
     virtual void setViewport(int width, int height);
-    virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque);
+    virtual status_t prepareDirty(float left, float top, float right, float bottom, bool opaque);
+    virtual status_t clear(float left, float top, float right, float bottom, bool opaque);
     virtual void finish();
 
     ANDROID_API static Layer* createTextureLayer(bool isOpaque);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index b6be5b3..914516c 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -165,11 +165,12 @@
     mFirstSnapshot->viewport.set(0, 0, width, height);
 }
 
-int OpenGLRenderer::prepare(bool opaque) {
+status_t OpenGLRenderer::prepare(bool opaque) {
     return prepareDirty(0.0f, 0.0f, mWidth, mHeight, opaque);
 }
 
-int OpenGLRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) {
+status_t OpenGLRenderer::prepareDirty(float left, float top, float right, float bottom,
+        bool opaque) {
     mCaches.clearGarbage();
 
     mSnapshot = new Snapshot(mFirstSnapshot,
@@ -203,15 +204,18 @@
 
     debugOverdraw(true, true);
 
+    return clear(left, top, right, bottom, opaque);
+}
+
+status_t OpenGLRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
     if (!opaque) {
         mCaches.enableScissor();
         mCaches.setScissor(left, mSnapshot->height - bottom, right - left, bottom - top);
         glClear(GL_COLOR_BUFFER_BIT);
         return DrawGlInfo::kStatusDrew;
-    } else {
-        mCaches.resetScissor();
     }
 
+    mCaches.resetScissor();
     return DrawGlInfo::kStatusDone;
 }
 
@@ -743,6 +747,7 @@
             bounds.getWidth() / float(layer->getWidth()), 0.0f);
     layer->setColorFilter(mColorFilter);
     layer->setBlend(true);
+    layer->setDirty(false);
 
     // Save the layer in the snapshot
     mSnapshot->flags |= Snapshot::kFlagIsLayer;
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index a40d69a..c5e4c8e 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -94,7 +94,7 @@
      *               and will not be cleared. If false, the target surface
      *               will be cleared
      */
-    ANDROID_API int prepare(bool opaque);
+    ANDROID_API status_t prepare(bool opaque);
 
     /**
      * Prepares the renderer to draw a frame. This method must be invoked
@@ -110,7 +110,7 @@
      *               and will not be cleared. If false, the target surface
      *               will be cleared in the specified dirty rectangle
      */
-    virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque);
+    virtual status_t prepareDirty(float left, float top, float right, float bottom, bool opaque);
 
     /**
      * Indicates the end of a frame. This method must be invoked whenever
@@ -270,6 +270,11 @@
     void initViewport(int width, int height);
 
     /**
+     * Clears the underlying surface if needed.
+     */
+    virtual status_t clear(float left, float top, float right, float bottom, bool opaque);
+
+    /**
      * Call this method after updating a layer during a drawing pass.
      */
     void resumeAfterLayer();
@@ -355,6 +360,10 @@
         return false;
     }
 
+    Caches& getCaches() {
+        return mCaches;
+    }
+
 private:
     /**
      * Ensures the state of the renderer is the same as the state of
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 9e137ce..94e2286 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -165,16 +165,6 @@
          Value here is the same as WifiStateMachine.DEFAULT_MAX_DHCP_RETRIES -->
     <integer name="def_max_dhcp_retries">9</integer>
 
-    <!-- Dreams (screen saver) default settings -->
-    <!-- Whether the feature is enabled when charging (Settings.Secure.SCREENSAVER_ENABLED) -->
-    <bool name="def_screensaver_enabled">true</bool>
-    <!-- Whether the feature activates when docked (SCREENSAVER_ACTIVATE_ON_DOCK) -->
-    <bool name="def_screensaver_activate_on_dock">true</bool>
-    <!-- Whether the feature activates when docked (SCREENSAVER_ACTIVATE_ON_SLEEP) -->
-    <bool name="def_screensaver_activate_on_sleep">false</bool>
-    <!-- ComponentName of the default screen saver (Settings.Secure.SCREENSAVER_COMPONENT) -->
-    <string name="def_screensaver_component">com.google.android.deskclock/com.android.deskclock.Screensaver</string>
-
     <!-- Default for Settings.Secure.USER_SETUP_COMPLETE -->
     <bool name="def_user_setup_complete">false</bool>
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 0689268..b649b43 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -1166,15 +1166,15 @@
                 stmt = db.compileStatement("INSERT OR REPLACE INTO secure(name,value)"
                         + " VALUES(?,?);");
                 loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ENABLED,
-                        R.bool.def_screensaver_enabled);
+                        com.android.internal.R.bool.config_dreamsEnabledByDefault);
                 loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
-                        R.bool.def_screensaver_activate_on_dock);
+                        com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);
                 loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
-                        R.bool.def_screensaver_activate_on_sleep);
-                loadStringSetting(stmt, Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
-                        R.string.def_screensaver_component);
+                        com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault);
                 loadStringSetting(stmt, Settings.Secure.SCREENSAVER_COMPONENTS,
-                        R.string.def_screensaver_component);
+                        com.android.internal.R.string.config_dreamsDefaultComponent);
+                loadStringSetting(stmt, Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
+                        com.android.internal.R.string.config_dreamsDefaultComponent);
 
                 db.setTransactionSuccessful();
             } finally {
@@ -2027,15 +2027,15 @@
             }
 
             loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ENABLED,
-                    R.bool.def_screensaver_enabled);
+                    com.android.internal.R.bool.config_dreamsEnabledByDefault);
             loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
-                    R.bool.def_screensaver_activate_on_dock);
+                    com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);
             loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
-                    R.bool.def_screensaver_activate_on_sleep);
+                    com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault);
             loadStringSetting(stmt, Settings.Secure.SCREENSAVER_COMPONENTS,
-                    R.string.def_screensaver_component);
+                    com.android.internal.R.string.config_dreamsDefaultComponent);
             loadStringSetting(stmt, Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
-                    R.string.def_screensaver_component);
+                    com.android.internal.R.string.config_dreamsDefaultComponent);
 
             loadBooleanSetting(stmt, Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
                     R.bool.def_accessibility_display_magnification_enabled);
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index f0e5a87..cfe70dc 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -63,7 +63,6 @@
     <uses-permission android:name="android.permission.WRITE_DREAM_STATE" />
 
     <application
-        android:name="com.android.systemui.SystemUIApplication"
         android:persistent="true"
         android:allowClearUserData="false"
         android:allowBackup="false"
@@ -109,7 +108,7 @@
 
         <activity android:name=".recent.RecentsActivity"
                 android:label="@string/accessibility_desc_recent_apps"
-                android:theme="@android:style/Theme.Holo.Wallpaper.NoTitleBar"
+                android:theme="@style/RecentsStyle"
                 android:excludeFromRecents="true"
                 android:launchMode="singleInstance"
                 android:exported="true">
@@ -118,6 +117,15 @@
           </intent-filter>
         </activity>
 
+        <receiver
+            android:name=".recent.RecentsPreloadReceiver"
+            android:exported="false">
+            <intent-filter>
+                <action android:name="com.android.systemui.recent.action.PRELOAD" />
+                <action android:name="com.android.systemui.recent.action.CANCEL_PRELOAD" />
+            </intent-filter>
+        </receiver>
+
         <!-- started from UsbDeviceSettingsManager -->
         <activity android:name=".usb.UsbConfirmActivity"
             android:exported="true"
diff --git a/packages/SystemUI/res/anim/recents_launch_from_launcher_enter.xml b/packages/SystemUI/res/anim/recents_launch_from_launcher_enter.xml
index 73ae9f2..1135bc0 100644
--- a/packages/SystemUI/res/anim/recents_launch_from_launcher_enter.xml
+++ b/packages/SystemUI/res/anim/recents_launch_from_launcher_enter.xml
@@ -18,7 +18,6 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-     android:detachWallpaper="true"
      android:shareInterpolator="false"
      android:zAdjustment="normal">
   <!--scale android:fromXScale="2.0" android:toXScale="1.0"
@@ -28,9 +27,4 @@
          android:fillBefore="true" android:fillAfter="true"
          android:pivotX="50%p" android:pivotY="50%p"
          android:duration="250" /-->
-  <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
-         android:fillEnabled="true"
-         android:fillBefore="true" android:fillAfter="true"
-         android:interpolator="@android:interpolator/decelerate_cubic"
-         android:duration="250"/>
 </set>
diff --git a/packages/SystemUI/res/anim/recents_launch_from_launcher_exit.xml b/packages/SystemUI/res/anim/recents_launch_from_launcher_exit.xml
index becc9d0..fa28cf4 100644
--- a/packages/SystemUI/res/anim/recents_launch_from_launcher_exit.xml
+++ b/packages/SystemUI/res/anim/recents_launch_from_launcher_exit.xml
@@ -19,7 +19,7 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
      android:shareInterpolator="false"
-     android:zAdjustment="normal">
+     android:zAdjustment="top">
   <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
          android:fillEnabled="true"
          android:fillBefore="true" android:fillAfter="true"
diff --git a/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_enter.xml b/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_enter.xml
new file mode 100644
index 0000000..121daae
--- /dev/null
+++ b/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_enter.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, 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:shareInterpolator="false"
+     android:zAdjustment="normal">
+  <!--scale android:fromXScale="2.0" android:toXScale="1.0"
+         android:fromYScale="2.0" android:toYScale="1.0"
+         android:interpolator="@android:interpolator/decelerate_cubic"
+         android:fillEnabled="true"
+         android:fillBefore="true" android:fillAfter="true"
+         android:pivotX="50%p" android:pivotY="50%p"
+         android:duration="250" /-->
+  <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+         android:fillEnabled="true"
+         android:fillBefore="true" android:fillAfter="true"
+         android:interpolator="@android:interpolator/decelerate_cubic"
+         android:duration="250"/>
+</set>
diff --git a/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_exit.xml b/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_exit.xml
new file mode 100644
index 0000000..fa28cf4
--- /dev/null
+++ b/packages/SystemUI/res/anim/wallpaper_recents_launch_from_launcher_exit.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, 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:shareInterpolator="false"
+     android:zAdjustment="top">
+  <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+         android:fillEnabled="true"
+         android:fillBefore="true" android:fillAfter="true"
+         android:interpolator="@android:interpolator/decelerate_cubic"
+         android:duration="250"/>
+</set>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 18c1c34..1a59d6c 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -16,6 +16,24 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
 
+    <style name="RecentsStyle" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar">
+        <item name="android:windowAnimationStyle">@style/Animation.RecentsActivity</item>
+    </style>
+
+    <!-- Animations for a non-full-screen window or activity. -->
+    <style name="Animation.RecentsActivity" parent="@android:style/Animation.Activity">
+        <item name="android:activityOpenEnterAnimation">@anim/recents_launch_from_launcher_enter</item>
+        <item name="android:activityOpenExitAnimation">@anim/recents_launch_from_launcher_exit</item>
+        <item name="android:taskOpenEnterAnimation">@anim/recents_launch_from_launcher_enter</item>
+        <item name="android:taskOpenExitAnimation">@anim/recents_launch_from_launcher_exit</item>
+        <item name="android:taskToFrontEnterAnimation">@anim/recents_launch_from_launcher_enter</item>
+        <item name="android:taskToFrontExitAnimation">@anim/recents_launch_from_launcher_exit</item>
+        <item name="android:wallpaperOpenEnterAnimation">@anim/recents_launch_from_launcher_enter</item>
+        <item name="android:wallpaperOpenExitAnimation">@anim/recents_launch_from_launcher_exit</item>
+        <item name="android:wallpaperIntraOpenEnterAnimation">@anim/wallpaper_recents_launch_from_launcher_enter</item>
+        <item name="android:wallpaperIntraOpenExitAnimation">@anim/wallpaper_recents_launch_from_launcher_exit</item>
+    </style>
+
     <style name="TextAppearance.StatusBar.IntruderAlert"
         parent="@*android:style/TextAppearance.StatusBar">
     </style>
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
deleted file mode 100644
index c120690..0000000
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-package com.android.systemui;
-
-import android.app.Application;
-
-import com.android.systemui.recent.RecentTasksLoader;
-import com.android.systemui.recent.RecentsActivity;
-
-public class SystemUIApplication extends Application {
-    private RecentTasksLoader mRecentTasksLoader;
-    private boolean mWaitingForWinAnimStart;
-    private RecentsActivity.WindowAnimationStartListener mWinAnimStartListener;
-
-    public RecentTasksLoader getRecentTasksLoader() {
-        if (mRecentTasksLoader == null) {
-            mRecentTasksLoader = new RecentTasksLoader(this);
-        }
-        return mRecentTasksLoader;
-    }
-
-    public void setWaitingForWinAnimStart(boolean waiting) {
-        mWaitingForWinAnimStart = waiting;
-    }
-
-    public void setWindowAnimationStartListener(
-            RecentsActivity.WindowAnimationStartListener startListener) {
-        mWinAnimStartListener = startListener;
-    }
-
-    public RecentsActivity.WindowAnimationStartListener getWindowAnimationListener() {
-        return mWinAnimStartListener;
-    }
-
-    public void onWindowAnimationStart() {
-        if (mWinAnimStartListener != null) {
-            mWinAnimStartListener.onWindowAnimationStart();
-        }
-        mWaitingForWinAnimStart = false;
-    }
-
-    public boolean isWaitingForWindowAnimationStart() {
-        return mWaitingForWinAnimStart;
-    }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
index 7260844..9d6765a 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
@@ -30,6 +30,7 @@
 import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.Process;
+import android.os.UserHandle;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
@@ -52,6 +53,8 @@
 
     private Context mContext;
     private RecentsPanelView mRecentsPanel;
+
+    private Object mFirstTaskLock = new Object();
     private TaskDescription mFirstTask;
     private boolean mFirstTaskLoaded;
 
@@ -70,23 +73,16 @@
     private enum State { LOADING, LOADED, CANCELLED };
     private State mState = State.CANCELLED;
 
-    public TaskDescription getFirstTask() {
-        while (!mFirstTaskLoaded) {
-            if (mState == State.CANCELLED) {
-                loadTasksInBackground();
-            }
-            try {
-                if (mState == State.LOADED) {
-                    break;
-                }
-                Thread.sleep(5);
-            } catch (InterruptedException e) {
-            }
+
+    private static RecentTasksLoader sInstance;
+    public static RecentTasksLoader getInstance(Context context) {
+        if (sInstance == null) {
+            sInstance = new RecentTasksLoader(context);
         }
-        return mFirstTask;
+        return sInstance;
     }
 
-    public RecentTasksLoader(Context context) {
+    private RecentTasksLoader(Context context) {
         mContext = context;
         mHandler = new Handler();
 
@@ -295,8 +291,6 @@
             mThumbnailLoader = null;
         }
         mLoadedTasks = null;
-        mFirstTask = null;
-        mFirstTaskLoaded = false;
         if (mRecentsPanel != null) {
             mRecentsPanel.onTaskLoadingCancelled();
         }
@@ -304,6 +298,100 @@
         mState = State.CANCELLED;
     }
 
+    private void clearFirstTask() {
+        synchronized (mFirstTaskLock) {
+            mFirstTask = null;
+            mFirstTaskLoaded = false;
+        }
+    }
+
+    public void preloadFirstTask() {
+        Thread bgLoad = new Thread() {
+            public void run() {
+                TaskDescription first = loadFirstTask();
+                synchronized(mFirstTaskLock) {
+                    if (mCancelPreloadingFirstTask) {
+                        clearFirstTask();
+                    } else {
+                        mFirstTask = first;
+                        mFirstTaskLoaded = true;
+                    }
+                    mPreloadingFirstTask = false;
+                }
+            }
+        };
+        synchronized(mFirstTaskLock) {
+            if (!mPreloadingFirstTask) {
+                clearFirstTask();
+                mPreloadingFirstTask = true;
+                bgLoad.start();
+            }
+        }
+    }
+
+    public void cancelPreloadingFirstTask() {
+        synchronized(mFirstTaskLock) {
+            if (mPreloadingFirstTask) {
+                mCancelPreloadingFirstTask = true;
+            } else {
+                clearFirstTask();
+            }
+        }
+    }
+
+    boolean mPreloadingFirstTask;
+    boolean mCancelPreloadingFirstTask;
+    public TaskDescription getFirstTask() {
+        while(true) {
+            synchronized(mFirstTaskLock) {
+                if (mFirstTaskLoaded) {
+                    return mFirstTask;
+                } else if (!mFirstTaskLoaded && !mPreloadingFirstTask) {
+                    mFirstTask = loadFirstTask();
+                    mFirstTaskLoaded = true;
+                    return mFirstTask;
+                }
+            }
+            try {
+                Thread.sleep(3);
+            } catch (InterruptedException e) {
+            }
+        }
+    }
+
+    public TaskDescription loadFirstTask() {
+        final ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+
+        final List<ActivityManager.RecentTaskInfo> recentTasks = am.getRecentTasksForUser(
+                1, ActivityManager.RECENT_IGNORE_UNAVAILABLE, UserHandle.CURRENT.getIdentifier());
+        TaskDescription item = null;
+        if (recentTasks.size() > 0) {
+            ActivityManager.RecentTaskInfo recentInfo = recentTasks.get(0);
+
+            Intent intent = new Intent(recentInfo.baseIntent);
+            if (recentInfo.origActivity != null) {
+                intent.setComponent(recentInfo.origActivity);
+            }
+
+            // Don't load the current home activity.
+            if (isCurrentHomeActivity(intent.getComponent(), null)) {
+                return null;
+            }
+
+            // Don't load ourselves
+            if (intent.getComponent().getPackageName().equals(mContext.getPackageName())) {
+                return null;
+            }
+
+            item = createTaskDescription(recentInfo.id,
+                    recentInfo.persistentId, recentInfo.baseIntent,
+                    recentInfo.origActivity, recentInfo.description);
+            loadThumbnailAndIcon(item);
+            return item;
+        }
+        return null;
+    }
+
     public void loadTasksInBackground() {
         loadTasksInBackground(false);
     }
@@ -367,9 +455,6 @@
 
                     // Don't load the current home activity.
                     if (isCurrentHomeActivity(intent.getComponent(), homeInfo)) {
-                        if (index == 0) {
-                            mFirstTaskLoaded = true;
-                        }
                         continue;
                     }
 
@@ -466,10 +551,6 @@
                     }
                     loadThumbnailAndIcon(td);
 
-                    if (!mFirstTaskLoaded) {
-                        mFirstTask = td;
-                        mFirstTaskLoaded = true;
-                    }
                     publishProgress(td);
                 }
 
@@ -477,8 +558,6 @@
                 return null;
             }
         };
-        mFirstTask = null;
-        mFirstTaskLoaded = false;
         mThumbnailLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java
index ef9f36e..676326a 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java
@@ -30,14 +30,18 @@
 import android.view.WindowManager;
 
 import com.android.systemui.R;
-import com.android.systemui.SystemUIApplication;
 import com.android.systemui.statusbar.tablet.StatusBarPanel;
 
 import java.util.List;
 
 public class RecentsActivity extends Activity {
-    public static final String TOGGLE_RECENTS_INTENT = "com.android.systemui.TOGGLE_RECENTS";
-    public static final String CLOSE_RECENTS_INTENT = "com.android.systemui.CLOSE_RECENTS";
+    public static final String TOGGLE_RECENTS_INTENT = "com.android.systemui.recent.action.TOGGLE_RECENTS";
+    public static final String PRELOAD_INTENT = "com.android.systemui.recent.action.PRELOAD";
+    public static final String CANCEL_PRELOAD_INTENT = "com.android.systemui.recent.CANCEL_PRELOAD";
+    public static final String CLOSE_RECENTS_INTENT = "com.android.systemui.recent.action.CLOSE";
+    public static final String WINDOW_ANIMATION_START_INTENT = "com.android.systemui.recent.action.WINDOW_ANIMATION_START";
+    public static final String PRELOAD_PERMISSION = "com.android.systemui.recent.permission.PRELOAD";
+    public static final String WAITING_FOR_WINDOW_ANIMATION_PARAM = "com.android.systemui.recent.WAITING_FOR_WINDOW_ANIMATION";
     private static final String WAS_SHOWING = "was_showing";
 
     private RecentsPanelView mRecentsPanel;
@@ -48,19 +52,21 @@
     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            if (mRecentsPanel != null && mRecentsPanel.isShowing()) {
-                if (mShowing && !mForeground) {
-                    // Captures the case right before we transition to another activity
-                    mRecentsPanel.show(false);
+            if (CLOSE_RECENTS_INTENT.equals(intent.getAction())) {
+                if (mRecentsPanel != null && mRecentsPanel.isShowing()) {
+                    if (mShowing && !mForeground) {
+                        // Captures the case right before we transition to another activity
+                        mRecentsPanel.show(false);
+                    }
+                }
+            } else if (WINDOW_ANIMATION_START_INTENT.equals(intent.getAction())) {
+                if (mRecentsPanel != null) {
+                    mRecentsPanel.onWindowAnimationStart();
                 }
             }
         }
     };
 
-    public static interface WindowAnimationStartListener {
-        void onWindowAnimationStart();
-    }
-
     public class TouchOutsideListener implements View.OnTouchListener {
         private StatusBarPanel mPanel;
 
@@ -107,10 +113,14 @@
         }
     }
 
+    public static boolean forceOpaqueBackground(Context context) {
+        return WallpaperManager.getInstance(context).getWallpaperInfo() != null;
+    }
+
     @Override
     public void onStart() {
         // Hide wallpaper if it's not a static image
-        if (WallpaperManager.getInstance(this).getWallpaperInfo() != null) {
+        if (forceOpaqueBackground(this)) {
             updateWallpaperVisibility(false);
         } else {
             updateWallpaperVisibility(true);
@@ -164,25 +174,23 @@
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
-        final SystemUIApplication app = (SystemUIApplication) getApplication();
-        final RecentTasksLoader recentTasksLoader = app.getRecentTasksLoader();
-
         setContentView(R.layout.status_bar_recent_panel);
         mRecentsPanel = (RecentsPanelView) findViewById(R.id.recents_root);
         mRecentsPanel.setOnTouchListener(new TouchOutsideListener(mRecentsPanel));
-        mRecentsPanel.setRecentTasksLoader(recentTasksLoader);
+
+        final RecentTasksLoader recentTasksLoader = RecentTasksLoader.getInstance(this);
         recentTasksLoader.setRecentsPanel(mRecentsPanel, mRecentsPanel);
         mRecentsPanel.setMinSwipeAlpha(
                 getResources().getInteger(R.integer.config_recent_item_min_alpha) / 100f);
 
         if (savedInstanceState == null ||
                 savedInstanceState.getBoolean(WAS_SHOWING)) {
-            handleIntent(getIntent());
+            handleIntent(getIntent(), (savedInstanceState == null));
         }
         mIntentFilter = new IntentFilter();
         mIntentFilter.addAction(CLOSE_RECENTS_INTENT);
+        mIntentFilter.addAction(WINDOW_ANIMATION_START_INTENT);
         registerReceiver(mIntentReceiver, mIntentFilter);
-        app.setWindowAnimationStartListener(mRecentsPanel);
         super.onCreate(savedInstanceState);
     }
 
@@ -193,20 +201,17 @@
 
     @Override
     protected void onDestroy() {
-        final SystemUIApplication app = (SystemUIApplication) getApplication();
-        final RecentTasksLoader recentTasksLoader = app.getRecentTasksLoader();
-        recentTasksLoader.setRecentsPanel(null, mRecentsPanel);
+        RecentTasksLoader.getInstance(this).setRecentsPanel(null, mRecentsPanel);
         unregisterReceiver(mIntentReceiver);
-        app.setWindowAnimationStartListener(null);
         super.onDestroy();
     }
 
     @Override
     protected void onNewIntent(Intent intent) {
-        handleIntent(intent);
+        handleIntent(intent, true);
     }
 
-    private void handleIntent(Intent intent) {
+    private void handleIntent(Intent intent, boolean checkWaitingForAnimationParam) {
         super.onNewIntent(intent);
 
         if (TOGGLE_RECENTS_INTENT.equals(intent.getAction())) {
@@ -214,10 +219,11 @@
                 if (mRecentsPanel.isShowing()) {
                     dismissAndGoBack();
                 } else {
-                    final SystemUIApplication app = (SystemUIApplication) getApplication();
-                    final RecentTasksLoader recentTasksLoader = app.getRecentTasksLoader();
+                    final RecentTasksLoader recentTasksLoader = RecentTasksLoader.getInstance(this);
+                    boolean waitingForWindowAnimation = checkWaitingForAnimationParam &&
+                            intent.getBooleanExtra(WAITING_FOR_WINDOW_ANIMATION_PARAM, false);
                     mRecentsPanel.show(true, recentTasksLoader.getLoadedTasks(),
-                            recentTasksLoader.isFirstScreenful());
+                            recentTasksLoader.isFirstScreenful(), waitingForWindowAnimation);
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 9f0bcf5..2008d0e 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -59,7 +59,6 @@
 import android.widget.TextView;
 
 import com.android.systemui.R;
-import com.android.systemui.SystemUIApplication;
 import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
 import com.android.systemui.statusbar.tablet.StatusBarPanel;
@@ -68,7 +67,7 @@
 import java.util.ArrayList;
 
 public class RecentsPanelView extends FrameLayout implements OnItemClickListener, RecentsCallback,
-        StatusBarPanel, Animator.AnimatorListener, RecentsActivity.WindowAnimationStartListener {
+        StatusBarPanel, Animator.AnimatorListener {
     static final String TAG = "RecentsPanelView";
     static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false;
     private PopupMenu mPopup;
@@ -81,6 +80,7 @@
     private boolean mWaitingToShow;
     private int mNumItemsWaitingForThumbnailsAndIcons;
     private ViewHolder mItemToAnimateInWhenWindowAnimationIsFinished;
+    private boolean mWaitingForWindowAnimation;
 
     private RecentTasksLoader mRecentTasksLoader;
     private ArrayList<TaskDescription> mRecentTaskDescriptions;
@@ -147,13 +147,9 @@
                     (ImageView) convertView.findViewById(R.id.app_thumbnail_image);
             // If we set the default thumbnail now, we avoid an onLayout when we update
             // the thumbnail later (if they both have the same dimensions)
-            if (mRecentTasksLoader != null) {
-                updateThumbnail(holder, mRecentTasksLoader.getDefaultThumbnail(), false, false);
-            }
+            updateThumbnail(holder, mRecentTasksLoader.getDefaultThumbnail(), false, false);
             holder.iconView = (ImageView) convertView.findViewById(R.id.app_icon);
-            if (mRecentTasksLoader != null) {
-                holder.iconView.setImageBitmap(mRecentTasksLoader.getDefaultIcon());
-            }
+            holder.iconView.setImageBitmap(mRecentTasksLoader.getDefaultIcon());
             holder.labelView = (TextView) convertView.findViewById(R.id.app_label);
             holder.calloutLine = convertView.findViewById(R.id.recents_callout_line);
             holder.descriptionView = (TextView) convertView.findViewById(R.id.app_description);
@@ -183,8 +179,7 @@
             }
             if (index == 0) {
                 final Activity activity = (Activity) RecentsPanelView.this.getContext();
-                final SystemUIApplication app = (SystemUIApplication) activity.getApplication();
-                if (app.isWaitingForWindowAnimationStart()) {
+                if (mWaitingForWindowAnimation) {
                     if (mItemToAnimateInWhenWindowAnimationIsFinished != null) {
                         for (View v :
                             new View[] { holder.iconView, holder.labelView, holder.calloutLine }) {
@@ -247,6 +242,7 @@
                 defStyle, 0);
 
         mRecentItemLayoutId = a.getResourceId(R.styleable.RecentsPanelView_recentItemLayout, 0);
+        mRecentTasksLoader = RecentTasksLoader.getInstance(context);
         a.recycle();
     }
 
@@ -280,11 +276,12 @@
     }
 
     public void show(boolean show) {
-        show(show, null, false);
+        show(show, null, false, false);
     }
 
     public void show(boolean show, ArrayList<TaskDescription> recentTaskDescriptions,
-            boolean firstScreenful) {
+            boolean firstScreenful, boolean waitingForWindowAnimation) {
+        mWaitingForWindowAnimation = waitingForWindowAnimation;
         if (show) {
             mWaitingToShow = true;
             refreshRecentTasksList(recentTaskDescriptions, firstScreenful);
@@ -542,6 +539,7 @@
                 }
             }
             mItemToAnimateInWhenWindowAnimationIsFinished = null;
+            mWaitingForWindowAnimation = false;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPreloadReceiver.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPreloadReceiver.java
new file mode 100644
index 0000000..eb5892007
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPreloadReceiver.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+package com.android.systemui.recent;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class RecentsPreloadReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (RecentsActivity.PRELOAD_INTENT.equals(intent.getAction())) {
+            RecentTasksLoader.getInstance(context).preloadRecentTasksList();
+        } else if (RecentsActivity.CANCEL_PRELOAD_INTENT.equals(intent.getAction())){
+            RecentTasksLoader.getInstance(context).cancelPreloadingRecentTasksList();
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 577b1f4..fe33b02 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -25,7 +25,6 @@
 import com.android.systemui.R;
 import com.android.systemui.SearchPanelView;
 import com.android.systemui.SystemUI;
-import com.android.systemui.SystemUIApplication;
 import com.android.systemui.recent.RecentTasksLoader;
 import com.android.systemui.recent.RecentsActivity;
 import com.android.systemui.recent.TaskDescription;
@@ -37,7 +36,6 @@
 import android.app.ActivityOptions;
 import android.app.KeyguardManager;
 import android.app.PendingIntent;
-import android.app.Service;
 import android.app.TaskStackBuilder;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
@@ -72,9 +70,9 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.WindowManagerGlobal;
 import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.PopupMenu;
@@ -428,10 +426,6 @@
     protected abstract WindowManager.LayoutParams getSearchLayoutParams(
             LayoutParams layoutParams);
 
-    protected RecentTasksLoader getRecentTasksLoader() {
-        final SystemUIApplication app = (SystemUIApplication) ((Service) mContext).getApplication();
-        return app.getRecentTasksLoader();
-    }
 
     protected void updateSearchPanel() {
         // Search Panel
@@ -475,8 +469,8 @@
 
     protected void toggleRecentsActivity() {
         try {
-            final RecentTasksLoader recentTasksLoader = getRecentTasksLoader();
-            TaskDescription firstTask = recentTasksLoader.getFirstTask();
+
+            TaskDescription firstTask = RecentTasksLoader.getInstance(mContext).getFirstTask();
 
             Intent intent = new Intent(RecentsActivity.TOGGLE_RECENTS_INTENT);
             intent.setClassName("com.android.systemui",
@@ -485,11 +479,18 @@
                     | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
 
             if (firstTask == null) {
-                ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
-                        R.anim.recents_launch_from_launcher_enter,
-                        R.anim.recents_launch_from_launcher_exit);
-                mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
-                        UserHandle.USER_CURRENT));
+                if (RecentsActivity.forceOpaqueBackground(mContext)) {
+                    ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
+                            R.anim.recents_launch_from_launcher_enter,
+                            R.anim.recents_launch_from_launcher_exit);
+                    mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
+                            UserHandle.USER_CURRENT));
+                } else {
+                    // The correct window animation will be applied via the activity's style
+                    mContext.startActivityAsUser(intent, new UserHandle(
+                            UserHandle.USER_CURRENT));
+                }
+
             } else {
                 Bitmap first = firstTask.getThumbnail();
                 final Resources res = mContext.getResources();
@@ -576,17 +577,17 @@
                             + recentsItemTopPadding + thumbBgPadding + statusBarHeight);
                 }
 
-                final SystemUIApplication app =
-                        (SystemUIApplication) ((Service) mContext).getApplication();
-                app.setWaitingForWinAnimStart(true);
                 ActivityOptions opts = ActivityOptions.makeThumbnailScaleDownAnimation(
                         getStatusBarView(),
                         first, x, y,
                         new ActivityOptions.OnAnimationStartedListener() {
                             public void onAnimationStarted() {
-                                app.onWindowAnimationStart();
+                                Intent intent = new Intent(RecentsActivity.WINDOW_ANIMATION_START_INTENT);
+                                intent.setPackage("com.android.systemui");
+                                mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
                             }
                         });
+                intent.putExtra(RecentsActivity.WAITING_FOR_WINDOW_ANIMATION_PARAM, true);
                 mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
                         UserHandle.USER_CURRENT));
             }
@@ -596,8 +597,49 @@
         }
     }
 
+    protected View.OnTouchListener mRecentsPreloadOnTouchListener = new View.OnTouchListener() {
+        // additional optimization when we have software system buttons - start loading the recent
+        // tasks on touch down
+        @Override
+        public boolean onTouch(View v, MotionEvent event) {
+            int action = event.getAction() & MotionEvent.ACTION_MASK;
+            if (action == MotionEvent.ACTION_DOWN) {
+                preloadRecentTasksList();
+            } else if (action == MotionEvent.ACTION_CANCEL) {
+                cancelPreloadingRecentTasksList();
+            } else if (action == MotionEvent.ACTION_UP) {
+                if (!v.isPressed()) {
+                    cancelPreloadingRecentTasksList();
+                }
+
+            }
+            return false;
+        }
+    };
+
+    protected void preloadRecentTasksList() {
+        if (DEBUG) Slog.d(TAG, "preloading recents");
+        Intent intent = new Intent(RecentsActivity.PRELOAD_INTENT);
+        intent.setClassName("com.android.systemui",
+                "com.android.systemui.recent.RecentsPreloadReceiver");
+        mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+
+        RecentTasksLoader.getInstance(mContext).preloadFirstTask();
+    }
+
+    protected void cancelPreloadingRecentTasksList() {
+        if (DEBUG) Slog.d(TAG, "cancel preloading recents");
+        Intent intent = new Intent(RecentsActivity.CANCEL_PRELOAD_INTENT);
+        intent.setClassName("com.android.systemui",
+                "com.android.systemui.recent.RecentsPreloadReceiver");
+        mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+
+        RecentTasksLoader.getInstance(mContext).cancelPreloadingFirstTask();
+    }
+
     protected class H extends Handler {
         public void handleMessage(Message m) {
+            Intent intent;
             switch (m.what) {
              case MSG_TOGGLE_RECENTS_PANEL:
                  if (DEBUG) Slog.d(TAG, "toggle recents panel");
@@ -605,17 +647,15 @@
                  break;
              case MSG_CLOSE_RECENTS_PANEL:
                  if (DEBUG) Slog.d(TAG, "closing recents panel");
-                 Intent intent = new Intent(RecentsActivity.CLOSE_RECENTS_INTENT);
+                 intent = new Intent(RecentsActivity.CLOSE_RECENTS_INTENT);
                  intent.setPackage("com.android.systemui");
                  mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
                  break;
              case MSG_PRELOAD_RECENT_APPS:
-                  if (DEBUG) Slog.d(TAG, "preloading recents");
-                  getRecentTasksLoader().preloadRecentTasksList();
+                  preloadRecentTasksList();
                   break;
              case MSG_CANCEL_PRELOAD_RECENT_APPS:
-                  if (DEBUG) Slog.d(TAG, "cancel preloading recents");
-                  getRecentTasksLoader().cancelPreloadingRecentTasksList();
+                  cancelPreloadingRecentTasksList();
                   break;
              case MSG_OPEN_SEARCH_PANEL:
                  if (DEBUG) Slog.d(TAG, "opening search panel");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 1c4dff8..5bb9378 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -40,7 +40,6 @@
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.graphics.drawable.NinePatchDrawable;
 import android.inputmethodservice.InputMethodService;
 import android.os.Handler;
 import android.os.IBinder;
@@ -753,7 +752,7 @@
         mNavigationBarView.reorient();
 
         mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
-        mNavigationBarView.getRecentsButton().setOnTouchListener(getRecentTasksLoader());
+        mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPreloadOnTouchListener);
         mNavigationBarView.getHomeButton().setOnTouchListener(mHomeSearchActionListener);
         updateSearchPanel();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 97451ae..86c247a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -60,8 +60,6 @@
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.statusbar.StatusBarNotification;
 import com.android.systemui.R;
-import com.android.systemui.recent.RecentTasksLoader;
-import com.android.systemui.recent.RecentsPanelView;
 import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.DoNotDisturb;
@@ -353,7 +351,7 @@
 
         mWindowManager.addView(mCompatModePanel, lp);
 
-        mRecentButton.setOnTouchListener(getRecentTasksLoader());
+        mRecentButton.setOnTouchListener(mRecentsPreloadOnTouchListener);
 
         mPile = (NotificationRowLayout)mNotificationPanel.findViewById(R.id.content);
         mPile.removeAllViews();
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index eaaf33f..e46afd3 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -737,7 +737,7 @@
             }
             
             if (context.getResources().getBoolean(
-                    com.android.internal.R.bool.config_enableDreams)) {
+                    com.android.internal.R.bool.config_dreamsSupported)) {
                 try {
                     Slog.i(TAG, "Dreams Service");
                     // Dreams (interactive idle-time views, a/k/a screen savers)
diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java
index b94bceb..bf81a90 100644
--- a/services/java/com/android/server/power/PowerManagerService.java
+++ b/services/java/com/android/server/power/PowerManagerService.java
@@ -280,6 +280,15 @@
     // True if dreams are supported on this device.
     private boolean mDreamsSupportedConfig;
 
+    // Default value for dreams enabled
+    private boolean mDreamsEnabledByDefaultConfig;
+
+    // Default value for dreams activate-on-sleep
+    private boolean mDreamsActivatedOnSleepByDefaultConfig;
+
+    // Default value for dreams activate-on-dock
+    private boolean mDreamsActivatedOnDockByDefaultConfig;
+
     // True if dreams are enabled by the user.
     private boolean mDreamsEnabledSetting;
 
@@ -490,20 +499,29 @@
         mWakeUpWhenPluggedOrUnpluggedConfig = resources.getBoolean(
                 com.android.internal.R.bool.config_unplugTurnsOnScreen);
         mDreamsSupportedConfig = resources.getBoolean(
-                com.android.internal.R.bool.config_enableDreams);
+                com.android.internal.R.bool.config_dreamsSupported);
+        mDreamsEnabledByDefaultConfig = resources.getBoolean(
+                com.android.internal.R.bool.config_dreamsEnabledByDefault);
+        mDreamsActivatedOnSleepByDefaultConfig = resources.getBoolean(
+                com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault);
+        mDreamsActivatedOnDockByDefaultConfig = resources.getBoolean(
+                com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);
     }
 
     private void updateSettingsLocked() {
         final ContentResolver resolver = mContext.getContentResolver();
 
         mDreamsEnabledSetting = (Settings.Secure.getIntForUser(resolver,
-                Settings.Secure.SCREENSAVER_ENABLED, 0,
+                Settings.Secure.SCREENSAVER_ENABLED,
+                mDreamsEnabledByDefaultConfig ? 1 : 0,
                 UserHandle.USER_CURRENT) != 0);
         mDreamsActivateOnSleepSetting = (Settings.Secure.getIntForUser(resolver,
-                Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 0,
+                Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
+                mDreamsActivatedOnSleepByDefaultConfig ? 1 : 0,
                 UserHandle.USER_CURRENT) != 0);
         mDreamsActivateOnDockSetting = (Settings.Secure.getIntForUser(resolver,
-                Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, 0,
+                Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
+                mDreamsActivatedOnDockByDefaultConfig ? 1 : 0,
                 UserHandle.USER_CURRENT) != 0);
         mScreenOffTimeoutSetting = Settings.System.getIntForUser(resolver,
                 Settings.System.SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT,
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
index 3898ebc..68cdbfc 100644
--- a/services/java/com/android/server/wm/DisplayContent.java
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -66,14 +66,17 @@
     int mBaseDisplayWidth = 0;
     int mBaseDisplayHeight = 0;
     int mBaseDisplayDensity = 0;
-    final DisplayInfo mDisplayInfo = new DisplayInfo();
-    final Display mDisplay;
+    private final DisplayInfo mDisplayInfo = new DisplayInfo();
+    private final Display mDisplay;
 
     // Accessed directly by all users.
     boolean layoutNeeded;
     int pendingLayoutChanges;
     final boolean isDefaultDisplay;
 
+    /**
+     * @param display May not be null.
+     */
     DisplayContent(Display display) {
         mDisplay = display;
         mDisplayId = display.getDisplayId();
diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java
index 545fce5..72fc180 100644
--- a/services/java/com/android/server/wm/DragState.java
+++ b/services/java/com/android/server/wm/DragState.java
@@ -190,9 +190,11 @@
         }
 
         final WindowList windows = mService.getWindowListLocked(mDisplay);
-        final int N = windows.size();
-        for (int i = 0; i < N; i++) {
-            sendDragStartedLw(windows.get(i), touchX, touchY, mDataDescription);
+        if (windows != null) {
+            final int N = windows.size();
+            for (int i = 0; i < N; i++) {
+                sendDragStartedLw(windows.get(i), touchX, touchY, mDataDescription);
+            }
         }
     }
 
@@ -393,6 +395,9 @@
         final int y = (int) yf;
 
         final WindowList windows = mService.getWindowListLocked(mDisplay);
+        if (windows == null) {
+            return null;
+        }
         final int N = windows.size();
         for (int i = N - 1; i >= 0; i--) {
             WindowState child = windows.get(i);
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index e74b6db..52992a1 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -2092,6 +2092,11 @@
                 throw new IllegalStateException("Display has not been initialialized");
             }
 
+            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            if (displayContent == null) {
+                return WindowManagerGlobal.ADD_INVALID_DISPLAY;
+            }
+
             if (mWindowMap.containsKey(client.asBinder())) {
                 Slog.w(TAG, "Window " + client + " is already added");
                 return WindowManagerGlobal.ADD_DUPLICATE_ADD;
@@ -2174,7 +2179,6 @@
                 }
             }
 
-            final DisplayContent displayContent = getDisplayContentLocked(displayId);
             win = new WindowState(this, session, client, token,
                     attachedWindow, seq, attrs, viewVisibility, displayContent);
             if (win.mDeathRecipient == null) {
@@ -3385,8 +3389,15 @@
         } else {
             // Exiting app
             if (scaleUp) {
-                // noop animation
-                a = new AlphaAnimation(1, 0);
+                if (transit == WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN) {
+                    // Fade out while bringing up selected activity. This keeps the
+                    // current activity from showing through a launching wallpaper
+                    // activity.
+                    a = new AlphaAnimation(1, 0);
+                } else {
+                    // noop animation
+                    a = new AlphaAnimation(1, 1);
+                }
                 a.setDuration(duration);
             } else {
                 float scaleW = thumbWidth / displayInfo.appWidth;
@@ -5705,6 +5716,7 @@
      * @param width the width of the target bitmap
      * @param height the height of the target bitmap
      */
+    @Override
     public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height) {
         if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
                 "screenshotApplications()")) {
@@ -5724,6 +5736,9 @@
             long ident = Binder.clearCallingIdentity();
 
             final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            if (displayContent == null) {
+                return null;
+            }
             final DisplayInfo displayInfo = displayContent.getDisplayInfo();
             dw = displayInfo.logicalWidth;
             dh = displayInfo.logicalHeight;
@@ -6466,6 +6481,7 @@
         return success;
     }
 
+    @Override
     public void addDisplayContentChangeListener(int displayId,
             IDisplayContentChangeListener listener) {
         if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
@@ -6474,14 +6490,17 @@
         }
         synchronized(mWindowMap) {
             DisplayContent displayContent = getDisplayContentLocked(displayId);
-            if (displayContent.mDisplayContentChangeListeners == null) {
-                displayContent.mDisplayContentChangeListeners =
-                        new RemoteCallbackList<IDisplayContentChangeListener>();
-            displayContent.mDisplayContentChangeListeners.register(listener);
+            if (displayContent != null) {
+                if (displayContent.mDisplayContentChangeListeners == null) {
+                    displayContent.mDisplayContentChangeListeners =
+                            new RemoteCallbackList<IDisplayContentChangeListener>();
+                    displayContent.mDisplayContentChangeListeners.register(listener);
+                }
             }
         }
     }
 
+    @Override
     public void removeDisplayContentChangeListener(int displayId,
             IDisplayContentChangeListener listener) {
         if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
@@ -6490,11 +6509,13 @@
         }
         synchronized(mWindowMap) {
             DisplayContent displayContent = getDisplayContentLocked(displayId);
-            if (displayContent.mDisplayContentChangeListeners != null) {
-                displayContent.mDisplayContentChangeListeners.unregister(listener);
-                if (displayContent.mDisplayContentChangeListeners
-                        .getRegisteredCallbackCount() == 0) {
-                    displayContent.mDisplayContentChangeListeners = null;
+            if (displayContent != null) {
+                if (displayContent.mDisplayContentChangeListeners != null) {
+                    displayContent.mDisplayContentChangeListeners.unregister(listener);
+                    if (displayContent.mDisplayContentChangeListeners
+                            .getRegisteredCallbackCount() == 0) {
+                        displayContent.mDisplayContentChangeListeners = null;
+                    }
                 }
             }
         }
@@ -7150,7 +7171,6 @@
 
         synchronized(mWindowMap) {
             final DisplayContent displayContent = getDefaultDisplayContentLocked();
-            final Display display = displayContent.getDisplay();
             readForcedDisplaySizeAndDensityLocked(displayContent);
 
             mDisplayReady = true;
@@ -7174,24 +7194,25 @@
         }
     }
 
-    public void displayReady(int displayId) {
+    private void displayReady(int displayId) {
         synchronized(mWindowMap) {
             final DisplayContent displayContent = getDisplayContentLocked(displayId);
-            final DisplayInfo displayInfo;
-            mAnimator.addDisplayLocked(displayId);
-            synchronized(displayContent.mDisplaySizeLock) {
-                // Bootstrap the default logical display from the display manager.
-                displayInfo = displayContent.getDisplayInfo();
-                DisplayInfo newDisplayInfo = mDisplayManagerService.getDisplayInfo(displayId);
-                if (newDisplayInfo != null) {
-                    displayInfo.copyFrom(newDisplayInfo);
+            if (displayContent != null) {
+                mAnimator.addDisplayLocked(displayId);
+                synchronized(displayContent.mDisplaySizeLock) {
+                    // Bootstrap the default logical display from the display manager.
+                    final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+                    DisplayInfo newDisplayInfo = mDisplayManagerService.getDisplayInfo(displayId);
+                    if (newDisplayInfo != null) {
+                        displayInfo.copyFrom(newDisplayInfo);
+                    }
+                    displayContent.mInitialDisplayWidth = displayInfo.logicalWidth;
+                    displayContent.mInitialDisplayHeight = displayInfo.logicalHeight;
+                    displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi;
+                    displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth;
+                    displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight;
+                    displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity;
                 }
-                displayContent.mInitialDisplayWidth = displayInfo.logicalWidth;
-                displayContent.mInitialDisplayHeight = displayInfo.logicalHeight;
-                displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi;
-                displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth;
-                displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight;
-                displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity;
             }
         }
     }
@@ -7832,12 +7853,15 @@
         // TODO(cmautner): Access to DisplayContent should be locked on mWindowMap. Doing that
         //  could lead to deadlock since this is called from ActivityManager.
         final DisplayContent displayContent = getDisplayContentLocked(displayId);
-        synchronized(displayContent.mDisplaySizeLock) {
-            size.x = displayContent.mInitialDisplayWidth;
-            size.y = displayContent.mInitialDisplayHeight;
+        if (displayContent != null) {
+            synchronized(displayContent.mDisplaySizeLock) {
+                size.x = displayContent.mInitialDisplayWidth;
+                size.y = displayContent.mInitialDisplayHeight;
+            }
         }
     }
 
+    @Override
     public void setForcedDisplaySize(int displayId, int width, int height) {
         synchronized(mWindowMap) {
             // Set some sort of reasonable bounds on the size of the display that we
@@ -7846,14 +7870,15 @@
             final int MIN_HEIGHT = 200;
             final int MAX_SCALE = 2;
             final DisplayContent displayContent = getDisplayContentLocked(displayId);
-
-            width = Math.min(Math.max(width, MIN_WIDTH),
-                    displayContent.mInitialDisplayWidth * MAX_SCALE);
-            height = Math.min(Math.max(height, MIN_HEIGHT),
-                    displayContent.mInitialDisplayHeight * MAX_SCALE);
-            setForcedDisplaySizeLocked(displayContent, width, height);
-            Settings.Global.putString(mContext.getContentResolver(),
-                    Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
+            if (displayContent != null) {
+                width = Math.min(Math.max(width, MIN_WIDTH),
+                        displayContent.mInitialDisplayWidth * MAX_SCALE);
+                height = Math.min(Math.max(height, MIN_HEIGHT),
+                        displayContent.mInitialDisplayHeight * MAX_SCALE);
+                setForcedDisplaySizeLocked(displayContent, width, height);
+                Settings.Global.putString(mContext.getContentResolver(),
+                        Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
+            }
         }
     }
 
@@ -7896,6 +7921,7 @@
         }
     }
 
+    // displayContent must not be null
     private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
         Slog.i(TAG, "Using new display size: " + width + "x" + height);
 
@@ -7906,25 +7932,32 @@
         reconfigureDisplayLocked(displayContent);
     }
 
+    @Override
     public void clearForcedDisplaySize(int displayId) {
         synchronized(mWindowMap) {
             final DisplayContent displayContent = getDisplayContentLocked(displayId);
-            setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
-                    displayContent.mInitialDisplayHeight);
-            Settings.Global.putString(mContext.getContentResolver(),
-                    Settings.Global.DISPLAY_SIZE_FORCED, "");
+            if (displayContent != null) {
+                setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
+                        displayContent.mInitialDisplayHeight);
+                Settings.Global.putString(mContext.getContentResolver(),
+                        Settings.Global.DISPLAY_SIZE_FORCED, "");
+            }
         }
     }
 
+    @Override
     public void setForcedDisplayDensity(int displayId, int density) {
         synchronized(mWindowMap) {
             final DisplayContent displayContent = getDisplayContentLocked(displayId);
-            setForcedDisplayDensityLocked(displayContent, density);
-            Settings.Global.putString(mContext.getContentResolver(),
-                    Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
+            if (displayContent != null) {
+                setForcedDisplayDensityLocked(displayContent, density);
+                Settings.Global.putString(mContext.getContentResolver(),
+                        Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
+            }
         }
     }
 
+    // displayContent must not be null
     private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) {
         Slog.i(TAG, "Using new display density: " + density);
 
@@ -7934,15 +7967,19 @@
         reconfigureDisplayLocked(displayContent);
     }
 
+    @Override
     public void clearForcedDisplayDensity(int displayId) {
         synchronized(mWindowMap) {
             final DisplayContent displayContent = getDisplayContentLocked(displayId);
-            setForcedDisplayDensityLocked(displayContent, displayContent.mInitialDisplayDensity);
-            Settings.Global.putString(mContext.getContentResolver(),
-                    Settings.Global.DISPLAY_DENSITY_FORCED, "");
+            if (displayContent != null) {
+                setForcedDisplayDensityLocked(displayContent, displayContent.mInitialDisplayDensity);
+                Settings.Global.putString(mContext.getContentResolver(),
+                        Settings.Global.DISPLAY_DENSITY_FORCED, "");
+            }
         }
     }
 
+    // displayContent must not be null
     private void reconfigureDisplayLocked(DisplayContent displayContent) {
         // TODO: Multidisplay: for now only use with default display.
         mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
@@ -9712,7 +9749,9 @@
             for (int i = 0; i < count; ++i) {
                 final DisplayContent displayContent =
                         getDisplayContentLocked(pendingLayouts.keyAt(i));
-                displayContent.pendingLayoutChanges |= pendingLayouts.valueAt(i);
+                if (displayContent != null) {
+                    displayContent.pendingLayoutChanges |= pendingLayouts.valueAt(i);
+                }
             }
 
             mWindowDetachedWallpaper = animToLayout.mWindowDetachedWallpaper;
@@ -10838,11 +10877,20 @@
         mDisplayContents.put(display.getDisplayId(), displayContent);
     }
 
+    /**
+     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
+     * there is a Display for the displayId.
+     * @param displayId The display the caller is interested in.
+     * @return The DisplayContent associated with displayId or null if there is no Display for it.
+     */
     public DisplayContent getDisplayContentLocked(final int displayId) {
         DisplayContent displayContent = mDisplayContents.get(displayId);
         if (displayContent == null) {
-            displayContent = new DisplayContent(mDisplayManager.getDisplay(displayId));
-            mDisplayContents.put(displayId, displayContent);
+            final Display display = mDisplayManager.getDisplay(displayId);
+            if (display != null) {
+                displayContent = new DisplayContent(display);
+                mDisplayContents.put(displayId, displayContent);
+            }
         }
         return displayContent;
     }
@@ -10928,6 +10976,7 @@
         }
     }
 
+    // There is an inherent assumption that this will never return null.
     public DisplayContent getDefaultDisplayContentLocked() {
         return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
     }
@@ -10940,8 +10989,14 @@
         return getDefaultDisplayContentLocked().getDisplayInfo();
     }
 
+    /**
+     * Return the list of WindowStates associated on the passed display.
+     * @param display The screen to return windows from.
+     * @return The list of WindowStates on the screen, or null if the there is no screen.
+     */
     public WindowList getWindowListLocked(final Display display) {
-        return getDisplayContentLocked(display.getDisplayId()).getWindowList();
+        final DisplayContent displayContent = getDisplayContentLocked(display.getDisplayId());
+        return displayContent != null ? displayContent.getWindowList() : null;
     }
 
     @Override
@@ -10950,8 +11005,11 @@
     }
 
     private void handleDisplayAddedLocked(int displayId) {
-        createDisplayContentLocked(mDisplayManager.getDisplay(displayId));
-        displayReady(displayId);
+        final Display display = mDisplayManager.getDisplay(displayId);
+        if (display != null) {
+            createDisplayContentLocked(display);
+            displayReady(displayId);
+        }
     }
 
     @Override
@@ -10961,11 +11019,13 @@
 
     private void handleDisplayRemovedLocked(int displayId) {
         final DisplayContent displayContent = getDisplayContentLocked(displayId);
-        mDisplayContents.delete(displayId);
-        WindowList windows = displayContent.getWindowList();
-        while (!windows.isEmpty()) {
-            final WindowState win = windows.get(windows.size() - 1);
-            removeWindowLocked(win.mSession, win);
+        if (displayContent != null) {
+            mDisplayContents.delete(displayId);
+            WindowList windows = displayContent.getWindowList();
+            while (!windows.isEmpty()) {
+                final WindowState win = windows.get(windows.size() - 1);
+                removeWindowLocked(win.mSession, win);
+            }
         }
         mAnimator.removeDisplayLocked(displayId);
     }
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 7f32431..f0aef92 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -1465,6 +1465,12 @@
             if (mGroup.isGroupOwner()) {
                 setWifiP2pInfoOnGroupFormation(SERVER_ADDRESS);
             }
+
+            // In case of a negotiation group, connection changed is sent
+            // after a client joins. For autonomous, send now
+            if (mAutonomousGroup) {
+                sendP2pConnectionChangedBroadcast();
+            }
         }
 
         @Override
@@ -1479,7 +1485,11 @@
                                 deviceAddress.equals(mSavedProvDiscDevice.deviceAddress)) {
                             mSavedProvDiscDevice = null;
                         }
-                        mGroup.addClient(mPeers.get(deviceAddress));
+                        if (mPeers.get(deviceAddress) != null) {
+                            mGroup.addClient(mPeers.get(deviceAddress));
+                        } else {
+                            mGroup.addClient(deviceAddress);
+                        }
                         mPeers.updateStatus(deviceAddress, WifiP2pDevice.CONNECTED);
                         if (DBG) logd(getName() + " ap sta connected");
                         sendP2pPeersChangedBroadcast();