Fix surface frame size reporting.

The SurfaceHolder provided by the wallpaper service was not reporting
the correct size in getSurfaceFrame().  This broke an optimization in
the ImageWallpaper.  The old code happened to work because calling
lockCanvas on the SurfaceHolder with a null dirty rectangle happened
to have the side-effect of updating the SurfaceHolder's surface frame
size field because it passed mSurfaceFrame as the dirty rect, causing
mSurfaceFrame to be set to the size of the region to be drawn.

However, relying on this side-effect is wrong.  Among other things,
the dirty region could actually be smaller than the surface frame.

This patch fixes WallpaperService, SurfaceView and ViewRoot to ensure
that the surface frame size is always set explicitly and is not modified
by calls to lockCanvas.

Change-Id: I10948f5ec269409ceaf0f7d32b3f6731e9499ebc
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 52b0643..44887ed 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -546,7 +546,8 @@
                         sizeChanged = true;
                         mCurHeight = h;
                     }
-                    
+
+                    mSurfaceHolder.setSurfaceFrameSize(w, h);
                     mSurfaceHolder.mSurfaceLock.unlock();
 
                     if (!mSurfaceHolder.mSurface.isValid()) {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 6451d47..8a95664 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -158,6 +158,7 @@
     int mHeight = -1;
     int mFormat = -1;
     final Rect mSurfaceFrame = new Rect();
+    Rect mTmpDirty;
     int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1;
     boolean mUpdateWindowNeeded;
     boolean mReportDrawNeeded;
@@ -739,9 +740,16 @@
 
             Canvas c = null;
             if (!mDrawingStopped && mWindow != null) {
-                Rect frame = dirty != null ? dirty : mSurfaceFrame;
+                if (dirty == null) {
+                    if (mTmpDirty == null) {
+                        mTmpDirty = new Rect();
+                    }
+                    mTmpDirty.set(mSurfaceFrame);
+                    dirty = mTmpDirty;
+                }
+
                 try {
-                    c = mSurface.lockCanvas(frame);
+                    c = mSurface.lockCanvas(dirty);
                 } catch (Exception e) {
                     Log.e(LOG_TAG, "Exception locking surface", e);
                 }
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 19d7811..44aca7d 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1082,6 +1082,7 @@
                     //mSurfaceHolder.mSurface.copyFrom(mSurface);
                     mSurfaceHolder.mSurface = mSurface;
                 }
+                mSurfaceHolder.setSurfaceFrameSize(mWidth, mHeight);
                 mSurfaceHolder.mSurfaceLock.unlock();
                 if (mSurface.isValid()) {
                     if (!hadSurface) {
diff --git a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
index 78688ee..595c634 100644
--- a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
+++ b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
@@ -88,9 +88,13 @@
 
         class WallpaperObserver extends BroadcastReceiver {
             public void onReceive(Context context, Intent intent) {
+                if (DEBUG) {
+                    Log.d(TAG, "onReceive");
+                }
+
                 synchronized (mLock) {
                     updateWallpaperLocked();
-                    drawFrameLocked(true, false);
+                    drawFrameLocked();
                 }
 
                 // Assume we are the only one using the wallpaper in this
@@ -101,6 +105,10 @@
 
         @Override
         public void onCreate(SurfaceHolder surfaceHolder) {
+            if (DEBUG) {
+                Log.d(TAG, "onCreate");
+            }
+
             super.onCreate(surfaceHolder);
             IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED);
             mReceiver = new WallpaperObserver();
@@ -120,9 +128,18 @@
 
         @Override
         public void onVisibilityChanged(boolean visible) {
+            if (DEBUG) {
+                Log.d(TAG, "onVisibilityChanged: visible=" + visible);
+            }
+
             synchronized (mLock) {
-                mVisible = visible;
-                drawFrameLocked(false, false);
+                if (mVisible != visible) {
+                    if (DEBUG) {
+                        Log.d(TAG, "Visibility changed to visible=" + visible);
+                    }
+                    mVisible = visible;
+                    drawFrameLocked();
+                }
             }
         }
 
@@ -135,6 +152,12 @@
         public void onOffsetsChanged(float xOffset, float yOffset,
                 float xOffsetStep, float yOffsetStep,
                 int xPixels, int yPixels) {
+            if (DEBUG) {
+                Log.d(TAG, "onOffsetsChanged: xOffset=" + xOffset + ", yOffset=" + yOffset
+                        + ", xOffsetStep=" + xOffsetStep + ", yOffsetStep=" + yOffsetStep
+                        + ", xPixels=" + xPixels + ", yPixels=" + yPixels);
+            }
+
             synchronized (mLock) {
                 if (mXOffset != xOffset || mYOffset != yOffset) {
                     if (DEBUG) {
@@ -142,36 +165,27 @@
                     }
                     mXOffset = xOffset;
                     mYOffset = yOffset;
-                    drawFrameLocked(false, true);
-                } else {
-                    drawFrameLocked(false, false);
+                    mOffsetsChanged = true;
                 }
+                drawFrameLocked();
             }
         }
 
         @Override
         public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+            if (DEBUG) {
+                Log.d(TAG, "onSurfaceChanged: width=" + width + ", height=" + height);
+            }
+
             super.onSurfaceChanged(holder, format, width, height);
-            
+
             synchronized (mLock) {
-                drawFrameLocked(true, false);
+                mRedrawNeeded = true;
+                drawFrameLocked();
             }
         }
 
-        @Override
-        public void onSurfaceCreated(SurfaceHolder holder) {
-            super.onSurfaceCreated(holder);
-        }
-
-        @Override
-        public void onSurfaceDestroyed(SurfaceHolder holder) {
-            super.onSurfaceDestroyed(holder);
-        }
-
-        void drawFrameLocked(boolean redrawNeeded, boolean offsetsChanged) {
-            mRedrawNeeded |= redrawNeeded;
-            mOffsetsChanged |= offsetsChanged;
-
+        void drawFrameLocked() {
             if (!mVisible) {
                 if (DEBUG) {
                     Log.d(TAG, "Suppressed drawFrame since wallpaper is not visible.");
diff --git a/core/java/com/android/internal/view/BaseSurfaceHolder.java b/core/java/com/android/internal/view/BaseSurfaceHolder.java
index 1e97cd6..f9f94be 100644
--- a/core/java/com/android/internal/view/BaseSurfaceHolder.java
+++ b/core/java/com/android/internal/view/BaseSurfaceHolder.java
@@ -49,6 +49,7 @@
     
     int mType = -1;
     final Rect mSurfaceFrame = new Rect();
+    Rect mTmpDirty;
     
     public abstract void onUpdateSurface();
     public abstract void onRelayoutContainer();
@@ -171,9 +172,16 @@
 
         Canvas c = null;
         if (onAllowLockCanvas()) {
-            Rect frame = dirty != null ? dirty : mSurfaceFrame;
+            if (dirty == null) {
+                if (mTmpDirty == null) {
+                    mTmpDirty = new Rect();
+                }
+                mTmpDirty.set(mSurfaceFrame);
+                dirty = mTmpDirty;
+            }
+
             try {
-                c = mSurface.lockCanvas(frame);
+                c = mSurface.lockCanvas(dirty);
             } catch (Exception e) {
                 Log.e(TAG, "Exception locking surface", e);
             }
@@ -215,4 +223,11 @@
     public Rect getSurfaceFrame() {
         return mSurfaceFrame;
     }
+
+    public void setSurfaceFrameSize(int width, int height) {
+        mSurfaceFrame.top = 0;
+        mSurfaceFrame.left = 0;
+        mSurfaceFrame.right = width;
+        mSurfaceFrame.bottom = height;
+    }
 };
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 6a1d199..88f30ed 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -116,7 +116,6 @@
     private ViewGroup mContentParent;
 
     SurfaceHolder.Callback2 mTakeSurfaceCallback;
-    BaseSurfaceHolder mSurfaceHolder;
     
     InputQueue.Callback mTakeInputQueueCallback;