Merge "Pressed states for the notification panel's title area."
diff --git a/api/current.xml b/api/current.xml
index f98edab..c1d2f66 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -220707,6 +220707,17 @@
 <parameter name="autoScale" type="boolean">
 </parameter>
 </method>
+<method name="buildLayer"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="cancelLongPress"
  return="void"
  abstract="false"
@@ -233470,6 +233481,17 @@
  visibility="protected"
 >
 </method>
+<method name="getBackgroundColor"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getDetachWallpaper"
  return="boolean"
  abstract="false"
@@ -233755,6 +233777,19 @@
 <parameter name="listener" type="android.view.animation.Animation.AnimationListener">
 </parameter>
 </method>
+<method name="setBackgroundColor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="bg" type="int">
+</parameter>
+</method>
 <method name="setDetachWallpaper"
  return="void"
  abstract="false"
@@ -266669,7 +266704,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="t" type="T">
+<parameter name="arg0" type="T">
 </parameter>
 </method>
 </interface>
diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java
index 8b59554..22dd3c7 100644
--- a/core/java/android/animation/LayoutTransition.java
+++ b/core/java/android/animation/LayoutTransition.java
@@ -168,7 +168,9 @@
      */
     private final HashMap<View, Animator> pendingAnimations = new HashMap<View, Animator>();
     private final HashMap<View, Animator> currentChangingAnimations = new HashMap<View, Animator>();
-    private final HashMap<View, Animator> currentVisibilityAnimations =
+    private final HashMap<View, Animator> currentAppearingAnimations =
+            new HashMap<View, Animator>();
+    private final HashMap<View, Animator> currentDisappearingAnimations =
             new HashMap<View, Animator>();
 
     /**
@@ -709,7 +711,8 @@
      * @return true if any animations in the transition are running.
      */
     public boolean isRunning() {
-        return (currentChangingAnimations.size() > 0 || currentVisibilityAnimations.size() > 0);
+        return (currentChangingAnimations.size() > 0 || currentAppearingAnimations.size() > 0 ||
+                currentDisappearingAnimations.size() > 0);
     }
 
     /**
@@ -721,17 +724,74 @@
      * @hide
      */
     public void cancel() {
-        HashMap<View, Animator> currentAnimCopy =
-                (HashMap<View, Animator>) currentChangingAnimations.clone();
-        for (Animator anim : currentAnimCopy.values()) {
-            anim.cancel();
+        if (currentChangingAnimations.size() > 0) {
+            HashMap<View, Animator> currentAnimCopy =
+                    (HashMap<View, Animator>) currentChangingAnimations.clone();
+            for (Animator anim : currentAnimCopy.values()) {
+                anim.cancel();
+            }
+            currentChangingAnimations.clear();
         }
-        currentChangingAnimations.clear();
-        currentAnimCopy = (HashMap<View, Animator>) currentVisibilityAnimations.clone();
-        for (Animator anim : currentAnimCopy.values()) {
-            anim.end();
+        if (currentAppearingAnimations.size() > 0) {
+            HashMap<View, Animator> currentAnimCopy =
+                    (HashMap<View, Animator>) currentAppearingAnimations.clone();
+            for (Animator anim : currentAnimCopy.values()) {
+                anim.end();
+            }
+            currentAppearingAnimations.clear();
         }
-        currentVisibilityAnimations.clear();
+        if (currentDisappearingAnimations.size() > 0) {
+            HashMap<View, Animator> currentAnimCopy =
+                    (HashMap<View, Animator>) currentDisappearingAnimations.clone();
+            for (Animator anim : currentAnimCopy.values()) {
+                anim.end();
+            }
+            currentDisappearingAnimations.clear();
+        }
+    }
+
+    /**
+     * Cancels the specified type of transition. Note that we cancel() the changing animations
+     * but end() the visibility animations. This is because this method is currently called
+     * in the context of starting a new transition, so we want to move things from their mid-
+     * transition positions, but we want them to have their end-transition visibility.
+     *
+     * @hide
+     */
+    public void cancel(int transitionType) {
+        switch (transitionType) {
+            case CHANGE_APPEARING:
+            case CHANGE_DISAPPEARING:
+                if (currentChangingAnimations.size() > 0) {
+                    HashMap<View, Animator> currentAnimCopy =
+                            (HashMap<View, Animator>) currentChangingAnimations.clone();
+                    for (Animator anim : currentAnimCopy.values()) {
+                        anim.cancel();
+                    }
+                    currentChangingAnimations.clear();
+                }
+                break;
+            case APPEARING:
+                if (currentAppearingAnimations.size() > 0) {
+                    HashMap<View, Animator> currentAnimCopy =
+                            (HashMap<View, Animator>) currentAppearingAnimations.clone();
+                    for (Animator anim : currentAnimCopy.values()) {
+                        anim.end();
+                    }
+                    currentAppearingAnimations.clear();
+                }
+                break;
+            case DISAPPEARING:
+                if (currentDisappearingAnimations.size() > 0) {
+                    HashMap<View, Animator> currentAnimCopy =
+                            (HashMap<View, Animator>) currentDisappearingAnimations.clone();
+                    for (Animator anim : currentAnimCopy.values()) {
+                        anim.end();
+                    }
+                    currentDisappearingAnimations.clear();
+                }
+                break;
+        }
     }
 
     /**
@@ -741,7 +801,7 @@
      * @param child The View being added to the ViewGroup.
      */
     private void runAppearingTransition(final ViewGroup parent, final View child) {
-        Animator currentAnimation = currentVisibilityAnimations.get(child);
+        Animator currentAnimation = currentDisappearingAnimations.get(child);
         if (currentAnimation != null) {
             currentAnimation.cancel();
         }
@@ -764,14 +824,14 @@
             anim.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationEnd(Animator anim) {
-                    currentVisibilityAnimations.remove(child);
+                    currentAppearingAnimations.remove(child);
                     for (TransitionListener listener : mListeners) {
                         listener.endTransition(LayoutTransition.this, parent, child, APPEARING);
                     }
                 }
             });
         }
-        currentVisibilityAnimations.put(child, anim);
+        currentAppearingAnimations.put(child, anim);
         anim.start();
     }
 
@@ -782,7 +842,7 @@
      * @param child The View being removed from the ViewGroup.
      */
     private void runDisappearingTransition(final ViewGroup parent, final View child) {
-        Animator currentAnimation = currentVisibilityAnimations.get(child);
+        Animator currentAnimation = currentAppearingAnimations.get(child);
         if (currentAnimation != null) {
             currentAnimation.cancel();
         }
@@ -802,7 +862,7 @@
             anim.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationEnd(Animator anim) {
-                    currentVisibilityAnimations.remove(child);
+                    currentDisappearingAnimations.remove(child);
                     for (TransitionListener listener : mListeners) {
                         listener.endTransition(LayoutTransition.this, parent, child, DISAPPEARING);
                     }
@@ -812,7 +872,7 @@
         if (anim instanceof ObjectAnimator) {
             ((ObjectAnimator) anim).setCurrentPlayTime(0);
         }
-        currentVisibilityAnimations.put(child, anim);
+        currentDisappearingAnimations.put(child, anim);
         anim.start();
     }
 
@@ -826,9 +886,10 @@
      * @param child The View being added to the ViewGroup.
      */
     public void addChild(ViewGroup parent, View child) {
-        if (isRunning()) {
-            cancel();
-        }
+        // Want disappearing animations to finish up before proceeding
+        cancel(DISAPPEARING);
+        // Also, cancel changing animations so that we start fresh ones from current locations
+        cancel(CHANGE_APPEARING);
         if (mListeners != null) {
             for (TransitionListener listener : mListeners) {
                 listener.startTransition(this, parent, child, APPEARING);
@@ -861,9 +922,10 @@
      * @param child The View being removed from the ViewGroup.
      */
     public void removeChild(ViewGroup parent, View child) {
-        if (isRunning()) {
-            cancel();
-        }
+        // Want appearing animations to finish up before proceeding
+        cancel(APPEARING);
+        // Also, cancel changing animations so that we start fresh ones from current locations
+        cancel(CHANGE_DISAPPEARING);
         if (mListeners != null) {
             for (TransitionListener listener : mListeners) {
                 listener.startTransition(this, parent, child, DISAPPEARING);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 8f9a76b..b409f2f 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -98,7 +98,6 @@
 import java.util.regex.Pattern;
 
 import dalvik.system.CloseGuard;
-import dalvik.system.SamplingProfiler;
 
 final class SuperNotCalledException extends AndroidRuntimeException {
     public SuperNotCalledException(String msg) {
@@ -355,6 +354,7 @@
         boolean restrictedBackupMode;
         Configuration config;
         boolean handlingProfiling;
+        Bundle coreSettings;
         public String toString() {
             return "AppBindData{appInfo=" + appInfo + "}";
         }
@@ -552,7 +552,7 @@
                 ComponentName instrumentationName, String profileFile,
                 Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
                 int debugMode, boolean isRestrictedBackupMode, Configuration config,
-                Map<String, IBinder> services) {
+                Map<String, IBinder> services, Bundle coreSettings) {
 
             if (services != null) {
                 // Setup the service cache in the ServiceManager
@@ -570,6 +570,7 @@
             data.debugMode = debugMode;
             data.restrictedBackupMode = isRestrictedBackupMode;
             data.config = config;
+            data.coreSettings = coreSettings;
             queueOrSendMessage(H.BIND_APPLICATION, data);
         }
 
@@ -896,6 +897,10 @@
         private void printRow(PrintWriter pw, String format, Object...objs) {
             pw.println(String.format(format, objs));
         }
+
+        public void setCoreSettings(Bundle settings) {
+            queueOrSendMessage(H.SET_CORE_SETTINGS, settings);
+        }
     }
 
     private final class H extends Handler {
@@ -937,6 +942,7 @@
         public static final int DUMP_HEAP               = 135;
         public static final int DUMP_ACTIVITY           = 136;
         public static final int SLEEPING                = 137;
+        public static final int SET_CORE_SETTINGS       = 138;
         String codeToString(int code) {
             if (DEBUG_MESSAGES) {
                 switch (code) {
@@ -978,6 +984,7 @@
                     case DUMP_HEAP: return "DUMP_HEAP";
                     case DUMP_ACTIVITY: return "DUMP_ACTIVITY";
                     case SLEEPING: return "SLEEPING";
+                    case SET_CORE_SETTINGS: return "SET_CORE_SETTINGS";
                 }
             }
             return "(unknown)";
@@ -1113,6 +1120,9 @@
                 case SLEEPING:
                     handleSleeping((IBinder)msg.obj, msg.arg1 != 0);
                     break;
+                case SET_CORE_SETTINGS:
+                    handleSetCoreSettings((Bundle) msg.obj);
+                    break;
             }
             if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + msg.what);
         }
@@ -2709,6 +2719,14 @@
         }
     }
 
+    private void handleSetCoreSettings(Bundle coreSettings) {
+        if (mBoundApplication != null) {
+            synchronized (mBoundApplication) {
+                mBoundApplication.coreSettings = coreSettings;
+            }
+        }
+    }
+
     private final void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
         final int N = results.size();
         for (int i=0; i<N; i++) {
@@ -3971,6 +3989,20 @@
         }
     }
 
+    public int getIntCoreSetting(String key, int defaultValue) {
+        if (mBoundApplication == null) {
+            return defaultValue;
+        }
+        synchronized (mBoundApplication) {
+            Bundle coreSettings = mBoundApplication.coreSettings;
+            if (coreSettings != null) {
+                return coreSettings.getInt(key, defaultValue);
+            } else {
+                return defaultValue;
+            }
+        }
+    }
+
     public static final void main(String[] args) {
         SamplingProfilerIntegration.start();
 
diff --git a/core/java/android/app/AppGlobals.java b/core/java/android/app/AppGlobals.java
index 9a39129..55515b8 100644
--- a/core/java/android/app/AppGlobals.java
+++ b/core/java/android/app/AppGlobals.java
@@ -38,12 +38,23 @@
     public static String getInitialPackage() {
         return ActivityThread.currentPackageName();
     }
-    
+
     /**
      * Return the raw interface to the package manager.
-     * @return
+     * @return The package manager.
      */
     public static IPackageManager getPackageManager() {
         return ActivityThread.getPackageManager();
     }
+
+    /**
+     * Gets the value of an integer core setting.
+     *
+     * @param key The setting key.
+     * @param defaultValue The setting default value.
+     * @return The core settings.
+     */
+    public static int getIntCoreSetting(String key, int defaultValue) {
+        return ActivityThread.currentActivityThread().getIntCoreSetting(key, defaultValue);
+    }
 }
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index ef92933..aa26b04 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -257,10 +257,11 @@
             boolean restrictedBackupMode = (data.readInt() != 0);
             Configuration config = Configuration.CREATOR.createFromParcel(data);
             HashMap<String, IBinder> services = data.readHashMap(null);
+            Bundle coreSettings = data.readBundle();
             bindApplication(packageName, info,
                             providers, testName, profileName,
                             testArgs, testWatcher, testMode, restrictedBackupMode,
-                            config, services);
+                            config, services, coreSettings);
             return true;
         }
         
@@ -454,6 +455,13 @@
             }
             return true;
         }
+
+        case SET_CORE_SETTINGS: {
+            data.enforceInterface(IApplicationThread.descriptor);
+            Bundle settings = data.readBundle();
+            setCoreSettings(settings);
+            return true;
+        }
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -712,7 +720,7 @@
             List<ProviderInfo> providers, ComponentName testName,
             String profileName, Bundle testArgs, IInstrumentationWatcher testWatcher, int debugMode,
             boolean restrictedBackupMode, Configuration config,
-            Map<String, IBinder> services) throws RemoteException {
+            Map<String, IBinder> services, Bundle coreSettings) throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeString(packageName);
@@ -731,6 +739,7 @@
         data.writeInt(restrictedBackupMode ? 1 : 0);
         config.writeToParcel(data, 0);
         data.writeMap(services);
+        data.writeBundle(coreSettings);
         mRemote.transact(BIND_APPLICATION_TRANSACTION, data, null,
                 IBinder.FLAG_ONEWAY);
         data.recycle();
@@ -938,4 +947,11 @@
         mRemote.transact(DUMP_ACTIVITY_TRANSACTION, data, null, 0);
         data.recycle();
     }
+
+    public void setCoreSettings(Bundle coreSettings) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        data.writeInterfaceToken(IApplicationThread.descriptor);
+        data.writeBundle(coreSettings);
+        mRemote.transact(SET_CORE_SETTINGS, data, null, IBinder.FLAG_ONEWAY);
+    }
 }
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 16c3c5c..55177a9 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -82,7 +82,8 @@
     void bindApplication(String packageName, ApplicationInfo info, List<ProviderInfo> providers,
             ComponentName testName, String profileName, Bundle testArguments, 
             IInstrumentationWatcher testWatcher, int debugMode, boolean restrictedBackupMode,
-            Configuration config, Map<String, IBinder> services) throws RemoteException;
+            Configuration config, Map<String, IBinder> services,
+            Bundle coreSettings) throws RemoteException;
     void scheduleExit() throws RemoteException;
     void scheduleSuicide() throws RemoteException;
     void requestThumbnail(IBinder token) throws RemoteException;
@@ -110,6 +111,7 @@
     void scheduleCrash(String msg) throws RemoteException;
     void dumpActivity(FileDescriptor fd, IBinder servicetoken, String prefix, String[] args)
             throws RemoteException;
+    void setCoreSettings(Bundle coreSettings) throws RemoteException;
 
     String descriptor = "android.app.IApplicationThread";
 
@@ -151,4 +153,5 @@
     int DUMP_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+36;
     int CLEAR_DNS_CACHE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+37;
     int SET_HTTP_PROXY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+38;
+    int SET_CORE_SETTINGS = IBinder.FIRST_CALL_TRANSACTION+39;
 }
diff --git a/core/java/android/preference/PreferenceFragment.java b/core/java/android/preference/PreferenceFragment.java
index b96defe..4e22ba0 100644
--- a/core/java/android/preference/PreferenceFragment.java
+++ b/core/java/android/preference/PreferenceFragment.java
@@ -187,6 +187,7 @@
     public void onDestroyView() {
         mList = null;
         mHandler.removeCallbacks(mRequestFocus);
+        mHandler.removeMessages(MSG_BIND_PREFERENCES);
         super.onDestroyView();
     }
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1718189..6deb5a0 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2698,6 +2698,12 @@
             "accessibility_web_content_key_bindings";
 
         /**
+         * The timout for considering a press to be a long press in milliseconds.
+         * @hide
+         */
+        public static final String LONG_PRESS_TIMEOUT = "long_press_timeout";
+
+        /**
          * Setting to always use the default text-to-speech settings regardless
          * of the application settings.
          * 1 = override application settings,
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index fc01ef2..53fa7c2 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -1169,6 +1169,30 @@
         return ret;
     }
 
+    /**
+     * Returns the next cursor position in the run.  This avoids placing the cursor between
+     * surrogates, between characters that form conjuncts, between base characters and combining
+     * marks, or within a reordering cluster.
+     *
+     * <p>The context is the shaping context for cursor movement, generally the bounds of the metric
+     * span enclosing the cursor in the direction of movement.
+     * <code>contextStart</code>, <code>contextEnd</code> and <code>offset</code> are relative to
+     * the start of the string.</p>
+     *
+     * <p>If cursorOpt is CURSOR_AT and the offset is not a valid cursor position,
+     * this returns -1.  Otherwise this will never return a value before contextStart or after
+     * contextEnd.</p>
+     *
+     * @param contextStart the start index of the context
+     * @param contextEnd the (non-inclusive) end index of the context
+     * @param flags either DIRECTION_RTL or DIRECTION_LTR
+     * @param offset the cursor position to move from
+     * @param cursorOpt how to move the cursor, one of CURSOR_AFTER,
+     * CURSOR_AT_OR_AFTER, CURSOR_BEFORE,
+     * CURSOR_AT_OR_BEFORE, or CURSOR_AT
+     * @param p the Paint object that is requesting this information
+     * @return the offset of the next position, or -1
+     */
     public int getTextRunCursor(int contextStart, int contextEnd, int flags, int offset,
             int cursorOpt, Paint p) {
 
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index a26dd04..076f712 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -937,6 +937,7 @@
     private static native int nativeSetSource(int nativePtr, int source);
     private static native int nativeGetAction(int nativePtr);
     private static native void nativeSetAction(int nativePtr, int action);
+    private static native boolean nativeIsTouchEvent(int nativePtr);
     private static native int nativeGetFlags(int nativePtr);
     private static native int nativeGetEdgeFlags(int nativePtr);
     private static native void nativeSetEdgeFlags(int nativePtr, int action);
@@ -1275,19 +1276,7 @@
      * @hide
      */
     public final boolean isTouchEvent() {
-        if ((getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
-            switch (getActionMasked()) {
-                case MotionEvent.ACTION_DOWN:
-                case MotionEvent.ACTION_MOVE:
-                case MotionEvent.ACTION_UP:
-                case MotionEvent.ACTION_POINTER_DOWN:
-                case MotionEvent.ACTION_POINTER_UP:
-                case MotionEvent.ACTION_CANCEL:
-                case MotionEvent.ACTION_OUTSIDE:
-                    return true;
-            }
-        }
-        return false;
+        return nativeIsTouchEvent(mNativePtr);
     }
 
     /**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 2170d72..32c9e27 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8488,6 +8488,7 @@
      *         {@link #LAYER_TYPE_HARDWARE}
      *
      * @see #setLayerType(int, android.graphics.Paint)
+     * @see #buildLayer() 
      * @see #LAYER_TYPE_NONE
      * @see #LAYER_TYPE_SOFTWARE
      * @see #LAYER_TYPE_HARDWARE
@@ -8497,6 +8498,36 @@
     }
 
     /**
+     * Forces this view's layer to be created and this view to be rendered
+     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
+     * invoking this method will have no effect.
+     * 
+     * This method can for instance be used to render a view into its layer before
+     * starting an animation. If this view is complex, rendering into the layer
+     * before starting the animation will avoid skipping frames.
+     * 
+     * @throws IllegalStateException If this view is not attached to a window
+     * 
+     * @see #setLayerType(int, android.graphics.Paint) 
+     */
+    public void buildLayer() {
+        if (mLayerType == LAYER_TYPE_NONE) return;
+
+        if (mAttachInfo == null) {
+            throw new IllegalStateException("This view must be attached to a window first");
+        }
+
+        switch (mLayerType) {
+            case LAYER_TYPE_HARDWARE:
+                getHardwareLayer();
+                break;
+            case LAYER_TYPE_SOFTWARE:
+                buildDrawingCache(true);
+                break;
+        }
+    }
+
+    /**
      * <p>Returns a hardware layer that can be used to draw this view again
      * without executing its draw method.</p>
      *
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index cc4e89c..d95c5b0 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -16,8 +16,11 @@
 
 package android.view;
 
+import android.app.AppGlobals;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.os.Bundle;
+import android.provider.Settings;
 import android.util.DisplayMetrics;
 import android.util.SparseArray;
 
@@ -74,7 +77,7 @@
      * Defines the duration in milliseconds before a press turns into
      * a long press
      */
-    private static final int LONG_PRESS_TIMEOUT = 500;
+    private static final int DEFAULTLONG_PRESS_TIMEOUT = 500;
     
     /**
      * Defines the duration in milliseconds a user needs to hold down the
@@ -320,15 +323,16 @@
     public static int getPressedStateDuration() {
         return PRESSED_STATE_DURATION;
     }
-    
+
     /**
      * @return the duration in milliseconds before a press turns into
      * a long press
      */
     public static int getLongPressTimeout() {
-        return LONG_PRESS_TIMEOUT;
+        return AppGlobals.getIntCoreSetting(Settings.Secure.LONG_PRESS_TIMEOUT,
+                DEFAULTLONG_PRESS_TIMEOUT);
     }
-    
+
     /**
      * @return the duration in milliseconds we will wait to see if a touch event
      * is a tap or a scroll. If the user does not move within this interval, it is
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index af4c221..3153ac5 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3001,8 +3001,10 @@
     private void addViewInner(View child, int index, LayoutParams params,
             boolean preventRequestLayout) {
 
-        if (mTransition != null && mTransition.isRunning()) {
-            mTransition.cancel();
+        if (mTransition != null) {
+            // Don't prevent other add transitions from completing, but cancel remove
+            // transitions to let them complete the process before we add to the container
+            mTransition.cancel(LayoutTransition.DISAPPEARING);
         }
 
         if (child.getParent() != null) {
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index be68cb9..334c68e 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -573,7 +573,21 @@
      *          {@link #ACTION_POKE_USER_ACTIVITY} and {@link #ACTION_GO_TO_SLEEP} flags.
      */
     public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn);
-    
+
+    /**
+     * Called from the input reader thread before a motion is enqueued when the screen is off.
+     *
+     * <p>There are some actions that need to be handled here because they
+     * affect the power state of the device, for example, waking on motions.
+     * Generally, it's best to keep as little as possible in the queue thread
+     * because it's the most fragile.
+     * @param policyFlags The policy flags associated with the motion.
+     *
+     * @return The bitwise or of the {@link #ACTION_PASS_TO_USER},
+     *          {@link #ACTION_POKE_USER_ACTIVITY} and {@link #ACTION_GO_TO_SLEEP} flags.
+     */
+    public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags);
+
     /**
      * Called from the input dispatcher thread before a key is dispatched to a window.
      *
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index 13d0ec1..87c759c 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -181,6 +181,11 @@
     private int mZAdjustment;
 
     /**
+     * Desired background color behind animation.
+     */
+    private int mBackgroundColor;
+
+    /**
      * scalefactor to apply to pivot points, etc. during animation. Subclasses retrieve the
      * value via getScaleFactor().
      */
@@ -236,6 +241,8 @@
 
         setZAdjustment(a.getInt(com.android.internal.R.styleable.Animation_zAdjustment, ZORDER_NORMAL));
         
+        setBackgroundColor(a.getInt(com.android.internal.R.styleable.Animation_background, 0));
+
         setDetachWallpaper(a.getBoolean(com.android.internal.R.styleable.Animation_detachWallpaper, false));
         
         ensureInterpolator();
@@ -568,6 +575,16 @@
     }
     
     /**
+     * Set background behind animation.
+     *
+     * @param bg The background color.  If 0, no background.  Currently must
+     * be black, with any desired alpha level.
+     */
+    public void setBackgroundColor(int bg) {
+        mBackgroundColor = bg;
+    }
+
+    /**
      * The scale factor is set by the call to <code>getTransformation</code>. Overrides of 
      * {@link #getTransformation(long, Transformation, float)} will get this value
      * directly. Overrides of {@link #applyTransformation(float, Transformation)} can
@@ -690,6 +707,13 @@
     }
 
     /**
+     * Returns the background color behind the animation.
+     */
+    public int getBackgroundColor() {
+        return mBackgroundColor;
+    }
+
+    /**
      * Return value of {@link #setDetachWallpaper(boolean)}.
      * @attr ref android.R.styleable#Animation_detachWallpaper
      */
diff --git a/core/java/android/widget/EdgeGlow.java b/core/java/android/widget/EdgeGlow.java
index c2cb0a0..75cef38 100644
--- a/core/java/android/widget/EdgeGlow.java
+++ b/core/java/android/widget/EdgeGlow.java
@@ -260,7 +260,7 @@
                 glowHeight * MAX_GLOW_HEIGHT);
         if (mWidth < mMinWidth) {
             // Center the glow and clip it.
-            int glowLeft = (mWidth - glowWidth)/2;
+            int glowLeft = (mWidth - mMinWidth)/2;
             mGlow.setBounds(glowLeft, 0, mWidth - glowLeft, glowBottom);
         } else {
             // Stretch the glow to fit.
@@ -274,7 +274,7 @@
         int edgeBottom = (int) (edgeHeight * mEdgeScaleY);
         if (mWidth < mMinWidth) {
             // Center the edge and clip it.
-            int edgeLeft = (mWidth - edgeWidth)/2;
+            int edgeLeft = (mWidth - mMinWidth)/2;
             mEdge.setBounds(edgeLeft, 0, mWidth - edgeLeft, edgeBottom);
         } else {
             // Stretch the edge to fit.
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index b014006..97cba23 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -429,6 +429,12 @@
     event->setAction(action);
 }
 
+static jboolean android_view_MotionEvent_nativeIsTouchEvent(JNIEnv* env, jclass clazz,
+        jint nativePtr) {
+    MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
+    return event->isTouchEvent();
+}
+
 static jint android_view_MotionEvent_nativeGetFlags(JNIEnv* env, jclass clazz,
         jint nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
@@ -661,6 +667,9 @@
     { "nativeSetAction",
             "(II)V",
             (void*)android_view_MotionEvent_nativeSetAction },
+    { "nativeIsTouchEvent",
+            "(I)Z",
+            (void*)android_view_MotionEvent_nativeIsTouchEvent },
     { "nativeGetFlags",
             "(I)I",
             (void*)android_view_MotionEvent_nativeGetFlags },
diff --git a/core/res/res/anim/task_close_enter.xml b/core/res/res/anim/task_close_enter.xml
index b479543..66d982f 100644
--- a/core/res/res/anim/task_close_enter.xml
+++ b/core/res/res/anim/task_close_enter.xml
@@ -18,7 +18,7 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:detachWallpaper="true" android:shareInterpolator="false">
+        android:background="#ff000000" android:shareInterpolator="false">
     <scale 	android:fromXScale="1.0" android:toXScale="1.0"
             android:fromYScale="0.95" android:toYScale="1.0"
             android:pivotX="50%p" android:pivotY="50%p"
diff --git a/core/res/res/anim/task_close_exit.xml b/core/res/res/anim/task_close_exit.xml
index e561e97..312946b 100644
--- a/core/res/res/anim/task_close_exit.xml
+++ b/core/res/res/anim/task_close_exit.xml
@@ -18,7 +18,7 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:detachWallpaper="true" android:shareInterpolator="false">
+        android:background="#ff000000" android:shareInterpolator="false">
     <scale android:fromXScale="1.0" android:toXScale="1.0"
             android:fromYScale="1.0" android:toYScale="0.0"
             android:pivotX="50%p" android:pivotY="50%p"
diff --git a/core/res/res/anim/task_open_enter.xml b/core/res/res/anim/task_open_enter.xml
index b3b3fd1..3dda797 100644
--- a/core/res/res/anim/task_open_enter.xml
+++ b/core/res/res/anim/task_open_enter.xml
@@ -18,7 +18,7 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:detachWallpaper="true" android:shareInterpolator="false">
+        android:background="#ff000000" android:shareInterpolator="false">
     <scale android:fromXScale="1.0" android:toXScale="1.0"
             android:fromYScale=".9" android:toYScale="1.0"
             android:pivotX="50%p" android:pivotY="50%p"
diff --git a/core/res/res/anim/task_open_exit.xml b/core/res/res/anim/task_open_exit.xml
index 763b581..e377c2a 100644
--- a/core/res/res/anim/task_open_exit.xml
+++ b/core/res/res/anim/task_open_exit.xml
@@ -18,7 +18,7 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:detachWallpaper="true" android:shareInterpolator="false">
+        android:background="#ff000000" android:shareInterpolator="false">
     <scale android:fromXScale="1.0" android:toXScale="1.0"
             android:fromYScale="1.0" android:toYScale="0.0"
             android:pivotX="50%p" android:pivotY="50%p"
diff --git a/core/res/res/drawable-hdpi/ic_paste_bubble_holo.png b/core/res/res/drawable-hdpi/ic_paste_bubble_holo.png
new file mode 100644
index 0000000..15bd8b2
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_paste_bubble_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_section_divider_holo_dark.9.png b/core/res/res/drawable-hdpi/list_section_divider_holo_dark.9.png
index 2dabb5f..21e2fb9 100644
--- a/core/res/res/drawable-hdpi/list_section_divider_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/list_section_divider_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_section_divider_holo_light.9.png b/core/res/res/drawable-hdpi/list_section_divider_holo_light.9.png
index 8069452..8e9c02c 100644
--- a/core/res/res/drawable-hdpi/list_section_divider_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/list_section_divider_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_edit_paste_window.9.png b/core/res/res/drawable-hdpi/text_edit_paste_window.9.png
index 7cd000b..6654e4d 100644
--- a/core/res/res/drawable-hdpi/text_edit_paste_window.9.png
+++ b/core/res/res/drawable-hdpi/text_edit_paste_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_edit_side_paste_window.9.png b/core/res/res/drawable-hdpi/text_edit_side_paste_window.9.png
index 7cd000b..c564495 100644
--- a/core/res/res/drawable-hdpi/text_edit_side_paste_window.9.png
+++ b/core/res/res/drawable-hdpi/text_edit_side_paste_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_left.png b/core/res/res/drawable-hdpi/text_select_handle_left.png
old mode 100755
new mode 100644
index 3743d91..e42a62e
--- a/core/res/res/drawable-hdpi/text_select_handle_left.png
+++ b/core/res/res/drawable-hdpi/text_select_handle_left.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_middle.png b/core/res/res/drawable-hdpi/text_select_handle_middle.png
old mode 100755
new mode 100644
index 5a83c6c..00d47f2
--- a/core/res/res/drawable-hdpi/text_select_handle_middle.png
+++ b/core/res/res/drawable-hdpi/text_select_handle_middle.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_right.png b/core/res/res/drawable-hdpi/text_select_handle_right.png
old mode 100755
new mode 100644
index 12a3dff..7426543
--- a/core/res/res/drawable-hdpi/text_select_handle_right.png
+++ b/core/res/res/drawable-hdpi/text_select_handle_right.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_paste_bubble_holo.png b/core/res/res/drawable-mdpi/ic_paste_bubble_holo.png
new file mode 100644
index 0000000..e483e84
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_paste_bubble_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_section_divider_holo_dark.9.png b/core/res/res/drawable-mdpi/list_section_divider_holo_dark.9.png
index f873edb..b888135 100644
--- a/core/res/res/drawable-mdpi/list_section_divider_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/list_section_divider_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_section_divider_holo_light.9.png b/core/res/res/drawable-mdpi/list_section_divider_holo_light.9.png
index ba11cfb..1cc1f7f 100644
--- a/core/res/res/drawable-mdpi/list_section_divider_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/list_section_divider_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_edit_paste_window.9.png b/core/res/res/drawable-mdpi/text_edit_paste_window.9.png
index 6b98c13..41886eb 100644
--- a/core/res/res/drawable-mdpi/text_edit_paste_window.9.png
+++ b/core/res/res/drawable-mdpi/text_edit_paste_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_edit_side_paste_window.9.png b/core/res/res/drawable-mdpi/text_edit_side_paste_window.9.png
index d87c35b..d8ae54c 100644
--- a/core/res/res/drawable-mdpi/text_edit_side_paste_window.9.png
+++ b/core/res/res/drawable-mdpi/text_edit_side_paste_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_left.png b/core/res/res/drawable-mdpi/text_select_handle_left.png
index 4ee2f42..959887f 100644
--- a/core/res/res/drawable-mdpi/text_select_handle_left.png
+++ b/core/res/res/drawable-mdpi/text_select_handle_left.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_middle.png b/core/res/res/drawable-mdpi/text_select_handle_middle.png
index 3d16052..42d4e1a 100644
--- a/core/res/res/drawable-mdpi/text_select_handle_middle.png
+++ b/core/res/res/drawable-mdpi/text_select_handle_middle.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_right.png b/core/res/res/drawable-mdpi/text_select_handle_right.png
index 3d38928..61f9c12 100644
--- a/core/res/res/drawable-mdpi/text_select_handle_right.png
+++ b/core/res/res/drawable-mdpi/text_select_handle_right.png
Binary files differ
diff --git a/core/res/res/layout/text_edit_paste_window.xml b/core/res/res/layout/text_edit_paste_window.xml
index 575b98e..01e5530 100644
--- a/core/res/res/layout/text_edit_paste_window.xml
+++ b/core/res/res/layout/text_edit_paste_window.xml
@@ -24,8 +24,8 @@
         android:paddingLeft="16dip"
         android:paddingRight="16dip"
         android:paddingTop="8dip"
-        android:paddingBottom="8dip"
-        android:drawableLeft="@android:drawable/ic_menu_paste_light"
+        android:paddingBottom="12dip"
+        android:drawableLeft="@android:drawable/ic_paste_bubble_holo"
         android:drawablePadding="8dip"
         android:gravity="center"
         android:textAppearance="?android:attr/textAppearanceMediumInverse"
diff --git a/core/res/res/layout/text_edit_side_paste_window.xml b/core/res/res/layout/text_edit_side_paste_window.xml
index 689a039..6651786 100644
--- a/core/res/res/layout/text_edit_side_paste_window.xml
+++ b/core/res/res/layout/text_edit_side_paste_window.xml
@@ -25,7 +25,7 @@
         android:paddingRight="16dip"
         android:paddingTop="8dip"
         android:paddingBottom="8dip"
-        android:drawableLeft="@android:drawable/ic_menu_paste_light"
+        android:drawableLeft="@android:drawable/ic_paste_bubble_holo"
         android:drawablePadding="8dip"
         android:gravity="center"
         android:textAppearance="?android:attr/textAppearanceMediumInverse"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 3b225a4..d3b1062 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3596,6 +3596,10 @@
                  content for the duration of the animation. -->
             <enum name="bottom" value="-1" />
         </attr>
+        <!-- Special background behind animation.  Only for use with window
+             animations.  Can only be a color, and only black.  If 0, the
+             default, there is no background. -->
+        <attr name="background" />
         <!-- Special option for window animations: if this window is on top
              of a wallpaper, don't animate the wallpaper with it. -->
         <attr name="detachWallpaper" format="boolean" />
diff --git a/data/sounds/effects/ogg/Lock.ogg b/data/sounds/effects/ogg/Lock.ogg
index 2e57d9e..a25513f 100644
--- a/data/sounds/effects/ogg/Lock.ogg
+++ b/data/sounds/effects/ogg/Lock.ogg
Binary files differ
diff --git a/drm/java/android/drm/DrmManagerClient.java b/drm/java/android/drm/DrmManagerClient.java
index 6caf678..c541456 100644
--- a/drm/java/android/drm/DrmManagerClient.java
+++ b/drm/java/android/drm/DrmManagerClient.java
@@ -479,6 +479,9 @@
      */
     public int acquireRights(DrmInfoRequest drmInfoRequest) {
         DrmInfo drmInfo = acquireDrmInfo(drmInfoRequest);
+        if (null == drmInfo) {
+            return ERROR_UNKNOWN;
+        }
         return processDrmInfo(drmInfo);
     }
 
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
index cce9129..7956788 100644
--- a/include/media/IMediaPlayerService.h
+++ b/include/media/IMediaPlayerService.h
@@ -55,17 +55,25 @@
     virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
     virtual sp<IOMX>            getOMX() = 0;
 
-    // codecs usage tracking for the battery app
+    // codecs and audio devices usage tracking for the battery app
     enum BatteryDataBits {
         // tracking audio codec
-        kBatteryDataTrackAudio          = 1,
+        kBatteryDataTrackAudio          = 0x1,
         // tracking video codec
-        kBatteryDataTrackVideo          = 2,
+        kBatteryDataTrackVideo          = 0x2,
         // codec is started, otherwise codec is paused
-        kBatteryDataCodecStarted        = 4,
+        kBatteryDataCodecStarted        = 0x4,
         // tracking decoder (for media player),
         // otherwise tracking encoder (for media recorder)
-        kBatteryDataTrackDecoder        = 8,
+        kBatteryDataTrackDecoder        = 0x8,
+        // start to play an audio on an audio device
+        kBatteryDataAudioFlingerStart   = 0x10,
+        // stop/pause the audio playback
+        kBatteryDataAudioFlingerStop    = 0x20,
+        // audio is rounted to speaker
+        kBatteryDataSpeakerOn           = 0x40,
+        // audio is rounted to devices other than speaker
+        kBatteryDataOtherAudioDeviceOn  = 0x80,
     };
 
     virtual void addBatteryData(uint32_t params) = 0;
diff --git a/include/ui/Input.h b/include/ui/Input.h
index 082f11c..e92d7f5 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -476,6 +476,11 @@
     status_t writeToParcel(Parcel* parcel) const;
 #endif
 
+    static bool isTouchEvent(int32_t source, int32_t action);
+    inline bool isTouchEvent() const {
+        return isTouchEvent(mSource, mAction);
+    }
+
     // Low-level accessors.
     inline const int32_t* getPointerIds() const { return mPointerIds.array(); }
     inline const nsecs_t* getSampleEventTimes() const { return mSampleEventTimes.array(); }
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp
index a80320e..0ed0866 100644
--- a/libs/ui/Input.cpp
+++ b/libs/ui/Input.cpp
@@ -616,6 +616,23 @@
 }
 #endif
 
+bool MotionEvent::isTouchEvent(int32_t source, int32_t action) {
+    if (source & AINPUT_SOURCE_CLASS_POINTER) {
+        // Specifically excludes HOVER_MOVE and SCROLL.
+        switch (action & AMOTION_EVENT_ACTION_MASK) {
+        case AMOTION_EVENT_ACTION_DOWN:
+        case AMOTION_EVENT_ACTION_MOVE:
+        case AMOTION_EVENT_ACTION_UP:
+        case AMOTION_EVENT_ACTION_POINTER_DOWN:
+        case AMOTION_EVENT_ACTION_POINTER_UP:
+        case AMOTION_EVENT_ACTION_CANCEL:
+        case AMOTION_EVENT_ACTION_OUTSIDE:
+            return true;
+        }
+    }
+    return false;
+}
+
 
 // --- InputDeviceInfo ---
 
diff --git a/media/java/android/mtp/MtpClient.java b/media/java/android/mtp/MtpClient.java
index 6c8b228..c4ee19e 100644
--- a/media/java/android/mtp/MtpClient.java
+++ b/media/java/android/mtp/MtpClient.java
@@ -163,15 +163,6 @@
         mContext.unregisterReceiver(mUsbReceiver);
     }
 
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            close();
-        } finally {
-            super.finalize();
-        }
-    }
-
     /**
      * Registers a {@link android.mtp.MtpClient.Listener} interface to receive
      * notifications when MTP or PTP devices are added or removed.
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index ec6188f..a42cca5 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -214,6 +214,15 @@
 {
     LOGV("MediaPlayerService created");
     mNextConnId = 1;
+
+    mBatteryAudio.refCount = 0;
+    for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
+        mBatteryAudio.deviceOn[i] = 0;
+        mBatteryAudio.lastTime[i] = 0;
+        mBatteryAudio.totalTime[i] = 0;
+    }
+    // speaker is on by default
+    mBatteryAudio.deviceOn[SPEAKER] = 1;
 }
 
 MediaPlayerService::~MediaPlayerService()
@@ -1777,12 +1786,88 @@
 void MediaPlayerService::addBatteryData(uint32_t params)
 {
     Mutex::Autolock lock(mLock);
+
+    int32_t time = systemTime() / 1000000L;
+
+    // change audio output devices. This notification comes from AudioFlinger
+    if ((params & kBatteryDataSpeakerOn)
+            || (params & kBatteryDataOtherAudioDeviceOn)) {
+
+        int deviceOn[NUM_AUDIO_DEVICES];
+        for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
+            deviceOn[i] = 0;
+        }
+
+        if ((params & kBatteryDataSpeakerOn)
+                && (params & kBatteryDataOtherAudioDeviceOn)) {
+            deviceOn[SPEAKER_AND_OTHER] = 1;
+        } else if (params & kBatteryDataSpeakerOn) {
+            deviceOn[SPEAKER] = 1;
+        } else {
+            deviceOn[OTHER_AUDIO_DEVICE] = 1;
+        }
+
+        for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
+            if (mBatteryAudio.deviceOn[i] != deviceOn[i]){
+
+                if (mBatteryAudio.refCount > 0) { // if playing audio
+                    if (!deviceOn[i]) {
+                        mBatteryAudio.lastTime[i] += time;
+                        mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i];
+                        mBatteryAudio.lastTime[i] = 0;
+                    } else {
+                        mBatteryAudio.lastTime[i] = 0 - time;
+                    }
+                }
+
+                mBatteryAudio.deviceOn[i] = deviceOn[i];
+            }
+        }
+        return;
+    }
+
+    // an sudio stream is started
+    if (params & kBatteryDataAudioFlingerStart) {
+        // record the start time only if currently no other audio
+        // is being played
+        if (mBatteryAudio.refCount == 0) {
+            for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
+                if (mBatteryAudio.deviceOn[i]) {
+                    mBatteryAudio.lastTime[i] -= time;
+                }
+            }
+        }
+
+        mBatteryAudio.refCount ++;
+        return;
+
+    } else if (params & kBatteryDataAudioFlingerStop) {
+        if (mBatteryAudio.refCount <= 0) {
+            LOGW("Battery track warning: refCount is <= 0");
+            return;
+        }
+
+        // record the stop time only if currently this is the only
+        // audio being played
+        if (mBatteryAudio.refCount == 1) {
+            for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
+                if (mBatteryAudio.deviceOn[i]) {
+                    mBatteryAudio.lastTime[i] += time;
+                    mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i];
+                    mBatteryAudio.lastTime[i] = 0;
+                }
+            }
+        }
+
+        mBatteryAudio.refCount --;
+        return;
+    }
+
     int uid = IPCThreadState::self()->getCallingUid();
     if (uid == AID_MEDIA) {
         return;
     }
     int index = mBatteryData.indexOfKey(uid);
-    int32_t time = systemTime() / 1000000L;
 
     if (index < 0) { // create a new entry for this UID
         BatteryUsageInfo info;
@@ -1792,7 +1877,10 @@
         info.videoLastTime = 0;
         info.refCount = 0;
 
-        mBatteryData.add(uid, info);
+        if (mBatteryData.add(uid, info) == NO_MEMORY) {
+            LOGE("Battery track error: no memory for new app");
+            return;
+        }
     }
 
     BatteryUsageInfo &info = mBatteryData.editValueFor(uid);
@@ -1837,6 +1925,26 @@
 
 status_t MediaPlayerService::pullBatteryData(Parcel* reply) {
     Mutex::Autolock lock(mLock);
+
+    // audio output devices usage
+    int32_t time = systemTime() / 1000000L; //in ms
+    int32_t totalTime;
+
+    for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
+        totalTime = mBatteryAudio.totalTime[i];
+
+        if (mBatteryAudio.deviceOn[i]
+            && (mBatteryAudio.lastTime[i] != 0)) {
+                int32_t tmpTime = mBatteryAudio.lastTime[i] + time;
+                totalTime += tmpTime;
+        }
+
+        reply->writeInt32(totalTime);
+        // reset the total time
+        mBatteryAudio.totalTime[i] = 0;
+   }
+
+    // codec usage
     BatteryUsageInfo info;
     int size = mBatteryData.size();
 
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 1175ed0..ff6ccf54 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -225,6 +225,25 @@
     };
     KeyedVector<int, BatteryUsageInfo>    mBatteryData;
 
+    enum {
+        SPEAKER,
+        OTHER_AUDIO_DEVICE,
+        SPEAKER_AND_OTHER,
+        NUM_AUDIO_DEVICES
+    };
+
+    struct BatteryAudioFlingerUsageInfo {
+        int refCount; // how many audio streams are being played
+        int deviceOn[NUM_AUDIO_DEVICES]; // whether the device is currently used
+        int32_t lastTime[NUM_AUDIO_DEVICES]; // in ms
+        // totalTime[]: total time of audio output devices usage
+        int32_t totalTime[NUM_AUDIO_DEVICES]; // in ms
+    };
+
+    // This varialble is used to record the usage of audio output device
+    // for battery app
+    BatteryAudioFlingerUsageInfo mBatteryAudio;
+
     // Collect info of the codec usage from media player and media recorder
     virtual void                addBatteryData(uint32_t params);
     // API for the Battery app to pull the data of codecs usage
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 2df6d68..bf06f947 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -121,4 +121,8 @@
     <integer name="def_download_manager_max_bytes_over_mobile">-1</integer>
     <!-- Default for Settings.Secure.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE. <=0 if no limit -->
     <integer name="def_download_manager_recommended_max_bytes_over_mobile">-1</integer>
+
+    <!-- Default for Settings.Secure.LONG_PRESS_TIMEOUT_MILLIS -->
+    <integer name="def_long_press_timeout_millis">500</integer>
+
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index f336f06..d901c2c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -819,6 +819,24 @@
              upgradeVersion = 64;
          }
 
+        if (upgradeVersion == 64) {
+            // New setting to configure the long press timeout.
+            db.beginTransaction();
+            SQLiteStatement stmt = null;
+            try {
+                stmt = db.compileStatement("INSERT INTO secure(name,value)"
+                        + " VALUES(?,?);");
+                loadIntegerSetting(stmt, Settings.Secure.LONG_PRESS_TIMEOUT,
+                        R.integer.def_long_press_timeout_millis);
+                stmt.close();
+                db.setTransactionSuccessful();
+            } finally {
+                db.endTransaction();
+                if (stmt != null) stmt.close();
+            }
+            upgradeVersion = 65;
+        }
+
         // *** Remember to update DATABASE_VERSION above!
 
         if (upgradeVersion != currentVersion) {
@@ -1332,6 +1350,9 @@
                 loadSetting(stmt, Settings.Secure.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE,
                         Integer.toString(recommendedMaxBytes));
             }
+
+            loadIntegerSetting(stmt, Settings.Secure.LONG_PRESS_TIMEOUT,
+                    R.integer.def_long_press_timeout_millis);
         } finally {
             if (stmt != null) stmt.close();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
index 1135b73..737a52b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
@@ -362,6 +362,9 @@
         mRecentsContainer.addFooterView(footer, null, false);
         mRecentsContainer.setAdapter(mListAdapter = new ActvityDescriptionAdapter(mContext));
         mRecentsContainer.setOnItemClickListener(this);
+        final int leftPadding = mContext.getResources()
+            .getDimensionPixelOffset(R.dimen.status_bar_recents_thumbnail_left_margin);
+        mRecentsContainer.setOverScrollEffectPadding(leftPadding, 0);
 
         mRecentsGlowView = findViewById(R.id.recents_glow);
         mRecentsScrim = (View) findViewById(R.id.recents_bg_protect);
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
index 36afd75..74dde9c 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
@@ -108,7 +108,8 @@
      * action should be posted to a handler.
      *
      * @param keyCode The wake key, which may be relevant for configuring the
-     *   keyguard.
+     *   keyguard.  May be {@link KeyEvent#KEYCODE_UNKNOWN} if waking for a reason
+     *   other than a key press.
      */
     abstract public void wakeWhenReadyTq(int keyCode);
 
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
index edab690..8d70a7b 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
@@ -201,7 +201,8 @@
      * Be sure not to take any action that takes a long time; any significant
      * action should be posted to a handler.
      *
-     * @param keyCode The wake key.
+     * @param keyCode The wake key.  May be {@link KeyEvent#KEYCODE_UNKNOWN} if waking
+     * for a reason other than a key press.
      */
     public boolean wakeWhenReadyTq(int keyCode) {
         if (DEBUG) Log.d(TAG, "wakeWhenReady(" + keyCode + ")");
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index b32a729..e7a9eb1 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -810,6 +810,28 @@
     }
 
     /**
+     * When a wake motion such as an external mouse movement is received when the screen
+     * is off and the keyguard is showing, we need to decide whether to actually turn
+     * on the screen, and if so, tell the keyguard to prepare itself and poke the wake
+     * lock when it is ready.
+     *
+     * The 'Tq' suffix is per the documentation in {@link WindowManagerPolicy}.
+     * Be sure not to take any action that takes a long time; any significant
+     * action should be posted to a handler.
+     *
+     * @return Whether we poked the wake lock (and turned the screen on)
+     */
+    public boolean onWakeMotionWhenKeyguardShowingTq() {
+        if (DEBUG) Log.d(TAG, "onWakeMotionWhenKeyguardShowing()");
+
+        // give the keyguard view manager a chance to adjust the state of the
+        // keyguard based on the key that woke the device before poking
+        // the wake lock
+        wakeWhenReadyLocked(KeyEvent.KEYCODE_UNKNOWN);
+        return true;
+    }
+
+    /**
      * Callbacks from {@link KeyguardViewManager}.
      */
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 75ef762..8e18f2a 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2364,6 +2364,25 @@
         return result;
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
+        int result = 0;
+
+        final boolean isWakeMotion = (policyFlags
+                & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
+        if (isWakeMotion) {
+            if (mKeyguardMediator.isShowing()) {
+                // If the keyguard is showing, let it decide what to do with the wake motion.
+                mKeyguardMediator.onWakeMotionWhenKeyguardShowingTq();
+            } else {
+                // Otherwise, wake the device ourselves.
+                result |= ACTION_POKE_USER_ACTIVITY;
+            }
+        }
+        return result;
+    }
+
     class PassHeadsetKey implements Runnable {
         KeyEvent mKeyEvent;
 
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index a07ebfc..2b08ab5 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -24,6 +24,7 @@
 #include <sys/time.h>
 #include <sys/resource.h>
 
+#include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <utils/Log.h>
 #include <binder/Parcel.h>
@@ -35,6 +36,7 @@
 
 #include <media/AudioTrack.h>
 #include <media/AudioRecord.h>
+#include <media/IMediaPlayerService.h>
 
 #include <private/media/AudioTrackShared.h>
 #include <private/media/AudioEffectShared.h>
@@ -121,6 +123,19 @@
 #endif
 }
 
+// To collect the amplifier usage
+static void addBatteryData(uint32_t params) {
+    sp<IBinder> binder =
+        defaultServiceManager()->getService(String16("media.player"));
+    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+    if (service.get() == NULL) {
+        LOGW("Cannot connect to the MediaPlayerService for battery tracking");
+        return;
+    }
+
+    service->addBatteryData(params);
+}
+
 // ----------------------------------------------------------------------------
 
 AudioFlinger::AudioFlinger()
@@ -1833,6 +1848,27 @@
             }
         }
         if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
+            // when changing the audio output device, call addBatteryData to notify
+            // the change
+            if (mDevice != value) {
+                uint32_t params = 0;
+                // check whether speaker is on
+                if (value & AudioSystem::DEVICE_OUT_SPEAKER) {
+                    params |= IMediaPlayerService::kBatteryDataSpeakerOn;
+                }
+
+                int deviceWithoutSpeaker
+                    = AudioSystem::DEVICE_OUT_ALL & ~AudioSystem::DEVICE_OUT_SPEAKER;
+                // check if any other device (except speaker) is on
+                if (value & deviceWithoutSpeaker ) {
+                    params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn;
+                }
+
+                if (params != 0) {
+                    addBatteryData(params);
+                }
+            }
+
             // forward device change to effects that have requested to be
             // aware of attached audio device.
             mDevice = (uint32_t)value;
@@ -2831,6 +2867,9 @@
                     AudioSystem::stopOutput(thread->id(),
                                             (AudioSystem::stream_type)mStreamType,
                                             mSessionId);
+
+                    // to track the speaker usage
+                    addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
                 }
                 AudioSystem::releaseOutput(thread->id());
             }
@@ -2941,6 +2980,11 @@
                                               (AudioSystem::stream_type)mStreamType,
                                               mSessionId);
             thread->mLock.lock();
+
+            // to track the speaker usage
+            if (status == NO_ERROR) {
+                addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStart);
+            }
         }
         if (status == NO_ERROR) {
             PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
@@ -2976,6 +3020,9 @@
                                     (AudioSystem::stream_type)mStreamType,
                                     mSessionId);
             thread->mLock.lock();
+
+            // to track the speaker usage
+            addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
         }
     }
 }
@@ -2995,6 +3042,9 @@
                                         (AudioSystem::stream_type)mStreamType,
                                         mSessionId);
                 thread->mLock.lock();
+
+                // to track the speaker usage
+                addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
             }
         }
     }
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index 25db25e..2fe5980 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -933,6 +933,11 @@
         return -1;
     }
 
+    // Determine whether the device is external or internal.
+    if (isExternalDevice(device)) {
+        device->classes |= INPUT_DEVICE_CLASS_EXTERNAL;
+    }
+
     LOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
             "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s",
          deviceId, fd, devicePath, device->identifier.name.string(),
@@ -997,6 +1002,17 @@
     android::clearKeyboardProperties(id);
 }
 
+bool EventHub::isExternalDevice(Device* device) {
+    if (device->configuration) {
+        bool value;
+        if (device->configuration->tryGetProperty(String8("device.internal"), value)
+                && value) {
+            return false;
+        }
+    }
+    return device->identifier.bus == BUS_USB || device->identifier.bus == BUS_BLUETOOTH;
+}
+
 bool EventHub::hasKeycodeLocked(Device* device, int keycode) const {
     if (!device->keyMap.haveKeyLayout() || !device->keyBitmask) {
         return false;
diff --git a/services/input/EventHub.h b/services/input/EventHub.h
index f7936d2..445c04b 100644
--- a/services/input/EventHub.h
+++ b/services/input/EventHub.h
@@ -126,6 +126,9 @@
 
     /* The input device is a joystick (implies gamepad, has joystick absolute axes). */
     INPUT_DEVICE_CLASS_JOYSTICK      = 0x00000100,
+
+    /* The input device is external (not built-in). */
+    INPUT_DEVICE_CLASS_EXTERNAL      = 0x80000000,
 };
 
 /*
@@ -304,6 +307,8 @@
     void setKeyboardProperties(Device* device, bool builtInKeyboard);
     void clearKeyboardProperties(Device* device, bool builtInKeyboard);
 
+    bool isExternalDevice(Device* device);
+
     // Protect all internal state.
     mutable Mutex mLock;
 
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index c064a9c..655b672 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -1572,7 +1572,7 @@
 }
 
 void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
-    int32_t eventType = POWER_MANAGER_BUTTON_EVENT;
+    int32_t eventType = POWER_MANAGER_OTHER_EVENT;
     switch (eventEntry->type) {
     case EventEntry::TYPE_MOTION: {
         const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry);
@@ -1580,7 +1580,7 @@
             return;
         }
 
-        if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
+        if (MotionEvent::isTouchEvent(motionEntry->source, motionEntry->action)) {
             eventType = POWER_MANAGER_TOUCH_EVENT;
         }
         break;
@@ -1590,6 +1590,7 @@
         if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) {
             return;
         }
+        eventType = POWER_MANAGER_BUTTON_EVENT;
         break;
     }
     }
@@ -2304,7 +2305,7 @@
     }
 
     policyFlags |= POLICY_FLAG_TRUSTED;
-    mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
+    mPolicy->interceptMotionBeforeQueueing(eventTime, /*byref*/ policyFlags);
 
     bool needWake;
     { // acquire lock
@@ -2498,7 +2499,7 @@
         }
 
         nsecs_t eventTime = motionEvent->getEventTime();
-        mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
+        mPolicy->interceptMotionBeforeQueueing(eventTime, /*byref*/ policyFlags);
 
         mLock.lock();
         const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index 304b1bb..1e118c4 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -165,14 +165,14 @@
      */
     virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) = 0;
 
-    /* Intercepts a generic touch, trackball or other event before queueing it.
+    /* Intercepts a touch, trackball or other motion event before queueing it.
      * The policy can use this method as an opportunity to perform power management functions
      * and early event preprocessing such as updating policy flags.
      *
      * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
      * should be dispatched to applications.
      */
-    virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;
+    virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;
 
     /* Allows the policy a chance to intercept a key before dispatching. */
     virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index c3c143c..b92c3b5 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -233,6 +233,11 @@
 InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
     InputDevice* device = new InputDevice(this, deviceId, name);
 
+    // External devices.
+    if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
+        device->setExternal(true);
+    }
+
     // Switch-like devices.
     if (classes & INPUT_DEVICE_CLASS_SWITCH) {
         device->addMapper(new SwitchInputMapper(device));
@@ -565,7 +570,7 @@
 // --- InputDevice ---
 
 InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
-        mContext(context), mId(id), mName(name), mSources(0) {
+        mContext(context), mId(id), mName(name), mSources(0), mIsExternal(false) {
 }
 
 InputDevice::~InputDevice() {
@@ -582,6 +587,7 @@
 
     dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
             deviceInfo.getName().string());
+    dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
     dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
     dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
 
@@ -985,6 +991,16 @@
         downTime = mLocked.downTime;
     } // release lock
 
+    // Key down on external an keyboard should wake the device.
+    // We don't do this for internal keyboards to prevent them from waking up in your pocket.
+    // For internal keyboards, the key layout file should specify the policy flags for
+    // each wake key individually.
+    // TODO: Use the input device configuration to control this behavior more finely.
+    if (down && getDevice()->isExternal()
+            && !(policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED))) {
+        policyFlags |= POLICY_FLAG_WAKE_DROPPED;
+    }
+
     if (metaStateChanged) {
         getContext()->updateGlobalMetaState();
     }
@@ -1379,9 +1395,18 @@
         }
     } // release lock
 
+    // Moving an external trackball or mouse should wake the device.
+    // We don't do this for internal cursor devices to prevent them from waking up
+    // the device in your pocket.
+    // TODO: Use the input device configuration to control this behavior more finely.
+    uint32_t policyFlags = 0;
+    if (getDevice()->isExternal()) {
+        policyFlags |= POLICY_FLAG_WAKE_DROPPED;
+    }
+
     int32_t metaState = mContext->getGlobalMetaState();
     int32_t pointerId = 0;
-    getDispatcher()->notifyMotion(when, getDeviceId(), mSources, 0,
+    getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
             motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
             1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
 
@@ -1391,7 +1416,7 @@
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
 
-        getDispatcher()->notifyMotion(when, getDeviceId(), mSources, 0,
+        getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
                 AMOTION_EVENT_ACTION_SCROLL, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
                 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
     }
@@ -2308,8 +2333,6 @@
 }
 
 void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
-    uint32_t policyFlags = 0;
-
     // Preprocess pointer data.
     if (mParameters.useBadTouchFilter) {
         if (applyBadTouchFilter()) {
@@ -2338,9 +2361,18 @@
         savedTouch = & mCurrentTouch;
     }
 
-    // Hide the pointer on an initial down.
+    uint32_t policyFlags = 0;
     if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
+        // Hide the pointer on an initial down.
         getContext()->fadePointer();
+
+        // Initial downs on external touch devices should wake the device.
+        // We don't do this for internal touch screens to prevent them from waking
+        // up in your pocket.
+        // TODO: Use the input device configuration to control this behavior more finely.
+        if (getDevice()->isExternal()) {
+            policyFlags |= POLICY_FLAG_WAKE_DROPPED;
+        }
     }
 
     // Process touches and virtual keys.
@@ -4017,8 +4049,14 @@
         axis.oldValue = axis.newValue;
     }
 
+    // Moving a joystick axis should not wake the devide because joysticks can
+    // be fairly noisy even when not in use.  On the other hand, pushing a gamepad
+    // button will likely wake the device.
+    // TODO: Use the input device configuration to control this behavior more finely.
+    uint32_t policyFlags = 0;
+
     int32_t pointerId = 0;
-    getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, 0,
+    getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
             AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
             1, &pointerId, &pointerCoords, 0, 0, 0);
 }
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index b344ffe..655f0f0 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -286,6 +286,9 @@
     inline const String8& getName() { return mName; }
     inline uint32_t getSources() { return mSources; }
 
+    inline bool isExternal() { return mIsExternal; }
+    inline void setExternal(bool external) { mIsExternal = external; }
+
     inline bool isIgnored() { return mMappers.isEmpty(); }
 
     void dump(String8& dump);
@@ -317,6 +320,7 @@
 
     String8 mName;
     uint32_t mSources;
+    bool mIsExternal;
 
     typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code);
     int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc);
diff --git a/services/input/tests/InputDispatcher_test.cpp b/services/input/tests/InputDispatcher_test.cpp
index 5ba1867..bb3449b 100644
--- a/services/input/tests/InputDispatcher_test.cpp
+++ b/services/input/tests/InputDispatcher_test.cpp
@@ -58,7 +58,7 @@
     virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
     }
 
-    virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
+    virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
     }
 
     virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 864241e..8404b3a 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -188,6 +188,8 @@
 class FakeInputDispatcher : public InputDispatcherInterface {
 public:
     struct NotifyConfigurationChangedArgs {
+        NotifyConfigurationChangedArgs() : eventTime(0) { }
+
         nsecs_t eventTime;
     };
 
@@ -687,6 +689,10 @@
         }
     }
 
+    virtual bool isExternal(int32_t deviceId) const {
+        return false;
+    }
+
     virtual void dump(String8& dump) {
     }
 };
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index e6dfb7f..40417b1 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -717,6 +717,8 @@
     final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
             = new SparseArray<HashMap<Uri, UriPermission>>();
 
+    CoreSettingsObserver mCoreSettingsObserver;
+
     /**
      * Thread-local storage used to carry caller permissions over through
      * indirect content-provider access.
@@ -3589,7 +3591,8 @@
                     app.instrumentationClass, app.instrumentationProfileFile,
                     app.instrumentationArguments, app.instrumentationWatcher, testMode, 
                     isRestrictedBackupMode || !normalMode,
-                    mConfiguration, getCommonServicesLocked());
+                    mConfiguration, getCommonServicesLocked(),
+                    mCoreSettingsObserver.getCoreSettingsLocked());
             updateLruProcessLocked(app, false, true);
             app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
         } catch (Exception e) {
@@ -5772,6 +5775,8 @@
         if (providers != null) {
             mSystemThread.installSystemProviders(providers);
         }
+
+        mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
     }
 
     /**
@@ -13030,4 +13035,17 @@
     public void monitor() {
         synchronized (this) { }
     }
+
+    public void onCoreSettingsChange(Bundle settings) {
+        for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
+            ProcessRecord processRecord = mLruProcesses.get(i);
+            try {
+                if (processRecord.thread != null) {
+                    processRecord.thread.setCoreSettings(settings);
+                }
+            } catch (RemoteException re) {
+                /* ignore */
+            }
+        }
+    }
 }
diff --git a/services/java/com/android/server/am/CoreSettingsObserver.java b/services/java/com/android/server/am/CoreSettingsObserver.java
new file mode 100644
index 0000000..25db84a
--- /dev/null
+++ b/services/java/com/android/server/am/CoreSettingsObserver.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2006-2011 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.server.am;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Helper class for watching a set of core settings which the framework
+ * propagates to application processes to avoid multiple lookups and potentially
+ * disk I/O operations. Note: This class assumes that all core settings reside
+ * in {@link Settings.Secure}.
+ */
+class CoreSettingsObserver extends ContentObserver {
+    private static final String LOG_TAG = CoreSettingsObserver.class.getSimpleName();
+
+    // mapping form property name to its type
+    private static final Map<String, Class<?>> sCoreSettingToTypeMap = new HashMap<
+            String, Class<?>>();
+    static {
+        sCoreSettingToTypeMap.put(Settings.Secure.LONG_PRESS_TIMEOUT, int.class);
+        // add other core settings here...
+    }
+
+    private final Bundle mCoreSettings = new Bundle();
+
+    private final ActivityManagerService mActivityManagerService;
+
+    public CoreSettingsObserver(ActivityManagerService activityManagerService) {
+        super(activityManagerService.mHandler);
+        mActivityManagerService = activityManagerService;
+        beginObserveCoreSettings();
+        populateCoreSettings(mCoreSettings);
+    }
+
+    public Bundle getCoreSettingsLocked() {
+        return (Bundle) mCoreSettings.clone();
+    }
+
+    @Override
+    public void onChange(boolean selfChange) {
+        synchronized (mActivityManagerService) {
+            populateCoreSettings(mCoreSettings);
+            mActivityManagerService.onCoreSettingsChange(mCoreSettings);
+        }
+    }
+
+    private void beginObserveCoreSettings() {
+        for (String setting : sCoreSettingToTypeMap.keySet()) {
+            Uri uri = Settings.Secure.getUriFor(setting);
+            mActivityManagerService.mContext.getContentResolver().registerContentObserver(
+                    uri, false, this);
+        }
+    }
+
+    private void populateCoreSettings(Bundle snapshot) {
+        Context context = mActivityManagerService.mContext;
+        for (Map.Entry<String, Class<?>> entry : sCoreSettingToTypeMap.entrySet()) {
+            String setting = entry.getKey();
+            Class<?> type = entry.getValue();
+            try {
+                if (type == String.class) {
+                    String value = Settings.Secure.getString(context.getContentResolver(),
+                            setting);
+                    snapshot.putString(setting, value);
+                } else if (type == int.class) {
+                    int value = Settings.Secure.getInt(context.getContentResolver(),
+                            setting);
+                    snapshot.putInt(setting, value);
+                } else if (type == float.class) {
+                    float value = Settings.Secure.getFloat(context.getContentResolver(),
+                            setting);
+                    snapshot.putFloat(setting, value);
+                } else if (type == long.class) {
+                    long value = Settings.Secure.getLong(context.getContentResolver(),
+                            setting);
+                    snapshot.putLong(setting, value);
+                }
+            } catch (SettingNotFoundException snfe) {
+                Log.w(LOG_TAG, "Cannot find setting \"" + setting + "\"", snfe);
+            }
+        }
+    }
+}
diff --git a/services/java/com/android/server/usb/UsbService.java b/services/java/com/android/server/usb/UsbService.java
index 94c25e9..8170c61 100644
--- a/services/java/com/android/server/usb/UsbService.java
+++ b/services/java/com/android/server/usb/UsbService.java
@@ -102,8 +102,8 @@
     private boolean mSystemReady;
 
     private UsbAccessory mCurrentAccessory;
-    // functions to restore after exiting accessory mode
-    private final ArrayList<String> mAccessoryRestoreFunctions = new ArrayList<String>();
+    // USB functions that are enabled by default, to restore after exiting accessory mode
+    private final ArrayList<String> mDefaultFunctions = new ArrayList<String>();
 
     private final Context mContext;
     private final Object mLock = new Object();
@@ -118,20 +118,6 @@
         boolean enteringAccessoryMode =
             (mHasUsbAccessory && enabled && UsbManager.USB_FUNCTION_ACCESSORY.equals(function));
 
-        if (enteringAccessoryMode) {
-            // keep a list of functions to reenable after exiting accessory mode
-            mAccessoryRestoreFunctions.clear();
-            int count = mEnabledFunctions.size();
-            for (int i = 0; i < count; i++) {
-                String f = mEnabledFunctions.get(i);
-                // RNDIS should not be restored and adb is handled automatically
-                if (!UsbManager.USB_FUNCTION_RNDIS.equals(f) &&
-                    !UsbManager.USB_FUNCTION_ADB.equals(f) &&
-                    !UsbManager.USB_FUNCTION_ACCESSORY.equals(f)) {
-                    mAccessoryRestoreFunctions.add(f);
-                }
-            }
-        }
         if (enabled) {
             if (!mEnabledFunctions.contains(function)) {
                 mEnabledFunctions.add(function);
@@ -261,6 +247,11 @@
                 String functionName = files[i].getName();
                 if (value == 1) {
                     mEnabledFunctions.add(functionName);
+                    // adb is enabled/disabled automatically by the adbd daemon,
+                    // so don't treat it as a default function
+                    if (!UsbManager.USB_FUNCTION_ADB.equals(functionName)) {
+                        mDefaultFunctions.add(functionName);
+                    }
                 } else {
                     mDisabledFunctions.add(functionName);
                 }
@@ -503,29 +494,24 @@
                 switch (msg.what) {
                     case MSG_UPDATE_STATE:
                         if (mConnected != mLastConnected || mConfiguration != mLastConfiguration) {
-                            if (mConnected == 0 && mCurrentAccessory != null) {
-                                // turn off accessory mode when we are disconnected
+                            if (mConnected == 0) {
+                                // make sure accessory mode is off, and restore default functions
                                 if (UsbManager.setFunctionEnabled(
                                         UsbManager.USB_FUNCTION_ACCESSORY, false)) {
                                     Log.d(TAG, "exited USB accessory mode");
 
-                                    // restore previously enabled functions
-                                    for (String function : mAccessoryRestoreFunctions) {
+                                    int count = mDefaultFunctions.size();
+                                    for (int i = 0; i < count; i++) {
+                                        String function = mDefaultFunctions.get(i);
                                         if (UsbManager.setFunctionEnabled(function, true)) {
                                             Log.e(TAG, "could not reenable function " + function);
                                         }
                                     }
-                                    mAccessoryRestoreFunctions.clear();
+                                }
 
+                                if (mCurrentAccessory != null) {
                                     mDeviceManager.accessoryDetached(mCurrentAccessory);
                                     mCurrentAccessory = null;
-
-                                    // this will cause an immediate reset of the USB bus,
-                                    // so there is no point in sending the
-                                    // function disabled broadcast.
-                                    return;
-                                } else {
-                                    Log.e(TAG, "could not disable USB_FUNCTION_ACCESSORY");
                                 }
                             }
 
@@ -581,14 +567,18 @@
                 pw.print(mDisabledFunctions.get(i) + " ");
             }
             pw.println("");
+            pw.print("    Default Functions: ");
+            for (int i = 0; i < mDefaultFunctions.size(); i++) {
+                pw.print(mDefaultFunctions.get(i) + " ");
+            }
+            pw.println("");
             pw.println("    mConnected: " + mConnected + ", mConfiguration: " + mConfiguration);
+            pw.println("    mCurrentAccessory: " + mCurrentAccessory);
 
             pw.println("  USB Host State:");
             for (String name : mDevices.keySet()) {
                 pw.println("    " + name + ": " + mDevices.get(name));
             }
-            pw.println("  mCurrentAccessory: " + mCurrentAccessory);
-
             mDeviceManager.dump(fd, pw);
         }
     }
diff --git a/services/java/com/android/server/wm/DimAnimator.java b/services/java/com/android/server/wm/DimAnimator.java
index 1fcb869..a266d70 100644
--- a/services/java/com/android/server/wm/DimAnimator.java
+++ b/services/java/com/android/server/wm/DimAnimator.java
@@ -45,7 +45,7 @@
                     + mDimSurface + ": CREATE");
             try {
                 mDimSurface = new Surface(session, 0,
-                        "DimSurface",
+                        "DimAnimator",
                         -1, 16, 16, PixelFormat.OPAQUE,
                         Surface.FX_SURFACE_DIM);
                 mDimSurface.setAlpha(0.0f);
@@ -84,7 +84,7 @@
      * {@link updateSurface} after all windows are examined.
      */
     void updateParameters(Resources res, WindowState w, long currentTime) {
-        mDimSurface.setLayer(w.mAnimLayer-1);
+        mDimSurface.setLayer(w.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM);
 
         final float target = w.mExiting ? 0 : w.mAttrs.dimAmount;
         if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM " + mDimSurface
@@ -177,8 +177,11 @@
         return animating;
     }
 
-    public void printTo(PrintWriter pw) {
-        pw.print("  mDimShown="); pw.print(mDimShown);
+    public void printTo(String prefix, PrintWriter pw) {
+        pw.print(prefix);
+        pw.print("mDimSurface="); pw.println(mDimSurface);
+        pw.print(prefix);
+        pw.print("mDimShown="); pw.print(mDimShown);
         pw.print(" current="); pw.print(mDimCurrentAlpha);
         pw.print(" target="); pw.print(mDimTargetAlpha);
         pw.print(" delta="); pw.print(mDimDeltaPerMs);
diff --git a/services/java/com/android/server/wm/DimSurface.java b/services/java/com/android/server/wm/DimSurface.java
new file mode 100644
index 0000000..084ac6f
--- /dev/null
+++ b/services/java/com/android/server/wm/DimSurface.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2011 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.server.wm;
+
+import android.graphics.PixelFormat;
+import android.util.Slog;
+import android.view.Surface;
+import android.view.SurfaceSession;
+
+import java.io.PrintWriter;
+
+class DimSurface {
+    Surface mDimSurface;
+    boolean mDimShown = false;
+    int mDimColor = 0;
+    int mLayer = -1;
+    int mLastDimWidth, mLastDimHeight;
+
+    DimSurface(SurfaceSession session) {
+        if (mDimSurface == null) {
+            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM "
+                    + mDimSurface + ": CREATE");
+            try {
+                mDimSurface = new Surface(session, 0,
+                        "DimSurface",
+                        -1, 16, 16, PixelFormat.OPAQUE,
+                        Surface.FX_SURFACE_DIM);
+                mDimSurface.setAlpha(0.0f);
+            } catch (Exception e) {
+                Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
+            }
+        }
+    }
+
+    /**
+     * Show the dim surface.
+     */
+    void show(int dw, int dh, int layer, int color) {
+        if (!mDimShown) {
+            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM " + mDimSurface + ": SHOW pos=(0,0) (" +
+                    dw + "x" + dh + ")");
+            mDimShown = true;
+            try {
+                mLastDimWidth = dw;
+                mLastDimHeight = dh;
+                mDimSurface.setPosition(0, 0);
+                mDimSurface.setSize(dw, dh);
+                mDimSurface.show();
+            } catch (RuntimeException e) {
+                Slog.w(WindowManagerService.TAG, "Failure showing dim surface", e);
+            }
+        } else if (mLastDimWidth != dw || mLastDimHeight != dh || mDimColor != color
+                || mLayer != layer) {
+            mLastDimWidth = dw;
+            mLastDimHeight = dh;
+            mLayer = layer;
+            mDimColor = color;
+            mDimSurface.setSize(dw, dh);
+            mDimSurface.setLayer(layer);
+            mDimSurface.setAlpha(((color>>24)&0xff)/255.0f);
+        }
+    }
+
+    void hide() {
+        if (mDimShown) {
+            mDimShown = false;
+            try {
+                mDimSurface.hide();
+            } catch (RuntimeException e) {
+                Slog.w(WindowManagerService.TAG, "Illegal argument exception hiding dim surface");
+            }
+        }
+    }
+
+    public void printTo(String prefix, PrintWriter pw) {
+        pw.print(prefix); pw.print("mDimSurface="); pw.println(mDimSurface);
+        pw.print(prefix); pw.print("mDimShown="); pw.print(mDimShown);
+                pw.print(" mLayer="); pw.println(mLayer);
+                pw.print(" mDimColor=0x"); pw.println(Integer.toHexString(mDimColor));
+        pw.print(prefix); pw.print("mLastDimWidth="); pw.print(mLastDimWidth);
+                pw.print(" mLastDimWidth="); pw.println(mLastDimWidth);
+    }
+}
diff --git a/services/java/com/android/server/wm/InputManager.java b/services/java/com/android/server/wm/InputManager.java
index 326eca7..77cec5d 100644
--- a/services/java/com/android/server/wm/InputManager.java
+++ b/services/java/com/android/server/wm/InputManager.java
@@ -448,7 +448,13 @@
             return mWindowManagerService.mInputMonitor.interceptKeyBeforeQueueing(
                     event, policyFlags, isScreenOn);
         }
-        
+
+        @SuppressWarnings("unused")
+        public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
+            return mWindowManagerService.mInputMonitor.interceptMotionBeforeQueueingWhenScreenOff(
+                    policyFlags);
+        }
+
         @SuppressWarnings("unused")
         public boolean interceptKeyBeforeDispatching(InputWindowHandle focus,
                 KeyEvent event, int policyFlags) {
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java
index b1833c4..45a78af 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -258,7 +258,14 @@
             KeyEvent event, int policyFlags, boolean isScreenOn) {
         return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags, isScreenOn);
     }
-    
+
+    /* Provides an opportunity for the window manager policy to intercept early
+     * motion event processing when the screen is off since these events are normally
+     * dropped. */
+    public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
+        return mService.mPolicy.interceptMotionBeforeQueueingWhenScreenOff(policyFlags);
+    }
+
     /* Provides an opportunity for the window manager policy to process a key before
      * ordinary dispatch. */
     public boolean interceptKeyBeforeDispatching(
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 4356ce5..fbf1ec3 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -110,18 +110,16 @@
 
         Bitmap screenshot = Surface.screenshot(0, 0);
 
-        if (screenshot != null) {
-            // Screenshot does NOT include rotation!
-            mSnapshotRotation = 0;
-            mWidth = screenshot.getWidth();
-            mHeight = screenshot.getHeight();
-        } else {
-            // Just in case.
-            mSnapshotRotation = display.getRotation();
-            mWidth = mDisplayMetrics.widthPixels;
-            mHeight = mDisplayMetrics.heightPixels;
+        if (screenshot == null) {
+            // Device is not capable of screenshots...  we can't do an animation.
+            return;
         }
 
+        // Screenshot does NOT include rotation!
+        mSnapshotRotation = 0;
+        mWidth = screenshot.getWidth();
+        mHeight = screenshot.getHeight();
+
         mOriginalRotation = display.getRotation();
         mOriginalWidth = mDisplayMetrics.widthPixels;
         mOriginalHeight = mDisplayMetrics.heightPixels;
@@ -150,23 +148,19 @@
                     c = mSurface.lockCanvas(dirty);
                 } catch (IllegalArgumentException e) {
                     Slog.w(TAG, "Unable to lock surface", e);
-                    return;
                 } catch (Surface.OutOfResourcesException e) {
                     Slog.w(TAG, "Unable to lock surface", e);
-                    return;
                 }
                 if (c == null) {
-                    Slog.w(TAG, "Null surface");
+                    Slog.w(TAG, "Null surface canvas");
+                    mSurface.destroy();
+                    mSurface = null;
                     return;
                 }
         
-                if (screenshot != null) {
-                    Paint paint = new Paint(0);
-                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
-                    c.drawBitmap(screenshot, 0, 0, paint);
-                } else {
-                    c.drawColor(Color.BLACK, PorterDuff.Mode.SRC);
-                }
+                Paint paint = new Paint(0);
+                paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
+                c.drawBitmap(screenshot, 0, 0, paint);
 
                 mSurface.unlockCanvasAndPost(c);
             }
@@ -177,12 +171,14 @@
                         "<<< CLOSE TRANSACTION ScreenRotationAnimation");
             }
     
-            if (screenshot != null) {
-                screenshot.recycle();
-            }
+            screenshot.recycle();
         }
     }
 
+    boolean hasScreenshot() {
+        return mSurface != null;
+    }
+
     static int deltaRotation(int oldRotation, int newRotation) {
         int delta = newRotation - oldRotation;
         if (delta < 0) delta += 4;
@@ -250,17 +246,14 @@
      */
     public boolean dismiss(SurfaceSession session, long maxAnimationDuration,
             float animationScale) {
-        // Figure out how the screen has moved from the original rotation.
-        int delta = deltaRotation(mCurRotation, mOriginalRotation);
-        if (false && delta == 0) {
-            // Nothing changed, just remove the snapshot.
-            if (mSurface != null) {
-                mSurface.destroy();
-                mSurface = null;
-            }
+        if (mSurface == null) {
+            // Can't do animation.
             return false;
         }
 
+        // Figure out how the screen has moved from the original rotation.
+        int delta = deltaRotation(mCurRotation, mOriginalRotation);
+
         switch (delta) {
             case Surface.ROTATION_0:
                 mExitAnimation = AnimationUtils.loadAnimation(mContext,
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 15269dc..b5d84e8 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -180,6 +180,16 @@
      */
     static final int WINDOW_LAYER_MULTIPLIER = 5;
 
+    /**
+     * Dim surface layer is immediately below target window.
+     */
+    static final int LAYER_OFFSET_DIM = 1;
+
+    /**
+     * Blur surface layer is immediately below dim layer.
+     */
+    static final int LAYER_OFFSET_BLUR = 2;
+
     /** The maximum length we will accept for a loaded animation duration:
      * this is 10 seconds.
      */
@@ -276,8 +286,6 @@
 
     final IBatteryStats mBatteryStats;
 
-    private static final boolean mInEmulator = SystemProperties.get("ro.kernel.qemu").equals("1");
-
     /**
      * All currently active sessions with clients.
      */
@@ -468,6 +476,7 @@
     // visible behind it in case it animates in a way that would allow it to be
     // seen.
     WindowState mWindowDetachedWallpaper = null;
+    DimSurface mWindowAnimationBackgroundSurface = null;
     int mWallpaperAnimLayerAdjustment;
     float mLastWallpaperX = -1;
     float mLastWallpaperY = -1;
@@ -4940,7 +4949,8 @@
             if (mDisplayEnabled) {
                 // NOTE: We disable the rotation in the emulator because
                 //       it doesn't support hardware OpenGL emulation yet.
-                if (CUSTOM_SCREEN_ROTATION && !mInEmulator) {
+                if (CUSTOM_SCREEN_ROTATION && mScreenRotationAnimation != null
+                        && mScreenRotationAnimation.hasScreenshot()) {
                     Surface.freezeDisplay(0);
                     if (!inTransaction) {
                         if (SHOW_TRANSACTIONS) Slog.i(TAG,
@@ -6802,6 +6812,8 @@
                 boolean wallpaperMayChange = false;
                 boolean forceHiding = false;
                 WindowState windowDetachedWallpaper = null;
+                WindowState windowAnimationBackground = null;
+                int windowAnimationBackgroundColor = 0;
 
                 mPolicy.beginAnimationLw(dw, dh);
 
@@ -6851,8 +6863,15 @@
                         // an animating window and take care of a request to run
                         // a detached wallpaper animation.
                         if (nowAnimating) {
-                            if (w.mAnimation != null && w.mAnimation.getDetachWallpaper()) {
-                                windowDetachedWallpaper = w;
+                            if (w.mAnimation != null) {
+                                if (w.mAnimation.getDetachWallpaper()) {
+                                    windowDetachedWallpaper = w;
+                                }
+                                if (w.mAnimation.getBackgroundColor() != 0) {
+                                    windowAnimationBackground = w;
+                                    windowAnimationBackgroundColor =
+                                            w.mAnimation.getBackgroundColor();
+                                }
                             }
                             animating = true;
                         }
@@ -6860,9 +6879,15 @@
                         // If this window's app token is running a detached wallpaper
                         // animation, make a note so we can ensure the wallpaper is
                         // displayed behind it.
-                        if (w.mAppToken != null && w.mAppToken.animation != null
-                                && w.mAppToken.animation.getDetachWallpaper()) {
-                            windowDetachedWallpaper = w;
+                        if (w.mAppToken != null && w.mAppToken.animation != null) {
+                            if (w.mAppToken.animation.getDetachWallpaper()) {
+                                windowDetachedWallpaper = w;
+                            }
+                            if (w.mAppToken.animation.getBackgroundColor() != 0) {
+                                windowAnimationBackground = w;
+                                windowAnimationBackgroundColor =
+                                        w.mAppToken.animation.getBackgroundColor();
+                            }
                         }
 
                         if (wasAnimating && !w.mAnimating && mWallpaperTarget == w) {
@@ -7301,6 +7326,17 @@
                     wallpaperMayChange = true;
                 }
 
+                if (windowAnimationBackgroundColor != 0) {
+                    if (mWindowAnimationBackgroundSurface == null) {
+                        mWindowAnimationBackgroundSurface = new DimSurface(mFxSession);
+                    }
+                    mWindowAnimationBackgroundSurface.show(dw, dh,
+                            windowAnimationBackground.mAnimLayer - LAYER_OFFSET_DIM,
+                            windowAnimationBackgroundColor);
+                } else if (mWindowAnimationBackgroundSurface != null) {
+                    mWindowAnimationBackgroundSurface.hide();
+                }
+
                 if (wallpaperMayChange) {
                     if (DEBUG_WALLPAPER) Slog.v(TAG,
                             "Wallpaper may change!  Adjusting");
@@ -7730,7 +7766,7 @@
                                             dw + "x" + dh + "), layer=" + (w.mAnimLayer-1));
                                     mBlurSurface.setPosition(0, 0);
                                     mBlurSurface.setSize(dw, dh);
-                                    mBlurSurface.setLayer(w.mAnimLayer-2);
+                                    mBlurSurface.setLayer(w.mAnimLayer-LAYER_OFFSET_BLUR);
                                     if (!mBlurShown) {
                                         try {
                                             if (SHOW_TRANSACTIONS) Slog.i(TAG, "  BLUR "
@@ -7779,7 +7815,8 @@
                     // Using the same layer as Dim because they will never be shown at the
                     // same time.  NOTE: we do NOT use mAnimLayer, because we don't
                     // want this surface dragged up in front of stuff that is animating.
-                    mBackgroundFillerSurface.setLayer(mBackgroundFillerTarget.mLayer - 1);
+                    mBackgroundFillerSurface.setLayer(mBackgroundFillerTarget.mLayer
+                            - LAYER_OFFSET_DIM);
                     mBackgroundFillerSurface.show();
                 } catch (RuntimeException e) {
                     Slog.e(TAG, "Exception showing filler surface");
@@ -8294,6 +8331,9 @@
                 mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
                         mDisplay, mFxSession, inTransaction);
             }
+            if (!mScreenRotationAnimation.hasScreenshot()) {
+                Surface.freezeDisplay(0);
+            }
         } else {
             Surface.freezeDisplay(0);
         }
@@ -8316,17 +8356,21 @@
 
         boolean updateRotation = false;
         
-        if (CUSTOM_SCREEN_ROTATION) {
-            if (mScreenRotationAnimation != null) {
-                if (mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
-                        mTransitionAnimationScale)) {
-                    requestAnimationLocked(0);
-                } else {
-                    mScreenRotationAnimation = null;
-                    updateRotation = true;
-                }
+        if (CUSTOM_SCREEN_ROTATION && mScreenRotationAnimation != null
+                && mScreenRotationAnimation.hasScreenshot()) {
+            if (mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
+                    mTransitionAnimationScale)) {
+                requestAnimationLocked(0);
+            } else {
+                mScreenRotationAnimation = null;
+                updateRotation = true;
             }
         } else {
+            if (mScreenRotationAnimation != null) {
+                mScreenRotationAnimation.kill();
+                mScreenRotationAnimation = null;
+            }
+            updateRotation = true;
             Surface.unfreezeDisplay(0);
         }
 
@@ -8589,6 +8633,10 @@
             if (mWindowDetachedWallpaper != null) {
                 pw.print("  mWindowDetachedWallpaper="); pw.println(mWindowDetachedWallpaper);
             }
+            if (mWindowAnimationBackgroundSurface != null) {
+                pw.println("  mWindowAnimationBackgroundSurface:");
+                mWindowAnimationBackgroundSurface.printTo("    ", pw);
+            }
             pw.print("  mCurConfiguration="); pw.println(this.mCurConfiguration);
             pw.print("  mInTouchMode="); pw.print(mInTouchMode);
                     pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
@@ -8597,7 +8645,8 @@
             pw.print("  mLayoutNeeded="); pw.print(mLayoutNeeded);
                     pw.print(" mBlurShown="); pw.println(mBlurShown);
             if (mDimAnimator != null) {
-                mDimAnimator.printTo(pw);
+                pw.println("  mDimAnimator:");
+                mDimAnimator.printTo("    ", pw);
             } else {
                 pw.println( "  no DimAnimator ");
             }
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 5ef234a..00d0af1 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -59,6 +59,7 @@
     jmethodID notifyInputChannelBroken;
     jmethodID notifyANR;
     jmethodID interceptKeyBeforeQueueing;
+    jmethodID interceptMotionBeforeQueueingWhenScreenOff;
     jmethodID interceptKeyBeforeDispatching;
     jmethodID dispatchUnhandledKey;
     jmethodID checkInjectEventsPermission;
@@ -178,7 +179,7 @@
     virtual nsecs_t getKeyRepeatDelay();
     virtual int32_t getMaxEventsPerSecond();
     virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
-    virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
+    virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
     virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
             const KeyEvent* keyEvent, uint32_t policyFlags);
     virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
@@ -215,6 +216,7 @@
     } mLocked;
 
     void updateInactivityFadeDelayLocked(const sp<PointerController>& controller);
+    void handleInterceptActions(jint wmActions, nsecs_t when, uint32_t& policyFlags);
 
     // Power manager interactions.
     bool isScreenOn();
@@ -620,10 +622,6 @@
     // - Ask the window manager what to do with normal events and trusted injected events.
     // - For normal events wake and brighten the screen if currently off or dim.
     if ((policyFlags & POLICY_FLAG_TRUSTED)) {
-        const int32_t WM_ACTION_PASS_TO_USER = 1;
-        const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2;
-        const int32_t WM_ACTION_GO_TO_SLEEP = 4;
-
         nsecs_t when = keyEvent->getEventTime();
         bool isScreenOn = this->isScreenOn();
         bool isScreenBright = this->isScreenBright();
@@ -655,23 +653,13 @@
             }
         }
 
-        if (wmActions & WM_ACTION_GO_TO_SLEEP) {
-            android_server_PowerManagerService_goToSleep(when);
-        }
-
-        if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
-            android_server_PowerManagerService_userActivity(when, POWER_MANAGER_BUTTON_EVENT);
-        }
-
-        if (wmActions & WM_ACTION_PASS_TO_USER) {
-            policyFlags |= POLICY_FLAG_PASS_TO_USER;
-        }
+        handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
     } else {
         policyFlags |= POLICY_FLAG_PASS_TO_USER;
     }
 }
 
-void NativeInputManager::interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
+void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
     // Policy:
     // - Ignore untrusted events and pass them along.
     // - No special filtering for injected events required at this time.
@@ -684,12 +672,55 @@
             if (!isScreenBright()) {
                 policyFlags |= POLICY_FLAG_BRIGHT_HERE;
             }
+        } else {
+            JNIEnv* env = jniEnv();
+            jint wmActions = env->CallIntMethod(mCallbacksObj,
+                        gCallbacksClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
+                        policyFlags);
+            if (checkAndClearExceptionFromCallback(env,
+                    "interceptMotionBeforeQueueingWhenScreenOff")) {
+                wmActions = 0;
+            }
+
+            policyFlags |= POLICY_FLAG_WOKE_HERE | POLICY_FLAG_BRIGHT_HERE;
+            handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
         }
     } else {
         policyFlags |= POLICY_FLAG_PASS_TO_USER;
     }
 }
 
+void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when,
+        uint32_t& policyFlags) {
+    enum {
+        WM_ACTION_PASS_TO_USER = 1,
+        WM_ACTION_POKE_USER_ACTIVITY = 2,
+        WM_ACTION_GO_TO_SLEEP = 4,
+    };
+
+    if (wmActions & WM_ACTION_GO_TO_SLEEP) {
+#ifdef DEBUG_INPUT_DISPATCHER_POLICY
+        LOGD("handleInterceptActions: Going to sleep.");
+#endif
+        android_server_PowerManagerService_goToSleep(when);
+    }
+
+    if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
+#ifdef DEBUG_INPUT_DISPATCHER_POLICY
+        LOGD("handleInterceptActions: Poking user activity.");
+#endif
+        android_server_PowerManagerService_userActivity(when, POWER_MANAGER_BUTTON_EVENT);
+    }
+
+    if (wmActions & WM_ACTION_PASS_TO_USER) {
+        policyFlags |= POLICY_FLAG_PASS_TO_USER;
+    } else {
+#ifdef DEBUG_INPUT_DISPATCHER_POLICY
+        LOGD("handleInterceptActions: Not passing key to user.");
+#endif
+    }
+}
+
 bool NativeInputManager::interceptKeyBeforeDispatching(
         const sp<InputWindowHandle>& inputWindowHandle,
         const KeyEvent* keyEvent, uint32_t policyFlags) {
@@ -1204,6 +1235,10 @@
     GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
             "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;IZ)I");
 
+    GET_METHOD_ID(gCallbacksClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
+            gCallbacksClassInfo.clazz,
+            "interceptMotionBeforeQueueingWhenScreenOff", "(I)I");
+
     GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
             "interceptKeyBeforeDispatching",
             "(Lcom/android/server/wm/InputWindowHandle;Landroid/view/KeyEvent;I)Z");
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 40882d8..554fa43 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2150,8 +2150,8 @@
     sh = (!sh) ? hw_h : sh;
     const size_t size = sw * sh * 4;
 
-    LOGD("screenshot: sw=%d, sh=%d, minZ=%d, maxZ=%d",
-            sw, sh, minLayerZ, maxLayerZ);
+    //LOGD("screenshot: sw=%d, sh=%d, minZ=%d, maxZ=%d",
+    //        sw, sh, minLayerZ, maxLayerZ);
 
     // make sure to clear all GL error flags
     while ( glGetError() != GL_NO_ERROR ) ;
@@ -2236,7 +2236,7 @@
 
     hw.compositionComplete();
 
-    LOGD("screenshot: result = %s", result<0 ? strerror(result) : "OK");
+    // LOGD("screenshot: result = %s", result<0 ? strerror(result) : "OK");
 
     return result;
 }