Merge "Optimize orientation changes."
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 113c610..3626bf5 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -25,6 +25,8 @@
 import android.graphics.ColorFilter;
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
@@ -115,7 +117,9 @@
 
         @Override
         public void draw(Canvas canvas) {
-            canvas.drawBitmap(mBitmap, mDrawLeft, mDrawTop, null);
+            Paint paint = new Paint();
+            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
+            canvas.drawBitmap(mBitmap, mDrawLeft, mDrawTop, paint);
         }
 
         @Override
@@ -245,40 +249,20 @@
                 if (fd != null) {
                     int width = params.getInt("width", 0);
                     int height = params.getInt("height", 0);
-                    
-                    if (width <= 0 || height <= 0) {
-                        // Degenerate case: no size requested, just load
-                        // bitmap as-is.
-                        Bitmap bm = null;
-                        try {
-                            bm = BitmapFactory.decodeFileDescriptor(
-                                   fd.getFileDescriptor(), null, null);
-                        } catch (OutOfMemoryError e) {
-                            Log.w(TAG, "Can't decode file", e);
-                        }
+
+                    try {
+                        BitmapFactory.Options options = new BitmapFactory.Options();
+                        Bitmap bm = BitmapFactory.decodeFileDescriptor(
+                                fd.getFileDescriptor(), null, options);
+                        return generateBitmap(context, bm, width, height);
+                    } catch (OutOfMemoryError e) {
+                        Log.w(TAG, "Can't decode file", e);
+                    } finally {
                         try {
                             fd.close();
                         } catch (IOException e) {
                         }
-                        if (bm != null) {
-                            bm.setDensity(DisplayMetrics.DENSITY_DEVICE);
-                        }
-                        return bm;
                     }
-                    
-                    // 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.decodeFileDescriptor(
-                            fd.getFileDescriptor(), null, options);
-                    try {
-                        fd.close();
-                    } catch (IOException e) {
-                    }
-                    
-                    return generateBitmap(context, bm, width, height);
                 }
             } catch (RemoteException e) {
             }
@@ -292,42 +276,18 @@
                 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 = null;
-                        try {
-                            bm = BitmapFactory.decodeStream(is, null, null);
-                        } catch (OutOfMemoryError e) {
-                            Log.w(TAG, "Can't decode stream", e);
-                        }
+
+                    try {
+                        BitmapFactory.Options options = new BitmapFactory.Options();
+                        Bitmap bm = BitmapFactory.decodeStream(is, null, options);
+                        return generateBitmap(context, bm, width, height);
+                    } catch (OutOfMemoryError e) {
+                        Log.w(TAG, "Can't decode stream", e);
+                    } finally {
                         try {
                             is.close();
                         } catch (IOException e) {
                         }
-                        if (bm != null) {
-                            bm.setDensity(DisplayMetrics.DENSITY_DEVICE);
-                        }
-                        return bm;
-                    }
-                    
-                    // 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) {
-                    }
-                    
-                    try {
-                        return generateBitmap(context, bm, width, height);
-                    } catch (OutOfMemoryError e) {
-                        Log.w(TAG, "Can't generate default bitmap", e);
-                        return bm;
                     }
                 }
             } catch (RemoteException e) {
@@ -711,48 +671,54 @@
     
     static Bitmap generateBitmap(Context context, Bitmap bm, int width, int height) {
         if (bm == null) {
+            return null;
+        }
+
+        bm.setDensity(DisplayMetrics.DENSITY_DEVICE);
+
+        if (bm.getWidth() == width && bm.getHeight() == height) {
             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;
+        try {
+            Bitmap newbm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+            newbm.setDensity(DisplayMetrics.DENSITY_DEVICE);
+
+            Canvas c = new Canvas(newbm);
+            Rect targetRect = new Rect();
+            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.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.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
+            c.drawBitmap(bm, null, targetRect, paint);
+
+            bm.recycle();
+            return newbm;
+        } catch (OutOfMemoryError e) {
+            Log.w(TAG, "Can't generate default bitmap", e);
+            return bm;
         }
-        
-        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/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index eae7574..8fc8b9d 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -181,7 +181,7 @@
         
         final BaseSurfaceHolder mSurfaceHolder = new BaseSurfaceHolder() {
             {
-                mRequestedFormat = PixelFormat.RGB_565;
+                mRequestedFormat = PixelFormat.RGBX_8888;
             }
 
             @Override
diff --git a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
index 85095cf..45f3bc1 100644
--- a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
+++ b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
@@ -25,6 +25,7 @@
 import android.graphics.Rect;
 import android.graphics.Region.Op;
 import android.graphics.drawable.Drawable;
+import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Process;
@@ -46,19 +47,20 @@
 
     WallpaperManager mWallpaperManager;
     private HandlerThread mThread;
+    private Handler mHandler;
 
     @Override
     public void onCreate() {
         super.onCreate();
         mWallpaperManager = (WallpaperManager) getSystemService(WALLPAPER_SERVICE);
         Looper looper = WindowManagerPolicyThread.getLooper();
-        if (looper != null) {
-            setCallbackLooper(looper);
-        } else {
+        if (looper == null) {
             mThread = new HandlerThread("Wallpaper", Process.THREAD_PRIORITY_FOREGROUND);
             mThread.start();
-            setCallbackLooper(mThread.getLooper());
+            looper = mThread.getLooper();
         }
+        setCallbackLooper(looper);
+        mHandler = new Handler(looper);
     }
 
     public Engine onCreateEngine() {
@@ -96,10 +98,6 @@
                     updateWallpaperLocked();
                     drawFrameLocked();
                 }
-
-                // Assume we are the only one using the wallpaper in this
-                // process, and force a GC now to release the old wallpaper.
-                System.gc();
             }
         }
 
@@ -112,7 +110,7 @@
             super.onCreate(surfaceHolder);
             IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED);
             mReceiver = new WallpaperObserver();
-            registerReceiver(mReceiver, filter);
+            registerReceiver(mReceiver, filter, null, mHandler);
 
             updateSurfaceSize(surfaceHolder);
 
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 86c899e..1c87f5b 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -428,7 +428,6 @@
     boolean mDisplayFrozen = false;
     boolean mWaitingForConfig = false;
     boolean mWindowsFreezingScreen = false;
-    long mFreezeGcPending = 0;
     int mAppsFreezingScreen = 0;
     int mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 
@@ -4975,9 +4974,11 @@
      * MUST CALL setNewConfiguration() TO UNFREEZE THE SCREEN.
      */
     public boolean setRotationUncheckedLocked(int rotation, int animFlags, boolean inTransaction) {
-        if (mDragState != null || mScreenRotationAnimation != null) {
-            // Potential rotation during a drag.  Don't do the rotation now, but make
-            // a note to perform the rotation later.
+        if (mDragState != null
+                || (mScreenRotationAnimation != null && mScreenRotationAnimation.isAnimating())) {
+            // Potential rotation during a drag or while waiting for a previous orientation
+            // change to finish (rotation animation will be dismissed).
+            // Don't do the rotation now, but make a note to perform the rotation later.
             if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation.");
             if (rotation != WindowManagerPolicy.USE_LAST_ROTATION) {
                 mDeferredRotation = rotation;
@@ -6435,7 +6436,6 @@
                         if (mDisplayFrozen) {
                             return;
                         }
-                        mFreezeGcPending = 0;
                     }
                     Runtime.getRuntime().gc();
                     break;
@@ -8653,19 +8653,6 @@
 
         mScreenFrozenLock.acquire();
 
-        long now = SystemClock.uptimeMillis();
-        //Slog.i(TAG, "Freezing, gc pending: " + mFreezeGcPending + ", now " + now);
-        if (mFreezeGcPending != 0) {
-            if (now > (mFreezeGcPending+1000)) {
-                //Slog.i(TAG, "Gc!  " + now + " > " + (mFreezeGcPending+1000));
-                mH.removeMessages(H.FORCE_GC);
-                Runtime.getRuntime().gc();
-                mFreezeGcPending = now;
-            }
-        } else {
-            mFreezeGcPending = now;
-        }
-
         mDisplayFrozen = true;
         
         mInputMonitor.freezeInputDispatchingLw();