animation bugfix plus xml resources for new View properties

There was a bug around animation duration where it was possible,
for small durations or large inter-frame times, to calculate
fractions outside of the 0-1 range, causing bad value calculations.

Unrelated: new View properties for translation, scale, and rotation
were added in this release. This commit addes XML resources for
those properties.

Change-Id: Ieaf5dd729588adb2a40656aa82beecc3576f4af5
diff --git a/api/current.xml b/api/current.xml
index 6dabecf..a8193d7 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -2176,6 +2176,17 @@
  visibility="public"
 >
 </field>
+<field name="alpha"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843568"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="alphabeticShortcut"
  type="int"
  transient="false"
@@ -7720,6 +7731,39 @@
  visibility="public"
 >
 </field>
+<field name="rotation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843575"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="rotationX"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843576"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="rotationY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843577"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="rowDelay"
  type="int"
  transient="false"
@@ -7808,6 +7852,28 @@
  visibility="public"
 >
 </field>
+<field name="scaleX"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843573"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="scaleY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843574"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="scheme"
  type="int"
  transient="false"
@@ -9953,6 +10019,50 @@
  visibility="public"
 >
 </field>
+<field name="transformPivotX"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843569"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="transformPivotY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843570"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="translationX"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843571"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="translationY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843572"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="type"
  type="int"
  transient="false"
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index e192067..8e541c2 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -1072,12 +1072,11 @@
                             mListeners.get(i).onAnimationRepeat(this);
                         }
                     }
-                    ++mCurrentIteration;
                     if (mRepeatMode == REVERSE) {
                         mPlayingBackwards = mPlayingBackwards ? false : true;
                     }
-                    // TODO: doesn't account for fraction going Wayyyyy over 1, like 2+
-                    fraction = fraction - 1f;
+                    mCurrentIteration += (int)fraction;
+                    fraction = fraction % 1f;
                     mStartTime += mDuration;
                 } else {
                     done = true;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 011ad77..1d0f185 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -595,6 +595,11 @@
  * @attr ref android.R.styleable#View_paddingRight
  * @attr ref android.R.styleable#View_paddingTop
  * @attr ref android.R.styleable#View_saveEnabled
+ * @attr ref android.R.styleable#View_rotation
+ * @attr ref android.R.styleable#View_rotationX
+ * @attr ref android.R.styleable#View_rotationY
+ * @attr ref android.R.styleable#View_scaleX
+ * @attr ref android.R.styleable#View_scaleY
  * @attr ref android.R.styleable#View_scrollX
  * @attr ref android.R.styleable#View_scrollY
  * @attr ref android.R.styleable#View_scrollbarSize
@@ -610,6 +615,10 @@
  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
  * @attr ref android.R.styleable#View_soundEffectsEnabled
  * @attr ref android.R.styleable#View_tag
+ * @attr ref android.R.styleable#View_transformPivotX
+ * @attr ref android.R.styleable#View_transformPivotY
+ * @attr ref android.R.styleable#View_translationX
+ * @attr ref android.R.styleable#View_translationY
  * @attr ref android.R.styleable#View_visibility
  *
  * @see android.view.ViewGroup
@@ -2155,6 +2164,15 @@
         int x = 0;
         int y = 0;
 
+        float tx = 0;
+        float ty = 0;
+        float rotation = 0;
+        float rotationX = 0;
+        float rotationY = 0;
+        float sx = 1f;
+        float sy = 1f;
+        boolean transformSet = false;
+
         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
 
         int overScrollMode = mOverScrollMode;
@@ -2186,6 +2204,43 @@
                 case com.android.internal.R.styleable.View_scrollY:
                     y = a.getDimensionPixelOffset(attr, 0);
                     break;
+                case com.android.internal.R.styleable.View_alpha:
+                    setAlpha(a.getFloat(attr, 1f));
+                    break;
+                case com.android.internal.R.styleable.View_transformPivotX:
+                    setPivotX(a.getDimensionPixelOffset(attr, 0));
+                    break;
+                case com.android.internal.R.styleable.View_transformPivotY:
+                    setPivotY(a.getDimensionPixelOffset(attr, 0));
+                    break;
+                case com.android.internal.R.styleable.View_translationX:
+                    tx = a.getDimensionPixelOffset(attr, 0);
+                    transformSet = true;
+                    break;
+                case com.android.internal.R.styleable.View_translationY:
+                    ty = a.getDimensionPixelOffset(attr, 0);
+                    transformSet = true;
+                    break;
+                case com.android.internal.R.styleable.View_rotation:
+                    rotation = a.getFloat(attr, 0);
+                    transformSet = true;
+                    break;
+                case com.android.internal.R.styleable.View_rotationX:
+                    rotationX = a.getFloat(attr, 0);
+                    transformSet = true;
+                    break;
+                case com.android.internal.R.styleable.View_rotationY:
+                    rotationY = a.getFloat(attr, 0);
+                    transformSet = true;
+                    break;
+                case com.android.internal.R.styleable.View_scaleX:
+                    sx = a.getFloat(attr, 1f);
+                    transformSet = true;
+                    break;
+                case com.android.internal.R.styleable.View_scaleY:
+                    sy = a.getFloat(attr, 1f);
+                    transformSet = true;
+                    break;
                 case com.android.internal.R.styleable.View_id:
                     mID = a.getResourceId(attr, NO_ID);
                     break;
@@ -2404,6 +2459,16 @@
             scrollTo(x, y);
         }
 
+        if (transformSet) {
+            setTranslationX(tx);
+            setTranslationY(ty);
+            setRotation(rotation);
+            setRotationX(rotationX);
+            setRotationY(rotationY);
+            setScaleX(sx);
+            setScaleY(sy);
+        }
+
         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
             setScrollContainer(true);
         }
@@ -5286,6 +5351,8 @@
      * @param rotation The degrees of rotation.
      * @see #getPivotX()
      * @see #getPivotY()
+     *
+     * @attr ref android.R.styleable#View_rotation
      */
     public void setRotation(float rotation) {
         if (mRotation != rotation) {
@@ -5317,6 +5384,8 @@
      * @param rotationY The degrees of Y rotation.
      * @see #getPivotX()
      * @see #getPivotY()
+     *
+     * @attr ref android.R.styleable#View_rotationY
      */
     public void setRotationY(float rotationY) {
         if (mRotationY != rotationY) {
@@ -5348,6 +5417,8 @@
      * @param rotationX The degrees of X rotation.
      * @see #getPivotX()
      * @see #getPivotY()
+     *
+     * @attr ref android.R.styleable#View_rotationX
      */
     public void setRotationX(float rotationX) {
         if (mRotationX != rotationX) {
@@ -5381,6 +5452,8 @@
      * @param scaleX The scaling factor.
      * @see #getPivotX()
      * @see #getPivotY()
+     *
+     * @attr ref android.R.styleable#View_scaleX
      */
     public void setScaleX(float scaleX) {
         if (mScaleX != scaleX) {
@@ -5414,6 +5487,8 @@
      * @param scaleY The scaling factor.
      * @see #getPivotX()
      * @see #getPivotY()
+     *
+     * @attr ref android.R.styleable#View_scaleY
      */
     public void setScaleY(float scaleY) {
         if (mScaleY != scaleY) {
@@ -5452,6 +5527,8 @@
      * @see #getScaleX()
      * @see #getScaleY()
      * @see #getPivotY()
+     *
+     * @attr ref android.R.styleable#View_transformPivotX
      */
     public void setPivotX(float pivotX) {
         mPrivateFlags |= PIVOT_EXPLICITLY_SET;
@@ -5490,6 +5567,8 @@
      * @see #getScaleX()
      * @see #getScaleY()
      * @see #getPivotY()
+     *
+     * @attr ref android.R.styleable#View_transformPivotY
      */
     public void setPivotY(float pivotY) {
         mPrivateFlags |= PIVOT_EXPLICITLY_SET;
@@ -5519,6 +5598,8 @@
      * completely transparent and 1 means the view is completely opaque.
      *
      * @param alpha The opacity of the view.
+     *
+     * @attr ref android.R.styleable#View_alpha
      */
     public void setAlpha(float alpha) {
         mAlpha = alpha;
@@ -5810,6 +5891,8 @@
      *
      * @param translationX The horizontal position of this view relative to its left position,
      * in pixels.
+     *
+     * @attr ref android.R.styleable#View_translationX
      */
     public void setTranslationX(float translationX) {
         if (mTranslationX != translationX) {
@@ -5841,6 +5924,8 @@
      *
      * @param translationY The vertical position of this view relative to its top position,
      * in pixels.
+     *
+     * @attr ref android.R.styleable#View_translationY
      */
     public void setTranslationY(float translationY) {
         if (mTranslationY != translationY) {
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index dfbcafc0a..5daa944 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1674,6 +1674,42 @@
             <!-- Never show over-scroll effects. -->
             <enum name="never" value="2" />
         </attr>
+
+        <!-- alpha property of the view, as a value between 0 (completely transparent) and 1
+             (completely opaque). -->
+        <attr name="alpha" format="float" />
+
+        <!-- translation in x of the view. This value is added post-layout to the left
+             property of the view, which is set by its layout. -->
+        <attr name="translationX" format="dimension" />
+
+        <!-- translation in y of the view. This value is added post-layout to the left
+             property of the view, which is set by its layout. -->
+        <attr name="translationY" format="dimension" />
+
+        <!-- x location of the pivot point around which the view will rotate and scale.
+             This xml attribute sets the pivotX property of the View. -->
+        <attr name="transformPivotX" format="dimension" />
+
+        <!-- y location of the pivot point around which the view will rotate and scale.
+             This xml attribute sets the pivotY property of the View. -->
+        <attr name="transformPivotY" format="dimension" />
+
+        <!-- rotation of the view, in degrees. -->
+        <attr name="rotation" format="float" />
+
+        <!-- rotation of the view around the x axis, in degrees. -->
+        <attr name="rotationX" format="float" />
+
+        <!-- rotation of the view around the y axis, in degrees. -->
+        <attr name="rotationY" format="float" />
+
+        <!-- scale of the view in the x direction. -->
+        <attr name="scaleX" format="float" />
+
+        <!-- scale of the view in the y direction. -->
+        <attr name="scaleY" format="float" />
+
     </declare-styleable>
 
     <!-- Attributes that can be used with a {@link android.view.ViewGroup} or any
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index f2ab5cd..e1460e1 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1382,6 +1382,16 @@
   <public type="attr" name="baseline" />
   <public type="attr" name="homeLayout" />
   <public type="attr" name="opacity" />
+  <public type="attr" name="alpha"/>
+  <public type="attr" name="transformPivotX"/>
+  <public type="attr" name="transformPivotY"/>
+  <public type="attr" name="translationX"/>
+  <public type="attr" name="translationY"/>
+  <public type="attr" name="scaleX"/>
+  <public type="attr" name="scaleY"/>
+  <public type="attr" name="rotation"/>
+  <public type="attr" name="rotationX"/>
+  <public type="attr" name="rotationY"/>
 
   <public type="anim" name="animator_fade_in" />
   <public type="anim" name="animator_fade_out" />