Implement support for scrolling a wallpaper.

This currently only works for a wallpaper that is larger than the
screen.  Set the scroll position with the new wallpaper API.  Right
now only does jump scrolls.
diff --git a/api/current.xml b/api/current.xml
index 626946b..69d4d5c 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -26920,6 +26920,23 @@
 <exception name="IOException" type="java.io.IOException">
 </exception>
 </method>
+<method name="setWallpaperOffsets"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="windowToken" type="android.os.IBinder">
+</parameter>
+<parameter name="xOffset" type="float">
+</parameter>
+<parameter name="yOffset" type="float">
+</parameter>
+</method>
 <method name="suggestDesiredDimensions"
  return="void"
  abstract="false"
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 9019b54..78b6cf1 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -28,6 +28,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.view.ViewRoot;
 
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -312,6 +313,28 @@
     }
     
     /**
+     * Set the position of the current wallpaper within any larger space, when
+     * that wallpaper is visible behind the given window.  The X and Y offsets
+     * are floating point numbers ranging from 0 to 1, representing where the
+     * wallpaper should be positioned within the screen space.  These only
+     * make sense when the wallpaper is larger than the screen.
+     * 
+     * @param windowToken The window who these offsets should be associated
+     * with, as returned by {@link android.view.View#getWindowVisibility()
+     * View.getWindowToken()}.
+     * @param xOffset The offset olong the X dimension, from 0 to 1.
+     * @param yOffset The offset along the Y dimension, from 0 to 1.
+     */
+    public void setWallpaperOffsets(IBinder windowToken, float xOffset, float yOffset) {
+        try {
+            ViewRoot.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
+                    windowToken, xOffset, yOffset);
+        } catch (RemoteException e) {
+            // Ignore.
+        }
+    }
+    
+    /**
      * Remove any currently set wallpaper, reverting to the system's default
      * wallpaper. On success, the intent {@link Intent#ACTION_WALLPAPER_CHANGED}
      * is broadcast.
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 5607d4b..3e6cdc2 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -90,7 +90,6 @@
     void exitKeyguardSecurely(IOnKeyguardExitResult callback);
     boolean inKeyguardRestrictedInputMode();
 
-    
     // These can only be called with the SET_ANIMATON_SCALE permission.
     float getAnimationScale(int which);
     float[] getAnimationScales();
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 1156856..4d662d2 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -108,4 +108,10 @@
     boolean getInTouchMode();
     
     boolean performHapticFeedback(IWindow window, int effectId, boolean always);
+    
+    /**
+     * For windows with the wallpaper behind them, and the wallpaper is
+     * larger than the screen, set the offset within the screen.
+     */
+    void setWallpaperPosition(IBinder windowToken, float x, float y);
 }
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 69c48d3..641f251 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -1223,6 +1223,9 @@
         // what is below it for later.
         w = i > 0 ? (WindowState)localmWindows.get(i-1) : null;
         
+        final int dw = mDisplay.getWidth();
+        final int dh = mDisplay.getHeight();
+        
         // Start stepping backwards from here, ensuring that our wallpaper windows
         // are correctly placed.
         int curTokenIndex = mWallpaperTokens.size();
@@ -1247,6 +1250,10 @@
                     }
                 }
                 
+                if (visible) {
+                    updateWallpaperOffsetLocked(mWallpaperTarget, wallpaper, dw, dh);                        
+                }
+                
                 wallpaper.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
                 if (DEBUG_LAYERS) Log.v(TAG, "Wallpaper win " + wallpaper
                         + " anim layer: " + wallpaper.mAnimLayer);
@@ -1279,7 +1286,7 @@
         return changed;
     }
 
-    void setWallpaperAnimLayerAdjustment(int adj) {
+    void setWallpaperAnimLayerAdjustmentLocked(int adj) {
         if (DEBUG_LAYERS) Log.v(TAG, "Setting wallpaper layer adj to " + adj);
         mWallpaperAnimLayerAdjustment = adj;
         int curTokenIndex = mWallpaperTokens.size();
@@ -1297,6 +1304,50 @@
         }
     }
 
+    boolean updateWallpaperOffsetLocked(WindowState target,
+            WindowState wallpaperWin, int dw, int dh) {
+        int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
+        int offset = availw > 0 ? -(int)(availw*target.mWallpaperX+.5f) : 0;
+        boolean changed = wallpaperWin.mXOffset != offset;
+        if (changed) {
+            wallpaperWin.mXOffset = offset;
+        }
+        int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
+        offset = availh > 0 ? -(int)(availh*target.mWallpaperY+.5f) : 0;
+        if (wallpaperWin.mYOffset != offset) {
+            changed = true;
+            wallpaperWin.mYOffset = offset;
+        }
+        return changed;
+    }
+    
+    boolean updateWallpaperOffsetLocked() {
+        final int dw = mDisplay.getWidth();
+        final int dh = mDisplay.getHeight();
+        
+        boolean changed = false;
+        
+        WindowState target = mWallpaperTarget;
+        if (target != null) {
+            int curTokenIndex = mWallpaperTokens.size();
+            while (curTokenIndex > 0) {
+                curTokenIndex--;
+                WindowToken token = mWallpaperTokens.get(curTokenIndex);
+                int curWallpaperIndex = token.windows.size();
+                while (curWallpaperIndex > 0) {
+                    curWallpaperIndex--;
+                    WindowState wallpaper = token.windows.get(curWallpaperIndex);
+                    if (updateWallpaperOffsetLocked(target, wallpaper, dw, dh)) {
+                        wallpaper.computeShownFrameLocked();
+                        changed = true;
+                    }
+                }
+            }
+        }
+        
+        return changed;
+    }
+    
     public int addWindow(Session session, IWindow client,
             WindowManager.LayoutParams attrs, int viewVisibility,
             Rect outContentInsets) {
@@ -1710,6 +1761,19 @@
         }
     }
 
+    public void setWindowWallpaperPositionLocked(WindowState window, float x, float y) {
+        if (window.mWallpaperX != x || window.mWallpaperY != y)  {
+            window.mWallpaperX = x;
+            window.mWallpaperY = y;
+            
+            if (mWallpaperTarget == window) {
+                if (updateWallpaperOffsetLocked()) {
+                    performLayoutAndPlaceSurfacesLocked();
+                }
+            }
+        }
+    }
+    
     public int relayoutWindow(Session session, IWindow client,
             WindowManager.LayoutParams attrs, int requestedWidth,
             int requestedHeight, int viewVisibility, boolean insetsPending,
@@ -5810,6 +5874,18 @@
             }
         }
 
+        public void setWallpaperPosition(IBinder window, float x, float y) {
+            synchronized(mWindowMap) {
+                long ident = Binder.clearCallingIdentity();
+                try {
+                    setWindowWallpaperPositionLocked(windowForClientLocked(this, window),
+                            x, y);
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
+                }
+            }
+        }
+        
         void windowAddedLocked() {
             if (mSurfaceSession == null) {
                 if (localLOGV) Log.v(
@@ -5899,8 +5975,8 @@
         int mRequestedHeight;
         int mLastRequestedWidth;
         int mLastRequestedHeight;
-        int mReqXPos;
-        int mReqYPos;
+        int mXOffset;
+        int mYOffset;
         int mLayer;
         int mAnimLayer;
         int mLastLayer;
@@ -5985,6 +6061,9 @@
         boolean mHasLocalTransformation;
         final Transformation mTransformation = new Transformation();
 
+        float mWallpaperX = 0;
+        float mWallpaperY = 0;
+        
         // This is set after IWindowSession.relayout() has been called at
         // least once for the window.  It allows us to detect the situation
         // where we don't yet have a surface, but should have one soon, so
@@ -6104,8 +6183,8 @@
             mRequestedHeight = 0;
             mLastRequestedWidth = 0;
             mLastRequestedHeight = 0;
-            mReqXPos = 0;
-            mReqYPos = 0;
+            mXOffset = 0;
+            mYOffset = 0;
             mLayer = 0;
             mAnimLayer = 0;
             mLastLayer = 0;
@@ -6702,8 +6781,8 @@
                 mDtDx = tmpFloats[Matrix.MSKEW_X];
                 mDsDy = tmpFloats[Matrix.MSKEW_Y];
                 mDtDy = tmpFloats[Matrix.MSCALE_Y];
-                int x = (int)tmpFloats[Matrix.MTRANS_X];
-                int y = (int)tmpFloats[Matrix.MTRANS_Y];
+                int x = (int)tmpFloats[Matrix.MTRANS_X] + mXOffset;
+                int y = (int)tmpFloats[Matrix.MTRANS_Y] + mYOffset;
                 int w = frame.width();
                 int h = frame.height();
                 mShownFrame.set(x, y, x+w, y+h);
@@ -6740,6 +6819,9 @@
             }
 
             mShownFrame.set(mFrame);
+            if (mXOffset != 0 || mYOffset != 0) {
+                mShownFrame.offset(mXOffset, mYOffset);
+            }
             mShownAlpha = mAlpha;
             mDsDx = 1;
             mDtDx = 0;
@@ -7027,9 +7109,11 @@
                         pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
             }
             pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
-                    pw.print(" h="); pw.print(mRequestedHeight);
-                    pw.print(" x="); pw.print(mReqXPos);
-                    pw.print(" y="); pw.println(mReqYPos);
+                    pw.print(" h="); pw.println(mRequestedHeight);
+            if (mXOffset != 0 || mYOffset != 0) {
+                pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
+                        pw.print(" y="); pw.println(mYOffset);
+            }
             pw.print(prefix); pw.print("mGivenContentInsets=");
                     mGivenContentInsets.printShortString(pw);
                     pw.print(" mGivenVisibleInsets=");
@@ -7097,6 +7181,10 @@
                 pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
                         pw.print(" mVScale="); pw.println(mVScale);
             }
+            if (mWallpaperX != 0 || mWallpaperY != 0) {
+                pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
+                        pw.print(" mWallpaperY="); pw.println(mWallpaperY);
+            }
         }
 
         @Override
@@ -7282,7 +7370,7 @@
                     setInputMethodAnimLayerAdjustment(adj);
                 }
                 if (w == mWallpaperTarget) {
-                    setWallpaperAnimLayerAdjustment(adj);
+                    setWallpaperAnimLayerAdjustmentLocked(adj);
                 }
             }
         }
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 fd77d51..8e7d48f 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -990,6 +990,10 @@
             // pass for now.
         }
 
+        public void setWallpaperPosition(IBinder window, float x, float y) {
+            // pass for now.
+        }
+        
         public IBinder asBinder() {
             // pass for now.
             return null;