Merge "Add 'Property' object"
diff --git a/api/14.txt b/api/14.txt
index ac93afb..ea09dc9 100644
--- a/api/14.txt
+++ b/api/14.txt
@@ -1921,12 +1921,12 @@
 
   public class FloatEvaluator implements android.animation.TypeEvaluator {
     ctor public FloatEvaluator();
-    method public java.lang.Object evaluate(float, java.lang.Object, java.lang.Object);
+    method public java.lang.Float evaluate(float, java.lang.Number, java.lang.Number);
   }
 
   public class IntEvaluator implements android.animation.TypeEvaluator {
     ctor public IntEvaluator();
-    method public java.lang.Object evaluate(float, java.lang.Object, java.lang.Object);
+    method public java.lang.Integer evaluate(float, java.lang.Integer, java.lang.Integer);
   }
 
   public abstract class Keyframe implements java.lang.Cloneable {
@@ -2012,7 +2012,7 @@
   }
 
   public abstract interface TypeEvaluator {
-    method public abstract java.lang.Object evaluate(float, java.lang.Object, java.lang.Object);
+    method public abstract T evaluate(float, T, T);
   }
 
   public class ValueAnimator extends android.animation.Animator {
diff --git a/api/current.txt b/api/current.txt
index dc82cd8..6046026 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1968,12 +1968,12 @@
 
   public class FloatEvaluator implements android.animation.TypeEvaluator {
     ctor public FloatEvaluator();
-    method public java.lang.Object evaluate(float, java.lang.Object, java.lang.Object);
+    method public java.lang.Float evaluate(float, java.lang.Number, java.lang.Number);
   }
 
   public class IntEvaluator implements android.animation.TypeEvaluator {
     ctor public IntEvaluator();
-    method public java.lang.Object evaluate(float, java.lang.Object, java.lang.Object);
+    method public java.lang.Integer evaluate(float, java.lang.Integer, java.lang.Integer);
   }
 
   public abstract class Keyframe implements java.lang.Cloneable {
@@ -2034,9 +2034,13 @@
     method public java.lang.String getPropertyName();
     method public java.lang.Object getTarget();
     method public static android.animation.ObjectAnimator ofFloat(java.lang.Object, java.lang.String, float...);
+    method public static android.animation.ObjectAnimator ofFloat(T, android.util.Property<T, java.lang.Float>, float...);
     method public static android.animation.ObjectAnimator ofInt(java.lang.Object, java.lang.String, int...);
+    method public static android.animation.ObjectAnimator ofInt(T, android.util.Property<T, java.lang.Integer>, int...);
     method public static android.animation.ObjectAnimator ofObject(java.lang.Object, java.lang.String, android.animation.TypeEvaluator, java.lang.Object...);
+    method public static android.animation.ObjectAnimator ofObject(T, android.util.Property<T, V>, android.animation.TypeEvaluator<V>, V...);
     method public static android.animation.ObjectAnimator ofPropertyValuesHolder(java.lang.Object, android.animation.PropertyValuesHolder...);
+    method public void setProperty(android.util.Property);
     method public void setPropertyName(java.lang.String);
   }
 
@@ -2044,14 +2048,19 @@
     method public android.animation.PropertyValuesHolder clone();
     method public java.lang.String getPropertyName();
     method public static android.animation.PropertyValuesHolder ofFloat(java.lang.String, float...);
+    method public static android.animation.PropertyValuesHolder ofFloat(android.util.Property<?, java.lang.Float>, float...);
     method public static android.animation.PropertyValuesHolder ofInt(java.lang.String, int...);
+    method public static android.animation.PropertyValuesHolder ofInt(android.util.Property<?, java.lang.Integer>, int...);
     method public static android.animation.PropertyValuesHolder ofKeyframe(java.lang.String, android.animation.Keyframe...);
+    method public static android.animation.PropertyValuesHolder ofKeyframe(android.util.Property, android.animation.Keyframe...);
     method public static android.animation.PropertyValuesHolder ofObject(java.lang.String, android.animation.TypeEvaluator, java.lang.Object...);
+    method public static android.animation.PropertyValuesHolder ofObject(android.util.Property, android.animation.TypeEvaluator<V>, V...);
     method public void setEvaluator(android.animation.TypeEvaluator);
     method public void setFloatValues(float...);
     method public void setIntValues(int...);
     method public void setKeyframes(android.animation.Keyframe...);
     method public void setObjectValues(java.lang.Object...);
+    method public void setProperty(android.util.Property);
     method public void setPropertyName(java.lang.String);
   }
 
@@ -2060,7 +2069,7 @@
   }
 
   public abstract interface TypeEvaluator {
-    method public abstract java.lang.Object evaluate(float, java.lang.Object, java.lang.Object);
+    method public abstract T evaluate(float, T, T);
   }
 
   public class ValueAnimator extends android.animation.Animator {
@@ -20097,6 +20106,10 @@
     method public void previousMonth();
   }
 
+  public class NoSuchPropertyException extends java.lang.RuntimeException {
+    ctor public NoSuchPropertyException(java.lang.String);
+  }
+
   public class Pair {
     ctor public Pair(F, S);
     method public static android.util.Pair<A, B> create(A, B);
@@ -20132,6 +20145,16 @@
     method public abstract void println(java.lang.String);
   }
 
+  public abstract class Property {
+    ctor public Property(java.lang.Class<V>, java.lang.String);
+    method public abstract V get(T);
+    method public java.lang.String getName();
+    method public java.lang.Class<V> getType();
+    method public boolean isReadOnly();
+    method public static android.util.Property<T, V> of(java.lang.Class<T>, java.lang.Class<V>, java.lang.String);
+    method public void set(T, V);
+  }
+
   public class SparseArray {
     ctor public SparseArray();
     ctor public SparseArray(int);
@@ -21878,6 +21901,11 @@
     field protected static final int[] PRESSED_SELECTED_STATE_SET;
     field protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
     field protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
+    field public static android.util.Property ROTATION;
+    field public static android.util.Property ROTATION_X;
+    field public static android.util.Property ROTATION_Y;
+    field public static android.util.Property SCALE_X;
+    field public static android.util.Property SCALE_Y;
     field public static final int SCROLLBARS_INSIDE_INSET = 16777216; // 0x1000000
     field public static final int SCROLLBARS_INSIDE_OVERLAY = 0; // 0x0
     field public static final int SCROLLBARS_OUTSIDE_INSET = 50331648; // 0x3000000
@@ -21890,9 +21918,13 @@
     field public static final int SOUND_EFFECTS_ENABLED = 134217728; // 0x8000000
     field public static final int STATUS_BAR_HIDDEN = 1; // 0x1
     field public static final int STATUS_BAR_VISIBLE = 0; // 0x0
+    field public static android.util.Property TRANSLATION_X;
+    field public static android.util.Property TRANSLATION_Y;
     field protected static final java.lang.String VIEW_LOG_TAG = "View";
     field public static final int VISIBLE = 0; // 0x0
     field protected static final int[] WINDOW_FOCUSED_STATE_SET;
+    field public static android.util.Property X;
+    field public static android.util.Property Y;
   }
 
   public static class View.BaseSavedState extends android.view.AbsSavedState {
diff --git a/core/java/android/animation/FloatEvaluator.java b/core/java/android/animation/FloatEvaluator.java
index 9e2054d..9463aa1 100644
--- a/core/java/android/animation/FloatEvaluator.java
+++ b/core/java/android/animation/FloatEvaluator.java
@@ -19,7 +19,7 @@
 /**
  * This evaluator can be used to perform type interpolation between <code>float</code> values.
  */
-public class FloatEvaluator implements TypeEvaluator {
+public class FloatEvaluator implements TypeEvaluator<Number> {
 
     /**
      * This function returns the result of linearly interpolating the start and end values, with
@@ -35,8 +35,8 @@
      * @return A linear interpolation between the start and end values, given the
      *         <code>fraction</code> parameter.
      */
-    public Object evaluate(float fraction, Object startValue, Object endValue) {
-        float startFloat = ((Number) startValue).floatValue();
-        return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
+    public Float evaluate(float fraction, Number startValue, Number endValue) {
+        float startFloat = startValue.floatValue();
+        return startFloat + fraction * (endValue.floatValue() - startFloat);
     }
 }
\ No newline at end of file
diff --git a/core/java/android/animation/IntEvaluator.java b/core/java/android/animation/IntEvaluator.java
index 7288927..34fb0dc 100644
--- a/core/java/android/animation/IntEvaluator.java
+++ b/core/java/android/animation/IntEvaluator.java
@@ -19,7 +19,7 @@
 /**
  * This evaluator can be used to perform type interpolation between <code>int</code> values.
  */
-public class IntEvaluator implements TypeEvaluator {
+public class IntEvaluator implements TypeEvaluator<Integer> {
 
     /**
      * This function returns the result of linearly interpolating the start and end values, with
@@ -35,8 +35,8 @@
      * @return A linear interpolation between the start and end values, given the
      *         <code>fraction</code> parameter.
      */
-    public Object evaluate(float fraction, Object startValue, Object endValue) {
-        int startInt = ((Number) startValue).intValue();
-        return (int) (startInt + fraction * (((Number) endValue).intValue() - startInt));
+    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
+        int startInt = startValue;
+        return (int)(startInt + fraction * (endValue - startInt));
     }
 }
\ No newline at end of file
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index b8a7cb2..31c5f8d 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -17,6 +17,7 @@
 package android.animation;
 
 import android.util.Log;
+import android.util.Property;
 
 import java.lang.reflect.Method;
 import java.util.ArrayList;
@@ -39,6 +40,8 @@
 
     private String mPropertyName;
 
+    private Property mProperty;
+
     /**
      * Sets the name of the property that will be animated. This name is used to derive
      * a setter function that will be called to set animated values.
@@ -63,7 +66,7 @@
      * using more than one PropertyValuesHolder objects, then setting the propertyName simply
      * sets the propertyName in the first of those PropertyValuesHolder objects.</p>
      *
-     * @param propertyName The name of the property being animated.
+     * @param propertyName The name of the property being animated. Should not be null.
      */
     public void setPropertyName(String propertyName) {
         // mValues could be null if this is being constructed piecemeal. Just record the
@@ -81,6 +84,31 @@
     }
 
     /**
+     * Sets the property that will be animated. Property objects will take precedence over
+     * properties specified by the {@link #setPropertyName(String)} method. Animations should
+     * be set up to use one or the other, not both.
+     *
+     * @param property The property being animated. Should not be null.
+     */
+    public void setProperty(Property property) {
+        // mValues could be null if this is being constructed piecemeal. Just record the
+        // propertyName to be used later when setValues() is called if so.
+        if (mValues != null) {
+            PropertyValuesHolder valuesHolder = mValues[0];
+            String oldName = valuesHolder.getPropertyName();
+            valuesHolder.setProperty(property);
+            mValuesMap.remove(oldName);
+            mValuesMap.put(mPropertyName, valuesHolder);
+        }
+        if (mProperty != null) {
+            mPropertyName = property.getName();
+        }
+        mProperty = property;
+        // New property/values/target should cause re-initialization prior to starting
+        mInitialized = false;
+    }
+
+    /**
      * Gets the name of the property that will be animated. This name will be used to derive
      * a setter function that will be called to set animated values.
      * For example, a property name of <code>foo</code> will result
@@ -93,36 +121,6 @@
     }
 
     /**
-     * Determine the setter or getter function using the JavaBeans convention of setFoo or
-     * getFoo for a property named 'foo'. This function figures out what the name of the
-     * function should be and uses reflection to find the Method with that name on the
-     * target object.
-     *
-     * @param prefix "set" or "get", depending on whether we need a setter or getter.
-     * @return Method the method associated with mPropertyName.
-     */
-    private Method getPropertyFunction(String prefix, Class valueType) {
-        // TODO: faster implementation...
-        Method returnVal = null;
-        String firstLetter = mPropertyName.substring(0, 1);
-        String theRest = mPropertyName.substring(1);
-        firstLetter = firstLetter.toUpperCase();
-        String setterName = prefix + firstLetter + theRest;
-        Class args[] = null;
-        if (valueType != null) {
-            args = new Class[1];
-            args[0] = valueType;
-        }
-        try {
-            returnVal = mTarget.getClass().getMethod(setterName, args);
-        } catch (NoSuchMethodException e) {
-            Log.e("ObjectAnimator",
-                    "Couldn't find setter/getter for property " + mPropertyName + ": " + e);
-        }
-        return returnVal;
-    }
-
-    /**
      * Creates a new ObjectAnimator object. This default constructor is primarily for
      * use internally; the other constructors which take parameters are more generally
      * useful.
@@ -131,8 +129,8 @@
     }
 
     /**
-     * A constructor that takes a single property name and set of values. This constructor is
-     * used in the simple case of animating a single property.
+     * Private utility constructor that initializes the target object and name of the
+     * property being animated.
      *
      * @param target The object whose property is to be animated. This object should
      * have a public method on it called <code>setName()</code>, where <code>name</code> is
@@ -145,19 +143,29 @@
     }
 
     /**
+     * Private utility constructor that initializes the target object and property being animated.
+     *
+     * @param target The object whose property is to be animated.
+     * @param property The property being animated.
+     */
+    private <T> ObjectAnimator(T target, Property<T, ?> property) {
+        mTarget = target;
+        setProperty(property);
+    }
+
+    /**
      * Constructs and returns an ObjectAnimator that animates between int values. A single
-     * value implies that that value is the one being animated to. However, this is not typically
-     * useful in a ValueAnimator object because there is no way for the object to determine the
-     * starting value for the animation (unlike ObjectAnimator, which can derive that value
-     * from the target object and property being animated). Therefore, there should typically
-     * be two or more values.
+     * value implies that that value is the one being animated to. Two values imply a starting
+     * and ending values. More than two values imply a starting value, values to animate through
+     * along the way, and an ending value (these values will be distributed evenly across
+     * the duration of the animation).
      *
      * @param target The object whose property is to be animated. This object should
      * have a public method on it called <code>setName()</code>, where <code>name</code> is
      * the value of the <code>propertyName</code> parameter.
      * @param propertyName The name of the property being animated.
      * @param values A set of values that the animation will animate between over time.
-     * @return A ValueAnimator object that is set up to animate between the given values.
+     * @return An ObjectAnimator object that is set up to animate between the given values.
      */
     public static ObjectAnimator ofInt(Object target, String propertyName, int... values) {
         ObjectAnimator anim = new ObjectAnimator(target, propertyName);
@@ -166,19 +174,36 @@
     }
 
     /**
+     * Constructs and returns an ObjectAnimator that animates between int values. A single
+     * value implies that that value is the one being animated to. Two values imply a starting
+     * and ending values. More than two values imply a starting value, values to animate through
+     * along the way, and an ending value (these values will be distributed evenly across
+     * the duration of the animation).
+     *
+     * @param target The object whose property is to be animated.
+     * @param property The property being animated.
+     * @param values A set of values that the animation will animate between over time.
+     * @return An ObjectAnimator object that is set up to animate between the given values.
+     */
+    public static <T> ObjectAnimator ofInt(T target, Property<T, Integer> property, int... values) {
+        ObjectAnimator anim = new ObjectAnimator(target, property);
+        anim.setIntValues(values);
+        return anim;
+    }
+
+    /**
      * Constructs and returns an ObjectAnimator that animates between float values. A single
-     * value implies that that value is the one being animated to. However, this is not typically
-     * useful in a ValueAnimator object because there is no way for the object to determine the
-     * starting value for the animation (unlike ObjectAnimator, which can derive that value
-     * from the target object and property being animated). Therefore, there should typically
-     * be two or more values.
+     * value implies that that value is the one being animated to. Two values imply a starting
+     * and ending values. More than two values imply a starting value, values to animate through
+     * along the way, and an ending value (these values will be distributed evenly across
+     * the duration of the animation).
      *
      * @param target The object whose property is to be animated. This object should
      * have a public method on it called <code>setName()</code>, where <code>name</code> is
      * the value of the <code>propertyName</code> parameter.
      * @param propertyName The name of the property being animated.
      * @param values A set of values that the animation will animate between over time.
-     * @return A ValueAnimator object that is set up to animate between the given values.
+     * @return An ObjectAnimator object that is set up to animate between the given values.
      */
     public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {
         ObjectAnimator anim = new ObjectAnimator(target, propertyName);
@@ -187,21 +212,40 @@
     }
 
     /**
-     * A constructor that takes <code>PropertyValueHolder</code> values. This constructor should
-     * be used when animating several properties at once with the same ObjectAnimator, since
-     * PropertyValuesHolder allows you to associate a set of animation values with a property
-     * name.
+     * Constructs and returns an ObjectAnimator that animates between float values. A single
+     * value implies that that value is the one being animated to. Two values imply a starting
+     * and ending values. More than two values imply a starting value, values to animate through
+     * along the way, and an ending value (these values will be distributed evenly across
+     * the duration of the animation).
+     *
+     * @param target The object whose property is to be animated.
+     * @param property The property being animated.
+     * @param values A set of values that the animation will animate between over time.
+     * @return An ObjectAnimator object that is set up to animate between the given values.
+     */
+    public static <T> ObjectAnimator ofFloat(T target, Property<T, Float> property,
+            float... values) {
+        ObjectAnimator anim = new ObjectAnimator(target, property);
+        anim.setFloatValues(values);
+        return anim;
+    }
+
+    /**
+     * Constructs and returns an ObjectAnimator that animates between Object values. A single
+     * value implies that that value is the one being animated to. Two values imply a starting
+     * and ending values. More than two values imply a starting value, values to animate through
+     * along the way, and an ending value (these values will be distributed evenly across
+     * the duration of the animation).
      *
      * @param target The object whose property is to be animated. This object should
-     * have public methods on it called <code>setName()</code>, where <code>name</code> is
-     * the name of the property passed in as the <code>propertyName</code> parameter for
-     * each of the PropertyValuesHolder objects.
+     * have a public method on it called <code>setName()</code>, where <code>name</code> is
+     * the value of the <code>propertyName</code> parameter.
      * @param propertyName The name of the property being animated.
      * @param evaluator A TypeEvaluator that will be called on each animation frame to
-     * provide the ncessry interpolation between the Object values to derive the animated
+     * provide the necessary interpolation between the Object values to derive the animated
      * value.
-     * @param values The PropertyValuesHolder objects which hold each the property name and values
-     * to animate that property between.
+     * @param values A set of values that the animation will animate between over time.
+     * @return An ObjectAnimator object that is set up to animate between the given values.
      */
     public static ObjectAnimator ofObject(Object target, String propertyName,
             TypeEvaluator evaluator, Object... values) {
@@ -212,19 +256,44 @@
     }
 
     /**
-     * Constructs and returns an ObjectAnimator that animates between the sets of values
-     * specifed in <code>PropertyValueHolder</code> objects. This variant should
-     * be used when animating several properties at once with the same ObjectAnimator, since
-     * PropertyValuesHolder allows you to associate a set of animation values with a property
-     * name.
+     * Constructs and returns an ObjectAnimator that animates between Object values. A single
+     * value implies that that value is the one being animated to. Two values imply a starting
+     * and ending values. More than two values imply a starting value, values to animate through
+     * along the way, and an ending value (these values will be distributed evenly across
+     * the duration of the animation).
      *
-     * @param target The object whose property is to be animated. This object should
-     * have public methods on it called <code>setName()</code>, where <code>name</code> is
-     * the name of the property passed in as the <code>propertyName</code> parameter for
-     * each of the PropertyValuesHolder objects.
-     * @param values A set of PropertyValuesHolder objects whose values will be animated
-     * between over time.
-     * @return A ValueAnimator object that is set up to animate between the given values.
+     * @param target The object whose property is to be animated.
+     * @param property The property being animated.
+     * @param evaluator A TypeEvaluator that will be called on each animation frame to
+     * provide the necessary interpolation between the Object values to derive the animated
+     * value.
+     * @param values A set of values that the animation will animate between over time.
+     * @return An ObjectAnimator object that is set up to animate between the given values.
+     */
+    public static <T, V> ObjectAnimator ofObject(T target, Property<T, V> property,
+            TypeEvaluator<V> evaluator, V... values) {
+        ObjectAnimator anim = new ObjectAnimator(target, property);
+        anim.setObjectValues(values);
+        anim.setEvaluator(evaluator);
+        return anim;
+    }
+
+    /**
+     * Constructs and returns an ObjectAnimator that animates between the sets of values specified
+     * in <code>PropertyValueHolder</code> objects. This variant should be used when animating
+     * several properties at once with the same ObjectAnimator, since PropertyValuesHolder allows
+     * you to associate a set of animation values with a property name.
+     *
+     * @param target The object whose property is to be animated. Depending on how the
+     * PropertyValuesObjects were constructed, the target object should either have the {@link
+     * android.util.Property} objects used to construct the PropertyValuesHolder objects or (if the
+     * PropertyValuesHOlder objects were created with property names) the target object should have
+     * public methods on it called <code>setName()</code>, where <code>name</code> is the name of
+     * the property passed in as the <code>propertyName</code> parameter for each of the
+     * PropertyValuesHolder objects.
+     * @param values A set of PropertyValuesHolder objects whose values will be animated between
+     * over time.
+     * @return An ObjectAnimator object that is set up to animate between the given values.
      */
     public static ObjectAnimator ofPropertyValuesHolder(Object target,
             PropertyValuesHolder... values) {
@@ -239,7 +308,11 @@
         if (mValues == null || mValues.length == 0) {
             // No values yet - this animator is being constructed piecemeal. Init the values with
             // whatever the current propertyName is
-            setValues(PropertyValuesHolder.ofInt(mPropertyName, values));
+            if (mProperty != null) {
+                setValues(PropertyValuesHolder.ofInt(mProperty, values));
+            } else {
+                setValues(PropertyValuesHolder.ofInt(mPropertyName, values));
+            }
         } else {
             super.setIntValues(values);
         }
@@ -250,7 +323,11 @@
         if (mValues == null || mValues.length == 0) {
             // No values yet - this animator is being constructed piecemeal. Init the values with
             // whatever the current propertyName is
-            setValues(PropertyValuesHolder.ofFloat(mPropertyName, values));
+            if (mProperty != null) {
+                setValues(PropertyValuesHolder.ofFloat(mProperty, values));
+            } else {
+                setValues(PropertyValuesHolder.ofFloat(mPropertyName, values));
+            }
         } else {
             super.setFloatValues(values);
         }
@@ -261,7 +338,11 @@
         if (mValues == null || mValues.length == 0) {
             // No values yet - this animator is being constructed piecemeal. Init the values with
             // whatever the current propertyName is
-            setValues(PropertyValuesHolder.ofObject(mPropertyName, (TypeEvaluator)null, values));
+            if (mProperty != null) {
+                setValues(PropertyValuesHolder.ofObject(mProperty, (TypeEvaluator)null, values));
+            } else {
+                setValues(PropertyValuesHolder.ofObject(mPropertyName, (TypeEvaluator)null, values));
+            }
         } else {
             super.setObjectValues(values);
         }
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java
index 6f91fc0..58f23f7 100644
--- a/core/java/android/animation/PropertyValuesHolder.java
+++ b/core/java/android/animation/PropertyValuesHolder.java
@@ -16,7 +16,10 @@
 
 package android.animation;
 
+import android.util.FloatProperty;
+import android.util.IntProperty;
 import android.util.Log;
+import android.util.Property;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -39,6 +42,11 @@
     String mPropertyName;
 
     /**
+     * @hide
+     */
+    protected Property mProperty;
+
+    /**
      * The setter function, if needed. ObjectAnimator hands off this functionality to
      * PropertyValuesHolder, since it holds all of the per-property information. This
      * property is automatically
@@ -124,6 +132,17 @@
     }
 
     /**
+     * Internal utility constructor, used by the factory methods to set the property.
+     * @param property The property for this holder.
+     */
+    private PropertyValuesHolder(Property property) {
+        mProperty = property;
+        if (property != null) {
+            mPropertyName = property.getName();
+        }
+    }
+
+    /**
      * Constructs and returns a PropertyValuesHolder with a given property name and
      * set of int values.
      * @param propertyName The name of the property being animated.
@@ -131,8 +150,18 @@
      * @return PropertyValuesHolder The constructed PropertyValuesHolder object.
      */
     public static PropertyValuesHolder ofInt(String propertyName, int... values) {
-        PropertyValuesHolder pvh = new IntPropertyValuesHolder(propertyName, values);
-        return pvh;
+        return new IntPropertyValuesHolder(propertyName, values);
+    }
+
+    /**
+     * Constructs and returns a PropertyValuesHolder with a given property and
+     * set of int values.
+     * @param property The property being animated. Should not be null.
+     * @param values The values that the property will animate between.
+     * @return PropertyValuesHolder The constructed PropertyValuesHolder object.
+     */
+    public static PropertyValuesHolder ofInt(Property<?, Integer> property, int... values) {
+        return new IntPropertyValuesHolder(property, values);
     }
 
     /**
@@ -143,18 +172,28 @@
      * @return PropertyValuesHolder The constructed PropertyValuesHolder object.
      */
     public static PropertyValuesHolder ofFloat(String propertyName, float... values) {
-        PropertyValuesHolder pvh = new FloatPropertyValuesHolder(propertyName, values);
-        return pvh;
+        return new FloatPropertyValuesHolder(propertyName, values);
+    }
+
+    /**
+     * Constructs and returns a PropertyValuesHolder with a given property and
+     * set of float values.
+     * @param property The property being animated. Should not be null.
+     * @param values The values that the property will animate between.
+     * @return PropertyValuesHolder The constructed PropertyValuesHolder object.
+     */
+    public static PropertyValuesHolder ofFloat(Property<?, Float> property, float... values) {
+        return new FloatPropertyValuesHolder(property, values);
     }
 
     /**
      * Constructs and returns a PropertyValuesHolder with a given property name and
      * set of Object values. This variant also takes a TypeEvaluator because the system
-     * cannot interpolate between objects of unknown type.
+     * cannot automatically interpolate between objects of unknown type.
      *
      * @param propertyName The name of the property being animated.
      * @param evaluator A TypeEvaluator that will be called on each animation frame to
-     * provide the ncessry interpolation between the Object values to derive the animated
+     * provide the necessary interpolation between the Object values to derive the animated
      * value.
      * @param values The values that the named property will animate between.
      * @return PropertyValuesHolder The constructed PropertyValuesHolder object.
@@ -168,6 +207,26 @@
     }
 
     /**
+     * Constructs and returns a PropertyValuesHolder with a given property and
+     * set of Object values. This variant also takes a TypeEvaluator because the system
+     * cannot automatically interpolate between objects of unknown type.
+     *
+     * @param property The property being animated. Should not be null.
+     * @param evaluator A TypeEvaluator that will be called on each animation frame to
+     * provide the necessary interpolation between the Object values to derive the animated
+     * value.
+     * @param values The values that the property will animate between.
+     * @return PropertyValuesHolder The constructed PropertyValuesHolder object.
+     */
+    public static <V> PropertyValuesHolder ofObject(Property property,
+            TypeEvaluator<V> evaluator, V... values) {
+        PropertyValuesHolder pvh = new PropertyValuesHolder(property);
+        pvh.setObjectValues(values);
+        pvh.setEvaluator(evaluator);
+        return pvh;
+    }
+
+    /**
      * Constructs and returns a PropertyValuesHolder object with the specified property name and set
      * of values. These values can be of any type, but the type should be consistent so that
      * an appropriate {@link android.animation.TypeEvaluator} can be found that matches
@@ -202,6 +261,37 @@
     }
 
     /**
+     * Constructs and returns a PropertyValuesHolder object with the specified property and set
+     * of values. These values can be of any type, but the type should be consistent so that
+     * an appropriate {@link android.animation.TypeEvaluator} can be found that matches
+     * the common type.
+     * <p>If there is only one value, it is assumed to be the end value of an animation,
+     * and an initial value will be derived, if possible, by calling the property's
+     * {@link android.util.Property#get(Object)} function.
+     * Also, if any value is null, the value will be filled in when the animation
+     * starts in the same way. This mechanism of automatically getting null values only works
+     * if the PropertyValuesHolder object is used in conjunction with
+     * {@link ObjectAnimator}, since otherwise PropertyValuesHolder has
+     * no way of determining what the value should be.
+     * @param property The property associated with this set of values. Should not be null.
+     * @param values The set of values to animate between.
+     */
+    public static PropertyValuesHolder ofKeyframe(Property property, Keyframe... values) {
+        KeyframeSet keyframeSet = KeyframeSet.ofKeyframe(values);
+        if (keyframeSet instanceof IntKeyframeSet) {
+            return new IntPropertyValuesHolder(property, (IntKeyframeSet) keyframeSet);
+        } else if (keyframeSet instanceof FloatKeyframeSet) {
+            return new FloatPropertyValuesHolder(property, (FloatKeyframeSet) keyframeSet);
+        }
+        else {
+            PropertyValuesHolder pvh = new PropertyValuesHolder(property);
+            pvh.mKeyframeSet = keyframeSet;
+            pvh.mValueType = ((Keyframe)values[0]).getType();
+            return pvh;
+        }
+    }
+
+    /**
      * Set the animated values for this object to this set of ints.
      * If there is only one value, it is assumed to be the end value of an animation,
      * and an initial value will be derived, if possible, by calling a getter function
@@ -349,7 +439,6 @@
             // Have to lock property map prior to reading it, to guard against
             // another thread putting something in there after we've checked it
             // but before we've added an entry to it
-            // TODO: can we store the setter/getter per Class instead of per Object?
             mPropertyMapLock.writeLock().lock();
             HashMap<String, Method> propertyMap = propertyMapMap.get(targetClass);
             if (propertyMap != null) {
@@ -395,6 +484,22 @@
      * @param target The object on which the setter (and possibly getter) exist.
      */
     void setupSetterAndGetter(Object target) {
+        if (mProperty != null) {
+            // check to make sure that mProperty is on the class of target
+            try {
+                Object testValue = mProperty.get(target);
+                for (Keyframe kf : mKeyframeSet.mKeyframes) {
+                    if (!kf.hasValue()) {
+                        kf.setValue(mProperty.get(target));
+                    }
+                }
+                return;
+            } catch (ClassCastException e) {
+                Log.e("PropertyValuesHolder","No such property (" + mProperty.getName() +
+                        ") on target object " + target + ". Trying reflection instead");
+                mProperty = null;
+            }
+        }
         Class targetClass = target.getClass();
         if (mSetter == null) {
             setupSetter(targetClass);
@@ -423,6 +528,9 @@
      * @param kf The keyframe which holds the property name and value.
      */
     private void setupValue(Object target, Keyframe kf) {
+        if (mProperty != null) {
+            kf.setValue(mProperty.get(target));
+        }
         try {
             if (mGetter == null) {
                 Class targetClass = target.getClass();
@@ -465,6 +573,7 @@
         try {
             PropertyValuesHolder newPVH = (PropertyValuesHolder) super.clone();
             newPVH.mPropertyName = mPropertyName;
+            newPVH.mProperty = mProperty;
             newPVH.mKeyframeSet = mKeyframeSet.clone();
             newPVH.mEvaluator = mEvaluator;
             return newPVH;
@@ -482,6 +591,9 @@
      * @param target The target object on which the value is set
      */
     void setAnimatedValue(Object target) {
+        if (mProperty != null) {
+            mProperty.set(target, getAnimatedValue());
+        }
         if (mSetter != null) {
             try {
                 mTmpValueArray[0] = getAnimatedValue();
@@ -558,6 +670,18 @@
     }
 
     /**
+     * Sets the property that will be animated.
+     *
+     * <p>Note that if this PropertyValuesHolder object is used with ObjectAnimator, the property
+     * must exist on the target object specified in that ObjectAnimator.</p>
+     *
+     * @param property The property being animated.
+     */
+    public void setProperty(Property property) {
+        mProperty = property;
+    }
+
+    /**
      * Gets the name of the property that will be animated. This name will be used to derive
      * a setter function that will be called to set animated values.
      * For example, a property name of <code>foo</code> will result
@@ -597,17 +721,22 @@
      * specified above.
      */
     static String getMethodName(String prefix, String propertyName) {
-        char firstLetter = propertyName.charAt(0);
+        if (propertyName == null || propertyName.length() == 0) {
+            // shouldn't get here
+            return prefix;
+        }
+        char firstLetter = Character.toUpperCase(propertyName.charAt(0));
         String theRest = propertyName.substring(1);
-        firstLetter = Character.toUpperCase(firstLetter);
         return prefix + firstLetter + theRest;
     }
 
     static class IntPropertyValuesHolder extends PropertyValuesHolder {
 
+        // Cache JNI functions to avoid looking them up twice
         private static final HashMap<Class, HashMap<String, Integer>> sJNISetterPropertyMap =
                 new HashMap<Class, HashMap<String, Integer>>();
         int mJniSetter;
+        private IntProperty mIntProperty;
 
         IntKeyframeSet mIntKeyframeSet;
         int mIntAnimatedValue;
@@ -619,11 +748,29 @@
             mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet;
         }
 
+        public IntPropertyValuesHolder(Property property, IntKeyframeSet keyframeSet) {
+            super(property);
+            mValueType = int.class;
+            mKeyframeSet = keyframeSet;
+            mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet;
+            if (property instanceof  IntProperty) {
+                mIntProperty = (IntProperty) mProperty;
+            }
+        }
+
         public IntPropertyValuesHolder(String propertyName, int... values) {
             super(propertyName);
             setIntValues(values);
         }
 
+        public IntPropertyValuesHolder(Property property, int... values) {
+            super(property);
+            setIntValues(values);
+            if (property instanceof  IntProperty) {
+                mIntProperty = (IntProperty) mProperty;
+            }
+        }
+
         @Override
         public void setIntValues(int... values) {
             super.setIntValues(values);
@@ -656,6 +803,14 @@
          */
         @Override
         void setAnimatedValue(Object target) {
+            if (mIntProperty != null) {
+                mIntProperty.setValue(target, mIntAnimatedValue);
+                return;
+            }
+            if (mProperty != null) {
+                mProperty.set(target, mIntAnimatedValue);
+                return;
+            }
             if (mJniSetter != 0) {
                 nCallIntMethod(target, mJniSetter, mIntAnimatedValue);
                 return;
@@ -674,6 +829,9 @@
 
         @Override
         void setupSetter(Class targetClass) {
+            if (mProperty != null) {
+                return;
+            }
             // Check new static hashmap<propName, int> for setter method
             try {
                 mPropertyMapLock.writeLock().lock();
@@ -696,7 +854,8 @@
                     }
                 }
             } catch (NoSuchMethodError e) {
-                // System.out.println("Can't find native method using JNI, use reflection" + e);
+                Log.d("PropertyValuesHolder",
+                        "Can't find native method using JNI, use reflection" + e);
             } finally {
                 mPropertyMapLock.writeLock().unlock();
             }
@@ -709,9 +868,11 @@
 
     static class FloatPropertyValuesHolder extends PropertyValuesHolder {
 
+        // Cache JNI functions to avoid looking them up twice
         private static final HashMap<Class, HashMap<String, Integer>> sJNISetterPropertyMap =
                 new HashMap<Class, HashMap<String, Integer>>();
         int mJniSetter;
+        private FloatProperty mFloatProperty;
 
         FloatKeyframeSet mFloatKeyframeSet;
         float mFloatAnimatedValue;
@@ -723,11 +884,29 @@
             mFloatKeyframeSet = (FloatKeyframeSet) mKeyframeSet;
         }
 
+        public FloatPropertyValuesHolder(Property property, FloatKeyframeSet keyframeSet) {
+            super(property);
+            mValueType = float.class;
+            mKeyframeSet = keyframeSet;
+            mFloatKeyframeSet = (FloatKeyframeSet) mKeyframeSet;
+            if (property instanceof FloatProperty) {
+                mFloatProperty = (FloatProperty) mProperty;
+            }
+        }
+
         public FloatPropertyValuesHolder(String propertyName, float... values) {
             super(propertyName);
             setFloatValues(values);
         }
 
+        public FloatPropertyValuesHolder(Property property, float... values) {
+            super(property);
+            setFloatValues(values);
+            if (property instanceof  FloatProperty) {
+                mFloatProperty = (FloatProperty) mProperty;
+            }
+        }
+
         @Override
         public void setFloatValues(float... values) {
             super.setFloatValues(values);
@@ -760,6 +939,14 @@
          */
         @Override
         void setAnimatedValue(Object target) {
+            if (mFloatProperty != null) {
+                mFloatProperty.setValue(target, mFloatAnimatedValue);
+                return;
+            }
+            if (mProperty != null) {
+                mProperty.set(target, mFloatAnimatedValue);
+                return;
+            }
             if (mJniSetter != 0) {
                 nCallFloatMethod(target, mJniSetter, mFloatAnimatedValue);
                 return;
@@ -778,6 +965,9 @@
 
         @Override
         void setupSetter(Class targetClass) {
+            if (mProperty != null) {
+                return;
+            }
             // Check new static hashmap<propName, int> for setter method
             try {
                 mPropertyMapLock.writeLock().lock();
@@ -800,7 +990,8 @@
                     }
                 }
             } catch (NoSuchMethodError e) {
-                // System.out.println("Can't find native method using JNI, use reflection" + e);
+                Log.d("PropertyValuesHolder",
+                        "Can't find native method using JNI, use reflection" + e);
             } finally {
                 mPropertyMapLock.writeLock().unlock();
             }
diff --git a/core/java/android/animation/TypeEvaluator.java b/core/java/android/animation/TypeEvaluator.java
index fa49175..e738da1 100644
--- a/core/java/android/animation/TypeEvaluator.java
+++ b/core/java/android/animation/TypeEvaluator.java
@@ -24,7 +24,7 @@
  *
  * @see ValueAnimator#setEvaluator(TypeEvaluator)
  */
-public interface TypeEvaluator {
+public interface TypeEvaluator<T> {
 
     /**
      * This function returns the result of linearly interpolating the start and end values, with
@@ -39,6 +39,6 @@
      * @return A linear interpolation between the start and end values, given the
      *         <code>fraction</code> parameter.
      */
-    public Object evaluate(float fraction, Object startValue, Object endValue);
+    public T evaluate(float fraction, T startValue, T endValue);
 
 }
\ No newline at end of file
diff --git a/core/java/android/util/FloatProperty.java b/core/java/android/util/FloatProperty.java
new file mode 100644
index 0000000..a67b3cb
--- /dev/null
+++ b/core/java/android/util/FloatProperty.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.util;
+
+import android.util.Property;
+
+/**
+ * An implementation of {@link android.util.Property} to be used specifically with fields of type
+ * <code>float</code>. This type-specific subclass enables performance benefit by allowing
+ * calls to a {@link #set(Object, Float) set()} function that takes the primitive
+ * <code>float</code> type and avoids autoboxing and other overhead associated with the
+ * <code>Float</code> class.
+ *
+ * @param <T> The class on which the Property is declared.
+ *
+ * @hide
+ */
+public abstract class FloatProperty<T> extends Property<T, Float> {
+
+    public FloatProperty(String name) {
+        super(Float.class, name);
+    }
+
+    /**
+     * A type-specific override of the {@link #set(Object, Float)} that is faster when dealing
+     * with fields of type <code>float</code>.
+     */
+    public abstract void setValue(T object, float value);
+
+    @Override
+    final public void set(T object, Float value) {
+        setValue(object, value);
+    }
+
+}
\ No newline at end of file
diff --git a/core/java/android/util/IntProperty.java b/core/java/android/util/IntProperty.java
new file mode 100644
index 0000000..459d6b2
--- /dev/null
+++ b/core/java/android/util/IntProperty.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.util;
+
+import android.util.Property;
+
+/**
+ * An implementation of {@link android.util.Property} to be used specifically with fields of type
+ * <code>int</code>. This type-specific subclass enables performance benefit by allowing
+ * calls to a {@link #set(Object, Integer) set()} function that takes the primitive
+ * <code>int</code> type and avoids autoboxing and other overhead associated with the
+ * <code>Integer</code> class.
+ *
+ * @param <T> The class on which the Property is declared.
+ *
+ * @hide
+ */
+public abstract class IntProperty<T> extends Property<T, Integer> {
+
+    public IntProperty(String name) {
+        super(Integer.class, name);
+    }
+
+    /**
+     * A type-specific override of the {@link #set(Object, Integer)} that is faster when dealing
+     * with fields of type <code>int</code>.
+     */
+    public abstract void setValue(T object, int value);
+
+    @Override
+    final public void set(T object, Integer value) {
+        set(object, value.intValue());
+    }
+
+}
\ No newline at end of file
diff --git a/core/java/android/util/NoSuchPropertyException.java b/core/java/android/util/NoSuchPropertyException.java
new file mode 100644
index 0000000..b93f983
--- /dev/null
+++ b/core/java/android/util/NoSuchPropertyException.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.util;
+
+/**
+ * Thrown when code requests a {@link Property} on a class that does
+ * not expose the appropriate method or field.
+ *
+ * @see Property#of(java.lang.Class, java.lang.Class, java.lang.String)
+ */
+public class NoSuchPropertyException extends RuntimeException {
+
+    public NoSuchPropertyException(String s) {
+        super(s);
+    }
+
+}
diff --git a/core/java/android/util/Property.java b/core/java/android/util/Property.java
new file mode 100644
index 0000000..458e4c3
--- /dev/null
+++ b/core/java/android/util/Property.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.util;
+
+
+/**
+ * A property is an abstraction that can be used to represent a <emb>mutable</em> value that is held
+ * in a <em>host</em> object. The Property's {@link #set(Object, Object)} or {@link #get(Object)}
+ * methods can be implemented in terms of the private fields of the host object, or via "setter" and
+ * "getter" methods or by some other mechanism, as appropriate.
+ *
+ * @param <T> The class on which the property is declared.
+ * @param <V> The type that this property represents.
+ */
+public abstract class Property<T, V> {
+
+    private final String mName;
+    private final Class<V> mType;
+
+    /**
+     * This factory method creates and returns a Property given the <code>class</code> and
+     * <code>name</code> parameters, where the <code>"name"</code> parameter represents either:
+     * <ul>
+     *     <li>a public <code>getName()</code> method on the class which takes no arguments, plus an
+     *     optional public <code>setName()</code> method which takes a value of the same type
+     *     returned by <code>getName()</code>
+     *     <li>a public <code>isName()</code> method on the class which takes no arguments, plus an
+     *     optional public <code>setName()</code> method which takes a value of the same type
+     *     returned by <code>isName()</code>
+     *     <li>a public <code>name</code> field on the class
+     * </ul>
+     *
+     * <p>If either of the get/is method alternatives is found on the class, but an appropriate
+     * <code>setName()</code> method is not found, the <code>Property</code> will be
+     * {@link #isReadOnly() readOnly}. Calling the {@link #set(Object, Object)} method on such
+     * a property is allowed, but will have no effect.</p>
+     *
+     * <p>If neither the methods nor the field are found on the class a
+     * {@link NoSuchPropertyException} exception will be thrown.</p>
+     */
+    public static <T, V> Property<T, V> of(Class<T> hostType, Class<V> valueType, String name) {
+        return new ReflectiveProperty<T, V>(hostType, valueType, name);
+    }
+
+    /**
+     * A constructor that takes an identifying name and {@link #getType() type} for the property.
+     */
+    public Property(Class<V> type, String name) {
+        mName = name;
+        mType = type;
+    }
+
+    /**
+     * Returns true if the {@link #set(Object, Object)} method does not set the value on the target
+     * object (in which case the {@link #set(Object, Object) set()} method should throw a {@link
+     * NoSuchPropertyException} exception). This may happen if the Property wraps functionality that
+     * allows querying the underlying value but not setting it. For example, the {@link #of(Class,
+     * Class, String)} factory method may return a Property with name "foo" for an object that has
+     * only a <code>getFoo()</code> or <code>isFoo()</code> method, but no matching
+     * <code>setFoo()</code> method.
+     */
+    public boolean isReadOnly() {
+        return false;
+    }
+
+    /**
+     * Sets the value on <code>object</code> which this property represents. If the method is unable
+     * to set the value on the target object, it will throw a {@link NoSuchPropertyException}
+     * exception.
+     */
+    public void set(T object, V value) {
+        throw new NoSuchPropertyException("Property is read-only; set() is not implemented");
+    }
+
+    /**
+     * Returns the current value that this property represents on the given <code>object</code>.
+     */
+    public abstract V get(T object);
+
+    /**
+     * Returns the name for this property.
+     */
+    public String getName() {
+        return mName;
+    }
+
+    /**
+     * Returns the type for this property.
+     */
+    public Class<V> getType() {
+        return mType;
+    }
+}
diff --git a/core/java/android/util/ReflectiveProperty.java b/core/java/android/util/ReflectiveProperty.java
new file mode 100644
index 0000000..7bd7428
--- /dev/null
+++ b/core/java/android/util/ReflectiveProperty.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Internal class to automatically generate a Property for a given class/name pair, given the
+ * specification of {@link Property#of(java.lang.Class, java.lang.Class, java.lang.String)}
+ */
+class ReflectiveProperty<T, V> extends Property<T, V> {
+
+    private static final String PREFIX_GET = "get";
+    private static final String PREFIX_IS = "is";
+    private static final String PREFIX_SET = "set";
+    private Method mSetter;
+    private Method mGetter;
+    private Field mField;
+
+    /**
+     * For given property name 'name', look for getName/isName method or 'name' field.
+     * Also look for setName method (optional - could be readonly). Failing method getters and
+     * field results in throwing NoSuchPropertyException.
+     *
+     * @param propertyHolder The class on which the methods or field are found
+     * @param name The name of the property, where this name is capitalized and appended to
+     * "get" and "is to search for the appropriate methods. If the get/is methods are not found,
+     * the constructor will search for a field with that exact name.
+     */
+    public ReflectiveProperty(Class<T> propertyHolder, Class<V> valueType, String name) {
+         // TODO: cache reflection info for each new class/name pair
+        super(valueType, name);
+        char firstLetter = Character.toUpperCase(name.charAt(0));
+        String theRest = name.substring(1);
+        String capitalizedName = firstLetter + theRest;
+        String getterName = PREFIX_GET + capitalizedName;
+        try {
+            mGetter = propertyHolder.getMethod(getterName, (Class<?>[])null);
+        } catch (NoSuchMethodException e) {
+            // getName() not available - try isName() instead
+            getterName = PREFIX_IS + capitalizedName;
+            try {
+                mGetter = propertyHolder.getMethod(getterName, (Class<?>[])null);
+            } catch (NoSuchMethodException e1) {
+                // Try public field instead
+                try {
+                    mField = propertyHolder.getField(name);
+                    Class fieldType = mField.getType();
+                    if (!typesMatch(valueType, fieldType)) {
+                        throw new NoSuchPropertyException("Underlying type (" + fieldType + ") " +
+                                "does not match Property type (" + valueType + ")");
+                    }
+                    return;
+                } catch (NoSuchFieldException e2) {
+                    // no way to access property - throw appropriate exception
+                    throw new NoSuchPropertyException("No accessor method or field found for"
+                            + " property with name " + name);
+                }
+            }
+        }
+        Class getterType = mGetter.getReturnType();
+        // Check to make sure our getter type matches our valueType
+        if (!typesMatch(valueType, getterType)) {
+            throw new NoSuchPropertyException("Underlying type (" + getterType + ") " +
+                    "does not match Property type (" + valueType + ")");
+        }
+        String setterName = PREFIX_SET + capitalizedName;
+        try {
+            mSetter = propertyHolder.getMethod(setterName, getterType);
+        } catch (NoSuchMethodException ignored) {
+            // Okay to not have a setter - just a readonly property
+        }
+    }
+
+    /**
+     * Utility method to check whether the type of the underlying field/method on the target
+     * object matches the type of the Property. The extra checks for primitive types are because
+     * generics will force the Property type to be a class, whereas the type of the underlying
+     * method/field will probably be a primitive type instead. Accept float as matching Float,
+     * etc.
+     */
+    private boolean typesMatch(Class<V> valueType, Class getterType) {
+        if (getterType != valueType) {
+            if (getterType.isPrimitive()) {
+                return (getterType == float.class && valueType == Float.class) ||
+                        (getterType == int.class && valueType == Integer.class) ||
+                        (getterType == boolean.class && valueType == Boolean.class) ||
+                        (getterType == long.class && valueType == Long.class) ||
+                        (getterType == double.class && valueType == Double.class) ||
+                        (getterType == short.class && valueType == Short.class) ||
+                        (getterType == byte.class && valueType == Byte.class) ||
+                        (getterType == char.class && valueType == Character.class);
+            }
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public void set(T object, V value) {
+        if (mSetter != null) {
+            try {
+                mSetter.invoke(object, value);
+            } catch (IllegalAccessException e) {
+                throw new AssertionError();
+            } catch (InvocationTargetException e) {
+                throw new RuntimeException(e.getCause());
+            }
+        } else if (mField != null) {
+            try {
+                mField.set(object, value);
+            } catch (IllegalAccessException e) {
+                throw new AssertionError();
+            }
+        } else {
+            throw new NoSuchPropertyException("Property is read-only; set() is not implemented");
+        }
+    }
+
+    @Override
+    public V get(T object) {
+        if (mGetter != null) {
+            try {
+                return (V) mGetter.invoke(object, (Object[])null);
+            } catch (IllegalAccessException e) {
+                throw new AssertionError();
+            } catch (InvocationTargetException e) {
+                throw new RuntimeException(e.getCause());
+            }
+        } else if (mField != null) {
+            try {
+                return (V) mField.get(object);
+            } catch (IllegalAccessException e) {
+                throw new AssertionError();
+            }
+        }
+        // Should not get here: there should always be a non-null getter or field
+        throw new AssertionError();
+    }
+
+    /**
+     * Returns false if there is no setter or public field underlying this Property.
+     */
+    @Override
+    public boolean isReadOnly() {
+        return (mSetter == null && mField == null);
+    }
+}
diff --git a/core/java/android/view/GLES20RecordingCanvas.java b/core/java/android/view/GLES20RecordingCanvas.java
index 2603281..ec94fe7 100644
--- a/core/java/android/view/GLES20RecordingCanvas.java
+++ b/core/java/android/view/GLES20RecordingCanvas.java
@@ -25,7 +25,7 @@
 import android.graphics.RectF;
 import android.graphics.Shader;
 
-import java.util.HashSet;
+import java.util.ArrayList;
 
 /**
  * An implementation of a GL canvas that records drawing operations.
@@ -37,7 +37,7 @@
     // These lists ensure that any Bitmaps recorded by a DisplayList are kept alive as long
     // as the DisplayList is alive.
     @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})
-    private final HashSet<Bitmap> mBitmaps = new HashSet<Bitmap>();
+    private final ArrayList<Bitmap> mBitmaps = new ArrayList<Bitmap>(5);
 
     GLES20RecordingCanvas(boolean translucent) {
         super(true, translucent);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 70218ac..74926bb 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -16,6 +16,8 @@
 
 package android.view;
 
+import android.util.FloatProperty;
+import android.util.Property;
 import com.android.internal.R;
 import com.android.internal.util.Predicate;
 import com.android.internal.view.menu.MenuBuilder;
@@ -12436,6 +12438,169 @@
         return getVerticalScrollFactor();
     }
 
+    //
+    // Properties
+    //
+    /**
+     * A Property wrapper around the <code>alpha</code> functionality handled by the
+     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
+     */
+    static Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
+        @Override
+        public void setValue(View object, float value) {
+            object.setAlpha(value);
+        }
+
+        @Override
+        public Float get(View object) {
+            return object.getAlpha();
+        }
+    };
+
+    /**
+     * A Property wrapper around the <code>translationX</code> functionality handled by the
+     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
+     */
+    public static Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
+        @Override
+        public void setValue(View object, float value) {
+            object.setTranslationX(value);
+        }
+
+                @Override
+        public Float get(View object) {
+            return object.getTranslationX();
+        }
+    };
+
+    /**
+     * A Property wrapper around the <code>translationY</code> functionality handled by the
+     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
+     */
+    public static Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
+        @Override
+        public void setValue(View object, float value) {
+            object.setTranslationY(value);
+        }
+
+        @Override
+        public Float get(View object) {
+            return object.getTranslationY();
+        }
+    };
+
+    /**
+     * A Property wrapper around the <code>x</code> functionality handled by the
+     * {@link View#setX(float)} and {@link View#getX()} methods.
+     */
+    public static Property<View, Float> X = new FloatProperty<View>("x") {
+        @Override
+        public void setValue(View object, float value) {
+            object.setX(value);
+        }
+
+        @Override
+        public Float get(View object) {
+            return object.getX();
+        }
+    };
+
+    /**
+     * A Property wrapper around the <code>y</code> functionality handled by the
+     * {@link View#setY(float)} and {@link View#getY()} methods.
+     */
+    public static Property<View, Float> Y = new FloatProperty<View>("y") {
+        @Override
+        public void setValue(View object, float value) {
+            object.setY(value);
+        }
+
+        @Override
+        public Float get(View object) {
+            return object.getY();
+        }
+    };
+
+    /**
+     * A Property wrapper around the <code>rotation</code> functionality handled by the
+     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
+     */
+    public static Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
+        @Override
+        public void setValue(View object, float value) {
+            object.setRotation(value);
+        }
+
+        @Override
+        public Float get(View object) {
+            return object.getRotation();
+        }
+    };
+
+    /**
+     * A Property wrapper around the <code>rotationX</code> functionality handled by the
+     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
+     */
+    public static Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
+        @Override
+        public void setValue(View object, float value) {
+            object.setRotationX(value);
+        }
+
+        @Override
+        public Float get(View object) {
+            return object.getRotationX();
+        }
+    };
+
+    /**
+     * A Property wrapper around the <code>rotationY</code> functionality handled by the
+     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
+     */
+    public static Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
+        @Override
+        public void setValue(View object, float value) {
+            object.setRotationY(value);
+        }
+
+        @Override
+        public Float get(View object) {
+            return object.getRotationY();
+        }
+    };
+
+    /**
+     * A Property wrapper around the <code>scaleX</code> functionality handled by the
+     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
+     */
+    public static Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
+        @Override
+        public void setValue(View object, float value) {
+            object.setScaleX(value);
+        }
+
+        @Override
+        public Float get(View object) {
+            return object.getScaleX();
+        }
+    };
+
+    /**
+     * A Property wrapper around the <code>scaleY</code> functionality handled by the
+     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
+     */
+    public static Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
+        @Override
+        public void setValue(View object, float value) {
+            object.setScaleY(value);
+        }
+
+        @Override
+        public Float get(View object) {
+            return object.getScaleY();
+        }
+    };
+
     /**
      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
      * Each MeasureSpec represents a requirement for either the width or the height.