Merge change 24921 into eclair

* changes:
  add system properties for experimenting with sync timeouts.
diff --git a/api/current.xml b/api/current.xml
index f8cf61f..04823e5 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -24714,6 +24714,17 @@
  visibility="public"
 >
 </method>
+<method name="getFastDrawable"
+ return="android.graphics.drawable.Drawable"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getInstance"
  return="android.app.WallpaperManager"
  abstract="false"
@@ -24738,6 +24749,17 @@
  visibility="public"
 >
 </method>
+<method name="peekFastDrawable"
+ return="android.graphics.drawable.Drawable"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="setBitmap"
  return="void"
  abstract="false"
@@ -101558,6 +101580,17 @@
  visibility="protected"
 >
 </method>
+<method name="quit"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 </class>
 <interface name="IBinder"
  abstract="true"
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 8cfb758..6abed93 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -1398,9 +1398,8 @@
             }
 
             if (!imsi.equals(storedImsi) && !TextUtils.isEmpty(storedImsi)) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "wiping all passwords and authtokens");
-                }
+                Log.w(TAG, "wiping all passwords and authtokens because IMSI changed ("
+                        + "stored=" + storedImsi + ", current=" + imsi + ")");
                 SQLiteDatabase db = mOpenHelper.getWritableDatabase();
                 db.beginTransaction();
                 try {
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index da40c8a..38cac87 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -22,7 +22,9 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
+import android.graphics.ColorFilter;
 import android.graphics.Paint;
+import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
@@ -56,9 +58,96 @@
     
     private final Context mContext;
     
+    /**
+     * Special drawable that draws a wallpaper as fast as possible.  Assumes
+     * no scaling or placement off (0,0) of the wallpaper (this should be done
+     * at the time the bitmap is loaded).
+     */
+    static class FastBitmapDrawable extends Drawable {
+        private final Bitmap mBitmap;
+        private final int mWidth;
+        private final int mHeight;
+        private int mDrawLeft;
+        private int mDrawTop;
+
+        private FastBitmapDrawable(Bitmap bitmap) {
+            mBitmap = bitmap;
+            mWidth = bitmap.getWidth();
+            mHeight = bitmap.getHeight();
+            setBounds(0, 0, mWidth, mHeight);
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+            canvas.drawBitmap(mBitmap, mDrawLeft, mDrawTop, null);
+        }
+
+        @Override
+        public int getOpacity() {
+            return PixelFormat.OPAQUE;
+        }
+
+        @Override
+        public void setBounds(int left, int top, int right, int bottom) {
+            mDrawLeft = left + (right-left - mWidth) / 2;
+            mDrawTop = top + (bottom-top - mHeight) / 2;
+        }
+
+        @Override
+        public void setBounds(Rect bounds) {
+            // TODO Auto-generated method stub
+            super.setBounds(bounds);
+        }
+
+        @Override
+        public void setAlpha(int alpha) {
+            throw new UnsupportedOperationException(
+                    "Not supported with this drawable");
+        }
+
+        @Override
+        public void setColorFilter(ColorFilter cf) {
+            throw new UnsupportedOperationException(
+                    "Not supported with this drawable");
+        }
+
+        @Override
+        public void setDither(boolean dither) {
+            throw new UnsupportedOperationException(
+                    "Not supported with this drawable");
+        }
+
+        @Override
+        public void setFilterBitmap(boolean filter) {
+            throw new UnsupportedOperationException(
+                    "Not supported with this drawable");
+        }
+
+        @Override
+        public int getIntrinsicWidth() {
+            return mWidth;
+        }
+
+        @Override
+        public int getIntrinsicHeight() {
+            return mHeight;
+        }
+
+        @Override
+        public int getMinimumWidth() {
+            return mWidth;
+        }
+
+        @Override
+        public int getMinimumHeight() {
+            return mHeight;
+        }
+    }
+    
     static class Globals extends IWallpaperManagerCallback.Stub {
         private IWallpaperManager mService;
         private Bitmap mWallpaper;
+        private Bitmap mDefaultWallpaper;
         
         private static final int MSG_CLEAR_WALLPAPER = 1;
         
@@ -74,6 +163,7 @@
                         case MSG_CLEAR_WALLPAPER:
                             synchronized (this) {
                                 mWallpaper = null;
+                                mDefaultWallpaper = null;
                             }
                             break;
                     }
@@ -90,12 +180,19 @@
             mHandler.sendEmptyMessage(MSG_CLEAR_WALLPAPER);
         }
         
-        public Bitmap peekWallpaperBitmap(Context context) {
+        public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault) {
             synchronized (this) {
                 if (mWallpaper != null) {
                     return mWallpaper;
                 }
+                if (mDefaultWallpaper != null) {
+                    return mDefaultWallpaper;
+                }
                 mWallpaper = getCurrentWallpaperLocked(context);
+                if (mWallpaper == null && returnDefault) {
+                    mDefaultWallpaper = getDefaultWallpaperLocked(context);
+                    return mDefaultWallpaper;
+                }
                 return mWallpaper;
             }
         }
@@ -134,48 +231,48 @@
                         fd.close();
                     } catch (IOException e) {
                     }
-                    if (bm == null) {
+                    
+                    return generateBitmap(context, bm, width, height);
+                }
+            } catch (RemoteException e) {
+            }
+            return null;
+        }
+        
+        private Bitmap getDefaultWallpaperLocked(Context context) {
+            try {
+                InputStream is = context.getResources().openRawResource(
+                        com.android.internal.R.drawable.default_wallpaper);
+                if (is != null) {
+                    int width = mService.getWidthHint();
+                    int height = mService.getHeightHint();
+                    
+                    if (width <= 0 || height <= 0) {
+                        // Degenerate case: no size requested, just load
+                        // bitmap as-is.
+                        Bitmap bm = BitmapFactory.decodeStream(is, null, null);
+                        try {
+                            is.close();
+                        } catch (IOException e) {
+                        }
+                        if (bm != null) {
+                            bm.setDensity(DisplayMetrics.DENSITY_DEVICE);
+                        }
                         return bm;
                     }
-                    bm.setDensity(DisplayMetrics.DENSITY_DEVICE);
                     
-                    // This is the final bitmap we want to return.
-                    Bitmap newbm = Bitmap.createBitmap(width, height,
-                            bm.getConfig());
-                    newbm.setDensity(DisplayMetrics.DENSITY_DEVICE);
-                    Canvas c = new Canvas(newbm);
-                    c.setDensity(DisplayMetrics.DENSITY_DEVICE);
-                    Rect targetRect = new Rect();
-                    targetRect.left = targetRect.top = 0;
-                    targetRect.right = bm.getWidth();
-                    targetRect.bottom = bm.getHeight();
-                    
-                    int deltaw = width - targetRect.right;
-                    int deltah = height - targetRect.bottom;
-                    
-                    if (deltaw > 0 || deltah > 0) {
-                        // We need to scale up so it covers the entire
-                        // area.
-                        float scale = 1.0f;
-                        if (deltaw > deltah) {
-                            scale = width / (float)targetRect.right;
-                        } else {
-                            scale = height / (float)targetRect.bottom;
-                        }
-                        targetRect.right = (int)(targetRect.right*scale);
-                        targetRect.bottom = (int)(targetRect.bottom*scale);
-                        deltaw = width - targetRect.right;
-                        deltah = height - targetRect.bottom;
+                    // Load the bitmap with full color depth, to preserve
+                    // quality for later processing.
+                    BitmapFactory.Options options = new BitmapFactory.Options();
+                    options.inDither = false;
+                    options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+                    Bitmap bm = BitmapFactory.decodeStream(is, null, options);
+                    try {
+                        is.close();
+                    } catch (IOException e) {
                     }
                     
-                    targetRect.offset(deltaw/2, deltah/2);
-                    Paint paint = new Paint();
-                    paint.setFilterBitmap(true);
-                    paint.setDither(true);
-                    c.drawBitmap(bm, null, targetRect, paint);
-                    
-                    bm.recycle();
-                    return newbm;
+                    return generateBitmap(context, bm, width, height);
                 }
             } catch (RemoteException e) {
             }
@@ -219,9 +316,13 @@
      * @return Returns a Drawable object that will draw the wallpaper.
      */
     public Drawable getDrawable() {
-        Drawable dr = peekDrawable();
-        return dr != null ? dr : Resources.getSystem().getDrawable(
-                com.android.internal.R.drawable.default_wallpaper);
+        Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true);
+        if (bm != null) {
+            Drawable dr = new BitmapDrawable(mContext.getResources(), bm);
+            dr.setDither(false);
+            return dr;
+        }
+        return null;
     }
 
     /**
@@ -234,8 +335,51 @@
      * null pointer if these is none.
      */
     public Drawable peekDrawable() {
-        Bitmap bm = sGlobals.peekWallpaperBitmap(mContext);
-        return bm != null ? new BitmapDrawable(mContext.getResources(), bm) : null;
+        Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false);
+        if (bm != null) {
+            Drawable dr = new BitmapDrawable(mContext.getResources(), bm);
+            dr.setDither(false);
+            return dr;
+        }
+        return null;
+    }
+
+    /**
+     * Like {@link #peekFastDrawable}, but always returns a valid Drawable.  If
+     * no wallpaper is set, the system default wallpaper is returned.
+     *
+     * @return Returns a Drawable object that will draw the wallpaper.
+     */
+    public Drawable getFastDrawable() {
+        Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true);
+        if (bm != null) {
+            Drawable dr = new FastBitmapDrawable(bm);
+            return dr;
+        }
+        return null;
+    }
+
+    /**
+     * Like {@link #peekDrawable()}, but the returned Drawable has a number
+     * of limitations to reduce its overhead as much as possible: it will
+     * never scale the wallpaper (only centering it if the requested bounds
+     * do match the bitmap bounds, which should not be typical), doesn't
+     * allow setting an alpha, color filter, or other attributes, etc.  The
+     * bounds of the returned drawable will be initialized to the same bounds
+     * as the wallpaper, so normally you will not need to touch it.  The
+     * drawable also assumes that it will be used in a context running in
+     * the same density as the screen (not in density compatibility mode).
+     *
+     * @return Returns an optimized Drawable object that will draw the
+     * wallpaper or a null pointer if these is none.
+     */
+    public Drawable peekFastDrawable() {
+        Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false);
+        if (bm != null) {
+            Drawable dr = new FastBitmapDrawable(bm);
+            return dr;
+        }
+        return null;
     }
 
     /**
@@ -429,8 +573,10 @@
      */
     public void setWallpaperOffsets(IBinder windowToken, float xOffset, float yOffset) {
         try {
+            //Log.v(TAG, "Sending new wallpaper offsets from app...");
             ViewRoot.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
                     windowToken, xOffset, yOffset);
+            //Log.v(TAG, "...app returning after sending offsets!");
         } catch (RemoteException e) {
             // Ignore.
         }
@@ -466,4 +612,51 @@
     public void clear() throws IOException {
         setResource(com.android.internal.R.drawable.default_wallpaper);
     }
+    
+    static Bitmap generateBitmap(Context context, Bitmap bm, int width, int height) {
+        if (bm == null) {
+            return bm;
+        }
+        bm.setDensity(DisplayMetrics.DENSITY_DEVICE);
+        
+        // This is the final bitmap we want to return.
+        // XXX We should get the pixel depth from the system (to match the
+        // physical display depth), when there is a way.
+        Bitmap newbm = Bitmap.createBitmap(width, height,
+                Bitmap.Config.RGB_565);
+        newbm.setDensity(DisplayMetrics.DENSITY_DEVICE);
+        Canvas c = new Canvas(newbm);
+        c.setDensity(DisplayMetrics.DENSITY_DEVICE);
+        Rect targetRect = new Rect();
+        targetRect.left = targetRect.top = 0;
+        targetRect.right = bm.getWidth();
+        targetRect.bottom = bm.getHeight();
+        
+        int deltaw = width - targetRect.right;
+        int deltah = height - targetRect.bottom;
+        
+        if (deltaw > 0 || deltah > 0) {
+            // We need to scale up so it covers the entire
+            // area.
+            float scale = 1.0f;
+            if (deltaw > deltah) {
+                scale = width / (float)targetRect.right;
+            } else {
+                scale = height / (float)targetRect.bottom;
+            }
+            targetRect.right = (int)(targetRect.right*scale);
+            targetRect.bottom = (int)(targetRect.bottom*scale);
+            deltaw = width - targetRect.right;
+            deltah = height - targetRect.bottom;
+        }
+        
+        targetRect.offset(deltaw/2, deltah/2);
+        Paint paint = new Paint();
+        paint.setFilterBitmap(true);
+        paint.setDither(true);
+        c.drawBitmap(bm, null, targetRect, paint);
+        
+        bm.recycle();
+        return newbm;
+    }
 }
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index ba5c9ed..9d370fc 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -22,8 +22,6 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
-import android.content.pm.ApplicationInfo;
-import android.graphics.BitmapFactory;
 import android.graphics.Movie;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.ColorDrawable;
@@ -1699,7 +1697,7 @@
                 } else {
                     try {
                         InputStream is = mAssets.openNonAsset(
-                                value.assetCookie, file, AssetManager.ACCESS_BUFFER);
+                                value.assetCookie, file, AssetManager.ACCESS_STREAMING);
         //                System.out.println("Opened file " + file + ": " + is);
                         dr = Drawable.createFromResourceStream(this, value, is,
                                 file, null);
diff --git a/core/java/android/os/HandlerThread.java b/core/java/android/os/HandlerThread.java
index 0ce86db..65301e4 100644
--- a/core/java/android/os/HandlerThread.java
+++ b/core/java/android/os/HandlerThread.java
@@ -64,7 +64,7 @@
     /**
      * This method returns the Looper associated with this thread. If this thread not been started
      * or for any reason is isAlive() returns false, this method will return null. If this thread 
-     * has been started, this method will blocked until the looper has been initialized.  
+     * has been started, this method will block until the looper has been initialized.  
      * @return The looper.
      */
     public Looper getLooper() {
@@ -85,6 +85,21 @@
     }
     
     /**
+     * Ask the currently running looper to quit.  If the thread has not
+     * been started or has finished (that is if {@link #getLooper} returns
+     * null), then false is returned.  Otherwise the looper is asked to
+     * quit and true is returned.
+     */
+    public boolean quit() {
+        Looper looper = getLooper();
+        if (looper != null) {
+            looper.quit();
+            return true;
+        }
+        return false;
+    }
+    
+    /**
      * Returns the identifier of this thread. See Process.myTid().
      */
     public int getThreadId() {
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 6ce0f5f..78e2c27 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -399,7 +399,7 @@
         // Electronics, Flaircomm Electronics, Jatty Electronics, Delphi,
         // Clarion, Novero, Denso (Lexus, Toyota), Johnson Controls (Acura),
         // Continental Automotive, Harman/Becker
-        private final ArrayList<String>  mAutoPairingBlacklisted =
+        private final ArrayList<String>  mAutoPairingAddressBlacklist =
                 new ArrayList<String>(Arrays.asList(
                         "00:02:C7", "00:16:FE", "00:19:C1", "00:1B:FB", "00:1E:3D", "00:21:4F",
                         "00:23:06", "00:24:33", "00:A0:79", "00:0E:6D", "00:13:E0", "00:21:E8",
@@ -408,6 +408,12 @@
                         "00:0A:30", "00:1E:AE", "00:1C:D7"
                         ));
 
+        // List of names of Bluetooth devices for which auto pairing should be
+        // disabled.
+        private final ArrayList<String> mAutoPairingNameBlacklist =
+                new ArrayList<String>(Arrays.asList(
+                        "Motorola IHF1000", "i.TechBlueBAND", "X5 Stereo v1.3"));
+
         public synchronized void loadBondState() {
             if (mBluetoothState != BluetoothAdapter.STATE_TURNING_ON) {
                 return;
@@ -460,9 +466,16 @@
         }
 
         public boolean isAutoPairingBlacklisted(String address) {
-            for (String blacklistAddress : mAutoPairingBlacklisted) {
+            for (String blacklistAddress : mAutoPairingAddressBlacklist) {
                 if (address.startsWith(blacklistAddress)) return true;
             }
+
+            String name = getRemoteName(address);
+            if (name != null) {
+                for (String blacklistName : mAutoPairingNameBlacklist) {
+                    if (name.equals(blacklistName)) return true;
+                }
+            }
             return false;
         }
 
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index e5659d5..cd5cf10 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -28,9 +28,11 @@
 import android.content.IntentFilter;
 import android.graphics.Rect;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
 import android.util.Log;
+import android.util.LogPrinter;
 import android.view.Gravity;
 import android.view.IWindowSession;
 import android.view.MotionEvent;
@@ -74,6 +76,8 @@
     private static final int MSG_WINDOW_RESIZED = 10030;
     private static final int MSG_TOUCH_EVENT = 10040;
     
+    private Looper mCallbackLooper;
+    
     /**
      * The actual implementation of a wallpaper.  A wallpaper service may
      * have multiple instances running (for example as a real wallpaper
@@ -120,6 +124,7 @@
         boolean mOffsetMessageEnqueued;
         float mPendingXOffset;
         float mPendingYOffset;
+        boolean mPendingSync;
         MotionEvent mPendingMove;
         
         final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -212,10 +217,14 @@
             }
 
             @Override
-            public void dispatchWallpaperOffsets(float x, float y) {
+            public void dispatchWallpaperOffsets(float x, float y, boolean sync) {
                 synchronized (mLock) {
+                    if (DEBUG) Log.v(TAG, "Dispatch wallpaper offsets: " + x + ", " + y);
                     mPendingXOffset = x;
                     mPendingYOffset = y;
+                    if (sync) {
+                        mPendingSync = true;
+                    }
                     if (!mOffsetMessageEnqueued) {
                         mOffsetMessageEnqueued = true;
                         Message msg = mCaller.obtainMessage(MSG_WALLPAPER_OFFSETS);
@@ -551,9 +560,12 @@
             
             float xOffset;
             float yOffset;
+            boolean sync;
             synchronized (mLock) {
                 xOffset = mPendingXOffset;
                 yOffset = mPendingYOffset;
+                sync = mPendingSync;
+                mPendingSync = false;
                 mOffsetMessageEnqueued = false;
             }
             if (DEBUG) Log.v(TAG, "Offsets change in " + this
@@ -563,6 +575,14 @@
             final int availh = mIWallpaperEngine.mReqHeight-mCurHeight;
             final int yPixels = availh > 0 ? -(int)(availh*yOffset+.5f) : 0;
             onOffsetsChanged(xOffset, yOffset, xPixels, yPixels);
+            
+            if (sync) {
+                try {
+                    if (DEBUG) Log.v(TAG, "Reporting offsets change complete");
+                    mSession.wallpaperOffsetsComplete(mWindow.asBinder());
+                } catch (RemoteException e) {
+                }
+            }
         }
         
         void detach() {
@@ -622,7 +642,13 @@
         IWallpaperEngineWrapper(WallpaperService context,
                 IWallpaperConnection conn, IBinder windowToken,
                 int windowType, boolean isPreview, int reqWidth, int reqHeight) {
-            mCaller = new HandlerCaller(context, this);
+            if (DEBUG && mCallbackLooper != null) {
+                mCallbackLooper.setMessageLogging(new LogPrinter(Log.VERBOSE, TAG));
+            }
+            mCaller = new HandlerCaller(context,
+                    mCallbackLooper != null
+                            ? mCallbackLooper : context.getMainLooper(),
+                    this);
             mConnection = conn;
             mWindowToken = windowToken;
             mWindowType = windowType;
@@ -736,5 +762,18 @@
         return new IWallpaperServiceWrapper(this);
     }
     
+    /**
+     * This allows subclasses to change the thread that most callbacks
+     * occur on.  Currently hidden because it is mostly needed for the
+     * image wallpaper (which runs in the system process and doesn't want
+     * to get stuck running on that seriously in use main thread).  Not
+     * exposed right now because the semantics of this are not totally
+     * well defined and some callbacks can still happen on the main thread).
+     * @hide
+     */
+    public void setCallbackLooper(Looper looper) {
+        mCallbackLooper = looper;
+    }
+    
     public abstract Engine onCreateEngine();
 }
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index d61e888..ce25c47 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -208,7 +208,7 @@
 
         if ((mask & WEB_URLS) != 0) {
             gatherLinks(links, text, Regex.WEB_URL_PATTERN,
-                new String[] { "http://", "https://" },
+                new String[] { "http://", "https://", "rtsp://" },
                 sUrlMatchFilter, null);
         }
 
diff --git a/core/java/android/text/util/Regex.java b/core/java/android/text/util/Regex.java
index a349b82..a6844a4 100644
--- a/core/java/android/text/util/Regex.java
+++ b/core/java/android/text/util/Regex.java
@@ -65,7 +65,7 @@
      */
     public static final Pattern WEB_URL_PATTERN
         = Pattern.compile(
-            "((?:(http|https|Http|Https):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
+            "((?:(http|https|Http|Https|rtsp|Rtsp):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
             + "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
             + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?"
             + "((?:(?:[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}\\.)+"   // named host
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index ebc5f7b..b7953af 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -60,5 +60,5 @@
     /**
      * Called for wallpaper windows when their offsets change.
      */
-    void dispatchWallpaperOffsets(float x, float y);
+    void dispatchWallpaperOffsets(float x, float y, boolean sync);
 }
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 4d662d2..9b8b6d4 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -114,4 +114,6 @@
      * larger than the screen, set the offset within the screen.
      */
     void setWallpaperPosition(IBinder windowToken, float x, float y);
+    
+    void wallpaperOffsetsComplete(IBinder window);
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f63c2f1..2cc243e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6042,12 +6042,11 @@
         int height = mBottom - mTop;
 
         final AttachInfo attachInfo = mAttachInfo;
-        final float scale = attachInfo.mApplicationScale;
+        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
         width = (int) ((width * scale) + 0.5f);
         height = (int) ((height * scale) + 0.5f);
         
-        Bitmap bitmap = Bitmap.createBitmap(width > 0 ? width : 1,
-                height > 0 ? height : 1, quality);
+        Bitmap bitmap = Bitmap.createBitmap(width > 0 ? width : 1, height > 0 ? height : 1, quality);
         if (bitmap == null) {
             throw new OutOfMemoryError();
         }
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index b61465a..6748ade 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -2868,7 +2868,13 @@
             }
         }
         
-        public void dispatchWallpaperOffsets(float x, float y) {
+        public void dispatchWallpaperOffsets(float x, float y, boolean sync) {
+            if (sync) {
+                try {
+                    sWindowSession.wallpaperOffsetsComplete(asBinder());
+                } catch (RemoteException e) {
+                }
+            }
         }
     }
 
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index c93df74..2329e21 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -458,8 +458,7 @@
     private static final int SWITCH_TO_LONGPRESS        = 4;
     private static final int RELEASE_SINGLE_TAP         = 5;
     private static final int REQUEST_FORM_DATA          = 6;
-    private static final int SWITCH_TO_CLICK            = 7;
-    private static final int RESUME_WEBCORE_UPDATE      = 8;
+    private static final int RESUME_WEBCORE_UPDATE      = 7;
 
     //! arg1=x, arg2=y
     static final int SCROLL_TO_MSG_ID                   = 10;
@@ -1395,6 +1394,7 @@
      * Reload the current url.
      */
     public void reload() {
+        clearTextEntry();
         switchOutDrawHistory();
         mWebViewCore.sendMessage(EventHub.RELOAD);
     }
@@ -3664,16 +3664,27 @@
             if (mShiftIsPressed) {
                 return false;
             }
-            if (getSettings().supportZoom()
-                    && mTouchMode == TOUCH_DOUBLECLICK_MODE) {
-                zoomScrollOut();
-            } else {
-                mPrivateHandler.sendMessageDelayed(mPrivateHandler
-                        .obtainMessage(SWITCH_TO_CLICK), TAP_TIMEOUT);
-                if (DebugFlags.WEB_VIEW) {
-                    Log.v(LOGTAG, "TOUCH_DOUBLECLICK_MODE");
-                }
-                mTouchMode = TOUCH_DOUBLECLICK_MODE;
+
+            // perform the single click
+            Rect visibleRect = sendOurVisibleRect();
+            // Note that sendOurVisibleRect calls viewToContent, so the
+            // coordinates should be in content coordinates.
+            if (!nativeCursorIntersects(visibleRect)) {
+                return false;
+            }
+            nativeSetFollowedLink(true);
+            nativeUpdatePluginReceivesEvents();
+            WebViewCore.CursorData data = cursorData();
+            mWebViewCore.sendMessage(EventHub.SET_MOVE_MOUSE, data);
+            playSoundEffect(SoundEffectConstants.CLICK);
+            boolean isTextInput = nativeCursorIsTextInput();
+            if (isTextInput || !mCallbackProxy.uiOverrideUrlLoading(
+                        nativeCursorText())) {
+                mWebViewCore.sendMessage(EventHub.CLICK, data.mFrame,
+                        nativeCursorNodePointer());
+            }
+            if (isTextInput) {
+                rebuildWebTextView();
             }
             return true;
         }
@@ -4321,7 +4332,6 @@
             return true;
         }
         if (ev.getAction() == MotionEvent.ACTION_DOWN) {
-            mPrivateHandler.removeMessages(SWITCH_TO_CLICK);
             mTrackballDown = true;
             if (mNativeClass == 0) {
                 return false;
@@ -4570,7 +4580,7 @@
 
     private int computeMaxScrollY() {
         int maxContentH = computeVerticalScrollRange() + getTitleHeight();
-        return Math.max(maxContentH - getHeight(), 0);
+        return Math.max(maxContentH - getHeight(), getTitleHeight());
     }
 
     public void flingScroll(int vx, int vy) {
@@ -4876,6 +4886,9 @@
         }
         int x = viewToContentX((int) event.getX() + mWebTextView.getLeft());
         int y = viewToContentY((int) event.getY() + mWebTextView.getTop());
+        // In case the soft keyboard has been dismissed, bring it back up.
+        InputMethodManager.getInstance(getContext()).showSoftInput(mWebTextView,
+                0);
         nativeTextInputMotionUp(x, y);
     }
 
@@ -5184,32 +5197,6 @@
                     }
                     break;
                 }
-                case SWITCH_TO_CLICK:
-                    // The user clicked with the trackball, and did not click a
-                    // second time, so perform the action of a trackball single
-                    // click
-                    mTouchMode = TOUCH_DONE_MODE;
-                    Rect visibleRect = sendOurVisibleRect();
-                    // Note that sendOurVisibleRect calls viewToContent, so the
-                    // coordinates should be in content coordinates.
-                    if (!nativeCursorIntersects(visibleRect)) {
-                        break;
-                    }
-                    nativeSetFollowedLink(true);
-                    nativeUpdatePluginReceivesEvents();
-                    WebViewCore.CursorData data = cursorData();
-                    mWebViewCore.sendMessage(EventHub.SET_MOVE_MOUSE, data);
-                    playSoundEffect(SoundEffectConstants.CLICK);
-                    boolean isTextInput = nativeCursorIsTextInput();
-                    if (isTextInput || !mCallbackProxy.uiOverrideUrlLoading(
-                                nativeCursorText())) {
-                        mWebViewCore.sendMessage(EventHub.CLICK, data.mFrame,
-                                nativeCursorNodePointer());
-                    }
-                    if (isTextInput) {
-                        rebuildWebTextView();
-                    }
-                    break;
                 case SCROLL_BY_MSG_ID:
                     setContentScrollBy(msg.arg1, msg.arg2, (Boolean) msg.obj);
                     break;
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index e7b303a..f34823c 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -23,7 +23,6 @@
 import android.content.res.TypedArray;
 import android.graphics.Rect;
 import android.util.AttributeSet;
-import android.util.Config;
 import android.util.Log;
 import android.view.GestureDetector;
 import android.view.Gravity;
@@ -36,8 +35,6 @@
 import android.view.SoundEffectConstants;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.animation.Transformation;
-import android.widget.AbsSpinner;
-import android.widget.Scroller;
 
 /**
  * A view that shows items in a center-locked, horizontally scrolling list.
@@ -59,7 +56,7 @@
 
     private static final String TAG = "Gallery";
 
-    private static final boolean localLOGV = Config.LOGV;
+    private static final boolean localLOGV = false;
 
     /**
      * Duration in milliseconds from the start of a scroll during which we're
@@ -514,6 +511,7 @@
             // We haven't been callbacking during the fling, so do it now
             super.selectionChanged();
         }
+        invalidate();
     }
     
     @Override
@@ -534,12 +532,9 @@
         
         int galleryCenter = getCenterOfGallery();
         
-        if (selView != null) {
-
-            // Common case where the current selected position is correct
-            if (selView.getLeft() <= galleryCenter && selView.getRight() >= galleryCenter) {
-                return;
-            }
+        // Common case where the current selected position is correct
+        if (selView.getLeft() <= galleryCenter && selView.getRight() >= galleryCenter) {
+            return;
         }
         
         // TODO better search
@@ -627,7 +622,6 @@
         View sel = makeAndAddView(mSelectedPosition, 0, 0, true);
         
         // Put the selected child in the center
-        Gallery.LayoutParams lp = (Gallery.LayoutParams) sel.getLayoutParams();
         int selectedOffset = childrenLeft + (childrenWidth / 2) - (sel.getWidth() / 2);
         sel.offsetLeftAndRight(selectedOffset);
 
@@ -733,9 +727,6 @@
             child = mRecycler.get(position);
             if (child != null) {
                 // Can reuse an existing view
-                Gallery.LayoutParams lp = (Gallery.LayoutParams) 
-                    child.getLayoutParams();
-
                 int childLeft = child.getLeft();
                 
                 // Remember left and right edges of where views have been placed
@@ -798,7 +789,7 @@
         int childRight;
 
         // Position vertically based on gravity setting
-        int childTop = calculateTop(child, lp, true);
+        int childTop = calculateTop(child, true);
         int childBottom = childTop + child.getMeasuredHeight();
 
         int width = child.getMeasuredWidth();
@@ -817,11 +808,9 @@
      * Figure out vertical placement based on mGravity
      * 
      * @param child Child to place
-     * @param lp LayoutParams for this view (just so we don't keep looking them
-     *        up)
      * @return Where the top of the child should be
      */
-    private int calculateTop(View child, Gallery.LayoutParams lp, boolean duringLayout) {
+    private int calculateTop(View child, boolean duringLayout) {
         int myHeight = duringLayout ? mMeasuredHeight : getHeight();
         int childHeight = duringLayout ? child.getMeasuredHeight() : child.getHeight(); 
         
diff --git a/core/java/com/android/internal/os/HandlerCaller.java b/core/java/com/android/internal/os/HandlerCaller.java
index 5825024..35b9251 100644
--- a/core/java/com/android/internal/os/HandlerCaller.java
+++ b/core/java/com/android/internal/os/HandlerCaller.java
@@ -57,6 +57,13 @@
         mCallback = callback;
     }
 
+    public HandlerCaller(Context context, Looper looper, Callback callback) {
+        mContext = context;
+        mMainLooper = looper;
+        mH = new MyHandler(mMainLooper);
+        mCallback = callback;
+    }
+
     public SomeArgs obtainArgs() {
         synchronized (mH) {
             SomeArgs args = mArgsPool;
diff --git a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
index 5357469..0bc70de 100644
--- a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
+++ b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
@@ -20,6 +20,8 @@
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.os.HandlerThread;
+import android.os.Process;
 import android.service.wallpaper.WallpaperService;
 import android.view.MotionEvent;
 import android.view.SurfaceHolder;
@@ -33,20 +35,29 @@
  */
 public class ImageWallpaper extends WallpaperService {
     WallpaperManager mWallpaperManager;
+    private HandlerThread mThread;
 
     @Override
     public void onCreate() {
         super.onCreate();
         mWallpaperManager = (WallpaperManager) getSystemService(WALLPAPER_SERVICE);
+        mThread = new HandlerThread("Wallpaper", Process.THREAD_PRIORITY_FOREGROUND);
+        mThread.start();
+        setCallbackLooper(mThread.getLooper());
     }
 
     public Engine onCreateEngine() {
         return new DrawableEngine();
     }
 
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        mThread.quit();
+    }
+
     class DrawableEngine extends Engine {
         private final Object mLock = new Object();
-        private final Rect mBounds = new Rect();
         private WallpaperObserver mReceiver;
         Drawable mBackground;
         float mXOffset;
@@ -56,6 +67,9 @@
             public void onReceive(Context context, Intent intent) {
                 updateWallpaper();
                 drawFrame();
+                // Assume we are the only one using the wallpaper in this
+                // process, and force a GC now to release the old wallpaper.
+                System.gc();
             }
         }
 
@@ -67,7 +81,6 @@
             registerReceiver(mReceiver, filter);
             updateWallpaper();
             surfaceHolder.setSizeFromLayout();
-            //setTouchEventsEnabled(true);
         }
 
         @Override
@@ -137,11 +150,7 @@
 
         void updateWallpaper() {
             synchronized (mLock) {
-                mBackground = mWallpaperManager.getDrawable();
-                mBounds.left = mBounds.top = 0;
-                mBounds.right = mBackground.getIntrinsicWidth();
-                mBounds.bottom = mBackground.getIntrinsicHeight();
-                mBackground.setBounds(mBounds);
+                mBackground = mWallpaperManager.getFastDrawable();
             }
         }
     }
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index f4f6297..b8d19ac 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -90,6 +90,12 @@
     public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
     }
     
-    public void dispatchWallpaperOffsets(float x, float y) {
+    public void dispatchWallpaperOffsets(float x, float y, boolean sync) {
+        if (sync) {
+            try {
+                mSession.wallpaperOffsetsComplete(asBinder());
+            } catch (RemoteException e) {
+            }
+        }
     }
 }
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 7748aba..5b6c7ea 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -32,6 +32,7 @@
 #include <sys/errno.h>
 #include <sys/resource.h>
 #include <sys/types.h>
+#include <cutils/sched_policy.h>
 #include <dirent.h>
 #include <fcntl.h>
 #include <grp.h>
@@ -186,58 +187,6 @@
     return -1;
 }
 
-static int add_pid_to_cgroup(int pid, const char *grp_name)
-{
-    int fd;
-    char path[255];
-    char text[64];
-
-    sprintf(path, "/dev/cpuctl/%s/tasks", grp_name);
-
-    if ((fd = open(path, O_WRONLY)) < 0)
-        return -1;
-
-    sprintf(text, "%d", pid);
-    if (write(fd, text, strlen(text)) < 0) {
-        close(fd);
-        return -1;
-    }
-
-    close(fd);
-    return 0;
-}
-
-void setSchedPolicy(JNIEnv* env, jobject clazz, int pid, SchedPolicy policy)
-{
-    static int __sys_supports_schedgroups = -1;
-
-    if (__sys_supports_schedgroups < 0) {
-        if (!access("/dev/cpuctl/tasks", F_OK)) {
-            __sys_supports_schedgroups = 1;
-        } else {
-            __sys_supports_schedgroups = 0;
-        }
-    }
-
-    if (__sys_supports_schedgroups) {
-        const char *grp = NULL;
-
-        if (policy == SP_BACKGROUND) {
-            grp = "bg_non_interactive";
-        }
-
-        if (add_pid_to_cgroup(pid, grp)) {
-            if (errno != ESRCH && errno != ENOENT)
-                signalExceptionForGroupError(env, clazz, errno);
-        }
-    } else {
-        struct sched_param param;
-
-        param.sched_priority = 0;
-        sched_setscheduler(pid, (policy == SP_BACKGROUND) ? 5 : 0, &param);
-    }
-}
-
 void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int pid, jint grp)
 {
     if (grp > ANDROID_TGROUP_MAX || grp < 0) { 
@@ -245,9 +194,10 @@
         return;
     }
 
-    setSchedPolicy(env, clazz, pid,
-                   (grp == ANDROID_TGROUP_BG_NONINTERACT) ?
-                           SP_BACKGROUND : SP_FOREGROUND);
+    if (set_sched_policy(pid, (grp == ANDROID_TGROUP_BG_NONINTERACT) ?
+                                      SP_BACKGROUND : SP_FOREGROUND)) {
+        signalExceptionForGroupError(env, clazz, errno);
+    }
 }
 
 void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jint grp) 
@@ -291,9 +241,10 @@
             continue;
         }
      
-        setSchedPolicy(env, clazz, t_pid,
-                       (grp == ANDROID_TGROUP_BG_NONINTERACT) ?
-                               SP_BACKGROUND : SP_FOREGROUND);
+        if (set_sched_policy(t_pid, (grp == ANDROID_TGROUP_BG_NONINTERACT) ?
+                                            SP_BACKGROUND : SP_FOREGROUND)) {
+            signalExceptionForGroupError(env, clazz, errno);
+        }
     }
     closedir(d);
 }
@@ -301,10 +252,16 @@
 void android_os_Process_setThreadPriority(JNIEnv* env, jobject clazz,
                                               jint pid, jint pri)
 {
+    int rc = 0;
+
     if (pri >= ANDROID_PRIORITY_BACKGROUND) {
-        setSchedPolicy(env, clazz, pid, SP_BACKGROUND);
+        rc = set_sched_policy(pid, SP_BACKGROUND);
     } else if (getpriority(PRIO_PROCESS, pid) >= ANDROID_PRIORITY_BACKGROUND) {
-        setSchedPolicy(env, clazz, pid, SP_FOREGROUND);
+        rc = set_sched_policy(pid, SP_FOREGROUND);
+    }
+
+    if (rc) {
+        signalExceptionForGroupError(env, clazz, errno);
     }
 
     if (setpriority(PRIO_PROCESS, pid, pri) < 0) {
diff --git a/include/private/ui/SharedBufferStack.h b/include/private/ui/SharedBufferStack.h
index 6181f55..8b0f154 100644
--- a/include/private/ui/SharedBufferStack.h
+++ b/include/private/ui/SharedBufferStack.h
@@ -228,6 +228,8 @@
     friend struct Condition;
     friend struct DequeueCondition;
     friend struct LockCondition;
+    
+    int32_t computeTail() const;
 
     struct QueueUpdate : public UpdateBase {
         inline QueueUpdate(SharedBufferBase* sbb);
diff --git a/include/utils/threads.h b/include/utils/threads.h
index f5304f7..0fc533f 100644
--- a/include/utils/threads.h
+++ b/include/utils/threads.h
@@ -90,11 +90,6 @@
     ANDROID_TGROUP_MAX              = ANDROID_TGROUP_FG_BOOST,
 };
 
-typedef enum {
-    SP_BACKGROUND = 0,
-    SP_FOREGROUND = 1,
-} SchedPolicy;
-
 // Create and run a new thread.
 extern int androidCreateThread(android_thread_func_t, void *);
 
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 8685f99..a352431 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -1524,13 +1524,24 @@
                 result.append( l->lcblk->dump("      ") );
                 sp<const Buffer> buf0(l->getBuffer(0));
                 sp<const Buffer> buf1(l->getBuffer(1));
+                uint32_t w0=0, h0=0, s0=0;
+                uint32_t w1=0, h1=0, s1=0;
+                if (buf0 != 0) {
+                    w0 = buf0->getWidth();
+                    h0 = buf0->getHeight();
+                    s0 = buf0->getStride();
+                }
+                if (buf1 != 0) {
+                    w1 = buf1->getWidth();
+                    h1 = buf1->getHeight();
+                    s1 = buf1->getStride();
+                }
                 snprintf(buffer, SIZE,
                         "      "
                         "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
                         " freezeLock=%p\n",
                         l->pixelFormat(),
-                        buf0->getWidth(), buf0->getHeight(), buf0->getStride(),
-                        buf1->getWidth(), buf1->getHeight(), buf1->getStride(),
+                        w0, h0, s0, w1, h1, s1,
                         l->getFreezeLock().get());
                 result.append(buffer);
                 buffer[0] = 0;
diff --git a/libs/ui/SharedBufferStack.cpp b/libs/ui/SharedBufferStack.cpp
index 436d793..7789a3f 100644
--- a/libs/ui/SharedBufferStack.cpp
+++ b/libs/ui/SharedBufferStack.cpp
@@ -246,19 +246,26 @@
         int surface, int num)
     : SharedBufferBase(sharedClient, surface, num), tail(0)
 {
+    tail = computeTail();
+}
+
+int32_t SharedBufferClient::computeTail() const
+{
     SharedBufferStack& stack( *mSharedStack );
-    int32_t avail;
-    int32_t head;
     // we need to make sure we read available and head coherently,
     // w.r.t RetireUpdate.
+    int32_t newTail;
+    int32_t avail;
+    int32_t head;
     do {
         avail = stack.available;
         head = stack.head;
     } while (stack.available != avail);
-    tail = head - avail + 1;
-    if (tail < 0) {
-        tail += num;
+    newTail = head - avail + 1;
+    if (newTail < 0) {
+        newTail += mNumBuffers;
     }
+    return newTail;
 }
 
 ssize_t SharedBufferClient::dequeue()
@@ -296,6 +303,9 @@
 {
     UndoDequeueUpdate update(this);
     status_t err = updateCondition( update );
+    if (err == NO_ERROR) {
+        tail = computeTail();
+    }
     return err;
 }
 
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index d905619..22c2f39 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1266,6 +1266,8 @@
 
         CHECK_EQ(info->mOwnedByComponent, false);
 
+        CODEC_LOGV("freeing buffer %p on port %ld", info->mBuffer, portIndex);
+
         status_t err =
             mOMX->free_buffer(mNode, portIndex, info->mBuffer);
 
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 38df47b..ba65f01 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -63,7 +63,7 @@
 import java.util.Observer;
 
 class PowerManagerService extends IPowerManager.Stub
-        implements LocalPowerManager,Watchdog.Monitor, SensorEventListener {
+        implements LocalPowerManager, Watchdog.Monitor, SensorEventListener {
 
     private static final String TAG = "PowerManagerService";
     static final String PARTIAL_NAME = "PowerManagerService";
@@ -1848,7 +1848,17 @@
     }
     
     public void setKeyboardVisibility(boolean visible) {
-        mKeyboardVisible = visible;
+        synchronized (mLocks) {
+            if (mSpew) {
+                Log.d(TAG, "setKeyboardVisibility: " + visible);
+            }
+            mKeyboardVisible = visible;
+            // don't signal user activity when closing keyboard if the screen is off.
+            // otherwise, we want to make sure the backlights are adjusted.
+            if (visible || (mPowerState & SCREEN_ON_BIT) != 0) {
+                userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true);
+            }
+        }
     }
 
     /**
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index b0e4038..c844de2 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -418,6 +418,17 @@
     int mWallpaperAnimLayerAdjustment;
     float mLastWallpaperX;
     float mLastWallpaperY;
+    // Lock for waiting for the wallpaper.
+    final Object mWaitingOnWallpaperLock = new Object();
+    // This is set when we are waiting for a wallpaper to tell us it is done
+    // changing its scroll position.
+    WindowState mWaitingOnWallpaper;
+    // The last time we had a timeout when waiting for a wallpaper.
+    long mLastWallpaperTimeoutTime;
+    // We give a wallpaper up to 150ms to finish scrolling.
+    static final long WALLPAPER_TIMEOUT = 150;
+    // Time we wait after a timeout before trying to wait again.
+    static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
     
     AppWindowToken mFocusedApp = null;
 
@@ -1427,7 +1438,7 @@
                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
                 
                 if (visible) {
-                    updateWallpaperOffsetLocked(wallpaper, dw, dh);                        
+                    updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
                 }
                 
                 // First, make sure the client has the current visibility
@@ -1498,7 +1509,8 @@
         }
     }
 
-    boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh) {
+    boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
+            boolean sync) {
         boolean changed = false;
         boolean rawChanged = false;
         if (mLastWallpaperX >= 0) {
@@ -1536,8 +1548,37 @@
                 if (DEBUG_WALLPAPER) Log.v(TAG, "Report new wp offset "
                         + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
                         + " y=" + wallpaperWin.mWallpaperY);
+                if (sync) {
+                    synchronized (mWaitingOnWallpaperLock) {
+                        mWaitingOnWallpaper = wallpaperWin;
+                    }
+                }
                 wallpaperWin.mClient.dispatchWallpaperOffsets(
-                        wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY);
+                        wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY, sync);
+                if (sync) {
+                    synchronized (mWaitingOnWallpaperLock) {
+                        if (mWaitingOnWallpaper != null) {
+                            long start = SystemClock.uptimeMillis();
+                            if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY)
+                                    < start) {
+                                try {
+                                    if (DEBUG_WALLPAPER) Log.v(TAG,
+                                            "Waiting for offset complete...");
+                                    mWaitingOnWallpaperLock.wait(WALLPAPER_TIMEOUT);
+                                } catch (InterruptedException e) {
+                                }
+                                if (DEBUG_WALLPAPER) Log.v(TAG, "Offset complete!");
+                                if ((start+WALLPAPER_TIMEOUT)
+                                        < SystemClock.uptimeMillis()) {
+                                    Log.i(TAG, "Timeout waiting for wallpaper to offset: "
+                                            + wallpaperWin);
+                                    mLastWallpaperTimeoutTime = start;
+                                }
+                            }
+                            mWaitingOnWallpaper = null;
+                        }
+                    }
+                }
             } catch (RemoteException e) {
             }
         }
@@ -1545,7 +1586,17 @@
         return changed;
     }
     
-    boolean updateWallpaperOffsetLocked() {
+    void wallpaperOffsetsComplete(IBinder window) {
+        synchronized (mWaitingOnWallpaperLock) {
+            if (mWaitingOnWallpaper != null &&
+                    mWaitingOnWallpaper.mClient.asBinder() == window) {
+                mWaitingOnWallpaper = null;
+                mWaitingOnWallpaperLock.notifyAll();
+            }
+        }
+    }
+    
+    boolean updateWallpaperOffsetLocked(boolean sync) {
         final int dw = mDisplay.getWidth();
         final int dh = mDisplay.getHeight();
         
@@ -1563,9 +1614,11 @@
                 while (curWallpaperIndex > 0) {
                     curWallpaperIndex--;
                     WindowState wallpaper = token.windows.get(curWallpaperIndex);
-                    if (updateWallpaperOffsetLocked(wallpaper, dw, dh)) {
+                    if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
                         wallpaper.computeShownFrameLocked();
                         changed = true;
+                        // We only want to be synchronous with one wallpaper.
+                        sync = false;
                     }
                 }
             }
@@ -1595,7 +1648,7 @@
                 curWallpaperIndex--;
                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
                 if (visible) {
-                    updateWallpaperOffsetLocked(wallpaper, dw, dh);                        
+                    updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
                 }
                 
                 if (wallpaper.mWallpaperVisible != visible) {
@@ -1782,8 +1835,10 @@
                 imMayMove = false;
             } else {
                 addWindowToListInOrderLocked(win, true);
-                if (attrs.type == TYPE_WALLPAPER ||
-                        (attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
+                if (attrs.type == TYPE_WALLPAPER) {
+                    mLastWallpaperTimeoutTime = 0;
+                    adjustWallpaperWindowsLocked();
+                } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
                     adjustWallpaperWindowsLocked();
                 }
             }
@@ -1992,8 +2047,10 @@
             }
         }
 
-        if (win.mAttrs.type == TYPE_WALLPAPER ||
-                (win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
+        if (win.mAttrs.type == TYPE_WALLPAPER) {
+            mLastWallpaperTimeoutTime = 0;
+            adjustWallpaperWindowsLocked();
+        } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
             adjustWallpaperWindowsLocked();
         }
         
@@ -2070,7 +2127,7 @@
             window.mWallpaperY = y;
             
             if (mWallpaperTarget == window) {
-                if (updateWallpaperOffsetLocked()) {
+                if (updateWallpaperOffsetLocked(true)) {
                     performLayoutAndPlaceSurfacesLocked();
                 }
             }
@@ -2258,7 +2315,7 @@
             performLayoutAndPlaceSurfacesLocked();
             if (displayed && win.mIsWallpaper) {
                 updateWallpaperOffsetLocked(win, mDisplay.getWidth(),
-                        mDisplay.getHeight());
+                        mDisplay.getHeight(), false);
             }
             if (win.mAppToken != null) {
                 win.mAppToken.updateReportedVisibilityLocked();
@@ -6303,6 +6360,10 @@
             }
         }
         
+        public void wallpaperOffsetsComplete(IBinder window) {
+            WindowManagerService.this.wallpaperOffsetsComplete(window);
+        }
+        
         void windowAddedLocked() {
             if (mSurfaceSession == null) {
                 if (localLOGV) Log.v(
@@ -6698,7 +6759,7 @@
 
             if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
                 updateWallpaperOffsetLocked(this, mDisplay.getWidth(),
-                        mDisplay.getHeight());
+                        mDisplay.getHeight(), false);
             }
             
             if (localLOGV) {
diff --git a/tests/DumpRenderTree/assets/run_layout_tests.py b/tests/DumpRenderTree/assets/run_layout_tests.py
index c3e6b5b..c3627bb 100755
--- a/tests/DumpRenderTree/assets/run_layout_tests.py
+++ b/tests/DumpRenderTree/assets/run_layout_tests.py
@@ -197,7 +197,17 @@
     logging.error("DumpRenderTree crashed, output:\n" + adb_output)
 
     shell_cmd_str = adb_cmd + " shell cat /sdcard/android/running_test.txt"
-    crashed_test = subprocess.Popen(shell_cmd_str, shell=True, stdout=subprocess.PIPE).communicate()[0]
+    crashed_test = ""
+    while not crashed_test:
+      (crashed_test, err) = subprocess.Popen(
+          shell_cmd_str, shell=True, stdout=subprocess.PIPE,
+          stderr=subprocess.PIPE).communicate()
+      crashed_test = crashed_test.strip()
+      if not crashed_test:
+        logging.error('Cannot get crashed test name, device offline?')
+        logging.error('stderr: ' + err)
+        logging.error('retrying in 10s...')
+        time.sleep(10)
 
     logging.info(crashed_test + " CRASHED");
     crashed_tests.append(crashed_test);
diff --git a/tests/DumpRenderTree/assets/run_reliability_tests.py b/tests/DumpRenderTree/assets/run_reliability_tests.py
index 23f93df..59ac4a3 100755
--- a/tests/DumpRenderTree/assets/run_reliability_tests.py
+++ b/tests/DumpRenderTree/assets/run_reliability_tests.py
@@ -195,8 +195,18 @@
   while not DumpRenderTreeFinished(adb_cmd):
     logging.error("DumpRenderTree exited before all URLs are visited.")
     shell_cmd_str = adb_cmd + " shell cat " + TEST_STATUS_FILE
-    crashed_test = subprocess.Popen(shell_cmd_str, shell=True,
-                                    stdout=subprocess.PIPE).communicate()[0]
+    crashed_test = ""
+    while not crashed_test:
+      (crashed_test, err) = subprocess.Popen(
+          shell_cmd_str, shell=True, stdout=subprocess.PIPE,
+          stderr=subprocess.PIPE).communicate()
+      crashed_test = crashed_test.strip()
+      if not crashed_test:
+        logging.error('Cannot get crashed test name, device offline?')
+        logging.error('stderr: ' + err)
+        logging.error('retrying in 10s...')
+        time.sleep(10)
+
     logging.info(crashed_test + " CRASHED")
     crashed_tests.append(crashed_test)
     Bugreport(crashed_test, bugreport_dir, adb_cmd)
diff --git a/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutBridge.java b/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutBridge.java
index c562650..4dbcfdc 100644
--- a/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutBridge.java
+++ b/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutBridge.java
@@ -88,7 +88,7 @@
      * @param projectCallback The {@link IProjectCallback} object to get information from
      * the project.
      * @param logger the object responsible for displaying warning/errors to the user.
-     * @return an {@link ILayoutResult} object that contains the result of the layout.
+     * @return a new {@link ILayoutResult} object that contains the result of the layout.
      * @since 4
      */
     ILayoutResult computeLayout(IXmlPullParser layoutDescription,
@@ -123,7 +123,7 @@
      * @param projectCallback The {@link IProjectCallback} object to get information from
      * the project.
      * @param logger the object responsible for displaying warning/errors to the user.
-     * @return an {@link ILayoutResult} object that contains the result of the layout.
+     * @return a new {@link ILayoutResult} object that contains the result of the layout.
      * @since 3
      */
     @Deprecated
@@ -155,7 +155,7 @@
      * @param projectCallback The {@link IProjectCallback} object to get information from
      * the project.
      * @param logger the object responsible for displaying warning/errors to the user.
-     * @return an {@link ILayoutResult} object that contains the result of the layout.
+     * @return a new {@link ILayoutResult} object that contains the result of the layout.
      * @deprecated Use {@link #computeLayout(IXmlPullParser, Object, int, int, int, float, float, String, boolean, Map, Map, IProjectCallback, ILayoutLog)}
      * @since 2
      */
@@ -187,7 +187,7 @@
      * @param projectCallback The {@link IProjectCallback} object to get information from
      * the project.
      * @param logger the object responsible for displaying warning/errors to the user.
-     * @return an {@link ILayoutResult} object that contains the result of the layout.
+     * @return a new {@link ILayoutResult} object that contains the result of the layout.
      * @deprecated Use {@link #computeLayout(IXmlPullParser, Object, int, int, int, float, float, String, boolean, Map, Map, IProjectCallback, ILayoutLog)}
      * @since 1
      */
@@ -205,7 +205,7 @@
      * until this method is called.
      * <p/>The cache is not configuration dependent and should only be cleared when a
      * resource changes (at this time only bitmaps and 9 patches go into the cache).
-     * @param objectKey the key for the project.
+     * @param projectKey the key for the project.
      * @since 1
      */
     void clearCaches(Object projectKey);
diff --git a/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutResult.java b/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutResult.java
index 5a06349..2d8a210 100644
--- a/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutResult.java
+++ b/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutResult.java
@@ -23,13 +23,17 @@
  * {@link ILayoutLibBridge#computeLayout(IXmlPullParser, int, int, String, java.util.Map, java.util.Map, java.util.Map, IFontLoader, ILayoutLibLog, ICustomViewLoader)}
  */
 public interface ILayoutResult {
-    /** Sucess return code */
+    /**
+     * Success return code
+     */
     final static int SUCCESS = 0;
-    /** Error return code.
-     *  <p/>See {@link #getErrorMessage()}
-     */ 
+
+    /**
+     * Error return code, in which case an error message is guaranteed to be defined.
+     * @See {@link #getErrorMessage()}
+     */
     final static int ERROR = 1;
-    
+
     /**
      * Returns the result code.
      * @see #SUCCESS
@@ -62,18 +66,18 @@
          * Returns the list of children views.
          */
         ILayoutViewInfo[] getChildren();
-        
+
         /**
          * Returns the key associated with the node.
          * @see IXmlPullParser#getViewKey()
          */
         Object getViewKey();
-        
+
         /**
          * Returns the name of the view.
          */
         String getName();
-        
+
         /**
          * Returns the left of the view bounds.
          */
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 55fe4ac..0888fd8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -1051,15 +1051,22 @@
             // pass for now.
         }
 
+        @SuppressWarnings("unused")
         public void setInsets(IWindow window, int touchable, Rect contentInsets,
                 Rect visibleInsets) {
             // pass for now.
         }
 
+        @SuppressWarnings("unused")
         public void setWallpaperPosition(IBinder window, float x, float y) {
             // pass for now.
         }
 
+        @SuppressWarnings("unused")
+        public void wallpaperOffsetsComplete(IBinder window) {
+            // pass for now.
+        }
+        
         public IBinder asBinder() {
             // pass for now.
             return null;
@@ -1114,7 +1121,7 @@
         }
 
         @SuppressWarnings("unused")
-        public void dispatchWallpaperOffsets(float x, float y) {
+        public void dispatchWallpaperOffsets(float x, float y, boolean sync) {
             // pass for now.
         }